mediasoup-client 3.6.53 → 3.6.56

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.
Files changed (60) hide show
  1. package/lib/Consumer.d.ts.map +1 -1
  2. package/lib/Consumer.js +8 -0
  3. package/lib/EnhancedEventEmitter.d.ts +1 -1
  4. package/lib/EnhancedEventEmitter.d.ts.map +1 -1
  5. package/lib/Producer.d.ts +8 -0
  6. package/lib/Producer.d.ts.map +1 -1
  7. package/lib/Producer.js +2 -2
  8. package/lib/Transport.d.ts +3 -0
  9. package/lib/Transport.d.ts.map +1 -1
  10. package/lib/Transport.js +72 -11
  11. package/lib/handlers/Chrome55.d.ts +3 -1
  12. package/lib/handlers/Chrome55.d.ts.map +1 -1
  13. package/lib/handlers/Chrome55.js +17 -6
  14. package/lib/handlers/Chrome67.d.ts +3 -1
  15. package/lib/handlers/Chrome67.d.ts.map +1 -1
  16. package/lib/handlers/Chrome67.js +17 -6
  17. package/lib/handlers/Chrome70.d.ts +3 -1
  18. package/lib/handlers/Chrome70.d.ts.map +1 -1
  19. package/lib/handlers/Chrome70.js +20 -7
  20. package/lib/handlers/Chrome74.d.ts +3 -1
  21. package/lib/handlers/Chrome74.d.ts.map +1 -1
  22. package/lib/handlers/Chrome74.js +40 -7
  23. package/lib/handlers/Edge11.d.ts +3 -1
  24. package/lib/handlers/Edge11.d.ts.map +1 -1
  25. package/lib/handlers/Edge11.js +23 -12
  26. package/lib/handlers/FakeHandler.d.ts +3 -1
  27. package/lib/handlers/FakeHandler.d.ts.map +1 -1
  28. package/lib/handlers/FakeHandler.js +14 -3
  29. package/lib/handlers/Firefox60.d.ts +3 -1
  30. package/lib/handlers/Firefox60.d.ts.map +1 -1
  31. package/lib/handlers/Firefox60.js +42 -7
  32. package/lib/handlers/HandlerInterface.d.ts +4 -1
  33. package/lib/handlers/HandlerInterface.d.ts.map +1 -1
  34. package/lib/handlers/ReactNative.d.ts +3 -1
  35. package/lib/handlers/ReactNative.d.ts.map +1 -1
  36. package/lib/handlers/ReactNative.js +17 -6
  37. package/lib/handlers/Safari11.d.ts +3 -1
  38. package/lib/handlers/Safari11.d.ts.map +1 -1
  39. package/lib/handlers/Safari11.js +17 -6
  40. package/lib/handlers/Safari12.d.ts +3 -1
  41. package/lib/handlers/Safari12.d.ts.map +1 -1
  42. package/lib/handlers/Safari12.js +42 -7
  43. package/lib/index.d.ts +1 -1
  44. package/lib/index.js +1 -1
  45. package/package.json +6 -6
  46. package/src/Consumer.ts +14 -0
  47. package/src/EnhancedEventEmitter.ts +1 -1
  48. package/src/Producer.ts +10 -4
  49. package/src/Transport.ts +112 -19
  50. package/src/handlers/Chrome55.ts +24 -7
  51. package/src/handlers/Chrome67.ts +24 -7
  52. package/src/handlers/Chrome70.ts +27 -7
  53. package/src/handlers/Chrome74.ts +75 -7
  54. package/src/handlers/Edge11.ts +31 -14
  55. package/src/handlers/FakeHandler.ts +19 -3
  56. package/src/handlers/Firefox60.ts +77 -7
  57. package/src/handlers/HandlerInterface.ts +6 -1
  58. package/src/handlers/ReactNative.ts +24 -7
  59. package/src/handlers/Safari11.ts +24 -7
  60. package/src/handlers/Safari12.ts +77 -7
@@ -66,6 +66,7 @@ class Safari12 extends HandlerInterface_1.HandlerInterface {
66
66
  }
67
67
  catch (error) { }
68
68
  }
69
+ this.emit('@close');
69
70
  }
70
71
  async getNativeRtpCapabilities() {
71
72
  logger.debug('getNativeRtpCapabilities()');
@@ -284,6 +285,36 @@ class Safari12 extends HandlerInterface_1.HandlerInterface {
284
285
  await this._pc.setRemoteDescription(answer);
285
286
  this._mapMidTransceiver.delete(localId);
286
287
  }
288
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
289
+ async pauseSending(localId) {
290
+ this._assertSendDirection();
291
+ logger.debug('pauseSending() [localId:%s]', localId);
292
+ const transceiver = this._mapMidTransceiver.get(localId);
293
+ if (!transceiver)
294
+ throw new Error('associated RTCRtpTransceiver not found');
295
+ transceiver.direction = 'inactive';
296
+ const offer = await this._pc.createOffer();
297
+ logger.debug('pauseSending() | calling pc.setLocalDescription() [offer:%o]', offer);
298
+ await this._pc.setLocalDescription(offer);
299
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
300
+ logger.debug('pauseSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
301
+ await this._pc.setRemoteDescription(answer);
302
+ }
303
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
304
+ async resumeSending(localId) {
305
+ this._assertSendDirection();
306
+ logger.debug('resumeSending() [localId:%s]', localId);
307
+ const transceiver = this._mapMidTransceiver.get(localId);
308
+ if (!transceiver)
309
+ throw new Error('associated RTCRtpTransceiver not found');
310
+ transceiver.direction = 'sendonly';
311
+ const offer = await this._pc.createOffer();
312
+ logger.debug('resumeSending() | calling pc.setLocalDescription() [offer:%o]', offer);
313
+ await this._pc.setLocalDescription(offer);
314
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
315
+ logger.debug('resumeSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
316
+ await this._pc.setRemoteDescription(answer);
317
+ }
287
318
  async replaceTrack(localId, track) {
288
319
  this._assertSendDirection();
289
320
  if (track) {
@@ -437,20 +468,24 @@ class Safari12 extends HandlerInterface_1.HandlerInterface {
437
468
  }
438
469
  return results;
439
470
  }
440
- async stopReceiving(localId) {
471
+ async stopReceiving(localIds) {
441
472
  this._assertRecvDirection();
442
- logger.debug('stopReceiving() [localId:%s]', localId);
443
- const transceiver = this._mapMidTransceiver.get(localId);
444
- if (!transceiver)
445
- throw new Error('associated RTCRtpTransceiver not found');
446
- this._remoteSdp.closeMediaSection(transceiver.mid);
473
+ for (const localId of localIds) {
474
+ logger.debug('stopReceiving() [localId:%s]', localId);
475
+ const transceiver = this._mapMidTransceiver.get(localId);
476
+ if (!transceiver)
477
+ throw new Error('associated RTCRtpTransceiver not found');
478
+ this._remoteSdp.closeMediaSection(transceiver.mid);
479
+ }
447
480
  const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
448
481
  logger.debug('stopReceiving() | calling pc.setRemoteDescription() [offer:%o]', offer);
449
482
  await this._pc.setRemoteDescription(offer);
450
483
  const answer = await this._pc.createAnswer();
451
484
  logger.debug('stopReceiving() | calling pc.setLocalDescription() [answer:%o]', answer);
452
485
  await this._pc.setLocalDescription(answer);
453
- this._mapMidTransceiver.delete(localId);
486
+ for (const localId of localIds) {
487
+ this._mapMidTransceiver.delete(localId);
488
+ }
454
489
  }
455
490
  async pauseReceiving(localIds) {
456
491
  this._assertRecvDirection();
package/lib/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { types };
8
8
  /**
9
9
  * Expose mediasoup-client version.
10
10
  */
11
- export declare const version = "3.6.53";
11
+ export declare const version = "3.6.56";
12
12
  /**
13
13
  * Expose Device class and detectDevice() helper.
14
14
  */
package/lib/index.js CHANGED
@@ -37,7 +37,7 @@ exports.types = types;
37
37
  /**
38
38
  * Expose mediasoup-client version.
39
39
  */
40
- exports.version = '3.6.53';
40
+ exports.version = '3.6.56';
41
41
  /**
42
42
  * Expose parseScalabilityMode() function.
43
43
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediasoup-client",
3
- "version": "3.6.53",
3
+ "version": "3.6.56",
4
4
  "description": "mediasoup client side JavaScript library",
5
5
  "contributors": [
6
6
  "Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
@@ -49,11 +49,11 @@
49
49
  "devDependencies": {
50
50
  "@types/sdp-transform": "^2.4.5",
51
51
  "@types/uuid": "^3.4.9",
52
- "@typescript-eslint/eslint-plugin": "^5.30.0",
53
- "@typescript-eslint/parser": "^5.30.0",
54
- "eslint": "^8.18.0",
55
- "eslint-plugin-jest": "^26.5.3",
56
- "jest": "^28.1.2",
52
+ "@typescript-eslint/eslint-plugin": "^5.33.1",
53
+ "@typescript-eslint/parser": "^5.33.1",
54
+ "eslint": "^8.22.0",
55
+ "eslint-plugin-jest": "^26.8.3",
56
+ "jest": "^28.1.3",
57
57
  "jest-tobetype": "^1.2.3",
58
58
  "open-cli": "^7.0.1",
59
59
  "tsc-watch": "^5.0.3",
package/src/Consumer.ts CHANGED
@@ -260,6 +260,13 @@ export class Consumer extends EnhancedEventEmitter<ConsumerEvents>
260
260
  return;
261
261
  }
262
262
 
263
+ if (this._paused)
264
+ {
265
+ logger.debug('pause() | Consumer is already paused');
266
+
267
+ return;
268
+ }
269
+
263
270
  this._paused = true;
264
271
  this._track.enabled = false;
265
272
 
@@ -283,6 +290,13 @@ export class Consumer extends EnhancedEventEmitter<ConsumerEvents>
283
290
  return;
284
291
  }
285
292
 
293
+ if (!this._paused)
294
+ {
295
+ logger.debug('resume() | Consumer is already resumed');
296
+
297
+ return;
298
+ }
299
+
286
300
  this._paused = false;
287
301
  this._track.enabled = true;
288
302
 
@@ -109,7 +109,7 @@ export class EnhancedEventEmitter<E extends Events = Events> extends EventEmitte
109
109
  return this;
110
110
  }
111
111
 
112
- removeAllListeners<K extends keyof E & string>(eventName: K): this
112
+ removeAllListeners<K extends keyof E & string>(eventName?: K): this
113
113
  {
114
114
  super.removeAllListeners(eventName);
115
115
 
package/src/Producer.ts CHANGED
@@ -41,6 +41,14 @@ export type ProducerEvents =
41
41
  transportclose: [];
42
42
  trackended: [];
43
43
  // Private events.
44
+ '@pause': [
45
+ () => void,
46
+ (error: Error) => void
47
+ ];
48
+ '@resume': [
49
+ () => void,
50
+ (error: Error) => void
51
+ ];
44
52
  '@replacetrack':
45
53
  [
46
54
  MediaStreamTrack | null,
@@ -331,8 +339,7 @@ export class Producer extends EnhancedEventEmitter<ProducerEvents>
331
339
  new Promise<void>((resolve, reject) =>
332
340
  {
333
341
  this.safeEmit(
334
- '@replacetrack',
335
- null,
342
+ '@pause',
336
343
  resolve,
337
344
  reject
338
345
  );
@@ -369,8 +376,7 @@ export class Producer extends EnhancedEventEmitter<ProducerEvents>
369
376
  new Promise<void>((resolve, reject) =>
370
377
  {
371
378
  this.safeEmit(
372
- '@replacetrack',
373
- this._track,
379
+ '@resume',
374
380
  resolve,
375
381
  reject
376
382
  );
package/src/Transport.ts CHANGED
@@ -232,6 +232,10 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
232
232
  private _pendingResumeConsumers: Map<string, Consumer> = new Map();
233
233
  // Consumer resume in progress flag.
234
234
  private _consumerResumeInProgress = false;
235
+ // Consumers pending to be closed.
236
+ private _pendingCloseConsumers: Map<string, Consumer> = new Map();
237
+ // Consumer close in progress flag.
238
+ private _consumerCloseInProgress = false;
235
239
  // Observer instance.
236
240
  protected readonly _observer = new EnhancedEventEmitter<TransportObserverEvents>();
237
241
 
@@ -821,10 +825,17 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
821
825
  // This method is guaranteed to never throw.
822
826
  async _createPendingConsumers(): Promise<void>
823
827
  {
828
+ this._consumerCreationInProgress = true;
829
+
824
830
  this._awaitQueue.push(
825
831
  async () =>
826
832
  {
827
- this._consumerCreationInProgress = true;
833
+ if (this._pendingConsumerTasks.length === 0)
834
+ {
835
+ logger.debug('_createPendingConsumers() | there is no Consumer to be created');
836
+
837
+ return;
838
+ }
828
839
 
829
840
  const pendingConsumerTasks = [ ...this._pendingConsumerTasks ];
830
841
 
@@ -919,12 +930,12 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
919
930
  error);
920
931
  }
921
932
  }
922
-
923
- this._consumerCreationInProgress = false;
924
933
  },
925
934
  'transport._createPendingConsumers()')
926
935
  .then(() =>
927
936
  {
937
+ this._consumerCreationInProgress = false;
938
+
928
939
  // There are pending Consumer tasks, enqueue their creation.
929
940
  if (this._pendingConsumerTasks.length > 0)
930
941
  {
@@ -937,10 +948,17 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
937
948
 
938
949
  _pausePendingConsumers()
939
950
  {
951
+ this._consumerPauseInProgress = true;
952
+
940
953
  this._awaitQueue.push(
941
954
  async () =>
942
955
  {
943
- this._consumerPauseInProgress = true;
956
+ if (this._pendingPauseConsumers.size === 0)
957
+ {
958
+ logger.debug('_pausePendingConsumers() | there is no Consumer to be paused');
959
+
960
+ return;
961
+ }
944
962
 
945
963
  const pendingPauseConsumers = Array.from(this._pendingPauseConsumers.values());
946
964
 
@@ -949,20 +967,21 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
949
967
 
950
968
  try
951
969
  {
952
- await this._handler.pauseReceiving(
953
- pendingPauseConsumers.map((consumer) => consumer.localId)
954
- );
970
+ const localIds = pendingPauseConsumers
971
+ .map((consumer) => consumer.localId);
972
+
973
+ await this._handler.pauseReceiving(localIds);
955
974
  }
956
975
  catch (error)
957
976
  {
958
977
  logger.error('_pausePendingConsumers() | failed to pause Consumers:', error);
959
978
  }
960
-
961
- this._consumerPauseInProgress = false;
962
979
  },
963
- 'consumer @pause event')
980
+ 'transport._pausePendingConsumers')
964
981
  .then(() =>
965
982
  {
983
+ this._consumerPauseInProgress = false;
984
+
966
985
  // There are pending Consumers to be paused, do it.
967
986
  if (this._pendingPauseConsumers.size > 0)
968
987
  {
@@ -975,10 +994,17 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
975
994
 
976
995
  _resumePendingConsumers()
977
996
  {
997
+ this._consumerResumeInProgress = true;
998
+
978
999
  this._awaitQueue.push(
979
1000
  async () =>
980
1001
  {
981
- this._consumerResumeInProgress = true;
1002
+ if (this._pendingResumeConsumers.size === 0)
1003
+ {
1004
+ logger.debug('_resumePendingConsumers() | there is no Consumer to be resumed');
1005
+
1006
+ return;
1007
+ }
982
1008
 
983
1009
  const pendingResumeConsumers = Array.from(this._pendingResumeConsumers.values());
984
1010
 
@@ -987,16 +1013,17 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
987
1013
 
988
1014
  try
989
1015
  {
990
- await this._handler.resumeReceiving(
991
- pendingResumeConsumers.map((consumer) => consumer.localId)
992
- );
1016
+ const localIds = pendingResumeConsumers
1017
+ .map((consumer) => consumer.localId);
1018
+
1019
+ await this._handler.resumeReceiving(localIds);
993
1020
  }
994
1021
  catch (error)
995
1022
  {
996
1023
  logger.error('_resumePendingConsumers() | failed to resume Consumers:', error);
997
1024
  }
998
1025
  },
999
- 'consumer @resume event')
1026
+ 'transport._resumePendingConsumers')
1000
1027
  .then(() =>
1001
1028
  {
1002
1029
  this._consumerResumeInProgress = false;
@@ -1011,6 +1038,50 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
1011
1038
  .catch(() => { });
1012
1039
  }
1013
1040
 
1041
+ _closePendingConsumers()
1042
+ {
1043
+ this._consumerCloseInProgress = true;
1044
+
1045
+ this._awaitQueue.push(
1046
+ async () =>
1047
+ {
1048
+ if (this._pendingCloseConsumers.size === 0)
1049
+ {
1050
+ logger.debug('_closePendingConsumers() | there is no Consumer to be closed');
1051
+
1052
+ return;
1053
+ }
1054
+
1055
+ const pendingCloseConsumers = Array.from(this._pendingCloseConsumers.values());
1056
+
1057
+ // Clear pending close Consumer map.
1058
+ this._pendingCloseConsumers.clear();
1059
+
1060
+ try
1061
+ {
1062
+ await this._handler.stopReceiving(
1063
+ pendingCloseConsumers.map((consumer) => consumer.localId)
1064
+ );
1065
+ }
1066
+ catch (error)
1067
+ {
1068
+ logger.error('_closePendingConsumers() | failed to close Consumers:', error);
1069
+ }
1070
+ },
1071
+ 'transport._closePendingConsumers')
1072
+ .then(() =>
1073
+ {
1074
+ this._consumerCloseInProgress = false;
1075
+
1076
+ // There are pending Consumer to be resumed, do it.
1077
+ if (this._pendingCloseConsumers.size > 0)
1078
+ {
1079
+ this._closePendingConsumers();
1080
+ }
1081
+ })
1082
+ // NOTE: We only get here when the await queue is closed.
1083
+ .catch(() => { });
1084
+ }
1014
1085
  _handleHandler(): void
1015
1086
  {
1016
1087
  const handler = this._handler;
@@ -1060,6 +1131,24 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
1060
1131
  .catch((error: Error) => logger.warn('producer.close() failed:%o', error));
1061
1132
  });
1062
1133
 
1134
+ producer.on('@pause', (callback, errback) =>
1135
+ {
1136
+ this._awaitQueue.push(
1137
+ async () => this._handler.pauseSending(producer.localId),
1138
+ 'producer @pause event')
1139
+ .then(callback)
1140
+ .catch(errback);
1141
+ });
1142
+
1143
+ producer.on('@resume', (callback, errback) =>
1144
+ {
1145
+ this._awaitQueue.push(
1146
+ async () => this._handler.resumeSending(producer.localId),
1147
+ 'producer @resume event')
1148
+ .then(callback)
1149
+ .catch(errback);
1150
+ });
1151
+
1063
1152
  producer.on('@replacetrack', (track, callback, errback) =>
1064
1153
  {
1065
1154
  this._awaitQueue.push(
@@ -1111,10 +1200,14 @@ export class Transport extends EnhancedEventEmitter<TransportEvents>
1111
1200
  if (this._closed)
1112
1201
  return;
1113
1202
 
1114
- this._awaitQueue.push(
1115
- async () => this._handler.stopReceiving(consumer.localId),
1116
- 'consumer @close event')
1117
- .catch(() => {});
1203
+ // Store the Consumer into the close list.
1204
+ this._pendingCloseConsumers.set(consumer.id, consumer);
1205
+
1206
+ // There is no Consumer close in progress, do it now.
1207
+ if (this._consumerCloseInProgress === false)
1208
+ {
1209
+ this._closePendingConsumers();
1210
+ }
1118
1211
  });
1119
1212
 
1120
1213
  consumer.on('@pause', () =>
@@ -94,6 +94,8 @@ export class Chrome55 extends HandlerInterface
94
94
  try { this._pc.close(); }
95
95
  catch (error) {}
96
96
  }
97
+
98
+ this.emit('@close');
97
99
  }
98
100
 
99
101
  async getNativeRtpCapabilities(): Promise<RtpCapabilities>
@@ -474,6 +476,18 @@ export class Chrome55 extends HandlerInterface
474
476
  await this._pc.setRemoteDescription(answer);
475
477
  }
476
478
 
479
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
480
+ async pauseSending(localId: string): Promise<void>
481
+ {
482
+ // Unimplemented.
483
+ }
484
+
485
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
486
+ async resumeSending(localId: string): Promise<void>
487
+ {
488
+ // Unimplemented.
489
+ }
490
+
477
491
  async replaceTrack(
478
492
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
479
493
  localId: string, track: MediaStreamTrack | null
@@ -672,19 +686,22 @@ export class Chrome55 extends HandlerInterface
672
686
  return results;
673
687
  }
674
688
 
675
- async stopReceiving(localId: string): Promise<void>
689
+ async stopReceiving(localIds: string[]): Promise<void>
676
690
  {
677
691
  this._assertRecvDirection();
678
692
 
679
- logger.debug('stopReceiving() [localId:%s]', localId);
693
+ for (const localId of localIds)
694
+ {
695
+ logger.debug('stopReceiving() [localId:%s]', localId);
680
696
 
681
- const { mid, rtpParameters } = this._mapRecvLocalIdInfo.get(localId) || {};
697
+ const { mid, rtpParameters } = this._mapRecvLocalIdInfo.get(localId) || {};
682
698
 
683
- // Remove from the map.
684
- this._mapRecvLocalIdInfo.delete(localId);
699
+ // Remove from the map.
700
+ this._mapRecvLocalIdInfo.delete(localId);
685
701
 
686
- this._remoteSdp!.planBStopReceiving(
687
- { mid: mid!, offerRtpParameters: rtpParameters! });
702
+ this._remoteSdp!.planBStopReceiving(
703
+ { mid: mid!, offerRtpParameters: rtpParameters! });
704
+ }
688
705
 
689
706
  const offer = { type: 'offer', sdp: this._remoteSdp!.getSdp() };
690
707
 
@@ -95,6 +95,8 @@ export class Chrome67 extends HandlerInterface
95
95
  try { this._pc.close(); }
96
96
  catch (error) {}
97
97
  }
98
+
99
+ this.emit('@close');
98
100
  }
99
101
 
100
102
  async getNativeRtpCapabilities(): Promise<RtpCapabilities>
@@ -482,6 +484,18 @@ export class Chrome67 extends HandlerInterface
482
484
  await this._pc.setRemoteDescription(answer);
483
485
  }
484
486
 
487
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
488
+ async pauseSending(localId: string): Promise<void>
489
+ {
490
+ // Unimplemented.
491
+ }
492
+
493
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
494
+ async resumeSending(localId: string): Promise<void>
495
+ {
496
+ // Unimplemented.
497
+ }
498
+
485
499
  async replaceTrack(
486
500
  localId: string, track: MediaStreamTrack | null
487
501
  ): Promise<void>
@@ -751,19 +765,22 @@ export class Chrome67 extends HandlerInterface
751
765
  return results;
752
766
  }
753
767
 
754
- async stopReceiving(localId: string): Promise<void>
768
+ async stopReceiving(localIds: string[]): Promise<void>
755
769
  {
756
770
  this._assertRecvDirection();
757
771
 
758
- logger.debug('stopReceiving() [localId:%s]', localId);
772
+ for (const localId of localIds)
773
+ {
774
+ logger.debug('stopReceiving() [localId:%s]', localId);
759
775
 
760
- const { mid, rtpParameters } = this._mapRecvLocalIdInfo.get(localId) || {};
776
+ const { mid, rtpParameters } = this._mapRecvLocalIdInfo.get(localId) || {};
761
777
 
762
- // Remove from the map.
763
- this._mapRecvLocalIdInfo.delete(localId);
778
+ // Remove from the map.
779
+ this._mapRecvLocalIdInfo.delete(localId);
764
780
 
765
- this._remoteSdp!.planBStopReceiving(
766
- { mid: mid!, offerRtpParameters: rtpParameters! });
781
+ this._remoteSdp!.planBStopReceiving(
782
+ { mid: mid!, offerRtpParameters: rtpParameters! });
783
+ }
767
784
 
768
785
  const offer = { type: 'offer', sdp: this._remoteSdp!.getSdp() };
769
786
 
@@ -83,6 +83,8 @@ export class Chrome70 extends HandlerInterface
83
83
  try { this._pc.close(); }
84
84
  catch (error) {}
85
85
  }
86
+
87
+ this.emit('@close');
86
88
  }
87
89
 
88
90
  async getNativeRtpCapabilities(): Promise<RtpCapabilities>
@@ -498,6 +500,18 @@ export class Chrome70 extends HandlerInterface
498
500
  this._mapMidTransceiver.delete(localId);
499
501
  }
500
502
 
503
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
504
+ async pauseSending(localId: string): Promise<void>
505
+ {
506
+ // Unimplemented.
507
+ }
508
+
509
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
510
+ async resumeSending(localId: string): Promise<void>
511
+ {
512
+ // Unimplemented.
513
+ }
514
+
501
515
  async replaceTrack(
502
516
  localId: string, track: MediaStreamTrack | null
503
517
  ): Promise<void>
@@ -758,18 +772,21 @@ export class Chrome70 extends HandlerInterface
758
772
  return results;
759
773
  }
760
774
 
761
- async stopReceiving(localId: string): Promise<void>
775
+ async stopReceiving(localIds: string[]): Promise<void>
762
776
  {
763
777
  this._assertRecvDirection();
764
778
 
765
- logger.debug('stopReceiving() [localId:%s]', localId);
779
+ for (const localId of localIds)
780
+ {
781
+ logger.debug('stopReceiving() [localId:%s]', localId);
766
782
 
767
- const transceiver = this._mapMidTransceiver.get(localId);
783
+ const transceiver = this._mapMidTransceiver.get(localId);
768
784
 
769
- if (!transceiver)
770
- throw new Error('associated RTCRtpTransceiver not found');
785
+ if (!transceiver)
786
+ throw new Error('associated RTCRtpTransceiver not found');
771
787
 
772
- this._remoteSdp!.closeMediaSection(transceiver.mid!);
788
+ this._remoteSdp!.closeMediaSection(transceiver.mid!);
789
+ }
773
790
 
774
791
  const offer = { type: 'offer', sdp: this._remoteSdp!.getSdp() };
775
792
 
@@ -787,7 +804,10 @@ export class Chrome70 extends HandlerInterface
787
804
 
788
805
  await this._pc.setLocalDescription(answer);
789
806
 
790
- this._mapMidTransceiver.delete(localId);
807
+ for (const localId of localIds)
808
+ {
809
+ this._mapMidTransceiver.delete(localId);
810
+ }
791
811
  }
792
812
 
793
813
  async pauseReceiving(