Skip to content

Commit 2329691

Browse files
committed
screen sharing.
1 parent 6e19eac commit 2329691

File tree

4 files changed

+374
-19
lines changed

4 files changed

+374
-19
lines changed

lib/src/call_sample/call_sample.dart

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'dart:core';
3+
import '../widgets/screen_select_dialog.dart';
34
import 'signaling.dart';
45
import 'package:flutter_webrtc/flutter_webrtc.dart';
56

@@ -71,8 +72,7 @@ class _CallSampleState extends State<CallSample> {
7172
setState(() {
7273
_inCalling = true;
7374
});
74-
}
75-
else {
75+
} else {
7676
_reject();
7777
}
7878
break;
@@ -135,15 +135,19 @@ class _CallSampleState extends State<CallSample> {
135135
title: Text("title"),
136136
content: Text("accept?"),
137137
actions: <Widget>[
138-
TextButton(
139-
child: Text("reject"),
138+
MaterialButton(
139+
child: Text(
140+
'Reject',
141+
style: TextStyle(color: Colors.red),
142+
),
140143
onPressed: () => Navigator.of(context).pop(false),
141144
),
142-
TextButton(
143-
child: Text("accept"),
144-
onPressed: () {
145-
Navigator.of(context).pop(true);
146-
},
145+
MaterialButton(
146+
child: Text(
147+
'Accept',
148+
style: TextStyle(color: Colors.green),
149+
),
150+
onPressed: () => Navigator.of(context).pop(true),
147151
),
148152
],
149153
);
@@ -164,8 +168,7 @@ class _CallSampleState extends State<CallSample> {
164168
onPressed: () {
165169
Navigator.of(context).pop(false);
166170
_hangUp();
167-
},
168-
171+
},
169172
),
170173
],
171174
);
@@ -201,6 +204,36 @@ class _CallSampleState extends State<CallSample> {
201204
_signaling?.switchCamera();
202205
}
203206

207+
Future<void> selectScreenSourceDialog(BuildContext context) async {
208+
final source = await showDialog<DesktopCapturerSource>(
209+
context: context,
210+
builder: (context) => ScreenSelectDialog(),
211+
);
212+
if (source != null) {
213+
try {
214+
var stream =
215+
await navigator.mediaDevices.getDisplayMedia(<String, dynamic>{
216+
'video': {
217+
'deviceId': {'exact': source.id},
218+
'mandatory': {'frameRate': 30.0}
219+
}
220+
});
221+
stream.getVideoTracks()[0].onEnded = () {
222+
print(
223+
'By adding a listener on onEnded you can: 1) catch stop video sharing on Web');
224+
};
225+
_signaling?.switchToScreenSharing(stream);
226+
} catch (e) {
227+
print(e);
228+
}
229+
//await _makeCall(source);
230+
}
231+
}
232+
233+
_switchScreenSharing() {
234+
//_signaling?.switchToScreenSharing();
235+
}
236+
204237
_muteMic() {
205238
_signaling?.muteMic();
206239
}
@@ -254,14 +287,20 @@ class _CallSampleState extends State<CallSample> {
254287
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
255288
floatingActionButton: _inCalling
256289
? SizedBox(
257-
width: 200.0,
290+
width: 240.0,
258291
child: Row(
259292
mainAxisAlignment: MainAxisAlignment.spaceBetween,
260293
children: <Widget>[
261294
FloatingActionButton(
262295
child: const Icon(Icons.switch_camera),
296+
tooltip: 'Camera',
263297
onPressed: _switchCamera,
264298
),
299+
FloatingActionButton(
300+
child: const Icon(Icons.desktop_mac),
301+
tooltip: 'Screen Sharing',
302+
onPressed: () => selectScreenSourceDialog(context),
303+
),
265304
FloatingActionButton(
266305
onPressed: _hangUp,
267306
tooltip: 'Hangup',
@@ -270,6 +309,7 @@ class _CallSampleState extends State<CallSample> {
270309
),
271310
FloatingActionButton(
272311
child: const Icon(Icons.mic_off),
312+
tooltip: 'Mute Mic',
273313
onPressed: _muteMic,
274314
)
275315
]))

lib/src/call_sample/signaling.dart

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ enum CallState {
2424
CallStateBye,
2525
}
2626

27+
enum VideoSource {
28+
Camera,
29+
Screen,
30+
}
31+
2732
class Session {
2833
Session({required this.sid, required this.pid});
2934
String pid;
@@ -46,6 +51,8 @@ class Signaling {
4651
Map<String, Session> _sessions = {};
4752
MediaStream? _localStream;
4853
List<MediaStream> _remoteStreams = <MediaStream>[];
54+
List<RTCRtpSender> _senders = <RTCRtpSender>[];
55+
VideoSource videoSource = VideoSource.Camera;
4956

5057
Function(SignalingState state)? onSignalingStateChange;
5158
Function(Session session, CallState state)? onCallStateChange;
@@ -57,8 +64,7 @@ class Signaling {
5764
onDataChannelMessage;
5865
Function(Session session, RTCDataChannel dc)? onDataChannel;
5966

60-
String get sdpSemantics =>
61-
WebRTC.platformIsWindows ? 'plan-b' : 'unified-plan';
67+
String get sdpSemantics => 'unified-plan';
6268

6369
Map<String, dynamic> _iceServers = {
6470
'iceServers': [
@@ -96,10 +102,36 @@ class Signaling {
96102

97103
void switchCamera() {
98104
if (_localStream != null) {
99-
Helper.switchCamera(_localStream!.getVideoTracks()[0]);
105+
if (videoSource != VideoSource.Camera) {
106+
switchVideoSource(source: VideoSource.Camera);
107+
_senders.forEach((sender) {
108+
if (sender.track!.kind == 'video') {
109+
sender.replaceTrack(_localStream!.getVideoTracks()[0]);
110+
}
111+
});
112+
videoSource = VideoSource.Camera;
113+
onLocalStream?.call(_localStream!);
114+
} else {
115+
Helper.switchCamera(_localStream!.getVideoTracks()[0]);
116+
}
100117
}
101118
}
102119

120+
void switchToScreenSharing(MediaStream stream) {
121+
if (_localStream != null && videoSource != VideoSource.Screen) {
122+
switchVideoSource(source: VideoSource.Screen);
123+
_senders.forEach((sender) {
124+
if (sender.track!.kind == 'video') {
125+
sender.replaceTrack(stream.getVideoTracks()[0]);
126+
}
127+
});
128+
onLocalStream?.call(stream);
129+
videoSource = VideoSource.Screen;
130+
}
131+
}
132+
133+
void switchVideoSource({VideoSource source = VideoSource.Camera}) {}
134+
103135
void muteMic() {
104136
if (_localStream != null) {
105137
bool enabled = _localStream!.getAudioTracks()[0].enabled;
@@ -190,7 +222,6 @@ class Signaling {
190222
newSession.remoteCandidates.clear();
191223
}
192224
onCallStateChange?.call(newSession, CallState.CallStateNew);
193-
194225
onCallStateChange?.call(newSession, CallState.CallStateRinging);
195226
}
196227
break;
@@ -356,8 +387,8 @@ class Signaling {
356387
onAddRemoteStream?.call(newSession, event.streams[0]);
357388
}
358389
};
359-
_localStream!.getTracks().forEach((track) {
360-
pc.addTrack(track, _localStream!);
390+
_localStream!.getTracks().forEach((track) async {
391+
_senders.add(await pc.addTrack(track, _localStream!));
361392
});
362393
break;
363394
}

0 commit comments

Comments
 (0)