1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-29 08:16:28 +00:00

Get user media

This commit is contained in:
Pierre HUBERT 2020-04-21 13:26:58 +02:00
parent 167217a5a0
commit 4988c8fea8

View File

@ -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),
),
), ),
], ],
), ),