1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-25 22:39:22 +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;
final _peersConnections = Map<int, RTCPeerConnection>();
final _renderers = Map<int, RTCVideoRenderer>();
MediaStream _localStream;
bool get isStreamingVideo =>
_localStream != null && _localStream.getVideoTracks().length > 0;
@override
void initState() {
@ -130,12 +134,15 @@ class _CallScreenState extends SafeState<CallScreen> {
/// Do clean up operations when call screen is destroyed
void _endCall() async {
try {
// Leave the call
await CallsHelper.leave(convID);
// Close all ready members
for (final member in _membersList.readyPeers)
await _removeMember(member.userID);
// Close local stream
await _stopStreaming();
// Leave the call
await CallsHelper.leave(convID);
} catch (e, stack) {
print("Could not end call properly! $e\n$stack");
}
@ -151,6 +158,53 @@ class _CallScreenState extends SafeState<CallScreen> {
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
Future<void> _memberReady(int memberID) async {
try {
@ -170,7 +224,8 @@ class _CallScreenState extends SafeState<CallScreen> {
_peersConnections[memberID] = peerConnection;
// Create a renderer
_renderers[memberID] = RTCVideoRenderer()..initialize();
_renderers[memberID] = RTCVideoRenderer()
..initialize(); // TODO Use await instead for initialize
// Register callbacks
peerConnection.onIceCandidate =
@ -305,10 +360,19 @@ class _CallScreenState extends SafeState<CallScreen> {
/// Videos area
Widget _buildVideosArea() {
return Expanded(
child: Column(
child: Stack(
fit: StackFit.expand,
children: [
// 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]));
}
Widget _buildLocalVideo() {
return Positioned(
child: RTCVideoView(_renderers[userID()]),
height: 50,
width: 50,
right: 10,
bottom: 10,
);
}
/// Footer area
Widget _buildFooterArea() {
return Material(
@ -323,11 +397,29 @@ class _CallScreenState extends SafeState<CallScreen> {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// Toggle audio button
Expanded(
child: IconButton(
icon: Icon(Icons.mic_off),
onPressed: () => _startStreaming(false),
),
),
// Hang up call
IconButton(
Expanded(
child: IconButton(
icon: Icon(Icons.phone, color: Colors.red),
onPressed: () => _leaveCall(),
),
),
// Toggle video button
Expanded(
child: IconButton(
icon: Icon(Icons.videocam_off),
onPressed: () => _startStreaming(true),
),
),
],
),
);