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.
cloudsolutions-atoms/lib/modules/cx_module/chat/calling/call_provider.dart

339 lines
11 KiB
Dart

3 weeks ago
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:signalr_netcore/http_connection_options.dart';
import 'package:signalr_netcore/hub_connection.dart';
import 'package:signalr_netcore/hub_connection_builder.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
3 weeks ago
import 'package:test_sa/modules/cx_module/chat/api_client.dart';
import 'package:http/http.dart' as http;
3 weeks ago
import '../chat_provider.dart';
3 weeks ago
import '../model/chat_login_response_model.dart';
HubConnection? callHubConnection;
3 weeks ago
class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
///////////////////// Web RTC Video Calling //////////////////////
// Video Call
late RTCPeerConnection _peerConnection;
RTCVideoRenderer _localVideoRenderer = RTCVideoRenderer();
final RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
MediaStream? _localStream;
MediaStream? _remoteStream;
bool isMuted = false;
bool isSpeakerOn = false;
bool isCameraOn = true;
bool isPeerMuted = false;
bool isPeerCameraOn = true;
3 weeks ago
bool isLoading = false;
3 weeks ago
Future<void> _disposeConnection() async {
try {
3 weeks ago
if (callHubConnection != null) {
await callHubConnection!.stop();
3 weeks ago
}
} catch (e) {
} finally {
3 weeks ago
callHubConnection = null;
3 weeks ago
}
3 weeks ago
// isLoading = false;
// notifyListeners();
3 weeks ago
}
@override
void dispose() {
3 weeks ago
_disposeConnection().then((_) {}).catchError((error) {});
3 weeks ago
super.dispose();
}
3 weeks ago
Future<HubConnection> getHubConnection(String token) async {
3 weeks ago
HubConnection hub;
HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
hub = HubConnectionBuilder().withUrl("${URLs.chatHubUrlChat}?access_token=$token", options: httpOp).withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
3 weeks ago
return hub;
}
3 weeks ago
Future<bool> buildHubConnection(String employeeNumber) async {
3 weeks ago
try {
await _disposeConnection();
3 weeks ago
// isLoading = true;
// notifyListeners();
http.Response response = await ApiClient().postJsonForResponse(URLs.chatSdkToken, {"apiKey": URLs.chatApiKey, "employeeNumber": employeeNumber, "voIPToken": null});
3 weeks ago
if (response.statusCode == 200) {
ChatLoginResponse chatResponse = ChatLoginResponse.fromJson(jsonDecode(response.body));
print("chatResponse:${chatResponse.token}");
callHubConnection = await getHubConnection(chatResponse.token!);
await callHubConnection!.start();
// isLoading = false;
// notifyListeners();
return true;
3 weeks ago
}
3 weeks ago
// isLoading = false;
// notifyListeners();
return false;
3 weeks ago
} catch (e) {
3 weeks ago
print("buildHubConnectionE:$e");
3 weeks ago
await _disposeConnection();
return false;
}
}
void initAudioCallListeners() {
3 weeks ago
callHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync);
callHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync);
callHubConnection!.on("OnOfferAsync", onOfferAsync);
callHubConnection!.on("OnAnswerOffer", onAnswerOffer);
callHubConnection!.on("OnHangUpAsync", onHangUpAsync);
callHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
callHubConnection!.on('OnAudioToggle', onAudioToggle);
3 weeks ago
}
void initCallListeners() {
3 weeks ago
callHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync);
callHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync);
callHubConnection!.on("OnOfferAsync", onOfferAsync);
callHubConnection!.on("OnAnswerOffer", onAnswerOffer);
callHubConnection!.on("OnHangUpAsync", onHangUpAsync);
callHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
callHubConnection!.on('OnAudioToggle', onAudioToggle);
callHubConnection!.on('OnCameraToggle', onCameraToggle);
// callHubConnection!.on('OnIncomingCallAsync', onHandleIncomingCall);
// callHubConnection!.on('OnCallAcceptedAsync', _handleCallAccepted);
// callHubConnection!.on('OnCallDeclinedAsync', _handleCallDeclined);
// callHubConnection!.on('OnHangUpAsync', onHangUpAsync);
// callHubConnection!.on('OnOfferAsync', _handleOffer);
// callHubConnection!.on('OnAnswerOfferAsync', onAnswerOffer);
// callHubConnection!.on('OnIceCandidateAsync', _handleIceCandidate);
// callHubConnection!.on('OnAudioToggle', _handleAudioToggle);
// callHubConnection!.on('OnCameraToggle', _handleCameraToggle);
// callHubConnection!.on('OnUserOnlineAsync', _handleUserOnline);
// callHubConnection!.on('OnUserOfflineAsync', _handleUserOffline);
// callHubConnection!.on('OnCallHistoryUpdated', _handleCallHistoryUpdated);
// callHubConnection!.on('OnError', _handleError);
3 weeks ago
}
//Video Constraints
var videoConstraints = {
"video": {
"mandatory": {
"width": {"min": 320},
"height": {"min": 180}
},
"optional": [
{
"width": {"max": 1280}
},
{"frameRate": 25},
{"facingMode": "user"}
]
},
"frameRate": 25,
"width": 420, //420,//640,//1280,
"height": 240 //240//480//720
};
// Audio Constraints
var audioConstraints = {
"sampleRate": 8000,
"sampleSize": 16,
"channelCount": 2,
"echoCancellation": true,
"audio": true,
};
Future<RTCPeerConnection> _createPeerConnection() async {
// {"url": "stun:stun.l.google.com:19302"},
Map<String, dynamic> configuration = {
"iceServers": [
{"urls": 'stun:15.185.116.59:3478'},
{"urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin"}
]
};
Map<String, dynamic> offerSdpConstraints = {
"mandatory": {
"OfferToReceiveAudio": true,
"OfferToReceiveVideo": true,
},
"optional": [],
};
RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints);
// if (pc != null) print(pc);
//pc.addStream(widget.localStream);
pc.onIceCandidate = (e) {
if (e.candidate != null) {
print(json.encode({
'candidate': e.candidate.toString(),
'sdpMid': e.sdpMid.toString(),
'sdpMlineIndex': e.sdpMLineIndex,
}));
}
};
pc.onIceConnectionState = (e) {
print(e);
};
pc.onAddStream = (stream) {
print('addStream: ' + stream.id);
_remoteRenderer.srcObject = stream;
};
return pc;
}
void init() {
initRenderers();
_createPeerConnection().then((pc) {
_peerConnection = pc;
// _setRemoteDescription(widget.info);
});
}
void initRenderers() {
_localVideoRenderer.initialize();
_remoteRenderer.initialize();
initLocalCamera();
}
void initLocalCamera() async {
_localStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
_localVideoRenderer.srcObject = _localStream;
// _localVideoRenderer.srcObject = await navigator.mediaDevices
// .getUserMedia({'video': true, 'audio': true});
print('this source Object');
print('this suarce ${_localVideoRenderer.srcObject != null}');
notifyListeners();
}
late String senderN;
late String recipientN;
late bool isVideo;
int? moduleId;
int? referenceID;
void startCall(String senderN, String recipientN, bool isVideo, int? moduleId, int? referenceID) async {
this.senderN = senderN;
this.recipientN = recipientN;
this.isVideo = isVideo;
this.moduleId = moduleId;
this.referenceID = referenceID;
invoke(invokeMethod: "CallUserAsync", currentUserID: senderN, targetUserID: recipientN, isVideoCall: isVideo);
}
void acceptCall(String senderN, String recipientN, bool isVideo, int moduleId, int? referenceID) async {
invoke(invokeMethod: "AnswerCallAsync", currentUserID: senderN, targetUserID: recipientN, isVideoCall: isVideo);
}
void declineCall(String senderN, String recipientN, bool isVideo, int moduleId, int? referenceID) async {
invoke(invokeMethod: "CallDeclinedAsync", currentUserID: senderN, targetUserID: recipientN, isVideoCall: isVideo);
}
void endCall() {
invoke(invokeMethod: "HangUpAsync", currentUserID: senderN, targetUserID: recipientN, data: moduleId);
}
void toggleMute() {
invoke(invokeMethod: "AudioToggle", currentUserID: senderN, targetUserID: recipientN, isVideoCall: isVideo);
}
void checkCall(Map<String, dynamic> message) {
switch (message["callStatus"]) {
case 'connected':
{}
break;
case 'offer':
{}
break;
case 'accept':
{}
break;
case 'candidate':
{}
break;
case 'bye':
{}
break;
case 'leave':
{}
break;
}
}
//// Listeners Methods ////
void onCallAcceptedAsync(List<Object?>? params) {
print("onCallAcceptedAsync: $params");
}
void onIceCandidateAsync(List<Object?>? params) {
print("onCallAcceptedAsync: $params");
}
void onOfferAsync(List<Object?>? params) {
print("onCallAcceptedAsync: $params");
}
void onAnswerOffer(List<Object?>? params) {
print("onAnswerOffer: $params");
}
void onHangUpAsync(List<Object?>? params) {
print("onHangUpAsync: $params");
}
void onCallDeclinedAsync(List<Object?>? params) {
print("onCallDeclinedAsync: $params");
}
void onAudioToggle(List<Object?>? params) {
print("onAudioToggle: $params");
isMuted = !isMuted;
notifyListeners();
}
void onCameraToggle(List<Object?>? params) {
print("onCameraToggle: $params");
}
//// Invoke Methods
Future<void> invoke({required String invokeMethod, required String currentUserID, required String targetUserID, bool isVideoCall = false, var data}) async {
List<Object> args = [];
if (invokeMethod == "answerCallAsync") {
args = [currentUserID, targetUserID];
} else if (invokeMethod == "CallUserAsync") {
args = [currentUserID, targetUserID, isVideoCall];
} else if (invokeMethod == "HangUpAsync ") {
args = [currentUserID, targetUserID, data];
} else if (invokeMethod == "AudioToggle") {
args = [currentUserID, targetUserID, isVideoCall];
} else if (invokeMethod == "IceCandidateAsync") {
args = [targetUserID, data];
} else if (invokeMethod == "OfferAsync") {
args = [targetUserID, data];
} else if (invokeMethod == "AnswerOfferAsync") {
args = [targetUserID, data];
}
3 weeks ago
await callHubConnection?.invoke(invokeMethod, args: args);
3 weeks ago
}
void stopListeners() async {
3 weeks ago
callHubConnection?.off('OnCallDeclinedAsync');
callHubConnection?.off('OnCallAcceptedAsync');
callHubConnection?.off('OnIceCandidateAsync');
callHubConnection?.off('OnAnswerOffer');
callHubConnection?.off('OnOfferAsync');
callHubConnection?.off('OnHangUpAsync');
callHubConnection?.off('OnAudioToggle');
3 weeks ago
}
}