import 'dart:convert'; import 'dart:io'; import 'package:diplomaticquarterapp/app_state/app_state.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/uitl/navigation_service.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/voipcall/call/chat_incoming_call_screen.dart'; import 'package:diplomaticquarterapp/voipcall/consts.dart'; import 'package:diplomaticquarterapp/voipcall/model/get_single_user_chat_call.dart'; import 'package:diplomaticquarterapp/voipcall/model/get_user_login_token.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:just_audio/just_audio.dart'; import 'package:signalr_netcore/http_connection_options.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:signalr_netcore/hub_connection_builder.dart'; class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { ///////////////////// Web RTC Video Calling ////////////////////// // Video Call HubConnection? chatHubConnection; RTCPeerConnection? _pc; //late ChatProviderModel chatProvModel; RTCVideoRenderer? localVideoRenderer; RTCVideoRenderer? remoteRenderer; final AudioPlayer player = AudioPlayer(); MediaStream? _localStream; CallDataModel? outGoingCallData; bool isMicOff = false; bool isLoudSpeaker = false; bool isCamOff = false; bool isCallEnded = false; bool isVideoCall = false; bool isAudioCall = false; bool isCallStarted = false; bool isFrontCamera = true; SingleUserChatModel? incomingCallData; /// WebRTC Connection Variables bool isIncomingCallLoader = true; bool isIncomingCall = false; bool isOutGoingCall = false; bool isUserOnline = false; BuildContext? providerContext; List devices = []; Future buildHubConnection() async { try { chatHubConnection = await getHubConnection(); } catch (e) { Utils.showErrorToast(e.toString()); } await chatHubConnection!.start(); if (kDebugMode) { print("Hub Conn: Startedddddddd"); } // chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); // chatHubConnection.on("OnGetChatConversationCount", onNewChatConversion); // chatHubConnection.on("OnDeliveredGroupChatHistoryAsync", onGroupMsgReceived); registerCallListners(); } //{"id":341682,"userName":"Aamir.Muhammad","email":"Aamir.Muhammad@cloudsolutions.com.sa","phone":null,"title":"Aamir Saleem Ahmad Dost Muhammad","token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIzNDE2ODIiLCJlbWFpbCI6IkFhbWlyLk11aGFtbWFkQGNsb3Vkc29sdXRpb25zLmNvbS5zYSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvdXNlcmRhdGEiOiJBYW1pci5NdWhhbW1hZCIsIm5iZiI6MTcwNzIwNTAyMywiZXhwIjoxNzA3MjkxNDIzLCJpYXQiOjE3MDcyMDUwMjN9.Zz2bcsMwiLAAWGZh2E_p5Qs6ItMt0JHhDFI_0DLdggCQtt6HHcT4n8nvqMZx-uYr3jLwqhA_IAjTuaCeSE15sw","isDomainUser":true,"isActiveCode":false,"encryptedUserId":"nn7RkYzbnQc=","encryptedUserName":"/QruOyp4QMcmNXKZlljUgg=="} Future getHubConnection() async { AppState().chatDetails!.response = Response.fromJson( { "id": 341682, "userName": "Aamir.Muhammad", "email": "Aamir.Muhammad@cloudsolutions.com.sa", "phone": null, "title": "Aamir Saleem Ahmad Dost Muhammad", "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIzNDE2ODIiLCJlbWFpbCI6IkFhbWlyLk11aGFtbWFkQGNsb3Vkc29sdXRpb25zLmNvbS5zYSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvdXNlcmRhdGEiOiJBYW1pci5NdWhhbW1hZCIsIm5iZiI6MTcwNzIwNTAyMywiZXhwIjoxNzA3MjkxNDIzLCJpYXQiOjE3MDcyMDUwMjN9.Zz2bcsMwiLAAWGZh2E_p5Qs6ItMt0JHhDFI_0DLdggCQtt6HHcT4n8nvqMZx-uYr3jLwqhA_IAjTuaCeSE15sw", "isDomainUser": true, "isActiveCode": false, "encryptedUserId": "nn7RkYzbnQc=", "encryptedUserName": "/QruOyp4QMcmNXKZlljUgg==" }, ); HubConnection hub; HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hub = HubConnectionBuilder() .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails.response.id}&source=Desktop&access_token=${AppState().chatDetails.response.token}", options: httpOp) .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).build(); return hub; } void registerCallListners() { if (kDebugMode) { print("=================== Call Listeners Registered ======================="); } chatHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync!); chatHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync!); chatHubConnection!.on("OnOfferAsync", onOfferAsync!); chatHubConnection!.on("OnAnswerOffer", onAnswerOffer!); chatHubConnection!.on("OnHangUpAsync", onHangUpAsync!); // chatHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync); // chatHubConnection!.on("OnIncomingCallAsync", OnIncomingCallAsync); } // Audio Constraints Map audioConstraints = { "sampleRate": 8000, "sampleSize": 16, "channelCount": 2, "echoCancellation": true, "audio": true, }; Future init() async { _pc = await creatOfferWithCon(); Future.delayed(const Duration(seconds: 2), () { connectIncomingCall(); }); } ///////////////////////////////////////////////OutGoing Call//////////////////////////////////////////////////// Future initLocalCamera({callData, BuildContext context, bool isIncomingCall = false}) async { isCallEnded = false; outGoingCallData = callData; await initStreams(); await startCall(callType: isVideoCall ? "Video" : "Audio", context: context); _pc = await creatOfferWithCon(); connectOutgoing(); notifyListeners(); } void connectOutgoing() { isOutGoingCall = true; // notifyListeners(); } Future startCall({String callType, BuildContext context}) async { // chatProvModel.isTextMsg = true; // chatProvModel.isAttachmentMsg = false; // chatProvModel.isVoiceMsg = false; // chatProvModel.isReplyMsg = false; // chatProvModel.isCall = true; // chatProvModel.message.text = "Start $callType call ${outGoingCallData.receiverName.toString().replaceAll(".", " ")}"; // chatProvModel.sendChatMessage( // context, // targetUserId: outGoingCallData.receiverId, // userStatus: 1, // userEmail: outGoingCallData.receiverEmail, // targetUserName: outGoingCallData.receiverName, // ); await invoke( invokeMethod: "CallUserAsync", currentUserID: outGoingCallData.callerId, targetUserID: outGoingCallData.receiverId, ); await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId, targetUserID: outGoingCallData.receiverId, userStatus: 4); } // OutGoing Listeners void onCallAcceptedAsync(List? params) async { dynamic items = params!.toList(); RTCSessionDescription description = await _createOffer(); await _pc!.setLocalDescription(description); dynamic payload = {"target": items[0]["id"], "caller": outGoingCallData.callerId, "sdp": description.toMap()}; invoke(invokeMethod: "OfferAsync", currentUserID: outGoingCallData.callerId, targetUserID: items[0]["id"], data: jsonEncode(payload)); } Future onIceCandidateAsync(List? params) async { dynamic items = params!.toList(); if (isIncomingCall) { RemoteIceCandidatePayLoad data = RemoteIceCandidatePayLoad.fromJson(jsonDecode(items.first.toString())); if (_pc != null) { await _pc.addCandidate(RTCIceCandidate(data.candidate.candidate, data.candidate.sdpMid, data.candidate.sdpMLineIndex)); } } else { if (kDebugMode) { print("res: " + items.toString()); } RemoteIceCandidatePayLoad data = RemoteIceCandidatePayLoad.fromJson(jsonDecode(items.first.toString())); if (_pc != null) { await _pc.addCandidate(RTCIceCandidate(data.candidate.candidate, data.candidate.sdpMid, data.candidate.sdpMLineIndex)); if (!isCallStarted) { isCallStarted = true; notifyListeners(); if (isCallStarted) { isIncomingCallLoader = false; isOutGoingCall = true; if (Platform.isIOS) { Future.delayed(Duration(seconds: 2), () { Navigator.pushReplacement( providerContext, MaterialPageRoute( builder: (BuildContext context) => StartCallPage(), )); }); } else { Navigator.pushReplacement( providerContext, MaterialPageRoute( builder: (BuildContext context) => StartCallPage(), )); } } } } notifyListeners(); } } Future onOfferAsync(List? params) async { dynamic items = params!.toList(); var data = jsonDecode(items.toString()); if (isIncomingCall) { _pc!.setRemoteDescription(RTCSessionDescription(data[0]["sdp"]["sdp"], data[0]["sdp"]["type"])); RTCSessionDescription description = await _createAnswer(); await _pc!.setLocalDescription(description); dynamic payload = {"target": data[0]["caller"], "caller": AppState().chatDetails.response.id, "sdp": description.toMap()}; invoke(invokeMethod: "AnswerOfferAsync", currentUserID: AppState().chatDetails.response.id, targetUserID: incomingCallData.targetUserId, data: jsonEncode(payload)); } // else { // RTCSessionDescription description = await _createAnswer(); // await _pc.setLocalDescription(description); // var payload = {"target": items[0]["id"], "caller": outGoingCallData.callerId, "sdp": description.toMap()}; // invoke(invokeMethod: "AnswerOffer", currentUserID: outGoingCallData.callerId!, targetUserID: items[0]["id"], data: jsonEncode(payload)); // } notifyListeners(); } //////////////////////////// OutGoing Call End /////////////////////////////////////// Future endCall({bool? isUserOnline}) async { if (isIncomingCall) { print("-----------------------Endeddddd By Me---------------------------"); if (chatHubConnection!.state == HubConnectionState.Connected) { await invoke(invokeMethod: "HangUpAsync", currentUserID: AppState().chatDetails.response.id, targetUserID: incomingCallData.targetUserId, userStatus: 0); await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails.response.id, targetUserID: incomingCallData.targetUserId, userStatus: 1); } isCallStarted = false; isVideoCall = false; isCamOff = false; isMicOff = false; isLoudSpeaker = false; isIncomingCall = false; isOutGoingCall = false; isAudioCall = false; if (isCallConnected) { if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { if (kDebugMode) { print("------------------ PC Stopped ----------------------------"); } _pc.close(); _pc.dispose(); } } if (remoteRenderer != null) { remoteRenderer.dispose(); remoteRenderer = null; } if (localVideoRenderer != null) { localVideoRenderer.dispose(); localVideoRenderer = null; } if (_localStream != null) { _localStream.dispose(); _localStream = null; } if (chatHubConnection != null && !isUserOnline) { chatHubConnection.stop(); } await FlutterCallkitIncoming.endAllCalls(); return true; } else { if (isOutGoingCall) { await invoke(invokeMethod: "HangUpAsync", currentUserID: outGoingCallData.callerId, targetUserID: outGoingCallData.receiverId, userStatus: 1); await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId, targetUserID: outGoingCallData.receiverId, userStatus: 1); } else if (isIncomingCall) { await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails.response.id, targetUserID: incomingCallData.targetUserId, userStatus: 1); } isCallStarted = false; isVideoCall = false; isCamOff = false; isMicOff = false; isLoudSpeaker = false; if (isCallConnected) { if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { _pc.close(); _pc.dispose(); } } if (remoteRenderer != null) { remoteRenderer.dispose(); remoteRenderer = null; } if (localVideoRenderer != null) { localVideoRenderer.dispose(); localVideoRenderer = null; } if (_localStream != null) { _localStream.dispose(); _localStream = null; } isOutGoingCall = false; isIncomingCall = false; isAudioCall = false; return true; } } // Incoming Listeners void onAnswerOffer(List payload) async { // if (isIncomingCall) { // // print("--------------------- On Answer Offer Async ---------------------------------------"); // //await invoke(invokeMethod: "InvokeMobile", currentUserID: AppState().getchatUserDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, debugData: {"On Answer Offer Async"}); // } else { var items = payload.toList(); if (kDebugMode) { print("res: " + items.toString()); } CallSessionPayLoad data = CallSessionPayLoad.fromJson(jsonDecode(items.first.toString())); RTCSessionDescription description = RTCSessionDescription(data.sdp.sdp, 'answer'); _pc.setRemoteDescription(description); // } } void onHangUpAsync(List params) { print("--------------------- onHangUp ASYNC ---------------------------------"); dynamic items = params.toList(); // if (kDebugMode) { // logger.i("res: " + items.toString()); // } if (items[0]["id"] != AppState().chatDetails.response.id) { if (kDebugMode) { print("Call Ended By Other User"); } if (isIncomingCall) { endCall(isUserOnline: isUserOnline).then((bool value) { if (isCallConnected && isUserOnline) { isCallConnected = false; if (!AppState().isLogged) { Navigator.of(locator().navigatorKey.currentContext).pop(); } else { Navigator.of(locator().navigatorKey.currentContext).popUntil(ModalRoute.withName(HOME)); } } else { Navigator.of(locator().navigatorKey.currentContext).pop(); } }); } else { if (isOutGoingCall) { endCall(isUserOnline: isUserOnline).then((bool value) { if (isCallConnected && isUserOnline) { isCallConnected = false; Navigator.of(locator().navigatorKey.currentContext).popUntil(ModalRoute.withName(HOME)); } else { Navigator.of(locator().navigatorKey.currentContext).pop(); } }); } } } else { if (kDebugMode) { print("Call Ended By Me"); } if (isOutGoingCall) { if (isCallConnected && isUserOnline) { isCallConnected = false; Navigator.of(locator().navigatorKey.currentContext).popUntil(ModalRoute.withName(HOME)); } else { Navigator.of(locator().navigatorKey.currentContext).pop(); } } } // endCall(isUserOnline: isUserOnline).then((bool value) { // if (isCallConnected && isUserOnline) { // Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chatDetailed)); // isCallConnected = false; // } // if (items[0]["id"] != AppState().chatDetails!.response!.id && !AppState().isBackgroundCall) { // if (kDebugMode) { // print("Popped Due to Another User"); // } // if (AppState().isBackgroundCall) { // Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); // // Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.login)); // } else { // Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chat)); // } // } // if (AppState().isBackgroundCall) { // Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); // } // notifyListeners(); isCallEnded = true; // }); } // Future OnIncomingCallAsync(List? params) async { // print("--------------------- On Incoming Call ---------------------------------------"); // dynamic items = params!.toList(); // logger.d(items); // // Map json = { // // "callerID": items[0]["id"], // // "callerName": items[0]["userName"], // // "callerEmail": items[0]["email"], // // "callerTitle": items[0]["title"], // // "callerPhone": null, // // "receiverID": AppState().chatDetails!.response!.id, // // "receiverName": AppState().chatDetails!.response!.userName, // // "receiverEmail": AppState().chatDetails!.response!.email, // // "receiverTitle": AppState().chatDetails!.response!.title, // // "receiverPhone": AppState().chatDetails!.response!.phone, // // "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "), // // "callType": items[1] ? "Video" : "Audio", // // }; // // CallDataModel callData = CallDataModel.fromJson(json); // // ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), isOnline: true, incomingCallData: callData); // // // // if (!isOnIncomingCallPage) { // // Map json = { // // "callerID": items[0]["id"], // // "callerName": items[0]["userName"], // // "callerEmail": items[0]["email"], // // "callerTitle": items[0]["title"], // // "callerPhone": null, // // "receiverID": AppState().chatDetails!.response!.id, // // "receiverName": AppState().chatDetails!.response!.userName, // // "receiverEmail": AppState().chatDetails!.response!.email, // // "receiverTitle": AppState().chatDetails!.response!.title, // // "receiverPhone": AppState().chatDetails!.response!.phone, // // "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "), // // "callType": items[1] ? "Video" : "Audio", // // }; // // CallDataModel callData = CallDataModel.fromJson(json); // // await Navigator.push( // // providerContext, // // MaterialPageRoute( // // builder: (BuildContext context) => IncomingCall( // // isVideoCall: items[1] ? true : false, // // outGoingCallData: callData, // // ), // // ), // // ); // // isOnIncomingCallPage = true; // // } // } void onCallDeclinedAsync(List params) { print("================= On Declained ========================"); print(params); // endCall().then((bool value) { // if (value) { // isCallEnded = true; // notifyListeners(); // } // }); // if (params != null) { // endCall(isUserOnline: isUserOnline).then((bool value) { // if (isCallConnected) { // // Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); // isCallConnected = false; // } // isCallEnded = true; // }); // } } //// Invoke Methods Future invoke({String invokeMethod, int currentUserID, int targetUserID, var data, int userStatus = 1, var debugData}) async { List args = []; if (invokeMethod == "CallUserAsync") { args = [currentUserID, targetUserID, isVideoCall]; } else if (invokeMethod == "answerCallAsync") { args = [currentUserID, targetUserID]; } else if (invokeMethod == "IceCandidateAsync") { args = [targetUserID, data]; } else if (invokeMethod == "OfferAsync") { args = [targetUserID, data]; } else if (invokeMethod == "AnswerOfferAsync") { args = [targetUserID, data]; // json In Data } else if (invokeMethod == "UpdateUserStatusAsync") { args = [currentUserID, userStatus]; } else if (invokeMethod == "HangUpAsync") { args = [currentUserID, targetUserID]; } else if (invokeMethod == "InvokeMobile") { args = [debugData]; } try { await chatHubConnection.invoke("$invokeMethod", args: args); } catch (e) { print(e); } } void stopListeners() async { chatHubConnection.off('OnCallDeclinedAsync'); chatHubConnection.off('OnCallAcceptedAsync'); chatHubConnection.off('OnIceCandidateAsync'); chatHubConnection.off('OnAnswerOffer'); } void playRingtone() async { player.stop(); await player.setVolume(1.0); String audioAsset = ""; if (Platform.isAndroid) { audioAsset = "assets/audio/ring_60Sec.mp3"; } else { audioAsset = "assets/audio/ring_30Sec.caf"; } try { await player.setAsset(audioAsset); await player.load(); player.play(); } catch (e) { print("Error: $e"); } } //////////////////// Web RTC Offers & Connections //////////////////////// Future creatOfferWithCon() async { Map configuration = { "sdpSemantics": "plan-b", 'iceServers': [ { 'urls': 'stun:15.185.116.59:3478', }, { 'urls': 'turn:15.185.116.59:3479', 'username': 'admin', 'credential': 'admin', }, ] }; Map offerSdpConstraints = { 'mandatory': { 'OfferToReceiveAudio': true, 'OfferToReceiveVideo': true, }, 'optional': [] }; RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints); // await pc.addStream(_localStream!); //Changed By Aamir _localStream?.getTracks().forEach((track) { pc.addTrack(track, _localStream); }); pc.onConnectionState = (RTCPeerConnectionState state) {}; pc.onAddStream = (MediaStream stream) { remoteRenderer.srcObject = stream; notifyListeners(); }; pc.onIceCandidate = (RTCIceCandidate e) async { if (isIncomingCall) { if (e.candidate != null) { var payload = {"target": incomingCallData.targetUserId, "candidate": e.toMap()}; invoke(invokeMethod: "IceCandidateAsync", currentUserID: AppState().chatDetails.response.id, targetUserID: incomingCallData.targetUserId, data: jsonEncode(payload)); notifyListeners(); } } else { if (e.candidate != null) { var payload = {"target": outGoingCallData.callerId, "candidate": e.toMap()}; invoke(invokeMethod: "IceCandidateAsync", currentUserID: outGoingCallData.callerId, targetUserID: outGoingCallData.receiverId, data: jsonEncode(payload)); } } }; // pc!.onTrack = (RTCTrackEvent event) async { // // String streamId = const Uuid().toString(); // MediaStream remoteStream = await createLocalMediaStream(streamId); // event.streams[0].getTracks().forEach((MediaStreamTrack element) { // logger.i("Stream Track: " + element.id.toString()); // // remoteRenderer.srcObject = element; // remoteStream.addTrack(element); // }); // }; pc.onSignalingState = (RTCSignalingState state) { print("signaling state: " + state.name); // invoke( // invokeMethod: "InvokeMobile", // currentUserID: AppState().getchatUserDetails!.response!.id!, // targetUserID: incomingCallData.targetUserId!, // debugData: {"location": "Signaling", "parms": state.name}); }; pc.onIceGatheringState = (RTCIceGatheringState state) { print("rtc ice gathering state: " + state.name); }; pc.onIceConnectionState = (RTCIceConnectionState state) { if (RTCIceConnectionState.RTCIceConnectionStateFailed == state || RTCIceConnectionState.RTCIceConnectionStateDisconnected == state || RTCIceConnectionState.RTCIceConnectionStateClosed == state) { print("Ice Connection State:" + state.name); // endCall().then((value) { // notifyListeners(); // }); } }; // pc!.onRenegotiationNeeded = _onRenegotiate; return pc; } // void _onRenegotiate() async { // try { // print('onRenegotiationNeeded start'); // // makingOffer = true; // await _pc.setLocalDescription(await _pc.createOffer(videoConstraints)); // print('onRenegotiationNeeded state after setLocalDescription: ' + _pc.signalingState.toString()); // // send offer via callManager // var localDesc = await _pc.getLocalDescription(); // // callManager.sendCallMessage(MsgType.rtc_offer, RtcOfferAnswer(localDesc.sdp, localDesc.type)); // print('onRenegotiationNeeded; offer sent'); // } catch (e) { // print("onRenegotiationNeeded error: " + e.toString()); // } finally { // // makingOffer = false; // print('onRenegotiationNeeded done'); // } // } Future _createOffer() async { RTCSessionDescription description = await _pc.createOffer(); // _offer = true; return description; } Future _createAnswer() async { RTCSessionDescription description = await _pc.createAnswer(); // _offer = false; return description; } //////////////////// Web RTC End Offers //////////////////// //////////////////// CallPage Buttons ////////////////////// void micOff() { isMicOff = !isMicOff; _localStream.getAudioTracks().forEach((track) { track.enabled = !track.enabled; }); notifyListeners(); } void camOff() { isCamOff = !isCamOff; _localStream.getVideoTracks().forEach((track) { track.enabled = !track.enabled; }); // if (isCamOff) { // isVideoCall = false; // } else { // isVideoCall = true; // } notifyListeners(); } void loudOn() { isLoudSpeaker = !isLoudSpeaker; remoteRenderer.srcObject?.getAudioTracks().forEach((track) { if (isLoudSpeaker) { track.enableSpeakerphone(true); } else { track.enableSpeakerphone(false); } }); notifyListeners(); } void switchCamera() { isFrontCamera = !isFrontCamera; Helper.switchCamera(_localStream.getVideoTracks()[0]); notifyListeners(); } ///////////////// Incoming Call /////////////////////////////// Future initStreams() async { List devices = await navigator.mediaDevices.enumerateDevices(); remoteRenderer = RTCVideoRenderer(); localVideoRenderer ??= RTCVideoRenderer(); await localVideoRenderer.initialize(); try { _localStream = await navigator.mediaDevices.getUserMedia({ 'audio': true, 'video': isVideoCall ? { 'mandatory': { 'minWidth': '640', // Provide your own width, height and frame rate here 'minHeight': '480', 'minFrameRate': '30', }, 'facingMode': 'user', 'optional': [], } : false }); if (kDebugMode) { print(_localStream..toString()); } localVideoRenderer.srcObject = _localStream; localVideoRenderer.value = (const RTCVideoValue(width: 200, height: 200, renderVideo: true)); print("Working localStream"); } catch (e) { print("Failed to get user media: $e"); } // _localStream = await navigator.mediaDevices.getUserMedia(isVideoCall // ? Platform.isIOS // ? { // 'audio': true, // 'video': { // 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera // 'width': { // 'ideal': 1080, // Set the ideal width (maximum quality) // }, // 'height': { // 'ideal': 1920, // Set the ideal height (maximum quality) // }, // 'frameRate': { // 'ideal': 30, // Set the ideal frame rate (adjust as needed) // }, // }, // } // : { // 'audio': true, // 'video': { // 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera // 'width': { // 'ideal': 1920, // Set the ideal width (maximum quality) // }, // 'height': { // 'ideal': 1080, // Set the ideal height (maximum quality) // }, // 'frameRate': { // 'ideal': 30, // Set the ideal frame rate (adjust as needed) // }, // }, // } // // // ? { // // "video": { // // "mandatory": { // // "width": {"min": 1080}, // // "height": {"min": 1920} // // }, // // "optional": Platform.isAndroid // // ? [ // // {'sourceId': devices[1].deviceId}, // // { // // "width": {"max": 1080} // // }, // // {"frameRate": 30}, // // {"facingMode": "user"} // // ] // // : [ // // {"frameRate": 30}, // // {"facingMode": "user"} // // ] // // }, // // "frameRate": 30, // // "width": 1080, //420,//640,//1280, // // "height": 1920, //240//480//720 // // "audio": true, // // } // : audioConstraints); // localVideoRenderer.srcObject = _localStream; await remoteRenderer.initialize(); notifyListeners(); } Future startIncomingCallViaKit({bool isVCall = true, var inCallData}) async { AppSharedPrefs().setStringFromPrefs("isIncomingCall", "false"); if (isVCall) { isVideoCall = isVCall; } else { isAudioCall = true; } await initStreams(); isIncomingCall = true; incomingCallData = SingleUserChatModel.fromJson(inCallData); loudOn(); // notifyListeners(); } void connectIncomingCall() { invoke(invokeMethod: "answerCallAsync", currentUserID: AppState().getchatUserDetails.response.id, targetUserID: incomingCallData.targetUserId); isIncomingCallLoader = false; isIncomingCall = true; // isVideoCall = true; notifyListeners(); } // void startRecording() async { // print("=-=-=-=-=-=-= Call Recoding Started -=-=-=-=-=-=-=-=-==-="); // if (_localStream == null) throw Exception('Stream is not initialized'); // if (Platform.isIOS) { // print('Recording is not available on iOS'); // return; // } // Directory appDirectory = await getApplicationDocumentsDirectory(); // String dirPath = '${appDirectory.path}/webrtc_sample'; // if (!await Directory(dirPath).exists()) { // await Directory(dirPath).create(); // await File('$dirPath/.nomedia').create(); // } // if (appDirectory == null) throw Exception('Can\'t find storagePath'); // String filePath = dirPath + '/mobile.mp4'; // mobileRecoder = MediaRecorder(); // notifyListeners(); // MediaStreamTrack videoTrack = _localStream!.getVideoTracks().firstWhere((track) => track.kind == 'video'); // await mobileRecoder!.start(filePath, videoTrack: videoTrack); // // Future.delayed(Duration(minutes: 1), () { // stopRecording(); // }); // } // // void stopRecording() async { // print("=-=-=-=-=-=-= Call Recoding Stopped -=-=-=-=-=-=-=-=-==-="); // await mobileRecoder!.stop(); // mobileRecoder = null; // notifyListeners(); // } } class ChatService extends BaseService { Future getUserCallToken({String userid}) async { UserAutoLoginModel userLoginResponse = UserAutoLoginModel(); baseAppClient.post( "${ApiConsts.chatLoginTokenUrl}externaluserlogin", body: { "employeeNumber": userid, "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", }, onSuccess: (dynamic response, int statusCode) { userLoginResponse = userAutoLoginModelFromJson(response.body); }, onFailure: (String error, int statusCode) { hasError = true; print(error); super.error = error; }, ); return userLoginResponse; } }