import 'dart:async'; import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart'; import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart'; import 'package:diplomaticquarterapp/pages/webRTC/call_page.dart'; import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart'; import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import '../conference_button_bar.dart'; class CallHomePage extends StatefulWidget { final String receiverId; final String callerId; const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key); @override _CallHomePageState createState() => _CallHomePageState(); } class _CallHomePageState extends State { bool showNoise = false; RTCVideoRenderer _localRenderer = RTCVideoRenderer(); RTCVideoRenderer _remoteRenderer = RTCVideoRenderer(); final StreamController _audioButton = StreamController.broadcast(); final StreamController _videoButton = StreamController.broadcast(); final StreamController _onButtonBarVisibleStreamController = StreamController.broadcast(); final StreamController _onButtonBarHeightStreamController = StreamController.broadcast(); //Stream to enable video MediaStream localMediaStream; MediaStream remoteMediaStream; Signaling signaling = Signaling()..init(); @override void initState() { // TODO: implement initState super.initState(); startCall(); } startCall() async{ await _localRenderer.initialize(); await _remoteRenderer.initialize(); final connected = await receivedCall(); } Future receivedCall() async { //Stream local media localMediaStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true}); _localRenderer.srcObject = localMediaStream; final connected = await signaling.acceptCall(widget.callerId, widget.receiverId, localMediaStream: localMediaStream, onRemoteMediaStream: (remoteMediaStream){ this.remoteMediaStream = remoteMediaStream; _remoteRenderer.srcObject = remoteMediaStream; }); if(connected){ signaling.signalR.listen( onAcceptCall: (arg0){ print(arg0.toString()); }, onCandidate: (candidateJson){ signaling.addCandidate(candidateJson); }, onDeclineCall: (arg0,arg1){ _onHangup(); }, onHangupCall: (arg0){ _onHangup(); }, onOffer: (offerSdp, callerUser) async{ print('${offerSdp.toString()} | ${callerUser.toString()}'); await signaling.answerOffer(offerSdp); } ); } return connected; } @override void dispose() { // TODO: implement dispose super.dispose(); _localRenderer?.dispose(); _remoteRenderer?.dispose(); _audioButton?.close(); _videoButton?.close(); localMediaStream?.dispose(); remoteMediaStream?.dispose(); _disposeStreamsAndSubscriptions(); } Future _disposeStreamsAndSubscriptions() async { if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close(); if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close(); } @override Widget build(BuildContext context) { // return WillPopScope( // onWillPop: () async => false, // child: Scaffold( // backgroundColor: Colors.black, // // body: , // ), // ); return Scaffold( backgroundColor: Colors.white, body: showNoise ? _buildNoiseBox() : buildLayout(), ); } LayoutBuilder buildLayout() { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { return Stack( children: [ CamViewWidget( localRenderer: _localRenderer, remoteRenderer: _remoteRenderer, constraints: constraints, onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController, onButtonBarHeightStreamController: _onButtonBarHeightStreamController, ), ConferenceButtonBar( audioEnabled: _audioButton.stream, videoEnabled: _videoButton.stream, onAudioEnabled: _onAudioEnable, onVideoEnabled: _onVideoEnabled, onSwitchCamera: _onSwitchCamera, onHangup: _onHangup, onPersonAdd: () {}, onPersonRemove: () {}, onHeight: _onHeightBar, onShow: _onShowBar, onHide: _onHideBar, ), ], ); }, ); } NoiseBox _buildNoiseBox() { return NoiseBox( density: NoiseBoxDensity.xLow, backgroundColor: Colors.grey.shade900, child: Center( child: Container( color: Colors.black54, width: double.infinity, height: 40, child: Center( child: Text( 'Waiting for another participant to connect to the call...', key: Key('text-wait'), textAlign: TextAlign.center, style: TextStyle(color: Colors.white), ), ), ), ), ); } Function _onAudioEnable() { final audioTrack = localMediaStream.getAudioTracks()[0]; final mute = audioTrack.muted; Helper.setMicrophoneMute(!mute, audioTrack); _audioButton.add(mute); } Function _onVideoEnabled() { final videoTrack = localMediaStream.getVideoTracks()[0]; bool videoEnabled = videoTrack.enabled; localMediaStream.getVideoTracks()[0].enabled = !videoEnabled; _videoButton.add(!videoEnabled); } Function _onSwitchCamera() { Helper.switchCamera(localMediaStream.getVideoTracks()[0]); } void _onShowBar() { setState(() { }); _onButtonBarVisibleStreamController.add(true); } void _onHeightBar(double height) { _onButtonBarHeightStreamController.add(height); } void _onHideBar() { setState(() { SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]); }); _onButtonBarVisibleStreamController.add(false); } Future _onHangup() async { signaling.hangupCall(widget.callerId, widget.receiverId); print('onHangup'); Navigator.of(context).pop(); } }