mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-29 08:16:28 +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;
|
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),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user