mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 12:14:11 +00:00 
			
		
		
		
	Get user media
This commit is contained in:
		@@ -45,6 +45,10 @@ class _CallScreenState extends SafeState<CallScreen> {
 | 
				
			|||||||
  UsersList _usersList;
 | 
					  UsersList _usersList;
 | 
				
			||||||
  final _peersConnections = Map<int, RTCPeerConnection>();
 | 
					  final _peersConnections = Map<int, RTCPeerConnection>();
 | 
				
			||||||
  final _renderers = Map<int, RTCVideoRenderer>();
 | 
					  final _renderers = Map<int, RTCVideoRenderer>();
 | 
				
			||||||
 | 
					  MediaStream _localStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get isStreamingVideo =>
 | 
				
			||||||
 | 
					      _localStream != null && _localStream.getVideoTracks().length > 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initState() {
 | 
					  void initState() {
 | 
				
			||||||
@@ -130,12 +134,15 @@ class _CallScreenState extends SafeState<CallScreen> {
 | 
				
			|||||||
  /// Do clean up operations when call screen is destroyed
 | 
					  /// Do clean up operations when call screen is destroyed
 | 
				
			||||||
  void _endCall() async {
 | 
					  void _endCall() async {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // Leave the call
 | 
					 | 
				
			||||||
      await CallsHelper.leave(convID);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Close all ready members
 | 
					      // Close all ready members
 | 
				
			||||||
      for (final member in _membersList.readyPeers)
 | 
					      for (final member in _membersList.readyPeers)
 | 
				
			||||||
        await _removeMember(member.userID);
 | 
					        await _removeMember(member.userID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Close local stream
 | 
				
			||||||
 | 
					      await _stopStreaming();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Leave the call
 | 
				
			||||||
 | 
					      await CallsHelper.leave(convID);
 | 
				
			||||||
    } catch (e, stack) {
 | 
					    } catch (e, stack) {
 | 
				
			||||||
      print("Could not end call properly! $e\n$stack");
 | 
					      print("Could not end call properly! $e\n$stack");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -151,6 +158,53 @@ class _CallScreenState extends SafeState<CallScreen> {
 | 
				
			|||||||
    MainController.of(context).popPage();
 | 
					    MainController.of(context).popPage();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Start streaming on our end
 | 
				
			||||||
 | 
					  Future<void> _startStreaming(bool includeVideo) async {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      await _stopStreaming();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Request user media
 | 
				
			||||||
 | 
					      _localStream = await navigator.getUserMedia({
 | 
				
			||||||
 | 
					        "audio": true,
 | 
				
			||||||
 | 
					        "video": !includeVideo
 | 
				
			||||||
 | 
					            ? false
 | 
				
			||||||
 | 
					            : {
 | 
				
			||||||
 | 
					                "mandatory": {
 | 
				
			||||||
 | 
					                  "maxWidth": '320',
 | 
				
			||||||
 | 
					                  "maxHeight": '240',
 | 
				
			||||||
 | 
					                  "minFrameRate": '24',
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "facingMode": "user",
 | 
				
			||||||
 | 
					                "optional": [],
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Start renderer
 | 
				
			||||||
 | 
					      _renderers[userID()] = RTCVideoRenderer();
 | 
				
			||||||
 | 
					      await _renderers[userID()].initialize();
 | 
				
			||||||
 | 
					      _renderers[userID()].srcObject = _localStream;
 | 
				
			||||||
 | 
					      setState(() {});
 | 
				
			||||||
 | 
					    } catch (e, stack) {
 | 
				
			||||||
 | 
					      print("Could not start streaming! $e\n$stack");
 | 
				
			||||||
 | 
					      showSimpleSnack(context, tr("Could not start streaming!"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Stop local streaming
 | 
				
			||||||
 | 
					  Future<void> _stopStreaming() async {
 | 
				
			||||||
 | 
					    // Stop local stream
 | 
				
			||||||
 | 
					    if (_localStream != null) {
 | 
				
			||||||
 | 
					      await _localStream.dispose();
 | 
				
			||||||
 | 
					      _localStream = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Close renderer
 | 
				
			||||||
 | 
					    if (_renderers.containsKey(userID())) {
 | 
				
			||||||
 | 
					      await _renderers[userID()].dispose();
 | 
				
			||||||
 | 
					      _renderers.remove(userID());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Call this when a user started to stream media
 | 
					  /// Call this when a user started to stream media
 | 
				
			||||||
  Future<void> _memberReady(int memberID) async {
 | 
					  Future<void> _memberReady(int memberID) async {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@@ -170,7 +224,8 @@ class _CallScreenState extends SafeState<CallScreen> {
 | 
				
			|||||||
      _peersConnections[memberID] = peerConnection;
 | 
					      _peersConnections[memberID] = peerConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Create a renderer
 | 
					      // Create a renderer
 | 
				
			||||||
      _renderers[memberID] = RTCVideoRenderer()..initialize();
 | 
					      _renderers[memberID] = RTCVideoRenderer()
 | 
				
			||||||
 | 
					        ..initialize(); // TODO Use await instead for initialize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Register callbacks
 | 
					      // Register callbacks
 | 
				
			||||||
      peerConnection.onIceCandidate =
 | 
					      peerConnection.onIceCandidate =
 | 
				
			||||||
@@ -305,10 +360,19 @@ class _CallScreenState extends SafeState<CallScreen> {
 | 
				
			|||||||
  /// Videos area
 | 
					  /// Videos area
 | 
				
			||||||
  Widget _buildVideosArea() {
 | 
					  Widget _buildVideosArea() {
 | 
				
			||||||
    return Expanded(
 | 
					    return Expanded(
 | 
				
			||||||
        child: Column(
 | 
					        child: Stack(
 | 
				
			||||||
      children: _membersList.readyPeers
 | 
					      fit: StackFit.expand,
 | 
				
			||||||
          .map((f) => _buildMemberVideo(f.userID))
 | 
					      children: [
 | 
				
			||||||
          .toList(),
 | 
					        // Remove peers videos
 | 
				
			||||||
 | 
					        Column(
 | 
				
			||||||
 | 
					          children: _membersList.readyPeers
 | 
				
			||||||
 | 
					              .map((f) => _buildMemberVideo(f.userID))
 | 
				
			||||||
 | 
					              .toList(),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Local peer video
 | 
				
			||||||
 | 
					        isStreamingVideo ? _buildLocalVideo() : Container(),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
    ));
 | 
					    ));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -316,6 +380,16 @@ class _CallScreenState extends SafeState<CallScreen> {
 | 
				
			|||||||
    return Expanded(child: RTCVideoView(_renderers[peerID]));
 | 
					    return Expanded(child: RTCVideoView(_renderers[peerID]));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildLocalVideo() {
 | 
				
			||||||
 | 
					    return Positioned(
 | 
				
			||||||
 | 
					      child: RTCVideoView(_renderers[userID()]),
 | 
				
			||||||
 | 
					      height: 50,
 | 
				
			||||||
 | 
					      width: 50,
 | 
				
			||||||
 | 
					      right: 10,
 | 
				
			||||||
 | 
					      bottom: 10,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Footer area
 | 
					  /// Footer area
 | 
				
			||||||
  Widget _buildFooterArea() {
 | 
					  Widget _buildFooterArea() {
 | 
				
			||||||
    return Material(
 | 
					    return Material(
 | 
				
			||||||
@@ -323,10 +397,28 @@ class _CallScreenState extends SafeState<CallScreen> {
 | 
				
			|||||||
      child: Row(
 | 
					      child: Row(
 | 
				
			||||||
        mainAxisAlignment: MainAxisAlignment.center,
 | 
					        mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
        children: <Widget>[
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          // Toggle audio button
 | 
				
			||||||
 | 
					          Expanded(
 | 
				
			||||||
 | 
					            child: IconButton(
 | 
				
			||||||
 | 
					              icon: Icon(Icons.mic_off),
 | 
				
			||||||
 | 
					              onPressed: () => _startStreaming(false),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // Hang up call
 | 
					          // Hang up call
 | 
				
			||||||
          IconButton(
 | 
					          Expanded(
 | 
				
			||||||
            icon: Icon(Icons.phone, color: Colors.red),
 | 
					            child: IconButton(
 | 
				
			||||||
            onPressed: () => _leaveCall(),
 | 
					              icon: Icon(Icons.phone, color: Colors.red),
 | 
				
			||||||
 | 
					              onPressed: () => _leaveCall(),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Toggle video button
 | 
				
			||||||
 | 
					          Expanded(
 | 
				
			||||||
 | 
					            child: IconButton(
 | 
				
			||||||
 | 
					              icon: Icon(Icons.videocam_off),
 | 
				
			||||||
 | 
					              onPressed: () => _startStreaming(true),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user