// import 'dart:convert'; // import 'dart:async'; // import 'package:flutter/cupertino.dart'; // import 'package:flutter_webrtc/flutter_webrtc.dart'; // // import '../utils/websocket.dart' if (dart.library.js) '../utils/websocket_web.dart'; // import '../utils/turn.dart' if (dart.library.js) '../utils/turn_web.dart'; // // // enum SignalingState { Open, Closed, Error } // enum CallState { Calling, Ringing, Invite, Connected, Bye } // // // const JsonEncoder _encoder = JsonEncoder(); // const JsonDecoder _decoder = JsonDecoder(); // // class SessionOneToOne { // late String id; // late SocketUser local_user; // late SocketUser remote_user; // SessionOneToOne({required this.id, required this.local_user, required this.remote_user}); // // // late RTCPeerConnection pc; // late RTCDataChannel dc; // List remoteCandidates = []; // } // // class SocketUser{ // String? id; // String? name; // String? userAgent; // Map? moreInfo; // // SocketUser({required this.id, required this.name, required this.userAgent, required this.moreInfo}); // // SocketUser.from(dynamic json){ // id = json['id']; // name = json['name']; // userAgent = json['user_agent']; // moreInfo = json['more_info']; // } // // Map toJson() => { // "id": id, // "name": name, // "user_agent": userAgent, // "more_info": moreInfo // }; // } // // class Signaling { // var _host; // var _turnCredential; // // SimpleWebSocket? _socket; // SessionOneToOne? session; // // Signaling(this._host, {required this.session}); // // late MediaStream? localStream; // late final List remoteStreams = []; // // late Function(SignalingState state) onSignalingStateChange; // late Function(SessionOneToOne session, CallState state) onCallStateChange; // late Function(MediaStream stream) onLocalStream; // late Function(SessionOneToOne session, MediaStream stream) onAddRemoteStream; // late Function(SessionOneToOne session, MediaStream stream) onRemoveRemoteStream; // late Function(dynamic event) onPeersUpdate; // late Function(dynamic event) onConnected; // late Function(dynamic event) onRemoteConnected; // late Function(SessionOneToOne session, RTCDataChannel dc, RTCDataChannelMessage data) onDataChannelMessage; // late Function(SessionOneToOne session, RTCDataChannel dc) onDataChannel; // // String? get sdpSemantics => WebRTC.platformIsWindows ? 'plan-b' : 'unified-plan'; // // Map _iceServers = { // 'iceServers': [ // {'url': 'stun:stun.l.google.com:19302'}, // /* // * turn server configuration example. // { // 'url': 'turn:123.45.67.89:3478', // 'username': 'change_to_real_user', // 'credential': 'change_to_real_secret' // }, // */ // ] // }; // // final Map _config = { // 'mandatory': {}, // 'optional': [ // {'DtlsSrtpKeyAgreement': true}, // ] // }; // // final Map _dcConstraints = { // 'mandatory': { // 'OfferToReceiveAudio': false, // 'OfferToReceiveVideo': false, // }, // 'optional': [], // }; // // // close() async { // await finishSessions(); // _socket?.close(); // } // // void switchCamera() { // if (localStream != null) { // Helper.switchCamera(localStream! .getVideoTracks()[0]); // } // } // // void muteMic() { // if (localStream != null) { // bool enabled = localStream!.getAudioTracks()[0].enabled; // localStream!.getAudioTracks()[0].enabled = !enabled; // } // } // // // callAccepted(SessionOneToOne session){ // _send('call_accepted', { // 'to': session.remote_user?.id, // 'from': session.local_user.id, // 'session_id': session.id, // }); // } // // void offer(String media, bool useScreen) async { // if(session == null) // return; // // if (media == 'data') { // _createDataChannel(session!); // } // _createOffer(session!, media); // onCallStateChange?.call(session!, CallState.Calling); // } // // void bye(SessionOneToOne session) { // _send('bye', { // 'session_id': session.id, // 'from': session.local_user.id, // }); // _closeSession(session); // } // // void onMessage(message) async { // Map mapData = message; // var data = mapData['data']; // // switch (mapData['type']) { // case 'call_accepted': // { // onRemoteConnected?.call(data); // } // break; // // case 'connected': // { // if (onConnected != null) { // onConnected?.call(data); // } // } // break; // // case 'offer': // { // // var peerId = data['from']; // var description = data['description']; // var media = data['media']; // // await _initPeerConnection(session!, media: media, screenSharing: false); // await session!.pc?.setRemoteDescription(RTCSessionDescription(description['sdp'], description['type'])); // await _createAnswer(session!, media); // // if (session!.remoteCandidates!.isNotEmpty) { // session!.remoteCandidates!.forEach((candidate) async { // await session!.pc?.addCandidate(candidate); // }); // session!.remoteCandidates.clear(); // } // onCallStateChange?.call(session!, CallState.Calling); // } // break; // case 'answer': // { // // var description = data['description']; // var sessionId = data['session_id']; // session!.pc?.setRemoteDescription( // RTCSessionDescription(description['sdp'], description['type'])); // } // break; // case 'candidate': // { // // var peerId = data['from']; // var candidateMap = data['candidate']; // var sessionId = data['session_id']; // RTCIceCandidate candidate = RTCIceCandidate(candidateMap['candidate'], // candidateMap['sdpMid'], candidateMap['sdpMLineIndex']); // // if (session != null) { // if (session!.pc != null) { // await session!.pc?.addCandidate(candidate); // } else { // session!.remoteCandidates.add(candidate); // } // } else { // // _sessions[sessionId] = SessionOneToOne(pid: peerId, sid: sessionId) // // ..remoteCandidates.add(candidate); // } // } // break; // case 'leave': // { // var peerId = data as String; // _closeSessionById(peerId); // } // break; // case 'bye': // { // // var sessionId = data['session_id']; // print('bye: ' + sessionId); // if (session != null) { // onCallStateChange?.call(session!, CallState.Bye); // _closeSession(session!); // } // } // break; // case 'keepalive': // { // print('keepalive response!'); // } // break; // default: // break; // } // } // // Future connect() async { // _socket = SimpleWebSocket('$_host/ws'); // // if (_turnCredential == null) { // try { // _turnCredential = await getTurnCredential(_host); // /* // { // "username": "1584195784:mbzrxpgjys", // "password": "isyl6FF6nqMTB9/ig5MrMRUXqZg", // "ttl": 86400, // "uris": ["turn:127.0.0.1:19302?transport=udp"] // } // */ // _iceServers = { // 'iceServers': [ // { // 'urls': _turnCredential['uris'][0], // 'username': _turnCredential['username'], // 'credential': _turnCredential['password'] // }, // ] // }; // } catch (e) {} // } // // _socket?.onOpen = () { // print('onOpen'); // onSignalingStateChange?.call(SignalingState.Open); // _send('connect', session!.local_user!.toJson()); // }; // // _socket?.onMessage = (message) { // print('Received data: ' + message); // onMessage(_decoder.convert(message)); // }; // // _socket?.onClose = (int code, String reason) { // print('Closed by server [$code => $reason]!'); // onSignalingStateChange?.call(SignalingState.Closed); // }; // // await _socket?.connect(); // } // // Future createStream(String media, bool userScreen) async { // final Map mediaConstraints = { // 'audio': userScreen ? false : true, // 'video': userScreen // ? true // : { // 'mandatory': { // 'minWidth': '640', // Provide your own width, height and frame rate here // 'minHeight': '480', // 'minFrameRate': '30', // }, // 'facingMode': 'user', // 'optional': [], // } // }; // // MediaStream stream = userScreen // ? await navigator.mediaDevices.getDisplayMedia(mediaConstraints) // : await navigator.mediaDevices.getUserMedia(mediaConstraints); // onLocalStream?.call(stream); // return stream; // } // // Future _initPeerConnection(SessionOneToOne session, {required String media, required bool screenSharing}) async { // // if (media != 'data') // localStream = await createStream(media, screenSharing); // print(_iceServers); // RTCPeerConnection pc = await createPeerConnection({ // ..._iceServers, // ...{'sdpSemantics': sdpSemantics} // }, _config); // if (media != 'data') { // switch (sdpSemantics) { // case 'plan-b': // pc.onAddStream = (MediaStream stream) { // onAddRemoteStream?.call(session, stream); // remoteStreams.add(stream); // }; // await pc.addStream(localStream!); // break; // case 'unified-plan': // // Unified-Plan // pc.onTrack = (event) { // if (event.track.kind == 'video') { // onAddRemoteStream?.call(session, event.streams[0]); // } // }; // localStream! .getTracks().forEach((track) { // pc.addTrack(track, localStream!); // }); // break; // } // // // Unified-Plan: Simuclast // /* // await pc.addTransceiver( // track: _localStream.getAudioTracks()[0], // init: RTCRtpTransceiverInit( // direction: TransceiverDirection.SendOnly, streams: [_localStream]), // ); // // await pc.addTransceiver( // track: _localStream.getVideoTracks()[0], // init: RTCRtpTransceiverInit( // direction: TransceiverDirection.SendOnly, // streams: [ // _localStream // ], // sendEncodings: [ // RTCRtpEncoding(rid: 'f', active: true), // RTCRtpEncoding( // rid: 'h', // active: true, // scaleResolutionDownBy: 2.0, // maxBitrate: 150000, // ), // RTCRtpEncoding( // rid: 'q', // active: true, // scaleResolutionDownBy: 4.0, // maxBitrate: 100000, // ), // ]), // );*/ // /* // var sender = pc.getSenders().find(s => s.track.kind == "video"); // var parameters = sender.getParameters(); // if(!parameters) // parameters = {}; // parameters.encodings = [ // { rid: "h", active: true, maxBitrate: 900000 }, // { rid: "m", active: true, maxBitrate: 300000, scaleResolutionDownBy: 2 }, // { rid: "l", active: true, maxBitrate: 100000, scaleResolutionDownBy: 4 } // ]; // sender.setParameters(parameters); // */ // } // pc.onIceCandidate = (candidate) async { // if (candidate == null) { // print('onIceCandidate: complete!'); // return; // } // // This delay is needed to allow enough time to try an ICE candidate // // before skipping to the next one. 1 second is just an heuristic value // // and should be thoroughly tested in your own environment. // await Future.delayed( // const Duration(seconds: 1), // () => _send('candidate', { // 'to': session.remote_user?.id, // 'from': session.local_user.id, // 'candidate': { // 'sdpMLineIndex': candidate.sdpMLineIndex, // sdpMlineIndex or sdpMLineIndex // 'sdpMid': candidate.sdpMid, // 'candidate': candidate.candidate, // }, // 'session_id': session.id, // })); // }; // // pc.onIceConnectionState = (state) {}; // // pc.onRemoveStream = (stream) { // onRemoveRemoteStream?.call(session, stream); // remoteStreams.removeWhere((it) { // return (it.id == stream.id); // }); // }; // // pc.onDataChannel = (channel) { // _addDataChannel(session, channel); // }; // // session.pc = pc; // return session; // } // // void _addDataChannel(SessionOneToOne session, RTCDataChannel channel) { // channel.onDataChannelState = (e) {}; // channel.onMessage = (RTCDataChannelMessage data) { // onDataChannelMessage?.call(session, channel, data); // }; // session.dc = channel; // onDataChannel?.call(session, channel); // } // // Future _createDataChannel(SessionOneToOne session, {label= 'fileTransfer'}) async { // RTCDataChannelInit dataChannelDict = RTCDataChannelInit() // ..maxRetransmits = 30; // RTCDataChannel channel = // await session.pc .createDataChannel(label, dataChannelDict); // _addDataChannel(session, channel); // } // // Future _createOffer(SessionOneToOne session, String media) async { // try { // RTCSessionDescription s = // await session.pc .createOffer(media == 'data' ? _dcConstraints : {}); // await session.pc .setLocalDescription(s); // _send('offer', { // 'to': session.remote_user?.id, // 'from': session.local_user.id, // 'description': {'sdp': s.sdp, 'type': s.type}, // 'session_id': session.id, // 'media': media, // }); // } catch (e) { // print(e.toString()); // } // } // // Future _createAnswer(SessionOneToOne session, String media) async { // try { // RTCSessionDescription s = // await session.pc .createAnswer(media == 'data' ? _dcConstraints : {}); // await session.pc .setLocalDescription(s); // _send('answer', { // 'to': session.remote_user?.id, // 'from': session.local_user.id, // 'description': {'sdp': s.sdp, 'type': s.type}, // 'session_id': session.id, // }); // } catch (e) { // print(e.toString()); // } // } // // _send(event, data) { // var request = Map(); // request["type"] = event; // request["data"] = data; // _socket?.send(_encoder.convert(request)); // } // // Future finishSessions() async { // _closeSessionById(session!.id); // } // // void _closeSessionById(String sessionId) { // if (session != null && session!.id == sessionId) { // _closeSession(session!); // onCallStateChange?.call(session!, CallState.Bye); // } // } // // Future _closeSession(SessionOneToOne session) async { // localStream?.getTracks()?.forEach((element) async { // await element.stop(); // }); // await localStream?.dispose(); // localStream = null; // // await session.pc?.close(); // await session.dc?.close(); // } // }