You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
5.1 KiB
Dart
158 lines
5.1 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
|
|
|
typedef void StreamStateCallback(MediaStream stream);
|
|
typedef void RTCIceGatheringStateCallback(RTCIceGatheringState state);
|
|
typedef void RTCPeerConnectionStateCallback(RTCPeerConnectionState state);
|
|
typedef void RTCSignalingStateCallback(RTCSignalingState state);
|
|
|
|
class Signaling {
|
|
dispose() {
|
|
if (peerConnection != null) peerConnection.dispose();
|
|
signalR.closeConnection();
|
|
}
|
|
|
|
init() {
|
|
// Create Peer Connection
|
|
createPeerConnection(configuration).then((value) {
|
|
peerConnection = value;
|
|
registerPeerConnectionListeners();
|
|
});
|
|
}
|
|
|
|
initializeSignalR(String userName) async {
|
|
if (signalR != null) await signalR.closeConnection();
|
|
// https://vcallapi.hmg.com/webRTCHub?source=web&username=zohaib
|
|
signalR = SignalRUtil(hubName: "https://vcallapi.hmg.com/webRTCHub?source=mobile&username=$userName");
|
|
final connected = await signalR.openConnection();
|
|
if (!connected) throw 'Failed to connect SignalR';
|
|
}
|
|
|
|
Map<String, dynamic> configuration = {
|
|
// 'iceServers': [
|
|
// {
|
|
// 'urls': ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302']
|
|
// }
|
|
// ]
|
|
|
|
'iceServers': [
|
|
// {
|
|
// 'urls': ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302']
|
|
// }
|
|
|
|
{'url': "stun:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3478"},
|
|
{'url': "turn:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3479", 'credential': "admin", 'username': "admin"}
|
|
]
|
|
};
|
|
|
|
SignalRUtil signalR;
|
|
|
|
RTCPeerConnection peerConnection;
|
|
MediaStream localStream;
|
|
MediaStream remoteStream;
|
|
RTCDataChannel dataChannel;
|
|
|
|
// Future<bool> call(String patientId, String mobile, {@required RTCVideoRenderer localVideo, @required RTCVideoRenderer remoteVideo}) async {
|
|
// await initializeSignalR(patientId);
|
|
//
|
|
// // final isCallPlaced = await FCM.sendCallNotifcationTo(DOCTOR_TOKEN, patientId, mobile);
|
|
// if(!isCallPlaced)
|
|
// throw 'Failed to notify target for call';
|
|
//
|
|
// return isCallPlaced;
|
|
// }
|
|
|
|
Future<bool> acceptCall(String caller, String receiver, {@required MediaStream localMediaStream, @required Function(MediaStream) onRemoteMediaStream}) async {
|
|
await initializeSignalR(receiver);
|
|
signalR.setContributors(caller: caller, receiver: receiver);
|
|
await signalR.acceptCall(receiver, caller).catchError((e) => throw 'Failed to inform signalR that i accepted a call');
|
|
|
|
peerConnection.addStream(localMediaStream);
|
|
|
|
peerConnection?.onAddStream = (MediaStream stream) {
|
|
remoteStream = stream;
|
|
onRemoteMediaStream?.call(stream);
|
|
};
|
|
|
|
return true;
|
|
}
|
|
|
|
Future hangupCall(String caller, String receiver) async {
|
|
await signalR.hangupCall(caller, receiver);
|
|
dispose();
|
|
}
|
|
|
|
answerOffer(String sdp) async {
|
|
final offer = jsonDecode(sdp);
|
|
final caller = offer['caller'];
|
|
final receiver = offer['target'];
|
|
final offerSdp = offer['sdp'];
|
|
peerConnection.setRemoteDescription(rtcSessionDescriptionFrom(offerSdp)).then((value) {
|
|
return peerConnection.createAnswer();
|
|
}).then((anwser) {
|
|
return peerConnection.setLocalDescription(anwser);
|
|
}).then((value) {
|
|
return peerConnection.getLocalDescription();
|
|
}).then((answer) {
|
|
return signalR.answerOffer(answer, caller, receiver);
|
|
});
|
|
}
|
|
|
|
Future<void> hangUp(RTCVideoRenderer localVideo) async {}
|
|
|
|
Future<String> createSdpAnswer(String toOfferSdp) async {
|
|
final offerSdp = rtcSessionDescriptionFrom(jsonDecode(toOfferSdp));
|
|
peerConnection.setRemoteDescription(offerSdp);
|
|
|
|
final answer = await peerConnection.createAnswer();
|
|
var answerSdp = json.encode(answer); // Send SDP via Push or any channel
|
|
return answerSdp;
|
|
}
|
|
|
|
Future<String> createSdpOffer() async {
|
|
final offer = await peerConnection.createOffer();
|
|
await peerConnection.setLocalDescription(offer);
|
|
final map = offer.toMap();
|
|
var offerSdp = json.encode(map); // Send SDP via Push or any channel
|
|
return offerSdp;
|
|
}
|
|
|
|
addCandidate(String candidateJson) {
|
|
peerConnection.addCandidate(rtcIceCandidateFrom(candidateJson));
|
|
}
|
|
|
|
void registerPeerConnectionListeners() {
|
|
peerConnection.onIceCandidate = (RTCIceCandidate candidate) {
|
|
// print(json.encode(candidate.toMap()));
|
|
signalR.addIceCandidate(json.encode(candidate.toMap()));
|
|
};
|
|
|
|
peerConnection?.onIceGatheringState = (RTCIceGatheringState state) {
|
|
// print('ICE gathering state changed: $state');
|
|
};
|
|
|
|
peerConnection?.onConnectionState = (RTCPeerConnectionState state) {
|
|
// print('Connection state change: $state ${state.index}');
|
|
};
|
|
|
|
peerConnection?.onSignalingState = (RTCSignalingState state) {
|
|
// print('Signaling state change: $state');
|
|
};
|
|
}
|
|
}
|
|
|
|
rtcSessionDescriptionFrom(Map sdp) {
|
|
return RTCSessionDescription(
|
|
sdp['sdp'],
|
|
sdp['type'],
|
|
);
|
|
}
|
|
|
|
rtcIceCandidateFrom(String json) {
|
|
final map = jsonDecode(json)['candidate'];
|
|
return RTCIceCandidate(map['candidate'], map['sdpMid'], map['sdpMLineIndex']);
|
|
}
|