Skip to content

Commit 8357acb

Browse files
committed
Support custom MediaStream for call/answer.
1 parent 4c29f17 commit 8357acb

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

example/lib/src/callscreen.dart

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,22 @@ class _MyCallScreenWidget extends State<CallScreenWidget>
199199
_timer.cancel();
200200
}
201201

202-
void _handleAccept() {
203-
call.answer(helper.buildCallOptions());
202+
void _handleAccept() async {
203+
final mediaConstraints = <String, dynamic>{'audio': true, 'video': true};
204+
MediaStream mediaStream;
205+
206+
if (kIsWeb) {
207+
mediaStream =
208+
await navigator.mediaDevices.getDisplayMedia(mediaConstraints);
209+
mediaConstraints['video'] = false;
210+
MediaStream userStream =
211+
await navigator.mediaDevices.getUserMedia(mediaConstraints);
212+
mediaStream.addTrack(userStream.getAudioTracks()[0], addToNative: true);
213+
} else {
214+
mediaStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
215+
}
216+
217+
call.answer(helper.buildCallOptions(), mediaStream: mediaStream);
204218
}
205219

206220
void _switchCamera() {

example/lib/src/dialpad.dart

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import 'package:flutter/foundation.dart';
12
import 'package:flutter/material.dart';
23
import 'package:sip_ua/sip_ua.dart';
34
import 'package:shared_preferences/shared_preferences.dart';
5+
import 'package:flutter_webrtc/flutter_webrtc.dart';
46

57
import 'widgets/action_button.dart';
68

@@ -41,7 +43,8 @@ class _MyDialPadWidget extends State<DialPadWidget>
4143
helper.addSipUaHelperListener(this);
4244
}
4345

44-
Widget _handleCall(BuildContext context, [bool voiceonly = false]) {
46+
Future<Widget> _handleCall(BuildContext context,
47+
[bool voiceonly = false]) async {
4548
var dest = _textController.text;
4649
if (dest == null || dest.isEmpty) {
4750
showDialog<Null>(
@@ -64,7 +67,23 @@ class _MyDialPadWidget extends State<DialPadWidget>
6467
);
6568
return null;
6669
}
67-
helper.call(dest, voiceonly);
70+
71+
final mediaConstraints = <String, dynamic>{'audio': true, 'video': true};
72+
73+
MediaStream mediaStream;
74+
75+
if (kIsWeb) {
76+
mediaStream =
77+
await navigator.mediaDevices.getDisplayMedia(mediaConstraints);
78+
mediaConstraints['video'] = false;
79+
MediaStream userStream =
80+
await navigator.mediaDevices.getUserMedia(mediaConstraints);
81+
mediaStream.addTrack(userStream.getAudioTracks()[0], addToNative: true);
82+
} else {
83+
mediaStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
84+
}
85+
86+
helper.call(dest, voiceonly: voiceonly, mediaStream: mediaStream);
6887
_preferences.setString('dest', dest);
6988
return null;
7089
}

lib/src/rtc_session.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ class RTCSession extends EventManager {
590590
// A local MediaStream is given, use it.
591591
if (mediaStream != null) {
592592
stream = mediaStream;
593+
emit(EventStream(session: this, originator: 'local', stream: stream));
593594
}
594595
// Audio and/or video requested, prompt getUserMedia.
595596
else if (mediaConstraints['audio'] != null ||
@@ -2195,6 +2196,7 @@ class RTCSession extends EventManager {
21952196
// A stream is given, var the app set events such as 'peerconnection' and 'connecting'.
21962197
if (mediaStream != null) {
21972198
stream = mediaStream;
2199+
emit(EventStream(session: this, originator: 'local', stream: stream));
21982200
} // Request for user media access.
21992201
else if (mediaConstraints['audio'] != null ||
22002202
mediaConstraints['video'] != null) {

lib/src/sip_ua_helper.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,13 @@ class SIPUAHelper extends EventManager {
6969
}
7070

7171
Future<bool> call(String target,
72-
[bool voiceonly = false, MediaStream mediaStream = null]) async {
72+
{bool voiceonly = false, MediaStream mediaStream = null}) async {
7373
if (_ua != null && _ua.isConnected()) {
74-
_ua.call(target, buildCallOptions(voiceonly));
74+
Map<String, Object> options = buildCallOptions(voiceonly);
75+
if (mediaStream != null) {
76+
options['mediaStream'] = mediaStream;
77+
}
78+
_ua.call(target, options);
7579
return true;
7680
} else {
7781
logger.error(
@@ -387,8 +391,11 @@ class Call {
387391
String get id => _id;
388392
CallStateEnum state;
389393

390-
void answer(Map<String, Object> options) {
394+
void answer(Map<String, Object> options, {MediaStream mediaStream = null}) {
391395
assert(_session != null, 'ERROR(answer): rtc session is invalid!');
396+
if (mediaStream != null) {
397+
options['mediaStream'] = mediaStream;
398+
}
392399
_session.answer(options);
393400
}
394401

0 commit comments

Comments
 (0)