import 'dart:async'; import 'package:diplomaticquarterapp/pages/conference/conference_button_bar.dart'; import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart'; import 'package:diplomaticquarterapp/pages/videocall-webrtc-rnd/utils/device_info.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'dart:core'; import 'signaling.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; class StartVideoCall extends StatefulWidget { static String tag = 'webrtc'; final String host; String caller; String receiver; bool iAmCaller; StartVideoCall({@required this.caller, @required this.receiver, this.iAmCaller = false, @required this.host}); @override StartVideoCallState createState() => StartVideoCallState(receiverId: receiver, callerId: caller, iAmCaller: iAmCaller); } class StartVideoCallState extends State { Signaling _signaling; SessionOneToOne _session; StartVideoCallState({@required String callerId, @required String receiverId, @required bool iAmCaller}){ final self_role = iAmCaller ? "Caller" : "Receiver"; final self_id = iAmCaller ? callerId : receiverId; final self_user = SocketUser(id: self_id, name: "$self_role-$self_id", userAgent: DeviceInfo.userAgent, moreInfo: {}); final remote_role = !iAmCaller ? "Caller" : "Receiver"; final remote_id = !iAmCaller ? callerId : receiverId; final remote_user = SocketUser(id: remote_id, name: "$remote_role-$remote_id", userAgent: DeviceInfo.userAgent, moreInfo: {}); final session_id = "$callerId-$receiverId"; _session = SessionOneToOne(id: session_id, local_user: self_user, remote_user: remote_user); } bool showNoise = true; final StreamController _audioButton = StreamController.broadcast(); final StreamController _videoButton = StreamController.broadcast(); final StreamController _onButtonBarVisibleStreamController = StreamController.broadcast(); final StreamController _onButtonBarHeightStreamController = StreamController.broadcast(); final RTCVideoRenderer _localRenderer = RTCVideoRenderer(); final RTCVideoRenderer _remoteRenderer = RTCVideoRenderer(); MediaStream get localMediaStream => _signaling.localStream; MediaStream get remoteMediaStream => _signaling.remoteStreams.first; @override initState() { super.initState(); initRenderers(); _connect(); } initRenderers() async { await _localRenderer.initialize(); await _remoteRenderer.initialize(); } @override deactivate() { super.deactivate(); _signaling?.close(); _localRenderer.dispose(); _remoteRenderer.dispose(); } @override Widget build(BuildContext context) { return Scaffold( // appBar: AppBar( // title: Text('P2P Call Sample' + (_session?.local_user != null ? ' [Your ID (${_session?.local_user?.id})] ' : '')), // actions: [ // IconButton( // icon: const Icon(Icons.settings), // onPressed: (){ // setState(() { // }); // }, // tooltip: 'setup', // ), // ], // ), body: videoCanvasWidgets(), ); } LayoutBuilder videoCanvasWidgets() { 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, ), ], ); }, ); } void _connect() async { if(_session == null) return; _signaling ??= Signaling(widget.host, session: _session)..connect(); _signaling?.onSignalingStateChange = (SignalingState state) { switch (state) { case SignalingState.Closed: case SignalingState.Error: case SignalingState.Open: break; } }; _signaling?.onCallStateChange = (SessionOneToOne session, CallState state) { switch (state) { case CallState.Calling: setState(() {}); break; case CallState.Bye: setState(() { _localRenderer.srcObject = null; _remoteRenderer.srcObject = null; _session = null; }); break; case CallState.Invite: case CallState.Connected: case CallState.Ringing: } }; _signaling?.onConnected = ((event) { _signaling?.callAccepted(_session); }); _signaling?.onRemoteConnected = ((event) { }); _signaling?.onLocalStream = ((stream) { _localRenderer.srcObject = stream; setState(() { }); }); _signaling?.onAddRemoteStream = ((_, stream) { _remoteRenderer.srcObject = stream; setState(() {}); }); _signaling?.onRemoveRemoteStream = ((_, stream) { setState(() { _remoteRenderer.srcObject = null; }); }); } _hangUp() async{ if (_session != null) { _signaling?.bye(_session); } } _switchCamera() { _signaling?.switchCamera(); } _muteMic() { _signaling?.muteMic(); } 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.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom]); }); _onButtonBarVisibleStreamController.add(false); } Future _onHangup() async { _signaling?.finishSessions(); print('onHangup'); Navigator.of(context).pop(); } }