mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-25 22:39:22 +00:00
Get user media
This commit is contained in:
parent
167217a5a0
commit
4988c8fea8
@ -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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user