@sbhjt-gr/react-native-webrtc 137.0.3 → 137.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,6 +27,7 @@ import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoEncoderFactory;
27
27
  import org.webrtc.AddIceObserver;
28
28
  import org.webrtc.AudioProcessingFactory;
29
29
  import org.webrtc.AudioTrack;
30
+ import org.webrtc.AudioTrackSink;
30
31
  import org.webrtc.CryptoOptions;
31
32
  import org.webrtc.EglBase;
32
33
  import org.webrtc.IceCandidate;
@@ -52,12 +53,17 @@ import org.webrtc.VideoTrack;
52
53
  import org.webrtc.audio.AudioDeviceModule;
53
54
  import org.webrtc.audio.JavaAudioDeviceModule;
54
55
 
56
+ import java.nio.ByteBuffer;
57
+ import java.nio.ByteOrder;
58
+ import java.nio.IntBuffer;
59
+ import java.nio.ShortBuffer;
55
60
  import java.util.ArrayList;
56
61
  import java.util.HashMap;
57
62
  import java.util.List;
58
63
  import java.util.Map;
59
64
  import java.util.Objects;
60
65
  import java.util.concurrent.Callable;
66
+ import java.util.concurrent.ConcurrentHashMap;
61
67
  import java.util.concurrent.ExecutionException;
62
68
 
63
69
  @ReactModule(name = "WebRTCModule")
@@ -72,6 +78,7 @@ public class WebRTCModule extends ReactContextBaseJavaModule {
72
78
  // Need to expose the peer connection codec factories here to get capabilities
73
79
  private final SparseArray<PeerConnectionObserver> mPeerConnectionObservers;
74
80
  final Map<String, MediaStream> localStreams;
81
+ private final Map<String, AudioTrackSink> audioSinkMap = new ConcurrentHashMap<>();
75
82
 
76
83
  private final GetUserMediaImpl getUserMediaImpl;
77
84
 
@@ -479,6 +486,10 @@ public class WebRTCModule extends ReactContextBaseJavaModule {
479
486
  return pco.remoteTracks.get(trackId);
480
487
  }
481
488
 
489
+ private String audioSinkKey(int pcId, String trackId) {
490
+ return pcId + ":" + trackId;
491
+ }
492
+
482
493
  MediaStreamTrack getLocalTrack(String trackId) {
483
494
  return getUserMediaImpl.getTrack(trackId);
484
495
  }
@@ -971,9 +982,98 @@ public class WebRTCModule extends ReactContextBaseJavaModule {
971
982
  });
972
983
  }
973
984
 
985
+ private class AudioSamplesInterceptor implements AudioTrackSink {
986
+ private final String trackId;
987
+
988
+ AudioSamplesInterceptor(String trackId) {
989
+ this.trackId = trackId;
990
+ }
991
+
992
+ @Override
993
+ public void onData(
994
+ ByteBuffer audioData,
995
+ int bitsPerSample,
996
+ int sampleRate,
997
+ int numberOfChannels,
998
+ int numberOfFrames,
999
+ long absoluteCaptureTimestampMs) {
1000
+ WritableMap params = Arguments.createMap();
1001
+ params.putString("trackId", trackId);
1002
+ params.putArray("samples", convertSamples(audioData, bitsPerSample));
1003
+ params.putInt("sampleRate", sampleRate);
1004
+ params.putInt("channels", numberOfChannels);
1005
+ params.putInt("bitsPerSample", bitsPerSample);
1006
+ params.putInt("framesPerBuffer", numberOfFrames);
1007
+ params.putDouble("timestamp", (double) absoluteCaptureTimestampMs);
1008
+
1009
+ sendEvent("audioSamples", params);
1010
+ }
1011
+
1012
+ private WritableArray convertSamples(ByteBuffer audioData, int bitsPerSample) {
1013
+ WritableArray samples = Arguments.createArray();
1014
+ if (audioData == null) {
1015
+ return samples;
1016
+ }
1017
+
1018
+ ByteBuffer buffer = audioData.slice().order(ByteOrder.LITTLE_ENDIAN);
1019
+
1020
+ if (bitsPerSample == 16) {
1021
+ ShortBuffer shortBuffer = buffer.asShortBuffer();
1022
+ while (shortBuffer.hasRemaining()) {
1023
+ samples.pushDouble(shortBuffer.get());
1024
+ }
1025
+ } else if (bitsPerSample == 32) {
1026
+ IntBuffer intBuffer = buffer.asIntBuffer();
1027
+ while (intBuffer.hasRemaining()) {
1028
+ samples.pushDouble(intBuffer.get());
1029
+ }
1030
+ } else {
1031
+ while (buffer.hasRemaining()) {
1032
+ samples.pushDouble(buffer.get());
1033
+ }
1034
+ }
1035
+
1036
+ return samples;
1037
+ }
1038
+ }
1039
+
974
1040
  @ReactMethod
975
1041
  public void mediaStreamTrackEnableAudioSink(int pcId, String id, boolean enabled) {
976
- Log.d(TAG, "mediaStreamTrackEnableAudioSink() pcId=" + pcId + " trackId=" + id + " enabled=" + enabled + " - Not fully implemented on Android");
1042
+ ThreadUtils.runOnExecutor(() -> {
1043
+ String sinkKey = audioSinkKey(pcId, id);
1044
+
1045
+ if (enabled) {
1046
+ if (audioSinkMap.containsKey(sinkKey)) {
1047
+ return;
1048
+ }
1049
+
1050
+ MediaStreamTrack track = getTrack(pcId, id);
1051
+ if (track == null) {
1052
+ Log.d(TAG, "mediaStreamTrackEnableAudioSink() could not find track " + id);
1053
+ return;
1054
+ }
1055
+
1056
+ if (!(track instanceof AudioTrack)) {
1057
+ Log.d(TAG, "mediaStreamTrackEnableAudioSink() track is not an AudioTrack!");
1058
+ return;
1059
+ }
1060
+
1061
+ AudioSamplesInterceptor sink = new AudioSamplesInterceptor(id);
1062
+ ((AudioTrack) track).addSink(sink);
1063
+ audioSinkMap.put(sinkKey, sink);
1064
+ } else {
1065
+ AudioTrackSink sink = audioSinkMap.remove(sinkKey);
1066
+
1067
+ if (sink == null) {
1068
+ return;
1069
+ }
1070
+
1071
+ MediaStreamTrack track = getTrack(pcId, id);
1072
+ if (track instanceof AudioTrack) {
1073
+ ((AudioTrack) track).removeSink(sink);
1074
+ }
1075
+ }
1076
+ });
977
1077
  }
978
1078
 
979
1079
  /**
@@ -0,0 +1,8 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <WebRTC/WebRTC.h>
3
+
4
+ @interface WLVAudioDevice : NSObject<RTCAudioDevice>
5
+
6
+ - (void)pushAudioData:(NSData *)data sampleRate:(double)sampleRate channels:(NSInteger)channels;
7
+
8
+ @end
@@ -0,0 +1,201 @@
1
+ #import "WLVAudioDevice.h"
2
+ #import <AudioToolbox/AudioToolbox.h>
3
+ #import <math.h>
4
+
5
+ static const double kDefaultSampleRate = 48000.0;
6
+ static const NSInteger kDefaultChannels = 1;
7
+ static const NSTimeInterval kDefaultBufferDuration = 0.02;
8
+
9
+ @interface WLVAudioDevice ()
10
+
11
+ @property(nonatomic, weak) id<RTCAudioDeviceDelegate> delegate;
12
+ @property(nonatomic) BOOL initialized;
13
+ @property(nonatomic) BOOL playoutInitialized;
14
+ @property(nonatomic) BOOL recordingInitialized;
15
+ @property(nonatomic) BOOL playing;
16
+ @property(nonatomic) BOOL recording;
17
+ @property(nonatomic) double inRate;
18
+ @property(nonatomic) NSInteger inChannels;
19
+ @property(nonatomic) double outRate;
20
+ @property(nonatomic) NSInteger outChannels;
21
+ @property(nonatomic) NSTimeInterval inBufferDuration;
22
+ @property(nonatomic) NSTimeInterval outBufferDuration;
23
+ @property(nonatomic) NSTimeInterval inLatency;
24
+ @property(nonatomic) NSTimeInterval outLatency;
25
+ @property(nonatomic) double sampleTime;
26
+ @property(nonatomic, strong) dispatch_queue_t queue;
27
+
28
+ @end
29
+
30
+ @implementation WLVAudioDevice
31
+
32
+ - (instancetype)init {
33
+ self = [super init];
34
+ if (self) {
35
+ _inRate = kDefaultSampleRate;
36
+ _outRate = kDefaultSampleRate;
37
+ _inChannels = kDefaultChannels;
38
+ _outChannels = kDefaultChannels;
39
+ _inBufferDuration = kDefaultBufferDuration;
40
+ _outBufferDuration = kDefaultBufferDuration;
41
+ _queue = dispatch_queue_create("webrtc.virtual.audio", DISPATCH_QUEUE_SERIAL);
42
+ }
43
+ return self;
44
+ }
45
+
46
+ - (void)pushAudioData:(NSData *)data sampleRate:(double)sampleRate channels:(NSInteger)channels {
47
+ if (!self.recording || !self.delegate || data.length == 0) {
48
+ return;
49
+ }
50
+ NSInteger bytesPerFrame = channels * sizeof(int16_t);
51
+ if (bytesPerFrame == 0) {
52
+ return;
53
+ }
54
+ UInt32 frames = (UInt32)(data.length / bytesPerFrame);
55
+ if (frames == 0) {
56
+ return;
57
+ }
58
+ [self updateInputRate:sampleRate channels:channels];
59
+ NSData *chunk = [data copy];
60
+ dispatch_async(self.queue, ^{
61
+ if (!self.recording || !self.delegate) {
62
+ return;
63
+ }
64
+ AudioBuffer buffer;
65
+ buffer.mNumberChannels = (UInt32)channels;
66
+ buffer.mDataByteSize = (UInt32)chunk.length;
67
+ buffer.mData = (void *)chunk.bytes;
68
+ AudioBufferList list;
69
+ list.mNumberBuffers = 1;
70
+ list.mBuffers[0] = buffer;
71
+ AudioUnitRenderActionFlags flags = 0;
72
+ AudioTimeStamp stamp;
73
+ memset(&stamp, 0, sizeof(AudioTimeStamp));
74
+ stamp.mFlags = kAudioTimeStampSampleTimeValid;
75
+ stamp.mSampleTime = self.sampleTime;
76
+ self.sampleTime += frames;
77
+ RTC_OBJC_TYPE(RTCAudioDeviceDeliverRecordedDataBlock) block = self.delegate.deliverRecordedData;
78
+ if (block) {
79
+ block(&flags, &stamp, 0, frames, &list, NULL, nil);
80
+ }
81
+ });
82
+ }
83
+
84
+ - (void)updateInputRate:(double)rate channels:(NSInteger)channels {
85
+ BOOL rateChanged = fabs(self.inRate - rate) > 0.1;
86
+ BOOL channelChanged = self.inChannels != channels;
87
+ if (rateChanged) {
88
+ self.inRate = rate;
89
+ }
90
+ if (channelChanged) {
91
+ self.inChannels = channels;
92
+ }
93
+ if ((rateChanged || channelChanged) && self.delegate) {
94
+ [self.delegate dispatchAsync:^{
95
+ [self.delegate notifyAudioInputParametersChange];
96
+ }];
97
+ }
98
+ }
99
+
100
+ #pragma mark - RTCAudioDevice
101
+
102
+ - (double)deviceInputSampleRate {
103
+ return self.inRate;
104
+ }
105
+
106
+ - (NSTimeInterval)inputIOBufferDuration {
107
+ return self.inBufferDuration;
108
+ }
109
+
110
+ - (NSInteger)inputNumberOfChannels {
111
+ return self.inChannels;
112
+ }
113
+
114
+ - (NSTimeInterval)inputLatency {
115
+ return self.inLatency;
116
+ }
117
+
118
+ - (double)deviceOutputSampleRate {
119
+ return self.outRate;
120
+ }
121
+
122
+ - (NSTimeInterval)outputIOBufferDuration {
123
+ return self.outBufferDuration;
124
+ }
125
+
126
+ - (NSInteger)outputNumberOfChannels {
127
+ return self.outChannels;
128
+ }
129
+
130
+ - (NSTimeInterval)outputLatency {
131
+ return self.outLatency;
132
+ }
133
+
134
+ - (BOOL)isInitialized {
135
+ return self.initialized;
136
+ }
137
+
138
+ - (BOOL)initializeWithDelegate:(id<RTCAudioDeviceDelegate>)delegate {
139
+ self.delegate = delegate;
140
+ self.initialized = YES;
141
+ return YES;
142
+ }
143
+
144
+ - (BOOL)terminateDevice {
145
+ self.delegate = nil;
146
+ self.initialized = NO;
147
+ self.playoutInitialized = NO;
148
+ self.recordingInitialized = NO;
149
+ self.playing = NO;
150
+ self.recording = NO;
151
+ self.sampleTime = 0;
152
+ return YES;
153
+ }
154
+
155
+ - (BOOL)isPlayoutInitialized {
156
+ return self.playoutInitialized;
157
+ }
158
+
159
+ - (BOOL)initializePlayout {
160
+ self.playoutInitialized = YES;
161
+ return YES;
162
+ }
163
+
164
+ - (BOOL)isPlaying {
165
+ return self.playing;
166
+ }
167
+
168
+ - (BOOL)startPlayout {
169
+ self.playing = YES;
170
+ return YES;
171
+ }
172
+
173
+ - (BOOL)stopPlayout {
174
+ self.playing = NO;
175
+ return YES;
176
+ }
177
+
178
+ - (BOOL)isRecordingInitialized {
179
+ return self.recordingInitialized;
180
+ }
181
+
182
+ - (BOOL)initializeRecording {
183
+ self.recordingInitialized = YES;
184
+ return YES;
185
+ }
186
+
187
+ - (BOOL)isRecording {
188
+ return self.recording;
189
+ }
190
+
191
+ - (BOOL)startRecording {
192
+ self.recording = YES;
193
+ return YES;
194
+ }
195
+
196
+ - (BOOL)stopRecording {
197
+ self.recording = NO;
198
+ return YES;
199
+ }
200
+
201
+ @end
@@ -1,5 +1,10 @@
1
1
  #import <objc/runtime.h>
2
2
 
3
+ #import <AVFoundation/AVFoundation.h>
4
+ #import <math.h>
5
+ #import <limits.h>
6
+ #import <stdint.h>
7
+
3
8
  #import <WebRTC/RTCCameraVideoCapturer.h>
4
9
  #import <WebRTC/RTCMediaConstraints.h>
5
10
  #import <WebRTC/RTCMediaStreamTrack.h>
@@ -16,8 +21,109 @@
16
21
  #import "TrackCapturerEventsEmitter.h"
17
22
  #import "VideoCaptureController.h"
18
23
 
24
+ @interface AudioSamplesRenderer : NSObject<RTCAudioRenderer>
25
+
26
+ - (instancetype)initWithModule:(WebRTCModule *)module trackId:(NSString *)trackId;
27
+
28
+ @end
29
+
30
+ @implementation AudioSamplesRenderer {
31
+ __weak WebRTCModule *_module;
32
+ NSString *_trackId;
33
+ }
34
+
35
+ - (instancetype)initWithModule:(WebRTCModule *)module trackId:(NSString *)trackId {
36
+ self = [super init];
37
+ if (self) {
38
+ _module = module;
39
+ _trackId = [trackId copy];
40
+ }
41
+ return self;
42
+ }
43
+
44
+ - (void)render:(AVAudioPCMBuffer *)pcmBuffer {
45
+ WebRTCModule *module = _module;
46
+ if (!module) {
47
+ return;
48
+ }
49
+
50
+ AVAudioFrameCount frameLength = pcmBuffer.frameLength;
51
+ if (frameLength == 0) {
52
+ return;
53
+ }
54
+
55
+ UInt32 channelCount = pcmBuffer.format.channelCount;
56
+ if (channelCount == 0) {
57
+ return;
58
+ }
59
+
60
+ AVAudioCommonFormat format = pcmBuffer.format.commonFormat;
61
+ NSUInteger totalSamples = (NSUInteger)frameLength * (NSUInteger)channelCount;
62
+ NSMutableArray<NSNumber *> *samples = [NSMutableArray arrayWithCapacity:totalSamples];
63
+ int bitsPerSample = (int)pcmBuffer.format.streamDescription->mBitsPerChannel;
64
+
65
+ if (format == AVAudioPCMFormatInt16) {
66
+ int16_t **channelData = pcmBuffer.int16ChannelData;
67
+ if (!channelData) {
68
+ return;
69
+ }
70
+ for (AVAudioFrameCount frame = 0; frame < frameLength; frame++) {
71
+ for (UInt32 channel = 0; channel < channelCount; channel++) {
72
+ [samples addObject:@(channelData[channel][frame])];
73
+ }
74
+ }
75
+ } else if (format == AVAudioPCMFormatFloat32) {
76
+ float **channelData = pcmBuffer.floatChannelData;
77
+ if (!channelData) {
78
+ return;
79
+ }
80
+ bitsPerSample = 16;
81
+ for (AVAudioFrameCount frame = 0; frame < frameLength; frame++) {
82
+ for (UInt32 channel = 0; channel < channelCount; channel++) {
83
+ float value = channelData[channel][frame];
84
+ float clipped = fminf(fmaxf(value, -1.0f), 1.0f);
85
+ int16_t sample = (int16_t)lrintf(clipped * (float)INT16_MAX);
86
+ [samples addObject:@(sample)];
87
+ }
88
+ }
89
+ } else if (format == AVAudioPCMFormatInt32) {
90
+ int32_t **channelData = pcmBuffer.int32ChannelData;
91
+ if (!channelData) {
92
+ return;
93
+ }
94
+ bitsPerSample = 32;
95
+ for (AVAudioFrameCount frame = 0; frame < frameLength; frame++) {
96
+ for (UInt32 channel = 0; channel < channelCount; channel++) {
97
+ int32_t value = channelData[channel][frame];
98
+ [samples addObject:@(value)];
99
+ }
100
+ }
101
+ } else {
102
+ return;
103
+ }
104
+
105
+ NSTimeInterval timestampMs = [[NSDate date] timeIntervalSince1970] * 1000.0;
106
+
107
+ [module sendEventWithName:kEventAudioSamples
108
+ body:@{
109
+ @"trackId" : _trackId,
110
+ @"samples" : samples,
111
+ @"sampleRate" : @(pcmBuffer.format.sampleRate),
112
+ @"channels" : @(channelCount),
113
+ @"bitsPerSample" : @(bitsPerSample),
114
+ @"framesPerBuffer" : @(frameLength),
115
+ @"timestamp" : @(timestampMs)
116
+ }];
117
+ }
118
+
119
+ @end
120
+
19
121
  @implementation WebRTCModule (RTCMediaStream)
20
122
 
123
+ - (NSString *)audioSinkKeyForPcId:(NSNumber *)pcId trackId:(NSString *)trackId {
124
+ return [NSString stringWithFormat:@"%@:%@", pcId, trackId];
125
+ }
126
+
21
127
  - (VideoEffectProcessor *)videoEffectProcessor {
22
128
  return objc_getAssociatedObject(self, _cmd);
23
129
  }
@@ -217,6 +323,53 @@ RCT_EXPORT_METHOD(getDisplayMedia : (RCTPromiseResolveBlock)resolve rejecter : (
217
323
  #endif
218
324
  }
219
325
 
326
+ RCT_EXPORT_METHOD(createVirtualAudioTrack : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) {
327
+ #if TARGET_OS_TV
328
+ reject(@"unsupported_platform", @"tvOS is not supported", nil);
329
+ return;
330
+ #else
331
+ RTCPeerConnectionFactory *factory = [self virtualFactory];
332
+ if (!factory) {
333
+ reject(@"virtual_factory_error", @"Factory unavailable", nil);
334
+ return;
335
+ }
336
+ NSString *trackId = [[NSUUID UUID] UUIDString];
337
+ RTCAudioSource *source = [factory audioSourceWithConstraints:nil];
338
+ RTCAudioTrack *track = [factory audioTrackWithSource:source trackId:trackId];
339
+ NSArray *components = [self createMediaStream:@[ track ]];
340
+ resolve(@{ @"streamId" : components[0], @"tracks" : components[1] });
341
+ #endif
342
+ }
343
+
344
+ RCT_EXPORT_METHOD(pushVirtualAudioSamples
345
+ : (nonnull NSArray<NSNumber *> *)samples
346
+ sampleRate
347
+ : (nonnull NSNumber *)sampleRate
348
+ channels
349
+ : (nonnull NSNumber *)channels) {
350
+ #if TARGET_OS_TV
351
+ return;
352
+ #else
353
+ if (samples.count == 0) {
354
+ return;
355
+ }
356
+ if (!self.virtualAudioDevice) {
357
+ [self virtualFactory];
358
+ }
359
+ if (!self.virtualAudioDevice) {
360
+ return;
361
+ }
362
+ NSUInteger length = samples.count * sizeof(int16_t);
363
+ NSMutableData *data = [NSMutableData dataWithLength:length];
364
+ int16_t *buffer = data.mutableBytes;
365
+ NSUInteger idx = 0;
366
+ for (NSNumber *value in samples) {
367
+ buffer[idx++] = (int16_t)value.shortValue;
368
+ }
369
+ [self.virtualAudioDevice pushAudioData:data sampleRate:sampleRate.doubleValue channels:channels.integerValue];
370
+ #endif
371
+ }
372
+
220
373
  /**
221
374
  * Implements {@code getUserMedia}. Note that at this point constraints have
222
375
  * been normalized and permissions have been granted. The constraints only
@@ -497,7 +650,36 @@ RCT_EXPORT_METHOD(mediaStreamTrackSetPlaybackEnabled : (nonnull NSNumber *)pcId
497
650
  }
498
651
 
499
652
  RCT_EXPORT_METHOD(mediaStreamTrackEnableAudioSink : (nonnull NSNumber *)pcId : (nonnull NSString *)trackID : (BOOL)enabled) {
500
- RCTLogInfo(@"mediaStreamTrackEnableAudioSink: pcId=%@, trackId=%@, enabled=%d - Not fully implemented on iOS", pcId, trackID, enabled);
653
+ NSString *key = [self audioSinkKeyForPcId:pcId trackId:trackID];
654
+
655
+ if (enabled) {
656
+ if (self.audioRenderers[key]) {
657
+ return;
658
+ }
659
+
660
+ RTCMediaStreamTrack *track = [self trackForId:trackID pcId:pcId];
661
+ if (track == nil || ![track.kind isEqualToString:@"audio"]) {
662
+ return;
663
+ }
664
+
665
+ RTCAudioTrack *audioTrack = (RTCAudioTrack *)track;
666
+ AudioSamplesRenderer *renderer = [[AudioSamplesRenderer alloc] initWithModule:self trackId:trackID];
667
+ self.audioRenderers[key] = renderer;
668
+ [audioTrack addRenderer:renderer];
669
+ } else {
670
+ id<RTCAudioRenderer> renderer = self.audioRenderers[key];
671
+ if (!renderer) {
672
+ return;
673
+ }
674
+
675
+ RTCMediaStreamTrack *track = [self trackForId:trackID pcId:pcId];
676
+ if ([track isKindOfClass:[RTCAudioTrack class]]) {
677
+ RTCAudioTrack *audioTrack = (RTCAudioTrack *)track;
678
+ [audioTrack removeRenderer:renderer];
679
+ }
680
+
681
+ [self.audioRenderers removeObjectForKey:key];
682
+ }
501
683
  }
502
684
 
503
685
  RCT_EXPORT_METHOD(mediaStreamTrackSetVideoEffects
@@ -36,10 +36,13 @@ static NSString *const kEventAudioSamples = @"audioSamples";
36
36
  @property(nonatomic, strong) NSMutableDictionary<NSString *, RTCMediaStream *> *localStreams;
37
37
  @property(nonatomic, strong) NSMutableDictionary<NSString *, RTCMediaStreamTrack *> *localTracks;
38
38
 
39
+ @property(nonatomic, strong) NSMutableDictionary<NSString *, id<RTCAudioRenderer>> *audioRenderers;
40
+
39
41
  @property(nonatomic, strong) NSMutableDictionary<NSString *, RTCFrameCryptor *> *frameCryptors;
40
42
  @property(nonatomic, strong) NSMutableDictionary<NSString *, RTCFrameCryptorKeyProvider *> *keyProviders;
41
43
  @property(nonatomic, strong) NSMutableDictionary<NSString *, RTCDataPacketCryptor *> *dataPacketCryptors;
42
44
 
43
45
  - (RTCMediaStream *)streamForReactTag:(NSString *)reactTag;
46
+ - (RTCPeerConnectionFactory *)virtualFactory;
44
47
 
45
48
  @end
@@ -10,8 +10,13 @@
10
10
  #import "WebRTCModule+RTCPeerConnection.h"
11
11
  #import "WebRTCModule.h"
12
12
  #import "WebRTCModuleOptions.h"
13
+ #import "WLVAudioDevice.h"
13
14
 
14
15
  @interface WebRTCModule ()
16
+
17
+ @property(nonatomic, strong) WLVAudioDevice *virtualAudioDevice;
18
+ @property(nonatomic, strong) RTCPeerConnectionFactory *virtualPeerConnectionFactory;
19
+
15
20
  @end
16
21
 
17
22
  @implementation WebRTCModule
@@ -23,6 +28,8 @@
23
28
  - (void)dealloc {
24
29
  [_localTracks removeAllObjects];
25
30
  _localTracks = nil;
31
+ [_audioRenderers removeAllObjects];
32
+ _audioRenderers = nil;
26
33
  [_localStreams removeAllObjects];
27
34
  _localStreams = nil;
28
35
 
@@ -92,6 +99,7 @@
92
99
  _peerConnections = [NSMutableDictionary new];
93
100
  _localStreams = [NSMutableDictionary new];
94
101
  _localTracks = [NSMutableDictionary new];
102
+ _audioRenderers = [NSMutableDictionary new];
95
103
 
96
104
  _frameCryptors = [NSMutableDictionary new];
97
105
  _keyProviders = [NSMutableDictionary new];
@@ -125,6 +133,16 @@ RCT_EXPORT_MODULE();
125
133
  return _workerQueue;
126
134
  }
127
135
 
136
+ - (RTCPeerConnectionFactory *)virtualFactory {
137
+ if (_virtualPeerConnectionFactory == nil) {
138
+ self.virtualAudioDevice = [[WLVAudioDevice alloc] init];
139
+ _virtualPeerConnectionFactory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:_encoderFactory
140
+ decoderFactory:_decoderFactory
141
+ audioDevice:self.virtualAudioDevice];
142
+ }
143
+ return _virtualPeerConnectionFactory;
144
+ }
145
+
128
146
  - (NSArray<NSString *> *)supportedEvents {
129
147
  return @[
130
148
  kEventPeerConnectionSignalingStateChanged,
@@ -22,6 +22,7 @@
22
22
  4EE3A8D225B841DD00FAA24A /* CaptureController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EE3A8C925B841DD00FAA24A /* CaptureController.m */; };
23
23
  4EE3A8D325B841DD00FAA24A /* ScreenCaptureController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EE3A8CC25B841DD00FAA24A /* ScreenCaptureController.m */; };
24
24
  4EE3A8D425B841DD00FAA24A /* ScreenCapturer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EE3A8CD25B841DD00FAA24A /* ScreenCapturer.m */; };
25
+ E0C37C1F2D8D1C6A009E2E63 /* WLVAudioDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C37C1E2D8D1C6A009E2E63 /* WLVAudioDevice.m */; };
25
26
  D3FF699919D2664B25C9D458 /* Pods_RCTWebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A20F721AD842563B66292D5B /* Pods_RCTWebRTC.framework */; };
26
27
  D74EF94829652169000742E1 /* TrackCapturerEventsEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = D74EF94629652169000742E1 /* TrackCapturerEventsEmitter.m */; };
27
28
  D7F0711E2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m in Sources */ = {isa = PBXBuildFile; fileRef = D7F0711D2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m */; };
@@ -72,6 +73,8 @@
72
73
  4EE3A8CC25B841DD00FAA24A /* ScreenCaptureController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ScreenCaptureController.m; path = RCTWebRTC/ScreenCaptureController.m; sourceTree = SOURCE_ROOT; };
73
74
  4EE3A8CD25B841DD00FAA24A /* ScreenCapturer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ScreenCapturer.m; path = RCTWebRTC/ScreenCapturer.m; sourceTree = SOURCE_ROOT; };
74
75
  4EE3A8CE25B841DD00FAA24A /* SocketConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SocketConnection.h; path = RCTWebRTC/SocketConnection.h; sourceTree = SOURCE_ROOT; };
76
+ E0C37C1D2D8D1C6A009E2E63 /* WLVAudioDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WLVAudioDevice.h; path = RCTWebRTC/WLVAudioDevice.h; sourceTree = SOURCE_ROOT; };
77
+ E0C37C1E2D8D1C6A009E2E63 /* WLVAudioDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WLVAudioDevice.m; path = RCTWebRTC/WLVAudioDevice.m; sourceTree = SOURCE_ROOT; };
75
78
  A20F721AD842563B66292D5B /* Pods_RCTWebRTC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RCTWebRTC.framework; sourceTree = BUILT_PRODUCTS_DIR; };
76
79
  D74EF94529652148000742E1 /* CapturerEventsDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CapturerEventsDelegate.h; path = RCTWebRTC/CapturerEventsDelegate.h; sourceTree = SOURCE_ROOT; };
77
80
  D74EF94629652169000742E1 /* TrackCapturerEventsEmitter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TrackCapturerEventsEmitter.m; path = RCTWebRTC/TrackCapturerEventsEmitter.m; sourceTree = SOURCE_ROOT; };
@@ -157,6 +160,8 @@
157
160
  4EE3A8CD25B841DD00FAA24A /* ScreenCapturer.m */,
158
161
  4EE3A8CE25B841DD00FAA24A /* SocketConnection.h */,
159
162
  4EE3A8C825B841DD00FAA24A /* SocketConnection.m */,
163
+ E0C37C1D2D8D1C6A009E2E63 /* WLVAudioDevice.h */,
164
+ E0C37C1E2D8D1C6A009E2E63 /* WLVAudioDevice.m */,
160
165
  DEC96579264176DF0052DB35 /* DataChannelWrapper.h */,
161
166
  DEC96576264176C10052DB35 /* DataChannelWrapper.m */,
162
167
  );
@@ -255,6 +260,7 @@
255
260
  isa = PBXSourcesBuildPhase;
256
261
  buildActionMask = 2147483647;
257
262
  files = (
263
+ E0C37C1F2D8D1C6A009E2E63 /* WLVAudioDevice.m in Sources */,
258
264
  4EE3A8C525B8417800FAA24A /* WebRTCModule+VideoTrackAdapter.m in Sources */,
259
265
  4EE3A8BA25B8415900FAA24A /* WebRTCModule+RTCDataChannel.m in Sources */,
260
266
  4EE3A8B625B8414A00FAA24A /* WebRTCModule+Permissions.m in Sources */,
@@ -51,7 +51,9 @@ function removeListener(listener) {
51
51
  }
52
52
  function removeListenerForEvent(listener, eventName) {
53
53
  const subs = _subscriptions.get(listener);
54
- if (!subs) return;
54
+ if (!subs) {
55
+ return;
56
+ }
55
57
  const remaining = [];
56
58
  subs.forEach(sub => {
57
59
  if (sub.eventType === eventName) {
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_EventEmitter","_interopRequireDefault","obj","__esModule","default","WebRTCModule","NativeModules","nativeEmitter","NativeEventEmitter","NATIVE_EVENTS","eventEmitter","EventEmitter","setupNativeEvents","eventName","addListener","_len","arguments","length","args","Array","_key","emit","_subscriptions","Map","listener","eventHandler","_subscriptions$get","includes","Error","has","set","get","push","removeListener","_subscriptions$get2","forEach","sub","remove","delete","removeListenerForEvent","subs","remaining","eventType"],"sources":["EventEmitter.ts"],"sourcesContent":["import { NativeModules, NativeEventEmitter, EmitterSubscription } from 'react-native';\n// @ts-ignore\nimport EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';\n\nconst { WebRTCModule } = NativeModules;\n\n// This emitter is going to be used to listen to all the native events (once) and then\n// re-emit them on a JS-only emitter.\nconst nativeEmitter = new NativeEventEmitter(WebRTCModule);\n\nconst NATIVE_EVENTS = [\n 'peerConnectionSignalingStateChanged',\n 'peerConnectionStateChanged',\n 'peerConnectionOnRenegotiationNeeded',\n 'peerConnectionIceConnectionChanged',\n 'peerConnectionIceGatheringChanged',\n 'peerConnectionGotICECandidate',\n 'peerConnectionDidOpenDataChannel',\n 'peerConnectionOnRemoveTrack',\n 'peerConnectionOnTrack',\n 'dataChannelStateChanged',\n 'dataChannelReceiveMessage',\n 'dataChannelDidChangeBufferedAmount',\n 'mediaStreamTrackMuteChanged',\n 'mediaStreamTrackEnded',\n 'frameCryptionStateChanged',\n 'audioSamples',\n];\n\nconst eventEmitter = new EventEmitter();\n\nexport function setupNativeEvents() {\n for (const eventName of NATIVE_EVENTS) {\n nativeEmitter.addListener(eventName, (...args) => {\n eventEmitter.emit(eventName, ...args);\n });\n }\n}\n\ntype EventHandler = (event: unknown) => void;\ntype Listener = unknown;\n\nconst _subscriptions: Map<Listener, EmitterSubscription[]> = new Map();\n\nexport function addListener(listener: Listener, eventName: string, eventHandler: EventHandler): void {\n if (!NATIVE_EVENTS.includes(eventName)) {\n throw new Error(`Invalid event: ${eventName}`);\n }\n\n if (!_subscriptions.has(listener)) {\n _subscriptions.set(listener, []);\n }\n\n _subscriptions.get(listener)?.push(eventEmitter.addListener(eventName, eventHandler));\n}\n\nexport function removeListener(listener: Listener): void {\n _subscriptions.get(listener)?.forEach(sub => {\n sub.remove();\n });\n\n _subscriptions.delete(listener);\n}\n\nexport function removeListenerForEvent(listener: Listener, eventName: string): void {\n const subs = _subscriptions.get(listener);\n if (!subs) return;\n \n const remaining: EmitterSubscription[] = [];\n subs.forEach(sub => {\n if ((sub as any).eventType === eventName) {\n sub.remove();\n } else {\n remaining.push(sub);\n }\n });\n \n if (remaining.length === 0) {\n _subscriptions.delete(listener);\n } else {\n _subscriptions.set(listener, remaining);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["_reactNative","require","_EventEmitter","_interopRequireDefault","obj","__esModule","default","WebRTCModule","NativeModules","nativeEmitter","NativeEventEmitter","NATIVE_EVENTS","eventEmitter","EventEmitter","setupNativeEvents","eventName","addListener","_len","arguments","length","args","Array","_key","emit","_subscriptions","Map","listener","eventHandler","_subscriptions$get","includes","Error","has","set","get","push","removeListener","_subscriptions$get2","forEach","sub","remove","delete","removeListenerForEvent","subs","remaining","eventType"],"sources":["EventEmitter.ts"],"sourcesContent":["import { NativeModules, NativeEventEmitter, EmitterSubscription } from 'react-native';\n// @ts-ignore\nimport EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';\n\nconst { WebRTCModule } = NativeModules;\n\n// This emitter is going to be used to listen to all the native events (once) and then\n// re-emit them on a JS-only emitter.\nconst nativeEmitter = new NativeEventEmitter(WebRTCModule);\n\nconst NATIVE_EVENTS = [\n 'peerConnectionSignalingStateChanged',\n 'peerConnectionStateChanged',\n 'peerConnectionOnRenegotiationNeeded',\n 'peerConnectionIceConnectionChanged',\n 'peerConnectionIceGatheringChanged',\n 'peerConnectionGotICECandidate',\n 'peerConnectionDidOpenDataChannel',\n 'peerConnectionOnRemoveTrack',\n 'peerConnectionOnTrack',\n 'dataChannelStateChanged',\n 'dataChannelReceiveMessage',\n 'dataChannelDidChangeBufferedAmount',\n 'mediaStreamTrackMuteChanged',\n 'mediaStreamTrackEnded',\n 'frameCryptionStateChanged',\n 'audioSamples',\n];\n\nconst eventEmitter = new EventEmitter();\n\nexport function setupNativeEvents() {\n for (const eventName of NATIVE_EVENTS) {\n nativeEmitter.addListener(eventName, (...args) => {\n eventEmitter.emit(eventName, ...args);\n });\n }\n}\n\ntype EventHandler = (event: unknown) => void;\ntype Listener = unknown;\n\nconst _subscriptions: Map<Listener, EmitterSubscription[]> = new Map();\n\nexport function addListener(listener: Listener, eventName: string, eventHandler: EventHandler): void {\n if (!NATIVE_EVENTS.includes(eventName)) {\n throw new Error(`Invalid event: ${eventName}`);\n }\n\n if (!_subscriptions.has(listener)) {\n _subscriptions.set(listener, []);\n }\n\n _subscriptions.get(listener)?.push(eventEmitter.addListener(eventName, eventHandler));\n}\n\nexport function removeListener(listener: Listener): void {\n _subscriptions.get(listener)?.forEach(sub => {\n sub.remove();\n });\n\n _subscriptions.delete(listener);\n}\n\nexport function removeListenerForEvent(listener: Listener, eventName: string): void {\n const subs = _subscriptions.get(listener);\n\n if (!subs) {\n return;\n }\n\n const remaining: EmitterSubscription[] = [];\n\n subs.forEach(sub => {\n if ((sub as any).eventType === eventName) {\n sub.remove();\n } else {\n remaining.push(sub);\n }\n });\n\n if (remaining.length === 0) {\n _subscriptions.delete(listener);\n } else {\n _subscriptions.set(listener, remaining);\n }\n}\n"],"mappings":"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"}
@@ -42,6 +42,19 @@ class MediaDevices extends _index.EventTarget {
42
42
  getUserMedia(constraints) {
43
43
  return (0, _getUserMedia.default)(constraints);
44
44
  }
45
+ createVirtualAudioTrack() {
46
+ if (!WebRTCModule.createVirtualAudioTrack) {
47
+ return Promise.reject(new Error('virtual audio unavailable'));
48
+ }
49
+ return WebRTCModule.createVirtualAudioTrack();
50
+ }
51
+ pushVirtualAudioSamples(samples, sampleRate, channels) {
52
+ if (!WebRTCModule.pushVirtualAudioSamples) {
53
+ return;
54
+ }
55
+ const array = samples instanceof Int16Array ? Array.from(samples) : samples.slice();
56
+ WebRTCModule.pushVirtualAudioSamples(array, sampleRate, channels);
57
+ }
45
58
  }
46
59
 
47
60
  /**
@@ -1 +1 @@
1
- {"version":3,"names":["_index","require","_reactNative","_getDisplayMedia","_interopRequireDefault","_getUserMedia","obj","__esModule","default","WebRTCModule","NativeModules","MediaDevices","EventTarget","enumerateDevices","Promise","resolve","getDisplayMedia","getUserMedia","constraints","proto","prototype","defineEventAttribute","_default","exports"],"sources":["MediaDevices.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules } from 'react-native';\n\nimport getDisplayMedia from './getDisplayMedia';\nimport getUserMedia, { Constraints } from './getUserMedia';\n\nconst { WebRTCModule } = NativeModules;\n\ntype MediaDevicesEventMap = {\n devicechange: Event<'devicechange'>\n}\n\nclass MediaDevices extends EventTarget<MediaDevicesEventMap> {\n /**\n * W3C \"Media Capture and Streams\" compatible {@code enumerateDevices}\n * implementation.\n */\n enumerateDevices() {\n return new Promise(resolve => WebRTCModule.enumerateDevices(resolve));\n }\n\n /**\n * W3C \"Screen Capture\" compatible {@code getDisplayMedia} implementation.\n * See: https://w3c.github.io/mediacapture-screen-share/\n *\n * @returns {Promise}\n */\n getDisplayMedia() {\n return getDisplayMedia();\n }\n\n /**\n * W3C \"Media Capture and Streams\" compatible {@code getUserMedia}\n * implementation.\n * See: https://www.w3.org/TR/mediacapture-streams/#dom-mediadevices-enumeratedevices\n *\n * @param {*} constraints\n * @returns {Promise}\n */\n getUserMedia(constraints: Constraints) {\n return getUserMedia(constraints);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaDevices.prototype;\n\ndefineEventAttribute(proto, 'devicechange');\n\n\nexport default new MediaDevices();\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAEA,IAAAE,gBAAA,GAAAC,sBAAA,CAAAH,OAAA;AACA,IAAAI,aAAA,GAAAD,sBAAA,CAAAH,OAAA;AAA2D,SAAAG,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAE3D,MAAM;EAAEG;AAAa,CAAC,GAAGC,0BAAa;AAMtC,MAAMC,YAAY,SAASC,kBAAW,CAAuB;EACzD;AACJ;AACA;AACA;EACIC,gBAAgBA,CAAA,EAAG;IACf,OAAO,IAAIC,OAAO,CAACC,OAAO,IAAIN,YAAY,CAACI,gBAAgB,CAACE,OAAO,CAAC,CAAC;EACzE;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACIC,eAAeA,CAAA,EAAG;IACd,OAAO,IAAAA,wBAAe,EAAC,CAAC;EAC5B;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACIC,YAAYA,CAACC,WAAwB,EAAE;IACnC,OAAO,IAAAD,qBAAY,EAACC,WAAW,CAAC;EACpC;AACJ;;AAEA;AACA;AACA;AACA,MAAMC,KAAK,GAAGR,YAAY,CAACS,SAAS;AAEpC,IAAAC,2BAAoB,EAACF,KAAK,EAAE,cAAc,CAAC;AAAC,IAAAG,QAAA,GAG7B,IAAIX,YAAY,CAAC,CAAC;AAAAY,OAAA,CAAAf,OAAA,GAAAc,QAAA"}
1
+ {"version":3,"names":["_index","require","_reactNative","_getDisplayMedia","_interopRequireDefault","_getUserMedia","obj","__esModule","default","WebRTCModule","NativeModules","MediaDevices","EventTarget","enumerateDevices","Promise","resolve","getDisplayMedia","getUserMedia","constraints","createVirtualAudioTrack","reject","Error","pushVirtualAudioSamples","samples","sampleRate","channels","array","Int16Array","Array","from","slice","proto","prototype","defineEventAttribute","_default","exports"],"sources":["MediaDevices.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules } from 'react-native';\n\nimport { type MediaTrackSettings } from './MediaStreamTrack';\nimport getDisplayMedia from './getDisplayMedia';\nimport getUserMedia, { Constraints } from './getUserMedia';\n\nconst { WebRTCModule } = NativeModules;\n\ntype MediaDevicesEventMap = {\n devicechange: Event<'devicechange'>\n}\n\ntype VirtualTrackInfo = {\n enabled: boolean;\n id: string;\n kind: string;\n readyState: string;\n remote: boolean;\n settings: MediaTrackSettings;\n}\n\ntype VirtualAudioResponse = {\n streamId: string;\n tracks: VirtualTrackInfo[];\n}\n\nclass MediaDevices extends EventTarget<MediaDevicesEventMap> {\n /**\n * W3C \"Media Capture and Streams\" compatible {@code enumerateDevices}\n * implementation.\n */\n enumerateDevices() {\n return new Promise(resolve => WebRTCModule.enumerateDevices(resolve));\n }\n\n /**\n * W3C \"Screen Capture\" compatible {@code getDisplayMedia} implementation.\n * See: https://w3c.github.io/mediacapture-screen-share/\n *\n * @returns {Promise}\n */\n getDisplayMedia() {\n return getDisplayMedia();\n }\n\n /**\n * W3C \"Media Capture and Streams\" compatible {@code getUserMedia}\n * implementation.\n * See: https://www.w3.org/TR/mediacapture-streams/#dom-mediadevices-enumeratedevices\n *\n * @param {*} constraints\n * @returns {Promise}\n */\n getUserMedia(constraints: Constraints) {\n return getUserMedia(constraints);\n }\n\n createVirtualAudioTrack(): Promise<VirtualAudioResponse> {\n if (!WebRTCModule.createVirtualAudioTrack) {\n return Promise.reject(new Error('virtual audio unavailable'));\n }\n\n return WebRTCModule.createVirtualAudioTrack();\n }\n\n pushVirtualAudioSamples(samples: Int16Array | number[], sampleRate: number, channels: number) {\n if (!WebRTCModule.pushVirtualAudioSamples) {\n return;\n }\n\n const array = samples instanceof Int16Array ? Array.from(samples) : samples.slice();\n\n WebRTCModule.pushVirtualAudioSamples(array, sampleRate, channels);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaDevices.prototype;\n\ndefineEventAttribute(proto, 'devicechange');\n\n\nexport default new MediaDevices();\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAGA,IAAAE,gBAAA,GAAAC,sBAAA,CAAAH,OAAA;AACA,IAAAI,aAAA,GAAAD,sBAAA,CAAAH,OAAA;AAA2D,SAAAG,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAE3D,MAAM;EAAEG;AAAa,CAAC,GAAGC,0BAAa;AAoBtC,MAAMC,YAAY,SAASC,kBAAW,CAAuB;EACzD;AACJ;AACA;AACA;EACIC,gBAAgBA,CAAA,EAAG;IACf,OAAO,IAAIC,OAAO,CAACC,OAAO,IAAIN,YAAY,CAACI,gBAAgB,CAACE,OAAO,CAAC,CAAC;EACzE;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACIC,eAAeA,CAAA,EAAG;IACd,OAAO,IAAAA,wBAAe,EAAC,CAAC;EAC5B;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACIC,YAAYA,CAACC,WAAwB,EAAE;IACnC,OAAO,IAAAD,qBAAY,EAACC,WAAW,CAAC;EACpC;EAEAC,uBAAuBA,CAAA,EAAkC;IACrD,IAAI,CAACV,YAAY,CAACU,uBAAuB,EAAE;MACvC,OAAOL,OAAO,CAACM,MAAM,CAAC,IAAIC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACjE;IAEA,OAAOZ,YAAY,CAACU,uBAAuB,CAAC,CAAC;EACjD;EAEAG,uBAAuBA,CAACC,OAA8B,EAAEC,UAAkB,EAAEC,QAAgB,EAAE;IAC1F,IAAI,CAAChB,YAAY,CAACa,uBAAuB,EAAE;MACvC;IACJ;IAEA,MAAMI,KAAK,GAAGH,OAAO,YAAYI,UAAU,GAAGC,KAAK,CAACC,IAAI,CAACN,OAAO,CAAC,GAAGA,OAAO,CAACO,KAAK,CAAC,CAAC;IAEnFrB,YAAY,CAACa,uBAAuB,CAACI,KAAK,EAAEF,UAAU,EAAEC,QAAQ,CAAC;EACrE;AACJ;;AAEA;AACA;AACA;AACA,MAAMM,KAAK,GAAGpB,YAAY,CAACqB,SAAS;AAEpC,IAAAC,2BAAoB,EAACF,KAAK,EAAE,cAAc,CAAC;AAAC,IAAAG,QAAA,GAG7B,IAAIvB,YAAY,CAAC,CAAC;AAAAwB,OAAA,CAAA3B,OAAA,GAAA0B,QAAA"}
@@ -1 +1 @@
1
- {"version":3,"names":["_index","require","_reactNative","_EventEmitter","_Logger","_interopRequireDefault","_RTCUtil","obj","__esModule","default","_defineProperty","key","value","Object","defineProperty","enumerable","configurable","writable","log","Logger","WebRTCModule","NativeModules","MediaStreamTrack","EventTarget","constructor","info","_constraints","constraints","_enabled","enabled","_settings","settings","_muted","_peerConnectionId","peerConnectionId","_readyState","readyState","id","kind","remote","_registerEvents","Boolean","mediaStreamTrackSetEnabled","muted","stop","_switchCamera","Error","deepClone","deviceId","facingMode","applyConstraints","_setVideoEffects","names","mediaStreamTrackSetVideoEffects","_setVideoEffect","name","_setMutedInternal","dispatchEvent","Event","_setVolume","volume","mediaStreamTrackSetVolume","normalized","normalizeConstraints","video","mediaStreamTrackApplyConstraints","clone","getCapabilities","getConstraints","getSettings","addListener","ev","trackId","debug","_setAudioSinkCallback","callback","_audioSinkCallback","_handleAudioSamples","data","setAudioSink","_audioSinkListenerActive","mediaStreamTrackEnableAudioSink","removeListenerForEvent","setPlaybackEnabled","_playbackEnabled","mediaStreamTrackSetPlaybackEnabled","isPlaybackEnabled","release","removeListener","mediaStreamTrackRelease","exports","proto","prototype","defineEventAttribute"],"sources":["MediaStreamTrack.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules, NativeEventEmitter, Platform } from 'react-native';\n\nimport { MediaTrackConstraints } from './Constraints';\nimport { addListener, removeListener, removeListenerForEvent } from './EventEmitter';\nimport Logger from './Logger';\nimport { deepClone, normalizeConstraints } from './RTCUtil';\n\nconst log = new Logger('pc');\nconst { WebRTCModule } = NativeModules;\n\nexport type AudioSampleData = {\n trackId: string;\n samples: number[];\n sampleRate: number;\n channels: number;\n timestamp: number;\n}\n\nexport type AudioSinkCallback = (data: AudioSampleData) => void;\n\n\ntype MediaStreamTrackState = 'live' | 'ended';\n\nexport type MediaStreamTrackInfo = {\n id: string;\n kind: string;\n remote: boolean;\n constraints: object;\n enabled: boolean;\n settings: object;\n peerConnectionId: number;\n readyState: MediaStreamTrackState;\n}\n\nexport type MediaTrackSettings = {\n width?: number;\n height?: number;\n frameRate?: number;\n facingMode?: string;\n deviceId?: string;\n groupId?: string;\n}\n\ntype MediaStreamTrackEventMap = {\n ended: Event<'ended'>;\n mute: Event<'mute'>;\n unmute: Event<'unmute'>;\n}\n\nexport default class MediaStreamTrack extends EventTarget<MediaStreamTrackEventMap> {\n _constraints: MediaTrackConstraints;\n _enabled: boolean;\n _settings: MediaTrackSettings;\n _muted: boolean;\n _peerConnectionId: number;\n _readyState: MediaStreamTrackState;\n\n readonly id: string;\n readonly kind: string;\n readonly label: string = '';\n readonly remote: boolean;\n\n constructor(info: MediaStreamTrackInfo) {\n super();\n\n this._constraints = info.constraints || {};\n this._enabled = info.enabled;\n this._settings = info.settings || {};\n this._muted = false;\n this._peerConnectionId = info.peerConnectionId;\n this._readyState = info.readyState;\n\n this.id = info.id;\n this.kind = info.kind;\n this.remote = info.remote;\n\n if (!this.remote) {\n this._registerEvents();\n }\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(enabled: boolean) {\n if (enabled === this._enabled) {\n return;\n }\n\n this._enabled = Boolean(enabled);\n\n if (this._readyState === 'ended') {\n return;\n }\n\n WebRTCModule.mediaStreamTrackSetEnabled(this.remote ? this._peerConnectionId : -1, this.id, this._enabled);\n }\n\n get muted(): boolean {\n return this._muted;\n }\n\n get readyState(): string {\n return this._readyState;\n }\n\n stop(): void {\n this.enabled = false;\n this._readyState = 'ended';\n }\n\n /**\n * Private / custom API for switching the cameras on the fly, without the\n * need for adding / removing tracks or doing any SDP renegotiation.\n *\n * This is how the reference application (AppRTCMobile) implements camera\n * switching.\n *\n * @deprecated Use applyConstraints instead.\n */\n _switchCamera(): void {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n const constraints = deepClone(this._settings);\n\n delete constraints.deviceId;\n constraints.facingMode = this._settings.facingMode === 'user' ? 'environment' : 'user';\n\n this.applyConstraints(constraints);\n }\n\n _setVideoEffects(names: string[]) {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVideoEffects(this.id, names);\n }\n\n _setVideoEffect(name: string) {\n this._setVideoEffects([ name ]);\n }\n\n /**\n * Internal function which is used to set the muted state on remote tracks and\n * emit the mute / unmute event.\n *\n * @param muted Whether the track should be marked as muted / unmuted.\n */\n _setMutedInternal(muted: boolean) {\n if (!this.remote) {\n throw new Error('Track is not remote!');\n }\n\n this._muted = muted;\n this.dispatchEvent(new Event(muted ? 'mute' : 'unmute'));\n }\n\n /**\n * Custom API for setting the volume on an individual audio track.\n *\n * @param volume a gain value in the range of 0-10. defaults to 1.0\n */\n _setVolume(volume: number) {\n if (this.kind !== 'audio') {\n throw new Error('Only implemented for audio tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVolume(this.remote ? this._peerConnectionId : -1, this.id, volume);\n }\n\n /**\n * Applies a new set of constraints to the track.\n *\n * @param constraints An object listing the constraints\n * to apply to the track's constrainable properties; any existing\n * constraints are replaced with the new values specified, and any\n * constrainable properties not included are restored to their default\n * constraints. If this parameter is omitted, all currently set custom\n * constraints are cleared.\n */\n async applyConstraints(constraints?: MediaTrackConstraints): Promise<void> {\n if (this.kind !== 'video') {\n log.info(`Only implemented for video tracks, ignoring applyConstraints for ${this.id}`);\n\n return;\n }\n\n const normalized = normalizeConstraints({ video: constraints ?? true });\n\n this._settings = await WebRTCModule.mediaStreamTrackApplyConstraints(this.id, normalized.video);\n this._constraints = constraints ?? {};\n }\n\n clone(): never {\n throw new Error('Not implemented.');\n }\n\n getCapabilities(): never {\n throw new Error('Not implemented.');\n }\n\n getConstraints() {\n return deepClone(this._constraints);\n }\n\n getSettings(): MediaTrackSettings {\n return deepClone(this._settings);\n }\n\n _registerEvents(): void {\n addListener(this, 'mediaStreamTrackEnded', (ev: any) => {\n if (ev.trackId !== this.id || this._readyState === 'ended') {\n return;\n }\n\n log.debug(`${this.id} mediaStreamTrackEnded`);\n this._readyState = 'ended';\n\n this.dispatchEvent(new Event('ended'));\n });\n }\n\n private _audioSinkCallback: AudioSinkCallback | null = null;\n private _audioSinkListenerActive: boolean = false;\n private _playbackEnabled: boolean = true;\n\n _setAudioSinkCallback(callback: AudioSinkCallback | null): void {\n this._audioSinkCallback = callback;\n }\n\n _handleAudioSamples(data: AudioSampleData): void {\n if (this._audioSinkCallback) {\n this._audioSinkCallback(data);\n }\n }\n\n setAudioSink(callback: AudioSinkCallback | null): void {\n if (this.kind !== 'audio') {\n throw new Error('Audio sink only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Audio sink only available for remote tracks');\n }\n\n this._setAudioSinkCallback(callback);\n\n if (callback && !this._audioSinkListenerActive) {\n this._audioSinkListenerActive = true;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n true\n );\n addListener(this, 'audioSamples', (ev: any) => {\n if (ev.trackId === this.id) {\n this._handleAudioSamples(ev);\n }\n });\n } else if (!callback && this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n }\n\n setPlaybackEnabled(enabled: boolean): void {\n if (this.kind !== 'audio') {\n throw new Error('Playback control only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Playback control only available for remote tracks');\n }\n\n this._playbackEnabled = enabled;\n WebRTCModule.mediaStreamTrackSetPlaybackEnabled(\n this._peerConnectionId,\n this.id,\n enabled\n );\n }\n\n isPlaybackEnabled(): boolean {\n return this._playbackEnabled;\n }\n\n release(): void {\n if (this.remote) {\n if (this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n return;\n }\n\n removeListener(this);\n WebRTCModule.mediaStreamTrackRelease(this.id);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaStreamTrack.prototype;\n\ndefineEventAttribute(proto, 'ended');\ndefineEventAttribute(proto, 'mute');\ndefineEventAttribute(proto, 'unmute');\n"],"mappings":"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"}
1
+ {"version":3,"names":["_index","require","_reactNative","_EventEmitter","_Logger","_interopRequireDefault","_RTCUtil","obj","__esModule","default","_defineProperty","key","value","Object","defineProperty","enumerable","configurable","writable","log","Logger","WebRTCModule","NativeModules","MediaStreamTrack","EventTarget","constructor","info","_constraints","constraints","_enabled","enabled","_settings","settings","_muted","_peerConnectionId","peerConnectionId","_readyState","readyState","id","kind","remote","_registerEvents","Boolean","mediaStreamTrackSetEnabled","muted","stop","_switchCamera","Error","deepClone","deviceId","facingMode","applyConstraints","_setVideoEffects","names","mediaStreamTrackSetVideoEffects","_setVideoEffect","name","_setMutedInternal","dispatchEvent","Event","_setVolume","volume","mediaStreamTrackSetVolume","normalized","normalizeConstraints","video","mediaStreamTrackApplyConstraints","clone","getCapabilities","getConstraints","getSettings","addListener","ev","trackId","debug","_setAudioSinkCallback","callback","_audioSinkCallback","_handleAudioSamples","data","setAudioSink","_audioSinkListenerActive","mediaStreamTrackEnableAudioSink","removeListenerForEvent","setPlaybackEnabled","_playbackEnabled","mediaStreamTrackSetPlaybackEnabled","isPlaybackEnabled","release","removeListener","mediaStreamTrackRelease","exports","proto","prototype","defineEventAttribute"],"sources":["MediaStreamTrack.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules } from 'react-native';\n\nimport { MediaTrackConstraints } from './Constraints';\nimport { addListener, removeListener, removeListenerForEvent } from './EventEmitter';\nimport Logger from './Logger';\nimport { deepClone, normalizeConstraints } from './RTCUtil';\n\nconst log = new Logger('pc');\nconst { WebRTCModule } = NativeModules;\n\nexport type AudioSampleData = {\n trackId: string;\n samples: number[];\n sampleRate: number;\n channels: number;\n bitsPerSample: number;\n framesPerBuffer: number;\n timestamp: number;\n}\n\nexport type AudioSinkCallback = (data: AudioSampleData) => void;\n\n\ntype MediaStreamTrackState = 'live' | 'ended';\n\nexport type MediaStreamTrackInfo = {\n id: string;\n kind: string;\n remote: boolean;\n constraints: object;\n enabled: boolean;\n settings: object;\n peerConnectionId: number;\n readyState: MediaStreamTrackState;\n}\n\nexport type MediaTrackSettings = {\n width?: number;\n height?: number;\n frameRate?: number;\n facingMode?: string;\n deviceId?: string;\n groupId?: string;\n}\n\ntype MediaStreamTrackEventMap = {\n ended: Event<'ended'>;\n mute: Event<'mute'>;\n unmute: Event<'unmute'>;\n}\n\nexport default class MediaStreamTrack extends EventTarget<MediaStreamTrackEventMap> {\n _constraints: MediaTrackConstraints;\n _enabled: boolean;\n _settings: MediaTrackSettings;\n _muted: boolean;\n _peerConnectionId: number;\n _readyState: MediaStreamTrackState;\n\n readonly id: string;\n readonly kind: string;\n readonly label: string = '';\n readonly remote: boolean;\n\n constructor(info: MediaStreamTrackInfo) {\n super();\n\n this._constraints = info.constraints || {};\n this._enabled = info.enabled;\n this._settings = info.settings || {};\n this._muted = false;\n this._peerConnectionId = info.peerConnectionId;\n this._readyState = info.readyState;\n\n this.id = info.id;\n this.kind = info.kind;\n this.remote = info.remote;\n\n if (!this.remote) {\n this._registerEvents();\n }\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(enabled: boolean) {\n if (enabled === this._enabled) {\n return;\n }\n\n this._enabled = Boolean(enabled);\n\n if (this._readyState === 'ended') {\n return;\n }\n\n WebRTCModule.mediaStreamTrackSetEnabled(this.remote ? this._peerConnectionId : -1, this.id, this._enabled);\n }\n\n get muted(): boolean {\n return this._muted;\n }\n\n get readyState(): string {\n return this._readyState;\n }\n\n stop(): void {\n this.enabled = false;\n this._readyState = 'ended';\n }\n\n /**\n * Private / custom API for switching the cameras on the fly, without the\n * need for adding / removing tracks or doing any SDP renegotiation.\n *\n * This is how the reference application (AppRTCMobile) implements camera\n * switching.\n *\n * @deprecated Use applyConstraints instead.\n */\n _switchCamera(): void {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n const constraints = deepClone(this._settings);\n\n delete constraints.deviceId;\n constraints.facingMode = this._settings.facingMode === 'user' ? 'environment' : 'user';\n\n this.applyConstraints(constraints);\n }\n\n _setVideoEffects(names: string[]) {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVideoEffects(this.id, names);\n }\n\n _setVideoEffect(name: string) {\n this._setVideoEffects([ name ]);\n }\n\n /**\n * Internal function which is used to set the muted state on remote tracks and\n * emit the mute / unmute event.\n *\n * @param muted Whether the track should be marked as muted / unmuted.\n */\n _setMutedInternal(muted: boolean) {\n if (!this.remote) {\n throw new Error('Track is not remote!');\n }\n\n this._muted = muted;\n this.dispatchEvent(new Event(muted ? 'mute' : 'unmute'));\n }\n\n /**\n * Custom API for setting the volume on an individual audio track.\n *\n * @param volume a gain value in the range of 0-10. defaults to 1.0\n */\n _setVolume(volume: number) {\n if (this.kind !== 'audio') {\n throw new Error('Only implemented for audio tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVolume(this.remote ? this._peerConnectionId : -1, this.id, volume);\n }\n\n /**\n * Applies a new set of constraints to the track.\n *\n * @param constraints An object listing the constraints\n * to apply to the track's constrainable properties; any existing\n * constraints are replaced with the new values specified, and any\n * constrainable properties not included are restored to their default\n * constraints. If this parameter is omitted, all currently set custom\n * constraints are cleared.\n */\n async applyConstraints(constraints?: MediaTrackConstraints): Promise<void> {\n if (this.kind !== 'video') {\n log.info(`Only implemented for video tracks, ignoring applyConstraints for ${this.id}`);\n\n return;\n }\n\n const normalized = normalizeConstraints({ video: constraints ?? true });\n\n this._settings = await WebRTCModule.mediaStreamTrackApplyConstraints(this.id, normalized.video);\n this._constraints = constraints ?? {};\n }\n\n clone(): never {\n throw new Error('Not implemented.');\n }\n\n getCapabilities(): never {\n throw new Error('Not implemented.');\n }\n\n getConstraints() {\n return deepClone(this._constraints);\n }\n\n getSettings(): MediaTrackSettings {\n return deepClone(this._settings);\n }\n\n _registerEvents(): void {\n addListener(this, 'mediaStreamTrackEnded', (ev: any) => {\n if (ev.trackId !== this.id || this._readyState === 'ended') {\n return;\n }\n\n log.debug(`${this.id} mediaStreamTrackEnded`);\n this._readyState = 'ended';\n\n this.dispatchEvent(new Event('ended'));\n });\n }\n\n private _audioSinkCallback: AudioSinkCallback | null = null;\n private _audioSinkListenerActive = false;\n private _playbackEnabled = true;\n\n _setAudioSinkCallback(callback: AudioSinkCallback | null): void {\n this._audioSinkCallback = callback;\n }\n\n _handleAudioSamples(data: AudioSampleData): void {\n if (this._audioSinkCallback) {\n this._audioSinkCallback(data);\n }\n }\n\n setAudioSink(callback: AudioSinkCallback | null): void {\n if (this.kind !== 'audio') {\n throw new Error('Audio sink only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Audio sink only available for remote tracks');\n }\n\n this._setAudioSinkCallback(callback);\n\n if (callback && !this._audioSinkListenerActive) {\n this._audioSinkListenerActive = true;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n true\n );\n addListener(this, 'audioSamples', (ev: any) => {\n if (ev.trackId === this.id) {\n this._handleAudioSamples(ev);\n }\n });\n } else if (!callback && this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n }\n\n setPlaybackEnabled(enabled: boolean): void {\n if (this.kind !== 'audio') {\n throw new Error('Playback control only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Playback control only available for remote tracks');\n }\n\n this._playbackEnabled = enabled;\n WebRTCModule.mediaStreamTrackSetPlaybackEnabled(\n this._peerConnectionId,\n this.id,\n enabled\n );\n }\n\n isPlaybackEnabled(): boolean {\n return this._playbackEnabled;\n }\n\n release(): void {\n if (this.remote) {\n if (this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n\n return;\n }\n\n removeListener(this);\n WebRTCModule.mediaStreamTrackRelease(this.id);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaStreamTrack.prototype;\n\ndefineEventAttribute(proto, 'ended');\ndefineEventAttribute(proto, 'mute');\ndefineEventAttribute(proto, 'unmute');\n"],"mappings":"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"}
@@ -40,7 +40,9 @@ export function removeListener(listener) {
40
40
  }
41
41
  export function removeListenerForEvent(listener, eventName) {
42
42
  const subs = _subscriptions.get(listener);
43
- if (!subs) return;
43
+ if (!subs) {
44
+ return;
45
+ }
44
46
  const remaining = [];
45
47
  subs.forEach(sub => {
46
48
  if (sub.eventType === eventName) {
@@ -1 +1 @@
1
- {"version":3,"names":["NativeModules","NativeEventEmitter","EventEmitter","WebRTCModule","nativeEmitter","NATIVE_EVENTS","eventEmitter","setupNativeEvents","eventName","addListener","_len","arguments","length","args","Array","_key","emit","_subscriptions","Map","listener","eventHandler","_subscriptions$get","includes","Error","has","set","get","push","removeListener","_subscriptions$get2","forEach","sub","remove","delete","removeListenerForEvent","subs","remaining","eventType"],"sources":["EventEmitter.ts"],"sourcesContent":["import { NativeModules, NativeEventEmitter, EmitterSubscription } from 'react-native';\n// @ts-ignore\nimport EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';\n\nconst { WebRTCModule } = NativeModules;\n\n// This emitter is going to be used to listen to all the native events (once) and then\n// re-emit them on a JS-only emitter.\nconst nativeEmitter = new NativeEventEmitter(WebRTCModule);\n\nconst NATIVE_EVENTS = [\n 'peerConnectionSignalingStateChanged',\n 'peerConnectionStateChanged',\n 'peerConnectionOnRenegotiationNeeded',\n 'peerConnectionIceConnectionChanged',\n 'peerConnectionIceGatheringChanged',\n 'peerConnectionGotICECandidate',\n 'peerConnectionDidOpenDataChannel',\n 'peerConnectionOnRemoveTrack',\n 'peerConnectionOnTrack',\n 'dataChannelStateChanged',\n 'dataChannelReceiveMessage',\n 'dataChannelDidChangeBufferedAmount',\n 'mediaStreamTrackMuteChanged',\n 'mediaStreamTrackEnded',\n 'frameCryptionStateChanged',\n 'audioSamples',\n];\n\nconst eventEmitter = new EventEmitter();\n\nexport function setupNativeEvents() {\n for (const eventName of NATIVE_EVENTS) {\n nativeEmitter.addListener(eventName, (...args) => {\n eventEmitter.emit(eventName, ...args);\n });\n }\n}\n\ntype EventHandler = (event: unknown) => void;\ntype Listener = unknown;\n\nconst _subscriptions: Map<Listener, EmitterSubscription[]> = new Map();\n\nexport function addListener(listener: Listener, eventName: string, eventHandler: EventHandler): void {\n if (!NATIVE_EVENTS.includes(eventName)) {\n throw new Error(`Invalid event: ${eventName}`);\n }\n\n if (!_subscriptions.has(listener)) {\n _subscriptions.set(listener, []);\n }\n\n _subscriptions.get(listener)?.push(eventEmitter.addListener(eventName, eventHandler));\n}\n\nexport function removeListener(listener: Listener): void {\n _subscriptions.get(listener)?.forEach(sub => {\n sub.remove();\n });\n\n _subscriptions.delete(listener);\n}\n\nexport function removeListenerForEvent(listener: Listener, eventName: string): void {\n const subs = _subscriptions.get(listener);\n if (!subs) return;\n \n const remaining: EmitterSubscription[] = [];\n subs.forEach(sub => {\n if ((sub as any).eventType === eventName) {\n sub.remove();\n } else {\n remaining.push(sub);\n }\n });\n \n if (remaining.length === 0) {\n _subscriptions.delete(listener);\n } else {\n _subscriptions.set(listener, remaining);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["NativeModules","NativeEventEmitter","EventEmitter","WebRTCModule","nativeEmitter","NATIVE_EVENTS","eventEmitter","setupNativeEvents","eventName","addListener","_len","arguments","length","args","Array","_key","emit","_subscriptions","Map","listener","eventHandler","_subscriptions$get","includes","Error","has","set","get","push","removeListener","_subscriptions$get2","forEach","sub","remove","delete","removeListenerForEvent","subs","remaining","eventType"],"sources":["EventEmitter.ts"],"sourcesContent":["import { NativeModules, NativeEventEmitter, EmitterSubscription } from 'react-native';\n// @ts-ignore\nimport EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';\n\nconst { WebRTCModule } = NativeModules;\n\n// This emitter is going to be used to listen to all the native events (once) and then\n// re-emit them on a JS-only emitter.\nconst nativeEmitter = new NativeEventEmitter(WebRTCModule);\n\nconst NATIVE_EVENTS = [\n 'peerConnectionSignalingStateChanged',\n 'peerConnectionStateChanged',\n 'peerConnectionOnRenegotiationNeeded',\n 'peerConnectionIceConnectionChanged',\n 'peerConnectionIceGatheringChanged',\n 'peerConnectionGotICECandidate',\n 'peerConnectionDidOpenDataChannel',\n 'peerConnectionOnRemoveTrack',\n 'peerConnectionOnTrack',\n 'dataChannelStateChanged',\n 'dataChannelReceiveMessage',\n 'dataChannelDidChangeBufferedAmount',\n 'mediaStreamTrackMuteChanged',\n 'mediaStreamTrackEnded',\n 'frameCryptionStateChanged',\n 'audioSamples',\n];\n\nconst eventEmitter = new EventEmitter();\n\nexport function setupNativeEvents() {\n for (const eventName of NATIVE_EVENTS) {\n nativeEmitter.addListener(eventName, (...args) => {\n eventEmitter.emit(eventName, ...args);\n });\n }\n}\n\ntype EventHandler = (event: unknown) => void;\ntype Listener = unknown;\n\nconst _subscriptions: Map<Listener, EmitterSubscription[]> = new Map();\n\nexport function addListener(listener: Listener, eventName: string, eventHandler: EventHandler): void {\n if (!NATIVE_EVENTS.includes(eventName)) {\n throw new Error(`Invalid event: ${eventName}`);\n }\n\n if (!_subscriptions.has(listener)) {\n _subscriptions.set(listener, []);\n }\n\n _subscriptions.get(listener)?.push(eventEmitter.addListener(eventName, eventHandler));\n}\n\nexport function removeListener(listener: Listener): void {\n _subscriptions.get(listener)?.forEach(sub => {\n sub.remove();\n });\n\n _subscriptions.delete(listener);\n}\n\nexport function removeListenerForEvent(listener: Listener, eventName: string): void {\n const subs = _subscriptions.get(listener);\n\n if (!subs) {\n return;\n }\n\n const remaining: EmitterSubscription[] = [];\n\n subs.forEach(sub => {\n if ((sub as any).eventType === eventName) {\n sub.remove();\n } else {\n remaining.push(sub);\n }\n });\n\n if (remaining.length === 0) {\n _subscriptions.delete(listener);\n } else {\n _subscriptions.set(listener, remaining);\n }\n}\n"],"mappings":"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"}
@@ -35,6 +35,19 @@ class MediaDevices extends EventTarget {
35
35
  getUserMedia(constraints) {
36
36
  return getUserMedia(constraints);
37
37
  }
38
+ createVirtualAudioTrack() {
39
+ if (!WebRTCModule.createVirtualAudioTrack) {
40
+ return Promise.reject(new Error('virtual audio unavailable'));
41
+ }
42
+ return WebRTCModule.createVirtualAudioTrack();
43
+ }
44
+ pushVirtualAudioSamples(samples, sampleRate, channels) {
45
+ if (!WebRTCModule.pushVirtualAudioSamples) {
46
+ return;
47
+ }
48
+ const array = samples instanceof Int16Array ? Array.from(samples) : samples.slice();
49
+ WebRTCModule.pushVirtualAudioSamples(array, sampleRate, channels);
50
+ }
38
51
  }
39
52
 
40
53
  /**
@@ -1 +1 @@
1
- {"version":3,"names":["EventTarget","defineEventAttribute","NativeModules","getDisplayMedia","getUserMedia","WebRTCModule","MediaDevices","enumerateDevices","Promise","resolve","constraints","proto","prototype"],"sources":["MediaDevices.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules } from 'react-native';\n\nimport getDisplayMedia from './getDisplayMedia';\nimport getUserMedia, { Constraints } from './getUserMedia';\n\nconst { WebRTCModule } = NativeModules;\n\ntype MediaDevicesEventMap = {\n devicechange: Event<'devicechange'>\n}\n\nclass MediaDevices extends EventTarget<MediaDevicesEventMap> {\n /**\n * W3C \"Media Capture and Streams\" compatible {@code enumerateDevices}\n * implementation.\n */\n enumerateDevices() {\n return new Promise(resolve => WebRTCModule.enumerateDevices(resolve));\n }\n\n /**\n * W3C \"Screen Capture\" compatible {@code getDisplayMedia} implementation.\n * See: https://w3c.github.io/mediacapture-screen-share/\n *\n * @returns {Promise}\n */\n getDisplayMedia() {\n return getDisplayMedia();\n }\n\n /**\n * W3C \"Media Capture and Streams\" compatible {@code getUserMedia}\n * implementation.\n * See: https://www.w3.org/TR/mediacapture-streams/#dom-mediadevices-enumeratedevices\n *\n * @param {*} constraints\n * @returns {Promise}\n */\n getUserMedia(constraints: Constraints) {\n return getUserMedia(constraints);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaDevices.prototype;\n\ndefineEventAttribute(proto, 'devicechange');\n\n\nexport default new MediaDevices();\n"],"mappings":"AAAA,SAASA,WAAW,EAASC,oBAAoB,QAAQ,yBAAyB;AAClF,SAASC,aAAa,QAAQ,cAAc;AAE5C,OAAOC,eAAe,MAAM,mBAAmB;AAC/C,OAAOC,YAAY,MAAuB,gBAAgB;AAE1D,MAAM;EAAEC;AAAa,CAAC,GAAGH,aAAa;AAMtC,MAAMI,YAAY,SAASN,WAAW,CAAuB;EACzD;AACJ;AACA;AACA;EACIO,gBAAgBA,CAAA,EAAG;IACf,OAAO,IAAIC,OAAO,CAACC,OAAO,IAAIJ,YAAY,CAACE,gBAAgB,CAACE,OAAO,CAAC,CAAC;EACzE;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACIN,eAAeA,CAAA,EAAG;IACd,OAAOA,eAAe,CAAC,CAAC;EAC5B;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACIC,YAAYA,CAACM,WAAwB,EAAE;IACnC,OAAON,YAAY,CAACM,WAAW,CAAC;EACpC;AACJ;;AAEA;AACA;AACA;AACA,MAAMC,KAAK,GAAGL,YAAY,CAACM,SAAS;AAEpCX,oBAAoB,CAACU,KAAK,EAAE,cAAc,CAAC;AAG3C,eAAe,IAAIL,YAAY,CAAC,CAAC"}
1
+ {"version":3,"names":["EventTarget","defineEventAttribute","NativeModules","getDisplayMedia","getUserMedia","WebRTCModule","MediaDevices","enumerateDevices","Promise","resolve","constraints","createVirtualAudioTrack","reject","Error","pushVirtualAudioSamples","samples","sampleRate","channels","array","Int16Array","Array","from","slice","proto","prototype"],"sources":["MediaDevices.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules } from 'react-native';\n\nimport { type MediaTrackSettings } from './MediaStreamTrack';\nimport getDisplayMedia from './getDisplayMedia';\nimport getUserMedia, { Constraints } from './getUserMedia';\n\nconst { WebRTCModule } = NativeModules;\n\ntype MediaDevicesEventMap = {\n devicechange: Event<'devicechange'>\n}\n\ntype VirtualTrackInfo = {\n enabled: boolean;\n id: string;\n kind: string;\n readyState: string;\n remote: boolean;\n settings: MediaTrackSettings;\n}\n\ntype VirtualAudioResponse = {\n streamId: string;\n tracks: VirtualTrackInfo[];\n}\n\nclass MediaDevices extends EventTarget<MediaDevicesEventMap> {\n /**\n * W3C \"Media Capture and Streams\" compatible {@code enumerateDevices}\n * implementation.\n */\n enumerateDevices() {\n return new Promise(resolve => WebRTCModule.enumerateDevices(resolve));\n }\n\n /**\n * W3C \"Screen Capture\" compatible {@code getDisplayMedia} implementation.\n * See: https://w3c.github.io/mediacapture-screen-share/\n *\n * @returns {Promise}\n */\n getDisplayMedia() {\n return getDisplayMedia();\n }\n\n /**\n * W3C \"Media Capture and Streams\" compatible {@code getUserMedia}\n * implementation.\n * See: https://www.w3.org/TR/mediacapture-streams/#dom-mediadevices-enumeratedevices\n *\n * @param {*} constraints\n * @returns {Promise}\n */\n getUserMedia(constraints: Constraints) {\n return getUserMedia(constraints);\n }\n\n createVirtualAudioTrack(): Promise<VirtualAudioResponse> {\n if (!WebRTCModule.createVirtualAudioTrack) {\n return Promise.reject(new Error('virtual audio unavailable'));\n }\n\n return WebRTCModule.createVirtualAudioTrack();\n }\n\n pushVirtualAudioSamples(samples: Int16Array | number[], sampleRate: number, channels: number) {\n if (!WebRTCModule.pushVirtualAudioSamples) {\n return;\n }\n\n const array = samples instanceof Int16Array ? Array.from(samples) : samples.slice();\n\n WebRTCModule.pushVirtualAudioSamples(array, sampleRate, channels);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaDevices.prototype;\n\ndefineEventAttribute(proto, 'devicechange');\n\n\nexport default new MediaDevices();\n"],"mappings":"AAAA,SAASA,WAAW,EAASC,oBAAoB,QAAQ,yBAAyB;AAClF,SAASC,aAAa,QAAQ,cAAc;AAG5C,OAAOC,eAAe,MAAM,mBAAmB;AAC/C,OAAOC,YAAY,MAAuB,gBAAgB;AAE1D,MAAM;EAAEC;AAAa,CAAC,GAAGH,aAAa;AAoBtC,MAAMI,YAAY,SAASN,WAAW,CAAuB;EACzD;AACJ;AACA;AACA;EACIO,gBAAgBA,CAAA,EAAG;IACf,OAAO,IAAIC,OAAO,CAACC,OAAO,IAAIJ,YAAY,CAACE,gBAAgB,CAACE,OAAO,CAAC,CAAC;EACzE;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACIN,eAAeA,CAAA,EAAG;IACd,OAAOA,eAAe,CAAC,CAAC;EAC5B;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACIC,YAAYA,CAACM,WAAwB,EAAE;IACnC,OAAON,YAAY,CAACM,WAAW,CAAC;EACpC;EAEAC,uBAAuBA,CAAA,EAAkC;IACrD,IAAI,CAACN,YAAY,CAACM,uBAAuB,EAAE;MACvC,OAAOH,OAAO,CAACI,MAAM,CAAC,IAAIC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACjE;IAEA,OAAOR,YAAY,CAACM,uBAAuB,CAAC,CAAC;EACjD;EAEAG,uBAAuBA,CAACC,OAA8B,EAAEC,UAAkB,EAAEC,QAAgB,EAAE;IAC1F,IAAI,CAACZ,YAAY,CAACS,uBAAuB,EAAE;MACvC;IACJ;IAEA,MAAMI,KAAK,GAAGH,OAAO,YAAYI,UAAU,GAAGC,KAAK,CAACC,IAAI,CAACN,OAAO,CAAC,GAAGA,OAAO,CAACO,KAAK,CAAC,CAAC;IAEnFjB,YAAY,CAACS,uBAAuB,CAACI,KAAK,EAAEF,UAAU,EAAEC,QAAQ,CAAC;EACrE;AACJ;;AAEA;AACA;AACA;AACA,MAAMM,KAAK,GAAGjB,YAAY,CAACkB,SAAS;AAEpCvB,oBAAoB,CAACsB,KAAK,EAAE,cAAc,CAAC;AAG3C,eAAe,IAAIjB,YAAY,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"names":["EventTarget","Event","defineEventAttribute","NativeModules","addListener","removeListener","removeListenerForEvent","Logger","deepClone","normalizeConstraints","log","WebRTCModule","MediaStreamTrack","constructor","info","_defineProperty","_constraints","constraints","_enabled","enabled","_settings","settings","_muted","_peerConnectionId","peerConnectionId","_readyState","readyState","id","kind","remote","_registerEvents","Boolean","mediaStreamTrackSetEnabled","muted","stop","_switchCamera","Error","deviceId","facingMode","applyConstraints","_setVideoEffects","names","mediaStreamTrackSetVideoEffects","_setVideoEffect","name","_setMutedInternal","dispatchEvent","_setVolume","volume","mediaStreamTrackSetVolume","normalized","video","mediaStreamTrackApplyConstraints","clone","getCapabilities","getConstraints","getSettings","ev","trackId","debug","_setAudioSinkCallback","callback","_audioSinkCallback","_handleAudioSamples","data","setAudioSink","_audioSinkListenerActive","mediaStreamTrackEnableAudioSink","setPlaybackEnabled","_playbackEnabled","mediaStreamTrackSetPlaybackEnabled","isPlaybackEnabled","release","mediaStreamTrackRelease","proto","prototype"],"sources":["MediaStreamTrack.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules, NativeEventEmitter, Platform } from 'react-native';\n\nimport { MediaTrackConstraints } from './Constraints';\nimport { addListener, removeListener, removeListenerForEvent } from './EventEmitter';\nimport Logger from './Logger';\nimport { deepClone, normalizeConstraints } from './RTCUtil';\n\nconst log = new Logger('pc');\nconst { WebRTCModule } = NativeModules;\n\nexport type AudioSampleData = {\n trackId: string;\n samples: number[];\n sampleRate: number;\n channels: number;\n timestamp: number;\n}\n\nexport type AudioSinkCallback = (data: AudioSampleData) => void;\n\n\ntype MediaStreamTrackState = 'live' | 'ended';\n\nexport type MediaStreamTrackInfo = {\n id: string;\n kind: string;\n remote: boolean;\n constraints: object;\n enabled: boolean;\n settings: object;\n peerConnectionId: number;\n readyState: MediaStreamTrackState;\n}\n\nexport type MediaTrackSettings = {\n width?: number;\n height?: number;\n frameRate?: number;\n facingMode?: string;\n deviceId?: string;\n groupId?: string;\n}\n\ntype MediaStreamTrackEventMap = {\n ended: Event<'ended'>;\n mute: Event<'mute'>;\n unmute: Event<'unmute'>;\n}\n\nexport default class MediaStreamTrack extends EventTarget<MediaStreamTrackEventMap> {\n _constraints: MediaTrackConstraints;\n _enabled: boolean;\n _settings: MediaTrackSettings;\n _muted: boolean;\n _peerConnectionId: number;\n _readyState: MediaStreamTrackState;\n\n readonly id: string;\n readonly kind: string;\n readonly label: string = '';\n readonly remote: boolean;\n\n constructor(info: MediaStreamTrackInfo) {\n super();\n\n this._constraints = info.constraints || {};\n this._enabled = info.enabled;\n this._settings = info.settings || {};\n this._muted = false;\n this._peerConnectionId = info.peerConnectionId;\n this._readyState = info.readyState;\n\n this.id = info.id;\n this.kind = info.kind;\n this.remote = info.remote;\n\n if (!this.remote) {\n this._registerEvents();\n }\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(enabled: boolean) {\n if (enabled === this._enabled) {\n return;\n }\n\n this._enabled = Boolean(enabled);\n\n if (this._readyState === 'ended') {\n return;\n }\n\n WebRTCModule.mediaStreamTrackSetEnabled(this.remote ? this._peerConnectionId : -1, this.id, this._enabled);\n }\n\n get muted(): boolean {\n return this._muted;\n }\n\n get readyState(): string {\n return this._readyState;\n }\n\n stop(): void {\n this.enabled = false;\n this._readyState = 'ended';\n }\n\n /**\n * Private / custom API for switching the cameras on the fly, without the\n * need for adding / removing tracks or doing any SDP renegotiation.\n *\n * This is how the reference application (AppRTCMobile) implements camera\n * switching.\n *\n * @deprecated Use applyConstraints instead.\n */\n _switchCamera(): void {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n const constraints = deepClone(this._settings);\n\n delete constraints.deviceId;\n constraints.facingMode = this._settings.facingMode === 'user' ? 'environment' : 'user';\n\n this.applyConstraints(constraints);\n }\n\n _setVideoEffects(names: string[]) {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVideoEffects(this.id, names);\n }\n\n _setVideoEffect(name: string) {\n this._setVideoEffects([ name ]);\n }\n\n /**\n * Internal function which is used to set the muted state on remote tracks and\n * emit the mute / unmute event.\n *\n * @param muted Whether the track should be marked as muted / unmuted.\n */\n _setMutedInternal(muted: boolean) {\n if (!this.remote) {\n throw new Error('Track is not remote!');\n }\n\n this._muted = muted;\n this.dispatchEvent(new Event(muted ? 'mute' : 'unmute'));\n }\n\n /**\n * Custom API for setting the volume on an individual audio track.\n *\n * @param volume a gain value in the range of 0-10. defaults to 1.0\n */\n _setVolume(volume: number) {\n if (this.kind !== 'audio') {\n throw new Error('Only implemented for audio tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVolume(this.remote ? this._peerConnectionId : -1, this.id, volume);\n }\n\n /**\n * Applies a new set of constraints to the track.\n *\n * @param constraints An object listing the constraints\n * to apply to the track's constrainable properties; any existing\n * constraints are replaced with the new values specified, and any\n * constrainable properties not included are restored to their default\n * constraints. If this parameter is omitted, all currently set custom\n * constraints are cleared.\n */\n async applyConstraints(constraints?: MediaTrackConstraints): Promise<void> {\n if (this.kind !== 'video') {\n log.info(`Only implemented for video tracks, ignoring applyConstraints for ${this.id}`);\n\n return;\n }\n\n const normalized = normalizeConstraints({ video: constraints ?? true });\n\n this._settings = await WebRTCModule.mediaStreamTrackApplyConstraints(this.id, normalized.video);\n this._constraints = constraints ?? {};\n }\n\n clone(): never {\n throw new Error('Not implemented.');\n }\n\n getCapabilities(): never {\n throw new Error('Not implemented.');\n }\n\n getConstraints() {\n return deepClone(this._constraints);\n }\n\n getSettings(): MediaTrackSettings {\n return deepClone(this._settings);\n }\n\n _registerEvents(): void {\n addListener(this, 'mediaStreamTrackEnded', (ev: any) => {\n if (ev.trackId !== this.id || this._readyState === 'ended') {\n return;\n }\n\n log.debug(`${this.id} mediaStreamTrackEnded`);\n this._readyState = 'ended';\n\n this.dispatchEvent(new Event('ended'));\n });\n }\n\n private _audioSinkCallback: AudioSinkCallback | null = null;\n private _audioSinkListenerActive: boolean = false;\n private _playbackEnabled: boolean = true;\n\n _setAudioSinkCallback(callback: AudioSinkCallback | null): void {\n this._audioSinkCallback = callback;\n }\n\n _handleAudioSamples(data: AudioSampleData): void {\n if (this._audioSinkCallback) {\n this._audioSinkCallback(data);\n }\n }\n\n setAudioSink(callback: AudioSinkCallback | null): void {\n if (this.kind !== 'audio') {\n throw new Error('Audio sink only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Audio sink only available for remote tracks');\n }\n\n this._setAudioSinkCallback(callback);\n\n if (callback && !this._audioSinkListenerActive) {\n this._audioSinkListenerActive = true;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n true\n );\n addListener(this, 'audioSamples', (ev: any) => {\n if (ev.trackId === this.id) {\n this._handleAudioSamples(ev);\n }\n });\n } else if (!callback && this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n }\n\n setPlaybackEnabled(enabled: boolean): void {\n if (this.kind !== 'audio') {\n throw new Error('Playback control only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Playback control only available for remote tracks');\n }\n\n this._playbackEnabled = enabled;\n WebRTCModule.mediaStreamTrackSetPlaybackEnabled(\n this._peerConnectionId,\n this.id,\n enabled\n );\n }\n\n isPlaybackEnabled(): boolean {\n return this._playbackEnabled;\n }\n\n release(): void {\n if (this.remote) {\n if (this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n return;\n }\n\n removeListener(this);\n WebRTCModule.mediaStreamTrackRelease(this.id);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaStreamTrack.prototype;\n\ndefineEventAttribute(proto, 'ended');\ndefineEventAttribute(proto, 'mute');\ndefineEventAttribute(proto, 'unmute');\n"],"mappings":"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"}
1
+ {"version":3,"names":["EventTarget","Event","defineEventAttribute","NativeModules","addListener","removeListener","removeListenerForEvent","Logger","deepClone","normalizeConstraints","log","WebRTCModule","MediaStreamTrack","constructor","info","_defineProperty","_constraints","constraints","_enabled","enabled","_settings","settings","_muted","_peerConnectionId","peerConnectionId","_readyState","readyState","id","kind","remote","_registerEvents","Boolean","mediaStreamTrackSetEnabled","muted","stop","_switchCamera","Error","deviceId","facingMode","applyConstraints","_setVideoEffects","names","mediaStreamTrackSetVideoEffects","_setVideoEffect","name","_setMutedInternal","dispatchEvent","_setVolume","volume","mediaStreamTrackSetVolume","normalized","video","mediaStreamTrackApplyConstraints","clone","getCapabilities","getConstraints","getSettings","ev","trackId","debug","_setAudioSinkCallback","callback","_audioSinkCallback","_handleAudioSamples","data","setAudioSink","_audioSinkListenerActive","mediaStreamTrackEnableAudioSink","setPlaybackEnabled","_playbackEnabled","mediaStreamTrackSetPlaybackEnabled","isPlaybackEnabled","release","mediaStreamTrackRelease","proto","prototype"],"sources":["MediaStreamTrack.ts"],"sourcesContent":["import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';\nimport { NativeModules } from 'react-native';\n\nimport { MediaTrackConstraints } from './Constraints';\nimport { addListener, removeListener, removeListenerForEvent } from './EventEmitter';\nimport Logger from './Logger';\nimport { deepClone, normalizeConstraints } from './RTCUtil';\n\nconst log = new Logger('pc');\nconst { WebRTCModule } = NativeModules;\n\nexport type AudioSampleData = {\n trackId: string;\n samples: number[];\n sampleRate: number;\n channels: number;\n bitsPerSample: number;\n framesPerBuffer: number;\n timestamp: number;\n}\n\nexport type AudioSinkCallback = (data: AudioSampleData) => void;\n\n\ntype MediaStreamTrackState = 'live' | 'ended';\n\nexport type MediaStreamTrackInfo = {\n id: string;\n kind: string;\n remote: boolean;\n constraints: object;\n enabled: boolean;\n settings: object;\n peerConnectionId: number;\n readyState: MediaStreamTrackState;\n}\n\nexport type MediaTrackSettings = {\n width?: number;\n height?: number;\n frameRate?: number;\n facingMode?: string;\n deviceId?: string;\n groupId?: string;\n}\n\ntype MediaStreamTrackEventMap = {\n ended: Event<'ended'>;\n mute: Event<'mute'>;\n unmute: Event<'unmute'>;\n}\n\nexport default class MediaStreamTrack extends EventTarget<MediaStreamTrackEventMap> {\n _constraints: MediaTrackConstraints;\n _enabled: boolean;\n _settings: MediaTrackSettings;\n _muted: boolean;\n _peerConnectionId: number;\n _readyState: MediaStreamTrackState;\n\n readonly id: string;\n readonly kind: string;\n readonly label: string = '';\n readonly remote: boolean;\n\n constructor(info: MediaStreamTrackInfo) {\n super();\n\n this._constraints = info.constraints || {};\n this._enabled = info.enabled;\n this._settings = info.settings || {};\n this._muted = false;\n this._peerConnectionId = info.peerConnectionId;\n this._readyState = info.readyState;\n\n this.id = info.id;\n this.kind = info.kind;\n this.remote = info.remote;\n\n if (!this.remote) {\n this._registerEvents();\n }\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(enabled: boolean) {\n if (enabled === this._enabled) {\n return;\n }\n\n this._enabled = Boolean(enabled);\n\n if (this._readyState === 'ended') {\n return;\n }\n\n WebRTCModule.mediaStreamTrackSetEnabled(this.remote ? this._peerConnectionId : -1, this.id, this._enabled);\n }\n\n get muted(): boolean {\n return this._muted;\n }\n\n get readyState(): string {\n return this._readyState;\n }\n\n stop(): void {\n this.enabled = false;\n this._readyState = 'ended';\n }\n\n /**\n * Private / custom API for switching the cameras on the fly, without the\n * need for adding / removing tracks or doing any SDP renegotiation.\n *\n * This is how the reference application (AppRTCMobile) implements camera\n * switching.\n *\n * @deprecated Use applyConstraints instead.\n */\n _switchCamera(): void {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n const constraints = deepClone(this._settings);\n\n delete constraints.deviceId;\n constraints.facingMode = this._settings.facingMode === 'user' ? 'environment' : 'user';\n\n this.applyConstraints(constraints);\n }\n\n _setVideoEffects(names: string[]) {\n if (this.remote) {\n throw new Error('Not implemented for remote tracks');\n }\n\n if (this.kind !== 'video') {\n throw new Error('Only implemented for video tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVideoEffects(this.id, names);\n }\n\n _setVideoEffect(name: string) {\n this._setVideoEffects([ name ]);\n }\n\n /**\n * Internal function which is used to set the muted state on remote tracks and\n * emit the mute / unmute event.\n *\n * @param muted Whether the track should be marked as muted / unmuted.\n */\n _setMutedInternal(muted: boolean) {\n if (!this.remote) {\n throw new Error('Track is not remote!');\n }\n\n this._muted = muted;\n this.dispatchEvent(new Event(muted ? 'mute' : 'unmute'));\n }\n\n /**\n * Custom API for setting the volume on an individual audio track.\n *\n * @param volume a gain value in the range of 0-10. defaults to 1.0\n */\n _setVolume(volume: number) {\n if (this.kind !== 'audio') {\n throw new Error('Only implemented for audio tracks');\n }\n\n WebRTCModule.mediaStreamTrackSetVolume(this.remote ? this._peerConnectionId : -1, this.id, volume);\n }\n\n /**\n * Applies a new set of constraints to the track.\n *\n * @param constraints An object listing the constraints\n * to apply to the track's constrainable properties; any existing\n * constraints are replaced with the new values specified, and any\n * constrainable properties not included are restored to their default\n * constraints. If this parameter is omitted, all currently set custom\n * constraints are cleared.\n */\n async applyConstraints(constraints?: MediaTrackConstraints): Promise<void> {\n if (this.kind !== 'video') {\n log.info(`Only implemented for video tracks, ignoring applyConstraints for ${this.id}`);\n\n return;\n }\n\n const normalized = normalizeConstraints({ video: constraints ?? true });\n\n this._settings = await WebRTCModule.mediaStreamTrackApplyConstraints(this.id, normalized.video);\n this._constraints = constraints ?? {};\n }\n\n clone(): never {\n throw new Error('Not implemented.');\n }\n\n getCapabilities(): never {\n throw new Error('Not implemented.');\n }\n\n getConstraints() {\n return deepClone(this._constraints);\n }\n\n getSettings(): MediaTrackSettings {\n return deepClone(this._settings);\n }\n\n _registerEvents(): void {\n addListener(this, 'mediaStreamTrackEnded', (ev: any) => {\n if (ev.trackId !== this.id || this._readyState === 'ended') {\n return;\n }\n\n log.debug(`${this.id} mediaStreamTrackEnded`);\n this._readyState = 'ended';\n\n this.dispatchEvent(new Event('ended'));\n });\n }\n\n private _audioSinkCallback: AudioSinkCallback | null = null;\n private _audioSinkListenerActive = false;\n private _playbackEnabled = true;\n\n _setAudioSinkCallback(callback: AudioSinkCallback | null): void {\n this._audioSinkCallback = callback;\n }\n\n _handleAudioSamples(data: AudioSampleData): void {\n if (this._audioSinkCallback) {\n this._audioSinkCallback(data);\n }\n }\n\n setAudioSink(callback: AudioSinkCallback | null): void {\n if (this.kind !== 'audio') {\n throw new Error('Audio sink only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Audio sink only available for remote tracks');\n }\n\n this._setAudioSinkCallback(callback);\n\n if (callback && !this._audioSinkListenerActive) {\n this._audioSinkListenerActive = true;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n true\n );\n addListener(this, 'audioSamples', (ev: any) => {\n if (ev.trackId === this.id) {\n this._handleAudioSamples(ev);\n }\n });\n } else if (!callback && this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n }\n\n setPlaybackEnabled(enabled: boolean): void {\n if (this.kind !== 'audio') {\n throw new Error('Playback control only available for audio tracks');\n }\n\n if (!this.remote) {\n throw new Error('Playback control only available for remote tracks');\n }\n\n this._playbackEnabled = enabled;\n WebRTCModule.mediaStreamTrackSetPlaybackEnabled(\n this._peerConnectionId,\n this.id,\n enabled\n );\n }\n\n isPlaybackEnabled(): boolean {\n return this._playbackEnabled;\n }\n\n release(): void {\n if (this.remote) {\n if (this._audioSinkListenerActive) {\n this._audioSinkListenerActive = false;\n WebRTCModule.mediaStreamTrackEnableAudioSink(\n this._peerConnectionId,\n this.id,\n false\n );\n removeListenerForEvent(this, 'audioSamples');\n }\n\n return;\n }\n\n removeListener(this);\n WebRTCModule.mediaStreamTrackRelease(this.id);\n }\n}\n\n/**\n * Define the `onxxx` event handlers.\n */\nconst proto = MediaStreamTrack.prototype;\n\ndefineEventAttribute(proto, 'ended');\ndefineEventAttribute(proto, 'mute');\ndefineEventAttribute(proto, 'unmute');\n"],"mappings":"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"}
@@ -1,8 +1,21 @@
1
1
  import { EventTarget, Event } from 'event-target-shim/index';
2
+ import { type MediaTrackSettings } from './MediaStreamTrack';
2
3
  import { Constraints } from './getUserMedia';
3
4
  declare type MediaDevicesEventMap = {
4
5
  devicechange: Event<'devicechange'>;
5
6
  };
7
+ declare type VirtualTrackInfo = {
8
+ enabled: boolean;
9
+ id: string;
10
+ kind: string;
11
+ readyState: string;
12
+ remote: boolean;
13
+ settings: MediaTrackSettings;
14
+ };
15
+ declare type VirtualAudioResponse = {
16
+ streamId: string;
17
+ tracks: VirtualTrackInfo[];
18
+ };
6
19
  declare class MediaDevices extends EventTarget<MediaDevicesEventMap> {
7
20
  /**
8
21
  * W3C "Media Capture and Streams" compatible {@code enumerateDevices}
@@ -25,6 +38,8 @@ declare class MediaDevices extends EventTarget<MediaDevicesEventMap> {
25
38
  * @returns {Promise}
26
39
  */
27
40
  getUserMedia(constraints: Constraints): Promise<import("./MediaStream").default>;
41
+ createVirtualAudioTrack(): Promise<VirtualAudioResponse>;
42
+ pushVirtualAudioSamples(samples: Int16Array | number[], sampleRate: number, channels: number): void;
28
43
  }
29
44
  declare const _default: MediaDevices;
30
45
  export default _default;
@@ -5,6 +5,8 @@ export declare type AudioSampleData = {
5
5
  samples: number[];
6
6
  sampleRate: number;
7
7
  channels: number;
8
+ bitsPerSample: number;
9
+ framesPerBuffer: number;
8
10
  timestamp: number;
9
11
  };
10
12
  export declare type AudioSinkCallback = (data: AudioSampleData) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sbhjt-gr/react-native-webrtc",
3
- "version": "137.0.3",
3
+ "version": "137.0.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/sbhjt-gr/react-native-webrtc.git"
@@ -64,9 +64,13 @@ export function removeListener(listener: Listener): void {
64
64
 
65
65
  export function removeListenerForEvent(listener: Listener, eventName: string): void {
66
66
  const subs = _subscriptions.get(listener);
67
- if (!subs) return;
68
-
67
+
68
+ if (!subs) {
69
+ return;
70
+ }
71
+
69
72
  const remaining: EmitterSubscription[] = [];
73
+
70
74
  subs.forEach(sub => {
71
75
  if ((sub as any).eventType === eventName) {
72
76
  sub.remove();
@@ -74,7 +78,7 @@ export function removeListenerForEvent(listener: Listener, eventName: string): v
74
78
  remaining.push(sub);
75
79
  }
76
80
  });
77
-
81
+
78
82
  if (remaining.length === 0) {
79
83
  _subscriptions.delete(listener);
80
84
  } else {
@@ -1,6 +1,7 @@
1
1
  import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';
2
2
  import { NativeModules } from 'react-native';
3
3
 
4
+ import { type MediaTrackSettings } from './MediaStreamTrack';
4
5
  import getDisplayMedia from './getDisplayMedia';
5
6
  import getUserMedia, { Constraints } from './getUserMedia';
6
7
 
@@ -10,6 +11,20 @@ type MediaDevicesEventMap = {
10
11
  devicechange: Event<'devicechange'>
11
12
  }
12
13
 
14
+ type VirtualTrackInfo = {
15
+ enabled: boolean;
16
+ id: string;
17
+ kind: string;
18
+ readyState: string;
19
+ remote: boolean;
20
+ settings: MediaTrackSettings;
21
+ }
22
+
23
+ type VirtualAudioResponse = {
24
+ streamId: string;
25
+ tracks: VirtualTrackInfo[];
26
+ }
27
+
13
28
  class MediaDevices extends EventTarget<MediaDevicesEventMap> {
14
29
  /**
15
30
  * W3C "Media Capture and Streams" compatible {@code enumerateDevices}
@@ -40,6 +55,24 @@ class MediaDevices extends EventTarget<MediaDevicesEventMap> {
40
55
  getUserMedia(constraints: Constraints) {
41
56
  return getUserMedia(constraints);
42
57
  }
58
+
59
+ createVirtualAudioTrack(): Promise<VirtualAudioResponse> {
60
+ if (!WebRTCModule.createVirtualAudioTrack) {
61
+ return Promise.reject(new Error('virtual audio unavailable'));
62
+ }
63
+
64
+ return WebRTCModule.createVirtualAudioTrack();
65
+ }
66
+
67
+ pushVirtualAudioSamples(samples: Int16Array | number[], sampleRate: number, channels: number) {
68
+ if (!WebRTCModule.pushVirtualAudioSamples) {
69
+ return;
70
+ }
71
+
72
+ const array = samples instanceof Int16Array ? Array.from(samples) : samples.slice();
73
+
74
+ WebRTCModule.pushVirtualAudioSamples(array, sampleRate, channels);
75
+ }
43
76
  }
44
77
 
45
78
  /**
@@ -1,5 +1,5 @@
1
1
  import { EventTarget, Event, defineEventAttribute } from 'event-target-shim/index';
2
- import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
2
+ import { NativeModules } from 'react-native';
3
3
 
4
4
  import { MediaTrackConstraints } from './Constraints';
5
5
  import { addListener, removeListener, removeListenerForEvent } from './EventEmitter';
@@ -14,6 +14,8 @@ export type AudioSampleData = {
14
14
  samples: number[];
15
15
  sampleRate: number;
16
16
  channels: number;
17
+ bitsPerSample: number;
18
+ framesPerBuffer: number;
17
19
  timestamp: number;
18
20
  }
19
21
 
@@ -234,8 +236,8 @@ export default class MediaStreamTrack extends EventTarget<MediaStreamTrackEventM
234
236
  }
235
237
 
236
238
  private _audioSinkCallback: AudioSinkCallback | null = null;
237
- private _audioSinkListenerActive: boolean = false;
238
- private _playbackEnabled: boolean = true;
239
+ private _audioSinkListenerActive = false;
240
+ private _playbackEnabled = true;
239
241
 
240
242
  _setAudioSinkCallback(callback: AudioSinkCallback | null): void {
241
243
  this._audioSinkCallback = callback;
@@ -313,6 +315,7 @@ export default class MediaStreamTrack extends EventTarget<MediaStreamTrackEventM
313
315
  );
314
316
  removeListenerForEvent(this, 'audioSamples');
315
317
  }
318
+
316
319
  return;
317
320
  }
318
321