8000 Merge remote-tracking branch 'origin' into test · next-coder/flutter-webrtc@7d1b85f · GitHub
[go: up one dir, main page]

Skip to content

Commit 7d1b85f

Browse files
committed
Merge remote-tracking branch 'origin' into test
2 parents a148e55 + 1c089de commit 7d1b85f

12 files changed

+209
-23
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Changelog
22

33
--------------------------------------------
4+
[0.3.3] - 2020.09.14
5+
6+
* Add RTCDTMFSender for mobile, web and macOS.
7+
* Improve RenegotiationNeededCallback.
8+
* Refactor RTCVideoView for web and solve the resize problem.
9+
* Reduce code size.
10+
411
[0.3.2] - 2020.09.11
512

613
* Reorganize the directory structure.
@@ -15,7 +22,6 @@
1522

1623
* [Dart] FIX - missing null check onIceGatheringState (web)
1724

18-
--------------------------------------------
1925
[0.3.0] - 2020.09.05
2026

2127
* [Dart] Improve RTCVideoView.

android/src/main/java/com/cloudwebrtc/webrtc/MethodCallHandlerImpl.java

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,28 @@
11
package com.cloudwebrtc.webrtc;
22

3-
import static com.cloudwebrtc.webrtc.utils.MediaConstraintsUtils.parseMediaConstraints;
4-
53
import android.app.Activity;
64
import android.content.Context;
75
import android.graphics.SurfaceTexture;
86
import android.hardware.Camera;
97
import android.hardware.Camera.CameraInfo;
108
import android.util.Log;
119
import android.util.LongSparseArray;
10+
1211
import androidx.annotation.NonNull;
1312
import androidx.annotation.Nullable;
13+
1414
import com.cloudwebrtc.webrtc.record.AudioChannel;
1515
import com.cloudwebrtc.webrtc.record.FrameCapturer;
1616
import com.cloudwebrtc.webrtc.utils.AnyThreadResult;
1717
import com.cloudwebrtc.webrtc.utils.ConstraintsArray;
1818
import com.cloudwebrtc.webrtc.utils.ConstraintsMap;
1919
import com.cloudwebrtc.webrtc.utils.EglUtils;
2020
import com.cloudwebrtc.webrtc.utils.ObjectType;
21-
import com.cloudwebrtc.webrtc.utils.RTCAudioManager;
22-
import io.flutter.plugin.common.BinaryMessenger;
23-
import io.flutter.plugin.common.EventChannel;
24-
import io.flutter.plugin.common.MethodCall;
25-
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
26-
import io.flutter.plugin.common.MethodChannel.Result;
27-
import io.flutter.view.TextureRegistry;
28-
import io.flutter.view.TextureRegistry.SurfaceTextureEntry;
29-
import java.io.File;
30-
import java.io.UnsupportedEncodingException;
31-
import java.nio.ByteBuffer;
32-
import java.util.ArrayList;
33-
import java.util.HashMap;
34-
import java.util.List;
35-
import java.util.Map;
36-
import java.util.Map.Entry;
37-
import java.util.UUID;
21+
3822
import org.webrtc.AudioTrack;
3923
import org.webrtc.DefaultVideoDecoderFactory;
4024
import org.webrtc.DefaultVideoEncoderFactory;
25+
import org.webrtc.DtmfSender;
4126
import org.webrtc.EglBase;
4227
import org.webrtc.IceCandidate;
4328
import org.webrtc.Logging;
@@ -60,13 +45,34 @@
6045
import org.webrtc.PeerConnectionFactory;
6146
import org.webrtc.PeerConnectionFactory.InitializationOptions;
6247
import org.webrtc.PeerConnectionFactory.Options;
48+
import org.webrtc.RtpSender;
6349
import org.webrtc.SdpObserver;
6450
import org.webrtc.SessionDescription;
6551
import org.webrtc.SessionDescription.Type;
6652
import org.webrtc.VideoTrack;
6753
import org.webrtc.audio.AudioDeviceModule;
6854
import org.webrtc.audio.JavaAudioDeviceModule;
6955

56+
import java.io.File;
57+
import java.io.UnsupportedEncodingException;
58+
import java.nio.ByteBuffer;
59+
import java.util.ArrayList;
60+
import java.util.HashMap;
61+
import java.util.List;
62+
import java.util.Map;
63+
import java.util.Map.Entry;
64+
import java.util.UUID;
65+
66+
import io.flutter.plugin.common.BinaryMessenger;
67+
import io.flutter.plugin.common.EventChannel;
68+
import io.flutter.plugin.common.MethodCall;
69+
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
70+
import io.flutter.plugin.common.MethodChannel.Result;
71+
import io.flutter.view.TextureRegistry;
72+
import io.flutter.view.TextureRegistry.SurfaceTextureEntry;
73+
74+
import static com.cloudwebrtc.webrtc.utils.MediaConstraintsUtils.parseMediaConstraints;
75+
7076
public class MethodCallHandlerImpl implements MethodCallHandler, StateProvider {
7177

7278

@@ -249,6 +255,33 @@ public void onMethodCall(MethodCall call, @NonNull Result notSafeResult) {
249255
result);
250256
break;
251257
}
258+
case "sendDtmf": {
259+
String peerConnectionId = call.argument("peerConnectionId");
260+
String tone = call.argument("tone");
261+
int duration = call.argument("duration");
262+
int gap = call.argument("gap");
263+
PeerConnection peerConnection = getPeerConnection(peerConnectionId);
264+
if (peerConnection != null) {
265+
RtpSender audioSender = null;
266+
for (RtpSender sender : peerConnection.getSenders()) {
267+
268+
if (sender.track().kind().equals("audio")) {
269+
audioSender = sender;
270+
}
271+
}
272+
if (audioSender != null) {
273+
DtmfSender dtmfSender = audioSender.dtmf();
274+
dtmfSender.insertDtmf(tone, duration, gap);
275+
}
276+
result.success("success");
277+
} else {
278+
Log.d(TAG, "dtmf() peerConnection is null");
279+
result
280+
.error("dtmf", "sendDtmf() peerConnection is null",
281+
null);
282+
}
283+
break;
284+
}
252285
case "addCandidate": {
253286
String peerConnectionId = call.argument("peerConnectionId");
254287
Map<String, Object> candidate = call.argument("candidate");

example/lib/src/loopback_sample.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ class _MyAppState extends State<LoopBackSample> {
176176
_timer.cancel();
177177
}
178178

179+
void _sendDtmf() async {
180+
var dtmfSender =
181+
_peerConnection.createDtmfSender(_localStream.getAudioTracks()[0]);
182+
await dtmfSender.sendDtmf('123#');
183+
}
184+
179185
@override
180186
Widget build(BuildContext context) {
181187
var widgets = <Widget>[
@@ -189,6 +195,14 @@ class _MyAppState extends State<LoopBackSample> {
189195
return Scaffold(
190196
appBar: AppBar(
191197
title: Text('LoopBack example'),
198+
actions: _inCalling
199+
? <Widget>[
200+
IconButton(
201+
icon: Icon(Icons.keyboard),
202+
onPressed: _sendDtmf,
203+
),
204+
]
205+
: null,
192206
),
193207
body: OrientationBuilder(
194208
builder: (context, orientation) {

ios/Classes/FlutterWebRTCPlugin.m

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,39 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult) result
239239
message:[NSString stringWithFormat:@"Error: peerConnection not found!"]
240240
details:nil]);
241241
}
242+
} else if ([@"sendDtmf" isEqualToString:call.method]) {
243+
NSDictionary* argsMap = call.arguments;
244+
NSString* peerConnectionId = argsMap[@"peerConnectionId"];
245+
NSString* tone = argsMap[@"tone"];
246+
int duration = ((NSNumber*)argsMap[@"duration"]).intValue;
247+
int interToneGap = ((NSNumber*)argsMap[@"gap"]).intValue;
248+
249+
RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
250+
if(peerConnection) {
251+
252+
RTCRtpSender* audioSender = nil ;
253+
for( RTCRtpSender *rtpSender in peerConnection.senders){
254+
if([[[rtpSender track] kind] isEqualToString:@"audio"]) {
255+
audioSender = rtpSender;
256+
}
257+
}
258+
if(audioSender){
259+
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
260+
[queue addOperationWithBlock:^{
261+
double durationMs = duration / 1000.0;
262+
double interToneGapMs = interToneGap / 1000.0;
263+
[audioSender.dtmfSender insertDtmf :(NSString *)tone
264+
duration:(NSTimeInterval) durationMs interToneGap:(NSTimeInterval)interToneGapMs];
265+
NSLog(@"DTMF Tone played ");
266+
}];
267+
}
268+
269+
result(@{@"result": @"success"});
270+
} else {
271+
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%@Failed",call.method]
272+
message:[NSString stringWithFormat:@"Error: peerConnection not found!"]
273+
details:nil]);
274+
}
242275
} else if ([@"addCandidate" isEqualToString:call.method]) {
243276
NSDictionary* argsMap = call.arguments;
244277
NSString* peerConnectionId = argsMap[@"peerConnectionId"];

lib/flutter_webrtc.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export 'src/media_stream_track.dart'
1111
if (dart.library.html) 'src/web/media_stream_track.dart';
1212
export 'src/rtc_data_channel.dart'
1313
if (dart.library.html) 'src/web/rtc_data_channel.dart';
14+
export 'src/rtc_dtmf_sender.dart'
15+
if (dart.library.html) 'src/web/rtc_dtmf_sender.dart';
1416
export 'src/rtc_ice_candidate.dart'
1517
if (dart.library.html) 'src/web/rtc_ice_candidate.dart';
1618
export 'src/rtc_peerconnection.dart'

lib/src/rtc_dtmf_sender.dart

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,30 @@
1-
class RTCDTMFSender {}
1+
import 'package:flutter/services.dart';
2+
3+
import 'utils.dart';
4+
5+
class RTCDTMFSender {
6+
RTCDTMFSender(this._peerConnectionId);
7+
// peer connection Id must be defined as a variable where this function will be called.
8+
final String _peerConnectionId;
9+
final MethodChannel _channel = WebRTC.methodChannel();
10+
11+
/// tones:A String containing the DTMF codes to be transmitted to the recipient.
12+
/// Specifying an empty string as the tones parameter clears the tone
13+
/// buffer, aborting any currently queued tones. A "," character inserts
14+
/// a two second delay.
15+
/// duration: This value must be between 40 ms and 6000 ms (6 seconds).
16+
/// The default is 100 ms.
17+
/// interToneGap: The length of time, in milliseconds, to wait between tones.
18+
/// The browser will enforce a minimum value of 30 ms (that is,
19+
/// if you specify a lower value, 30 ms will be used instead);
20+
/// the default is 70 ms.
21+
Future<void> sendDtmf(String tones,
22+
{int duration = 100, int interToneGap = 70}) async {
23+
await _channel.invokeMethod('sendDtmf', <String, dynamic>{
24+
'peerConnectionId': _peerConnectionId,
25+
'tone': tones,
26+
'duration': duration,
27+
'gap': interToneGap,
28+
});
29+
}
30+
}

lib/src/rtc_peerconnection.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'enums.dart';
66
import 'media_stream.dart';
77
import 'media_stream_track.dart';
88
import 'rtc_data_channel.dart';
9+
import 'rtc_dtmf_sender.dart';
910
import 'rtc_ice_candidate.dart';
1011
import 'rtc_session_description.dart';
1112
import 'rtc_stats_report.dart';
@@ -48,7 +49,6 @@ class RTCPeerConnection {
4849
RTCSignalingState _signalingState;
4950
RTCIceGatheringState _iceGatheringState;
5051
RTCIceConnectionState _iceConnectionState;
51-
5252
// public: delegate
5353
SignalingStateCallback onSignalingState;
5454
IceGatheringStateCallback onIceGatheringState;
@@ -357,6 +357,10 @@ class RTCPeerConnection {
357357
}
358358
}
359359

360+
RTCDTMFSender createDtmfSender(MediaStreamTrack track) {
361+
return RTCDTMFSender(_peerConnectionId);
362+
}
363+
360364
Future<Null> close() async {
361365
try {
362366
await _channel.invokeMethod('peerConnectionClose', <String, dynamic>{

lib/src/web/rtc_dtmf_sender.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import 'dart:html' as html;
2+
3+
class RTCDTMFSender {
4+
RTCDTMFSender(this._jsDtmfSender);
5+
final html.RtcDtmfSender _jsDtmfSender;
6+
7+
/// tones:A String containing the DTMF codes to be transmitted to the recipient.
8+
/// Specifying an empty string as the tones parameter clears the tone
9+
/// buffer, aborting any currently queued tones. A "," character inserts
10+
/// a two second delay.
11+
/// duration: This value must be between 40 ms and 6000 ms (6 seconds).
12+
/// The default is 100 ms.
13+
/// interToneGap: The length of time, in milliseconds, to wait between tones.
14+
/// The browser will enforce a minimum value of 30 ms (that is,
15+
/// if you specify a lower value, 30 ms will be used instead);
16+
/// the default is 70 ms.
17+
Future<void> sendDtmf(String tones,
18+
{int duration = 100, int interToneGap = 70}) async {
19+
return _jsDtmfSender.insertDtmf(tones, duration, interToneGap);
20+
}
21+
}

lib/src/web/rtc_peerconnection.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import '../rtc_stats_report.dart';
88
import 'media_stream.dart';
99
import 'media_stream_track.dart';
1010
import 'rtc_data_channel.dart';
11+
import 'rtc_dtmf_sender.dart';
1112
import 'rtc_ice_candidate.dart';
1213
import 'rtc_session_description.dart';
1314

@@ -233,4 +234,9 @@ class RTCPeerConnection {
233234
jsutil.callMethod(_jsPc, 'addTransceiver', [type, jsOptions]);
234235
}
235236
}
237+
238+
RTCDTMFSender createDtmfSender(MediaStreamTrack track) {
239+
var jsDtmfSender = _jsPc.createDtmfSender(track.jsTrack);
240+
return RTCDTMFSender(jsDtmfSender);
241+
}
236242
}

macos/Classes/FlutterWebRTCPlugin.m

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,39 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult) result
208208
message:[NSString stringWithFormat:@"Error: peerConnection not found!"]
209209
details:nil]);
210210
}
211+
} else if ([@"sendDtmf" isEqualToString:call.method]) {
212+
NSDictionary* argsMap = call.arguments;
213+
NSString* peerConnectionId = argsMap[@"peerConnectionId"];
214+
NSString* tone = argsMap[@"tone"];
215+
int duration = ((NSNumber*)argsMap[@"duration"]).intValue;
216+
int interToneGap = ((NSNumber*)argsMap[@"gap"]).intValue;
217+
218+
RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
219+
if(peerConnection) {
220+
221+
RTCRtpSender* audioSender = nil ;
222+
for( RTCRtpSender *rtpSender in peerConnection.senders){
223+
if([[[rtpSender track] kind] isEqualToString:@"audio"]) {
224+
audioSender = rtpSender;
225+
}
226+
}
227+
if(audioSender){
228+
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
229+
[queue addOperationWithBlock:^{
230+
double durationMs = duration / 1000.0;
231+
double interToneGapMs = interToneGap / 1000.0;
232+
[audioSender.dtmfSender insertDtmf :(NSString *)tone
233+
duration:(NSTimeInterval) durationMs interToneGap:(NSTimeInterval)interToneGapMs];
234+
NSLog(@"DTMF Tone played ");
235+
}];
236+
}
237+
238+
result(@{@"result": @"success"});
239+
} else {
240+
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%@Failed",call.method]
241+
message:[NSString stringWithFormat:@"Error: peerConnection not found!"]
242+
details:nil]);
243+
}
211244
} else if ([@"addCandidate" isEqualToString:call.method]) {
212245
NSDictionary* argsMap = call.arguments;
213246
NSString* peerConnectionId = argsMap[@"peerConnectionId"];

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flutter_webrtc
22
description: Flutter WebRTC plugin for iOS/Android/Destkop/Web, based on GoogleWebRTC.
3-
version: 0.3.2
3+
version: 0.3.3
44
homepage: https://github.com/cloudwebrtc/flutter-webrtc
55
environment:
66
sdk: '>=2.2.2 <3.0.0'

renovate.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"extends": [
3+
"config:base"
4+
]
5+
}

0 commit comments

Comments
 (0)
0