Skip to content

Commit 0d29d55

Browse files
committed
chore: fix bugs.
1 parent 9e1b84c commit 0d29d55

File tree

4 files changed

+119
-69
lines changed

4 files changed

+119
-69
lines changed

lib/src/call_sample/call_sample.dart

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -207,33 +207,38 @@ class _CallSampleState extends State<CallSample> {
207207
}
208208

209209
Future<void> selectScreenSourceDialog(BuildContext context) async {
210-
final source = await showDialog<DesktopCapturerSource>(
211-
context: context,
212-
builder: (context) => ScreenSelectDialog(),
213-
);
214-
if (source != null) {
215-
try {
216-
var stream =
217-
await navigator.mediaDevices.getDisplayMedia(<String, dynamic>{
218-
'video': {
219-
'deviceId': {'exact': source.id},
220-
'mandatory': {'frameRate': 30.0}
221-
}
222-
});
223-
stream.getVideoTracks()[0].onEnded = () {
224-
print(
225-
'By adding a listener on onEnded you can: 1) catch stop video sharing on Web');
226-
};
227-
_signaling?.switchToScreenSharing(stream);
228-
} catch (e) {
229-
print(e);
210+
MediaStream? screenStream;
211+
if (WebRTC.platformIsDesktop) {
212+
final source = await showDialog<DesktopCapturerSource>(
213+
context: context,
214+
builder: (context) => ScreenSelectDialog(),
215+
);
216+
if (source != null) {
217+
try {
218+
var stream =
219+
await navigator.mediaDevices.getDisplayMedia(<String, dynamic>{
220+
'video': {
221+
'deviceId': {'exact': source.id},
222+
'mandatory': {'frameRate': 30.0}
223+
}
224+
});
225+
stream.getVideoTracks()[0].onEnded = () {
226+
print(
227+
'By adding a listener on onEnded you can: 1) catch stop video sharing on Web');
228+
};
229+
screenStream = stream;
230+
} catch (e) {
231+
print(e);
232+
}
230233
}
231-
//await _makeCall(source);
234+
} else if (WebRTC.platformIsWeb) {
235+
screenStream =
236+
await navigator.mediaDevices.getDisplayMedia(<String, dynamic>{
237+
'audio': false,
238+
'video': true,
239+
});
232240
}
233-
}
234-
235-
_switchScreenSharing() {
236-
//_signaling?.switchToScreenSharing();
241+
if (screenStream != null) _signaling?.switchToScreenSharing(screenStream);
237242
}
238243

239244
_muteMic() {

lib/src/call_sample/signaling.dart

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Signaling {
5252
MediaStream? _localStream;
5353
List<MediaStream> _remoteStreams = <MediaStream>[];
5454
List<RTCRtpSender> _senders = <RTCRtpSender>[];
55-
VideoSource videoSource = VideoSource.Camera;
55+
VideoSource _videoSource = VideoSource.Camera;
5656

5757
Function(SignalingState state)? onSignalingStateChange;
5858
Function(Session session, CallState state)? onCallStateChange;
@@ -102,14 +102,13 @@ class Signaling {
102102

103103
void switchCamera() {
104104
if (_localStream != null) {
105-
if (videoSource != VideoSource.Camera) {
106-
switchVideoSource(source: VideoSource.Camera);
105+
if (_videoSource != VideoSource.Camera) {
107106
_senders.forEach((sender) {
108107
if (sender.track!.kind == 'video') {
109108
sender.replaceTrack(_localStream!.getVideoTracks()[0]);
110109
}
111110
});
112-
videoSource = VideoSource.Camera;
111+
_videoSource = VideoSource.Camera;
113112
onLocalStream?.call(_localStream!);
114113
} else {
115114
Helper.switchCamera(_localStream!.getVideoTracks()[0]);
@@ -118,20 +117,17 @@ class Signaling {
118117
}
119118

120119
void switchToScreenSharing(MediaStream stream) {
121-
if (_localStream != null && videoSource != VideoSource.Screen) {
122-
switchVideoSource(source: VideoSource.Screen);
120+
if (_localStream != null && _videoSource != VideoSource.Screen) {
123121
_senders.forEach((sender) {
124122
if (sender.track!.kind == 'video') {
125123
sender.replaceTrack(stream.getVideoTracks()[0]);
126124
}
127125
});
128126
onLocalStream?.call(stream);
129-
videoSource = VideoSource.Screen;
127+
_videoSource = VideoSource.Screen;
130128
}
131129
}
132130

133-
void switchVideoSource({VideoSource source = VideoSource.Camera}) {}
134-
135131
void muteMic() {
136132
if (_localStream != null) {
137133
bool enabled = _localStream!.getAudioTracks()[0].enabled;
@@ -571,5 +567,7 @@ class Signaling {
571567

572568
await session.pc?.close();
573569
await session.dc?.close();
570+
_senders.clear();
571+
_videoSource = VideoSource.Camera;
574572
}
575573
}

lib/src/widgets/screen_select_dialog.dart

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,51 @@ class ScreenSelectDialog extends Dialog {
88
ScreenSelectDialog() {
99
Future.delayed(Duration(milliseconds: 100), () {
1010
_getSources();
11-
_timer = Timer.periodic(Duration(milliseconds: 2000), (timer) {
12-
_getSources();
13-
});
1411
});
12+
_subscriptions.add(desktopCapturer.onAdded.stream.listen((source) {
13+
_sources[source.id] = source;
14+
_stateSetter?.call(() {});
15+
}));
16+
17+
_subscriptions.add(desktopCapturer.onRemoved.stream.listen((source) {
18+
_sources.remove(source.id);
19+
_stateSetter?.call(() {});
20+
}));
21+
22+
_subscriptions.add(desktopCapturer.onNameChanged.stream.listen((source) {
23+
_sources[source.id] = source;
24+
_stateSetter?.call(() {});
25+
}));
26+
27+
_subscriptions
28+
.add(desktopCapturer.onThumbnailChanged.stream.listen((source) {
29+
_sources[source.id] = source;
30+
_stateSetter?.call(() {});
31+
}));
1532
}
16-
List<DesktopCapturerSource> _sources = [];
33+
final Map<String, DesktopCapturerSource> _sources = {};
1734
SourceType _sourceType = SourceType.Screen;
1835
DesktopCapturerSource? _selected_source;
36+
final List<StreamSubscription<DesktopCapturerSource>> _subscriptions = [];
1937
StateSetter? _stateSetter;
2038
Timer? _timer;
2139

22-
void _pop(context) {
40+
void _ok(context) async {
2341
_timer?.cancel();
42+
_subscriptions.forEach((element) {
43+
element.cancel();
44+
});
2445
Navigator.pop<DesktopCapturerSource>(context, _selected_source);
2546
}
2647

48+
void _cancel(context) async {
49+
_timer?.cancel();
50+
_subscriptions.forEach((element) {
51+
element.cancel();
52+
});
53+
Navigator.pop<DesktopCapturerSource>(context, null);
54+
}
55+
2756
Future<void> _getSources() async {
2857
try {
2958
var sources = await desktopCapturer.getSources(types: [_sourceType]);
@@ -32,7 +61,13 @@ class ScreenSelectDialog extends Dialog {
3261
'name: ${element.name}, id: ${element.id}, type: ${element.type}');
3362
});
3463
_stateSetter?.call(() {
35-
_sources = sources;
64+
sources.forEach((element) {
65+
_sources[element.id] = element;
66+
});
67+
});
68+
_timer?.cancel();
69+
_timer = Timer.periodic(Duration(seconds: 3), (timer) {
70+
desktopCapturer.updateSources(types: [_sourceType]);
3671
});
3772
return;
3873
} catch (e) {
@@ -66,7 +101,7 @@ class ScreenSelectDialog extends Dialog {
66101
alignment: Alignment.topRight,
67102
child: InkWell(
68103
child: Icon(Icons.close),
69-
onTap: () => _pop(context),
104+
onTap: () => _cancel(context),
70105
),
71106
),
72107
],
@@ -97,7 +132,7 @@ class ScreenSelectDialog extends Dialog {
97132
tabs: [
98133
Tab(
99134
child: Text(
100-
'Entrire Screen',
135+
'Entire Screen',
101136
style: TextStyle(color: Colors.black54),
102137
)),
103138
Tab(
@@ -119,9 +154,9 @@ class ScreenSelectDialog extends Dialog {
119154
child: GridView.count(
120155
crossAxisSpacing: 8,
121156
crossAxisCount: 2,
122-
children: _sources
157+
children: _sources.entries
123158
.where((element) =>
124-
element.type ==
159+
element.value.type ==
125160
SourceType.Screen)
126161
.map((e) => Column(
127162
children: [
@@ -131,7 +166,7 @@ class ScreenSelectDialog extends Dialog {
131166
null &&
132167
_selected_source!
133168
.id ==
134-
e.id)
169+
e.value.id)
135170
? BoxDecoration(
136171
border: Border.all(
137172
width: 2,
@@ -141,16 +176,18 @@ class ScreenSelectDialog extends Dialog {
141176
child: InkWell(
142177
onTap: () {
143178
print(
144-
'Selected screen id => ${e.id}');
179+
'Selected screen id => ${e.value.id}');
145180
setState(() {
146181
_selected_source =
147-
e;
182+
e.value;
148183
});
149184
},
150185
child:
151-
e.thumbnail != null
186+
e.value.thumbnail !=
187+
null
152188
? Image.memory(
153-
e.thumbnail!,
189+
e.value
190+
.thumbnail!,
154191
scale: 1.0,
155192
repeat: ImageRepeat
156193
.noRepeat,
@@ -159,15 +196,16 @@ class ScreenSelectDialog extends Dialog {
159196
),
160197
)),
161198
Text(
162-
e.name,
199+
e.value.name,
163200
style: TextStyle(
164201
fontSize: 12,
165202
color: Colors.black87,
166203
fontWeight: (_selected_source !=
167204
null &&
168205
_selected_source!
169206
.id ==
170-
e.id)
207+
e.value
208+
.id)
171209
? FontWeight.bold
172210
: FontWeight
173211
.normal),
@@ -183,9 +221,9 @@ class ScreenSelectDialog extends Dialog {
183221
child: GridView.count(
184222
crossAxisSpacing: 8,
185223
crossAxisCount: 3,
186-
children: _sources
224+
children: _sources.entries
187225
.where((element) =>
188-
element.type ==
226+
element.value.type ==
189227
SourceType.Window)
190228
.map((e) => Column(
191229
children: [
@@ -195,7 +233,7 @@ class ScreenSelectDialog extends Dialog {
195233
null &&
196234
_selected_source!
197235
.id ==
198-
e.id)
236+
e.value.id)
199237
? BoxDecoration(
200238
border: Border.all(
201239
width: 2,
@@ -205,33 +243,38 @@ class ScreenSelectDialog extends Dialog {
205243
child: InkWell(
206244
onTap: () {
207245
print(
208-
'Selected window id => ${e.id}');
246+
'Selected window id => ${e.value.id}');
209247
setState(() {
210248
_selected_source =
211-
e;
249+
e.value;
212250
});
213251
},
214-
child:
215-
e.thumbnail != null
216-
? Image.memory(
217-
e.thumbnail!,
218-
scale: 1.0,
219-
repeat: ImageRepeat
252+
child: e
253+
.value
254+
.thumbnail!
255+
.isNotEmpty
256+
? Image.memory(
257+
e.value
258+
.thumbnail!,
259+
scale: 1.0,
260+
repeat:
261+
ImageRepeat
220262
.noRepeat,
221-
)
222-
: Container(),
263+
)
264+
: Container(),
223265
),
224266
)),
225267
Text(
226-
e.name,
268+
e.value.name,
227269
style: TextStyle(
228270
fontSize: 12,
229271
color: Colors.black87,
230272
fontWeight: (_selected_source !=
231273
null &&
232274
_selected_source!
233275
.id ==
234-
e.id)
276+
e.value
277+
.id)
235278
? FontWeight.bold
236279
: FontWeight
237280
.normal),
@@ -261,7 +304,7 @@ class ScreenSelectDialog extends Dialog {
261304
style: TextStyle(color: Colors.black54),
262305
),
263306
onPressed: () {
264-
_pop(context);
307+
_cancel(context);
265308
},
266309
),
267310
MaterialButton(
@@ -270,7 +313,7 @@ class ScreenSelectDialog extends Dialog {
270313
'Share',
271314
),
272315
onPressed: () {
273-
_pop(context);
316+
_ok(context);
274317
},
275318
),
276319
],

pubspec.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ dependencies:
1111
sdk: flutter
1212

1313
cupertino_icons: ^1.0.3
14-
flutter_webrtc: ^0.8.12
14+
flutter_webrtc:
15+
git:
16+
url: https://github.com/flutter-webrtc/flutter-webrtc.git
17+
ref: feat/screen-capture-event-listener-for-win
18+
1519
shared_preferences: ^2.0.7
1620
http: ^0.13.3
1721
path_provider: ^2.0.2

0 commit comments

Comments
 (0)