import 'dart:convert'; // import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; typedef void StreamStateCallback(MediaStream stream); class Signaling { Map configuration = { 'iceServers': [ { 'urls': ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'] } ] }; RTCPeerConnection peerConnection; MediaStream localStream; MediaStream remoteStream; String roomId; String currentRoomText; StreamStateCallback onAddRemoteStream; Future createRoom(RTCVideoRenderer remoteRenderer) async { // FirebaseFirestore db = FirebaseFirestore.instance; // DocumentReference roomRef = db.collection('rooms').doc(); print('Create PeerConnection with configuration: $configuration'); peerConnection = await createPeerConnection(configuration); registerPeerConnectionListeners(); localStream.getTracks().forEach((track) { peerConnection?.addTrack(track, localStream); }); // Code for collecting ICE candidates below // var callerCandidatesCollection = roomRef.collection('callerCandidates'); peerConnection?.onIceCandidate = (RTCIceCandidate candidate) { print('Got candidate: ${candidate.toMap()}'); // callerCandidatesCollection.add(candidate.toMap()); }; // Finish Code for collecting ICE candidate // Add code for creating a room RTCSessionDescription offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); print('Created offer: $offer'); Map roomWithOffer = {'offer': offer.toMap()}; // await roomRef.set(roomWithOffer); // var roomId = roomRef.id; print('New room created with SDK offer. Room ID: $roomId'); currentRoomText = 'Current room is $roomId - You are the caller!'; // Created a Room peerConnection?.onTrack = (RTCTrackEvent event) { print('Got remote track: ${event.streams[0]}'); event.streams[0].getTracks().forEach((track) { print('Add a track to the remoteStream $track'); remoteStream?.addTrack(track); }); }; // Listening for remote session description below // roomRef.snapshots().listen((snapshot) async { // print('Got updated room: ${snapshot.data()}'); // // Map data = snapshot.data() as Map; // if (peerConnection?.getRemoteDescription() != null && data['answer'] != null) { // var answer = RTCSessionDescription( // data['answer']['sdp'], // data['answer']['type'], // ); // // print("Someone tried to connect"); // await peerConnection?.setRemoteDescription(answer); // } // }); // // Listening for remote session description above // // // Listen for remote Ice candidates below // roomRef.collection('calleeCandidates').snapshots().listen((snapshot) { // snapshot.docChanges.forEach((change) { // if (change.type == DocumentChangeType.added) { // Map data = change.doc.data() as Map; // print('Got new remote ICE candidate: ${jsonEncode(data)}'); // peerConnection.addCandidate( // RTCIceCandidate( // data['candidate'], // data['sdpMid'], // data['sdpMLineIndex'], // ), // ); // } // }); // }); // Listen for remote ICE candidates above return roomId; } Future joinRoom(String roomId, RTCVideoRenderer remoteVideo) async { // FirebaseFirestore db = FirebaseFirestore.instance; // DocumentReference roomRef = db.collection('rooms').doc('$roomId'); // var roomSnapshot = await roomRef.get(); // print('Got room ${roomSnapshot.exists}'); // if (roomSnapshot.exists) { // print('Create PeerConnection with configuration: $configuration'); // peerConnection = await createPeerConnection(configuration); // // registerPeerConnectionListeners(); // // localStream.getTracks().forEach((track) { // peerConnection?.addTrack(track, localStream); // }); // // // Code for collecting ICE candidates below // // var calleeCandidatesCollection = roomRef.collection('calleeCandidates'); // peerConnection.onIceCandidate = (RTCIceCandidate candidate) { // if (candidate == null) { // print('onIceCandidate: complete!'); // return; // } // print('onIceCandidate: ${candidate.toMap()}'); // // calleeCandidatesCollection.add(candidate.toMap()); // }; // // Code for collecting ICE candidate above // // peerConnection?.onTrack = (RTCTrackEvent event) { // print('Got remote track: ${event.streams[0]}'); // event.streams[0].getTracks().forEach((track) { // print('Add a track to the remoteStream: $track'); // remoteStream?.addTrack(track); // }); // }; // // // Code for creating SDP answer below // var data = roomSnapshot.data() as Map; // print('Got offer $data'); // var offer = data['offer']; // await peerConnection?.setRemoteDescription( // RTCSessionDescription(offer['sdp'], offer['type']), // ); // var answer = await peerConnection.createAnswer(); // print('Created Answer $answer'); // // await peerConnection.setLocalDescription(answer); // // Map roomWithAnswer = { // 'answer': {'type': answer.type, 'sdp': answer.sdp} // }; // // await roomRef.update(roomWithAnswer); // // Finished creating SDP answer // // // Listening for remote ICE candidates below // // roomRef.collection('callerCandidates').snapshots().listen((snapshot) { // // snapshot.docChanges.forEach((document) { // // var data = document.doc.data() as Map; // // print(data); // // print('Got new remote ICE candidate: $data'); // // peerConnection.addCandidate( // // RTCIceCandidate( // // data['candidate'], // // data['sdpMid'], // // data['sdpMLineIndex'], // // ), // // ); // // }); // // }); // } } Future openUserMedia( RTCVideoRenderer localVideo, RTCVideoRenderer remoteVideo, ) async { var stream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': false}); localVideo.srcObject = stream; localStream = stream; remoteVideo.srcObject = await createLocalMediaStream('key'); } Future hangUp(RTCVideoRenderer localVideo) async { List tracks = localVideo.srcObject.getTracks(); tracks.forEach((track) { track.stop(); }); if (remoteStream != null) { remoteStream.getTracks().forEach((track) => track.stop()); } if (peerConnection != null) peerConnection.close(); if (roomId != null) { // var db = FirebaseFirestore.instance; // var roomRef = db.collection('rooms').doc(roomId); // var calleeCandidates = await roomRef.collection('calleeCandidates').get(); // calleeCandidates.docs.forEach((document) => document.reference.delete()); // var callerCandidates = await roomRef.collection('callerCandidates').get(); // callerCandidates.docs.forEach((document) => document.reference.delete()); // await roomRef.delete(); } localStream.dispose(); remoteStream?.dispose(); } void registerPeerConnectionListeners() { peerConnection?.onIceGatheringState = (RTCIceGatheringState state) { print('ICE gathering state changed: $state'); }; peerConnection?.onConnectionState = (RTCPeerConnectionState state) { print('Connection state change: $state'); }; peerConnection?.onSignalingState = (RTCSignalingState state) { print('Signaling state change: $state'); }; peerConnection?.onIceGatheringState = (RTCIceGatheringState state) { print('ICE connection state change: $state'); }; peerConnection?.onAddStream = (MediaStream stream) { print("Add remote stream"); onAddRemoteStream?.call(stream); remoteStream = stream; }; } }