@webex/web-client-media-engine 3.11.0 → 3.11.2

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.
package/dist/cjs/index.js CHANGED
@@ -490,6 +490,7 @@ exports.WebrtcCoreErrorType = void 0;
490
490
  (function (WebrtcCoreErrorType) {
491
491
  WebrtcCoreErrorType["DEVICE_PERMISSION_DENIED"] = "DEVICE_PERMISSION_DENIED";
492
492
  WebrtcCoreErrorType["CREATE_STREAM_FAILED"] = "CREATE_STREAM_FAILED";
493
+ WebrtcCoreErrorType["ADD_EFFECT_FAILED"] = "ADD_EFFECT_FAILED";
493
494
  })(exports.WebrtcCoreErrorType || (exports.WebrtcCoreErrorType = {}));
494
495
  /**
495
496
  * Represents a WebRTC core error, which contains error type and error message.
@@ -1250,11 +1251,12 @@ class _Stream {
1250
1251
  _a$1$1 = exports.StreamEventNames.MuteStateChange, _b$1 = exports.StreamEventNames.Ended;
1251
1252
  const Stream = AddEvents(_Stream);
1252
1253
 
1253
- var _a$6, _b;
1254
+ var _a$6, _b, _c;
1254
1255
  exports.LocalStreamEventNames = void 0;
1255
1256
  (function (LocalStreamEventNames) {
1256
1257
  LocalStreamEventNames["ConstraintsChange"] = "constraints-change";
1257
1258
  LocalStreamEventNames["OutputTrackChange"] = "output-track-change";
1259
+ LocalStreamEventNames["EffectAdded"] = "effect-added";
1258
1260
  })(exports.LocalStreamEventNames || (exports.LocalStreamEventNames = {}));
1259
1261
  /**
1260
1262
  * A stream which originates on the local device.
@@ -1269,6 +1271,7 @@ class _LocalStream extends Stream {
1269
1271
  super(stream);
1270
1272
  this[_a$6] = new TypedEvent$1();
1271
1273
  this[_b] = new TypedEvent$1();
1274
+ this[_c] = new TypedEvent$1();
1272
1275
  this.effects = [];
1273
1276
  this.loadingEffects = new Map();
1274
1277
  this.inputStream = stream;
@@ -1282,11 +1285,30 @@ class _LocalStream extends Stream {
1282
1285
  get inputTrack() {
1283
1286
  return this.inputStream.getTracks()[0];
1284
1287
  }
1288
+ /**
1289
+ * @inheritdoc
1290
+ */
1291
+ handleTrackMuted() {
1292
+ if (this.inputTrack.enabled) {
1293
+ super.handleTrackMuted();
1294
+ }
1295
+ }
1296
+ /**
1297
+ * @inheritdoc
1298
+ */
1299
+ handleTrackUnmuted() {
1300
+ if (this.inputTrack.enabled) {
1301
+ super.handleTrackUnmuted();
1302
+ }
1303
+ }
1285
1304
  /**
1286
1305
  * @inheritdoc
1287
1306
  */
1288
1307
  get muted() {
1289
- return !this.inputTrack.enabled;
1308
+ // Calls to `setMuted` will only affect the "enabled" state, but there are specific cases in
1309
+ // which the browser may mute the track, which will affect the "muted" state but not the
1310
+ // "enabled" state, e.g. minimizing a shared window or unplugging a shared screen.
1311
+ return !this.inputTrack.enabled || this.inputTrack.muted;
1290
1312
  }
1291
1313
  /**
1292
1314
  * Set the mute state of this stream.
@@ -1297,7 +1319,9 @@ class _LocalStream extends Stream {
1297
1319
  if (this.inputTrack.enabled === isMuted) {
1298
1320
  this.inputTrack.enabled = !isMuted;
1299
1321
  // setting `enabled` will not automatically emit MuteStateChange, so we emit it here
1300
- this[exports.StreamEventNames.MuteStateChange].emit(isMuted);
1322
+ if (!this.inputTrack.muted) {
1323
+ this[exports.StreamEventNames.MuteStateChange].emit(isMuted);
1324
+ }
1301
1325
  }
1302
1326
  }
1303
1327
  /**
@@ -1360,55 +1384,110 @@ class _LocalStream extends Stream {
1360
1384
  /**
1361
1385
  * Adds an effect to a local stream.
1362
1386
  *
1363
- * @param name - The name of the effect.
1364
1387
  * @param effect - The effect to add.
1365
1388
  */
1366
- addEffect(name, effect) {
1389
+ addEffect(effect) {
1367
1390
  return __awaiter$2(this, void 0, void 0, function* () {
1368
- // Load the effect
1369
- this.loadingEffects.set(name, effect);
1370
- const outputTrack = yield effect.load(this.outputTrack);
1371
- // Check that the loaded effect is the latest one and dispose if not
1372
- if (effect !== this.loadingEffects.get(name)) {
1391
+ // Check if the effect has already been added.
1392
+ if (this.effects.some((e) => e.id === effect.id)) {
1393
+ return;
1394
+ }
1395
+ // Load the effect. Because loading is asynchronous, keep track of the loading effects.
1396
+ this.loadingEffects.set(effect.kind, effect);
1397
+ yield effect.load(this.outputTrack);
1398
+ // After loading, check whether or not we still want to use this effect. If another effect of
1399
+ // the same kind was added while this effect was loading, we only want to use the latest effect,
1400
+ // so dispose this one. If the effects list was cleared while this effect was loading, also
1401
+ // dispose it.
1402
+ if (effect !== this.loadingEffects.get(effect.kind)) {
1373
1403
  yield effect.dispose();
1374
- throw new Error(`Effect "${name}" not required after loading`);
1404
+ throw new WebrtcCoreError(exports.WebrtcCoreErrorType.ADD_EFFECT_FAILED, `Another effect with kind ${effect.kind} was added while effect ${effect.id} was loading, or the effects list was cleared.`);
1375
1405
  }
1376
- // Use the effect
1377
- this.loadingEffects.delete(name);
1378
- this.effects.push({ name, effect });
1379
- this.changeOutputTrack(outputTrack);
1380
- // When the effect's track is updated, update the next effect or output stream.
1381
- // TODO: using EffectEvent.TrackUpdated will cause the entire web-media-effects lib to be built
1382
- // and makes the size of the webrtc-core build much larger, so we use type assertion here as a
1383
- // temporary workaround.
1384
- effect.on('track-updated', (track) => {
1385
- var _c;
1386
- const effectIndex = this.effects.findIndex((e) => e.name === name);
1406
+ this.loadingEffects.delete(effect.kind);
1407
+ /**
1408
+ * Handle when the effect's output track has been changed. This will update the input of the
1409
+ * next effect in the effects list of the output of the stream.
1410
+ *
1411
+ * @param track - The new output track of the effect.
1412
+ */
1413
+ const handleEffectTrackUpdated = (track) => {
1414
+ var _d;
1415
+ const effectIndex = this.effects.findIndex((e) => e.id === effect.id);
1387
1416
  if (effectIndex === this.effects.length - 1) {
1388
1417
  this.changeOutputTrack(track);
1389
1418
  }
1419
+ else if (effectIndex >= 0) {
1420
+ (_d = this.effects[effectIndex + 1]) === null || _d === void 0 ? void 0 : _d.replaceInputTrack(track);
1421
+ }
1390
1422
  else {
1391
- (_c = this.effects[effectIndex + 1]) === null || _c === void 0 ? void 0 : _c.effect.replaceInputTrack(track);
1423
+ logger$3.error(`Effect with ID ${effect.id} not found in effects list.`);
1392
1424
  }
1393
- });
1425
+ };
1426
+ /**
1427
+ * Handle when the effect has been disposed. This will remove all event listeners from the
1428
+ * effect.
1429
+ */
1430
+ const handleEffectDisposed = () => {
1431
+ effect.off('track-updated', handleEffectTrackUpdated);
1432
+ effect.off('disposed', handleEffectDisposed);
1433
+ };
1434
+ // TODO: using EffectEvent.TrackUpdated or EffectEvent.Disposed will cause the entire
1435
+ // web-media-effects lib to be rebuilt and inflates the size of the webrtc-core build, so
1436
+ // we use type assertion here as a temporary workaround.
1437
+ effect.on('track-updated', handleEffectTrackUpdated);
1438
+ effect.on('disposed', handleEffectDisposed);
1439
+ // Add the effect to the effects list. If an effect of the same kind has already been added,
1440
+ // dispose the existing effect and replace it with the new effect. If the existing effect was
1441
+ // enabled, also enable the new effect.
1442
+ const existingEffectIndex = this.effects.findIndex((e) => e.kind === effect.kind);
1443
+ if (existingEffectIndex >= 0) {
1444
+ const [existingEffect] = this.effects.splice(existingEffectIndex, 1, effect);
1445
+ if (existingEffect.isEnabled) {
1446
+ // If the existing effect is not the first effect in the effects list, then the input of the
1447
+ // new effect should be the output of the previous effect in the effects list. We know the
1448
+ // output track of the previous effect must exist because it must have been loaded (and all
1449
+ // loaded effects have an output track).
1450
+ const inputTrack = existingEffectIndex === 0
1451
+ ? this.inputTrack
1452
+ : this.effects[existingEffectIndex - 1].getOutputTrack();
1453
+ yield effect.replaceInputTrack(inputTrack);
1454
+ // Enabling the new effect will trigger the track-updated event, which will handle the new
1455
+ // effect's updated output track.
1456
+ yield effect.enable();
1457
+ }
1458
+ yield existingEffect.dispose();
1459
+ }
1460
+ else {
1461
+ this.effects.push(effect);
1462
+ }
1463
+ // Emit an event with the effect so others can listen to the effect events.
1464
+ this[exports.LocalStreamEventNames.EffectAdded].emit(effect);
1394
1465
  });
1395
1466
  }
1396
1467
  /**
1397
- * Get an effect from the effects list.
1468
+ * Get an effect from the effects list by ID.
1398
1469
  *
1399
- * @param name - The name of the effect you want to get.
1470
+ * @param id - The id of the effect you want to get.
1400
1471
  * @returns The effect or undefined.
1401
1472
  */
1402
- getEffect(name) {
1403
- var _c;
1404
- return (_c = this.effects.find((e) => e.name === name)) === null || _c === void 0 ? void 0 : _c.effect;
1473
+ getEffectById(id) {
1474
+ return this.effects.find((effect) => effect.id === id);
1475
+ }
1476
+ /**
1477
+ * Get an effect from the effects list by kind.
1478
+ *
1479
+ * @param kind - The kind of the effect you want to get.
1480
+ * @returns The effect or undefined.
1481
+ */
1482
+ getEffectByKind(kind) {
1483
+ return this.effects.find((effect) => effect.kind === kind);
1405
1484
  }
1406
1485
  /**
1407
1486
  * Get all the effects from the effects list.
1408
1487
  *
1409
- * @returns A list of effect items, each containing the name and the effect itself.
1488
+ * @returns A list of effects.
1410
1489
  */
1411
- getAllEffects() {
1490
+ getEffects() {
1412
1491
  return this.effects;
1413
1492
  }
1414
1493
  /**
@@ -1420,13 +1499,13 @@ class _LocalStream extends Stream {
1420
1499
  // Dispose of any effects currently in use
1421
1500
  if (this.effects.length > 0) {
1422
1501
  this.changeOutputTrack(this.inputTrack);
1423
- yield Promise.all(this.effects.map((item) => item.effect.dispose()));
1502
+ yield Promise.all(this.effects.map((effect) => effect.dispose()));
1424
1503
  this.effects = [];
1425
1504
  }
1426
1505
  });
1427
1506
  }
1428
1507
  }
1429
- _a$6 = exports.LocalStreamEventNames.ConstraintsChange, _b = exports.LocalStreamEventNames.OutputTrackChange;
1508
+ _a$6 = exports.LocalStreamEventNames.ConstraintsChange, _b = exports.LocalStreamEventNames.OutputTrackChange, _c = exports.LocalStreamEventNames.EffectAdded;
1430
1509
  const LocalStream = AddEvents(_LocalStream);
1431
1510
 
1432
1511
  /**
@@ -6170,6 +6249,80 @@ Logger$1.useDefaults({
6170
6249
  },
6171
6250
  });
6172
6251
 
6252
+ exports.MediaFamily = void 0;
6253
+ (function (MediaFamily) {
6254
+ MediaFamily["Audio"] = "AUDIO";
6255
+ MediaFamily["Video"] = "VIDEO";
6256
+ })(exports.MediaFamily || (exports.MediaFamily = {}));
6257
+ exports.MediaContent = void 0;
6258
+ (function (MediaContent) {
6259
+ MediaContent["Main"] = "MAIN";
6260
+ MediaContent["Slides"] = "SLIDES";
6261
+ })(exports.MediaContent || (exports.MediaContent = {}));
6262
+ exports.Policy = void 0;
6263
+ (function (Policy) {
6264
+ Policy["ActiveSpeaker"] = "active-speaker";
6265
+ Policy["ReceiverSelected"] = "receiver-selected";
6266
+ })(exports.Policy || (exports.Policy = {}));
6267
+ exports.MediaType = void 0;
6268
+ (function (MediaType) {
6269
+ MediaType["VideoMain"] = "VIDEO-MAIN";
6270
+ MediaType["VideoSlides"] = "VIDEO-SLIDES";
6271
+ MediaType["AudioMain"] = "AUDIO-MAIN";
6272
+ MediaType["AudioSlides"] = "AUDIO-SLIDES";
6273
+ })(exports.MediaType || (exports.MediaType = {}));
6274
+
6275
+ function randomInteger(min, max) {
6276
+ return Math.floor(Math.random() * (max - min + 1)) + min;
6277
+ }
6278
+ function generateSceneId() {
6279
+ return randomInteger(0, 0x7fffff);
6280
+ }
6281
+ function generateCsi(mediaFamily, sceneId) {
6282
+ let av;
6283
+ if (mediaFamily === exports.MediaFamily.Audio) {
6284
+ av = 0;
6285
+ }
6286
+ else {
6287
+ av = 1;
6288
+ }
6289
+ return (sceneId << 8) | av;
6290
+ }
6291
+ function getMediaType(mediaFamily, mediaContent) {
6292
+ if (mediaFamily === exports.MediaFamily.Video && mediaContent === exports.MediaContent.Main) {
6293
+ return exports.MediaType.VideoMain;
6294
+ }
6295
+ if (mediaFamily === exports.MediaFamily.Video && mediaContent === exports.MediaContent.Slides) {
6296
+ return exports.MediaType.VideoSlides;
6297
+ }
6298
+ if (mediaFamily === exports.MediaFamily.Audio && mediaContent === exports.MediaContent.Main) {
6299
+ return exports.MediaType.AudioMain;
6300
+ }
6301
+ return exports.MediaType.AudioSlides;
6302
+ }
6303
+ function getMediaFamily(mediaType) {
6304
+ return [exports.MediaType.VideoMain, exports.MediaType.VideoSlides].includes(mediaType)
6305
+ ? exports.MediaFamily.Video
6306
+ : exports.MediaFamily.Audio;
6307
+ }
6308
+ function getMediaContent(mediaType) {
6309
+ return [exports.MediaType.VideoMain, exports.MediaType.AudioMain].includes(mediaType)
6310
+ ? exports.MediaContent.Main
6311
+ : exports.MediaContent.Slides;
6312
+ }
6313
+ const truthyOrZero = (value) => value === 0 || value;
6314
+ function arraysAreEqual(left, right, predicate) {
6315
+ if (left.length !== right.length) {
6316
+ return false;
6317
+ }
6318
+ for (let i = 0; i < left.length; i += 1) {
6319
+ if (!predicate(left[i], right[i])) {
6320
+ return false;
6321
+ }
6322
+ }
6323
+ return true;
6324
+ }
6325
+
6173
6326
  class ActiveSpeakerInfo {
6174
6327
  constructor(priority, crossPriorityDuplication, crossPolicyDuplication, preferLiveVideo, namedMediaGroups) {
6175
6328
  this.priority = priority;
@@ -6193,15 +6346,7 @@ function areNamedMediaGroupArraysEqual(left, right) {
6193
6346
  if (left === undefined || right === undefined) {
6194
6347
  return left === right;
6195
6348
  }
6196
- if (left.length !== right.length) {
6197
- return false;
6198
- }
6199
- for (let i = 0; i < left.length; i += 1) {
6200
- if (left[i] !== right[i]) {
6201
- return false;
6202
- }
6203
- }
6204
- return true;
6349
+ return arraysAreEqual(left, right, (l, r) => l.type === r.type && l.value === r.value);
6205
6350
  }
6206
6351
  function areActiveSpeakerInfosEqual(left, right) {
6207
6352
  return (left.priority === right.priority &&
@@ -6403,69 +6548,6 @@ function areReceiverSelectedInfosEqual(left, right) {
6403
6548
  return left.csi === right.csi;
6404
6549
  }
6405
6550
 
6406
- exports.MediaFamily = void 0;
6407
- (function (MediaFamily) {
6408
- MediaFamily["Audio"] = "AUDIO";
6409
- MediaFamily["Video"] = "VIDEO";
6410
- })(exports.MediaFamily || (exports.MediaFamily = {}));
6411
- exports.MediaContent = void 0;
6412
- (function (MediaContent) {
6413
- MediaContent["Main"] = "MAIN";
6414
- MediaContent["Slides"] = "SLIDES";
6415
- })(exports.MediaContent || (exports.MediaContent = {}));
6416
- exports.Policy = void 0;
6417
- (function (Policy) {
6418
- Policy["ActiveSpeaker"] = "active-speaker";
6419
- Policy["ReceiverSelected"] = "receiver-selected";
6420
- })(exports.Policy || (exports.Policy = {}));
6421
- exports.MediaType = void 0;
6422
- (function (MediaType) {
6423
- MediaType["VideoMain"] = "VIDEO-MAIN";
6424
- MediaType["VideoSlides"] = "VIDEO-SLIDES";
6425
- MediaType["AudioMain"] = "AUDIO-MAIN";
6426
- MediaType["AudioSlides"] = "AUDIO-SLIDES";
6427
- })(exports.MediaType || (exports.MediaType = {}));
6428
-
6429
- function randomInteger(min, max) {
6430
- return Math.floor(Math.random() * (max - min + 1)) + min;
6431
- }
6432
- function generateSceneId() {
6433
- return randomInteger(0, 0x7fffff);
6434
- }
6435
- function generateCsi(mediaFamily, sceneId) {
6436
- let av;
6437
- if (mediaFamily === exports.MediaFamily.Audio) {
6438
- av = 0;
6439
- }
6440
- else {
6441
- av = 1;
6442
- }
6443
- return (sceneId << 8) | av;
6444
- }
6445
- function getMediaType(mediaFamily, mediaContent) {
6446
- if (mediaFamily === exports.MediaFamily.Video && mediaContent === exports.MediaContent.Main) {
6447
- return exports.MediaType.VideoMain;
6448
- }
6449
- if (mediaFamily === exports.MediaFamily.Video && mediaContent === exports.MediaContent.Slides) {
6450
- return exports.MediaType.VideoSlides;
6451
- }
6452
- if (mediaFamily === exports.MediaFamily.Audio && mediaContent === exports.MediaContent.Main) {
6453
- return exports.MediaType.AudioMain;
6454
- }
6455
- return exports.MediaType.AudioSlides;
6456
- }
6457
- function getMediaFamily(mediaType) {
6458
- return [exports.MediaType.VideoMain, exports.MediaType.VideoSlides].includes(mediaType)
6459
- ? exports.MediaFamily.Video
6460
- : exports.MediaFamily.Audio;
6461
- }
6462
- function getMediaContent(mediaType) {
6463
- return [exports.MediaType.VideoMain, exports.MediaType.AudioMain].includes(mediaType)
6464
- ? exports.MediaContent.Main
6465
- : exports.MediaContent.Slides;
6466
- }
6467
- const truthyOrZero = (value) => value === 0 || value;
6468
-
6469
6551
  class SourceAdvertisementMsg {
6470
6552
  constructor(seqNum, numTotalSources, numLiveSources, namedMediaGroups, videoContentHint) {
6471
6553
  this.seqNum = seqNum;
@@ -6526,26 +6608,10 @@ function arePolicySpecificInfosEqual(left, right) {
6526
6608
  throw new Error('Invalid PolicySpecificInfo');
6527
6609
  }
6528
6610
  function areCodecInfoArraysEqual(left, right) {
6529
- if (left.length !== right.length) {
6530
- return false;
6531
- }
6532
- for (let i = 0; i < left.length; i += 1) {
6533
- if (!areCodecInfosEqual(left[i], right[i])) {
6534
- return false;
6535
- }
6536
- }
6537
- return true;
6611
+ return arraysAreEqual(left, right, areCodecInfosEqual);
6538
6612
  }
6539
6613
  function areStreamIdArraysEqual(left, right) {
6540
- if (left.length !== right.length) {
6541
- return false;
6542
- }
6543
- for (let i = 0; i < left.length; i += 1) {
6544
- if (!compareStreamIds(left[i], right[i])) {
6545
- return false;
6546
- }
6547
- }
6548
- return true;
6614
+ return arraysAreEqual(left, right, compareStreamIds);
6549
6615
  }
6550
6616
  function areStreamRequestsEqual(left, right) {
6551
6617
  if (left.policy !== right.policy) {
@@ -6617,7 +6683,7 @@ function areStreamRequestArraysEqual(left, right) {
6617
6683
  return true;
6618
6684
  }
6619
6685
  class JmpSession extends events$3.EventEmitter {
6620
- constructor(mediaFamily, mediaContent, maxNumRetransmits = 3, retransmitIntervalMs = 250) {
6686
+ constructor(mediaFamily, mediaContent, maxNumRetransmits = 200, retransmitIntervalMs = 250) {
6621
6687
  super();
6622
6688
  this.currMediaRequestSeqNum = 1;
6623
6689
  this.currSourceAdvertisementSeqNum = 1;
@@ -6642,16 +6708,25 @@ class JmpSession extends events$3.EventEmitter {
6642
6708
  !areStreamRequestArraysEqual(this.lastSentMediaRequest.msg.requests, requests)) {
6643
6709
  this.sendJmpMsg(JmpMsgType.MediaRequest, mediaRequestMsg);
6644
6710
  (_a = this.lastSentMediaRequest) === null || _a === void 0 ? void 0 : _a.cancel();
6645
- this.lastSentMediaRequest = new RetransmitHandler(mediaRequestMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => this.sendJmpMsg(JmpMsgType.MediaRequest, mediaRequestMsg), (expiredJmpMsg) => {
6711
+ this.lastSentMediaRequest = new RetransmitHandler(mediaRequestMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => {
6712
+ this.logger.info(`Retransmitting previously sent MediaRequest...`);
6713
+ this.sendJmpMsg(JmpMsgType.MediaRequest, mediaRequestMsg);
6714
+ }, (expiredJmpMsg) => {
6646
6715
  this.logger.warn(`Retransmits for message expired: ${expiredJmpMsg}`);
6647
6716
  });
6648
6717
  this.currMediaRequestSeqNum++;
6649
6718
  }
6719
+ else {
6720
+ this.logger.info(`Duplicate MediaRequest detected and will not be sent: ${mediaRequestMsg}`);
6721
+ }
6650
6722
  }
6651
6723
  sendSourceAdvertisement(numTotalSources, numLiveSources, namedMediaGroups, videoContentHint) {
6652
6724
  const sourceAdvertisementMsg = new SourceAdvertisementMsg(this.currSourceAdvertisementSeqNum++, numTotalSources, numLiveSources, namedMediaGroups, videoContentHint);
6653
6725
  this.sendJmpMsg(JmpMsgType.SourceAdvertisement, sourceAdvertisementMsg);
6654
- this.lastSentSourceAdvertisement = new RetransmitHandler(sourceAdvertisementMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => this.sendJmpMsg(JmpMsgType.SourceAdvertisement, sourceAdvertisementMsg), (expiredMsg) => {
6726
+ this.lastSentSourceAdvertisement = new RetransmitHandler(sourceAdvertisementMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => {
6727
+ this.logger.info(`Retransmitting previously sent SourceAdvertisement...`);
6728
+ this.sendJmpMsg(JmpMsgType.SourceAdvertisement, sourceAdvertisementMsg);
6729
+ }, (expiredMsg) => {
6655
6730
  this.logger.warn(`Retransmits for message expired: `, expiredMsg);
6656
6731
  });
6657
6732
  }
@@ -6666,11 +6741,17 @@ class JmpSession extends events$3.EventEmitter {
6666
6741
  !compareStreamStateArrays(filteredStreamStates, this.lastSentMediaRequestStatus.msg.streamStates)) {
6667
6742
  this.sendJmpMsg(JmpMsgType.MediaRequestStatus, mediaRequestStatus);
6668
6743
  (_b = this.lastSentMediaRequestStatus) === null || _b === void 0 ? void 0 : _b.cancel();
6669
- this.lastSentMediaRequestStatus = new RetransmitHandler(mediaRequestStatus, this.maxNumRetransmits, this.retransmitIntervalMs, () => this.sendJmpMsg(JmpMsgType.MediaRequestStatus, mediaRequestStatus), (expiredMsg) => {
6744
+ this.lastSentMediaRequestStatus = new RetransmitHandler(mediaRequestStatus, this.maxNumRetransmits, this.retransmitIntervalMs, () => {
6745
+ this.logger.info(`Retransmitting previously sent MediaRequestStatus...`);
6746
+ this.sendJmpMsg(JmpMsgType.MediaRequestStatus, mediaRequestStatus);
6747
+ }, (expiredMsg) => {
6670
6748
  this.logger.warn(`Retransmits for message expired: `, expiredMsg);
6671
6749
  });
6672
6750
  this.currMediaRequestStatusSeqNum++;
6673
6751
  }
6752
+ else {
6753
+ this.logger.info(`Duplicate MediaRequestStatus detected and will not be sent: `, mediaRequestStatus);
6754
+ }
6674
6755
  }
6675
6756
  receive(jmpMsg) {
6676
6757
  if (jmpMsg.mediaContent !== this.mediaContent || jmpMsg.mediaFamily !== this.mediaFamily) {
@@ -6867,6 +6948,26 @@ class JmpSession extends events$3.EventEmitter {
6867
6948
  }
6868
6949
  }
6869
6950
 
6951
+ exports.WcmeErrorType = void 0;
6952
+ (function (WcmeErrorType) {
6953
+ WcmeErrorType["CREATE_OFFER_FAILED"] = "CREATE_OFFER_FAILED";
6954
+ WcmeErrorType["SET_ANSWER_FAILED"] = "SET_ANSWER_FAILED";
6955
+ WcmeErrorType["OFFER_ANSWER_MISMATCH"] = "OFFER_ANSWER_MISMATCH";
6956
+ WcmeErrorType["SDP_MUNGE_FAILED"] = "SDP_MUNGE_FAILED";
6957
+ WcmeErrorType["SDP_MUNGE_MISSING_CODECS"] = "SDP_MUNGE_MISSING_CODECS";
6958
+ WcmeErrorType["INVALID_STREAM_REQUEST"] = "INVALID_STREAM_REQUEST";
6959
+ WcmeErrorType["GET_TRANSCEIVER_FAILED"] = "GET_TRANSCEIVER_FAILED";
6960
+ WcmeErrorType["GET_MAX_BITRATE_FAILED"] = "GET_MAX_BITRATE_FAILED";
6961
+ WcmeErrorType["GET_PAYLOAD_TYPE_FAILED"] = "GET_PAYLOAD_TYPE_FAILED";
6962
+ WcmeErrorType["SET_NMG_FAILED"] = "SET_NMG_FAILED";
6963
+ })(exports.WcmeErrorType || (exports.WcmeErrorType = {}));
6964
+ class WcmeError {
6965
+ constructor(type, message = '') {
6966
+ this.type = type;
6967
+ this.message = message;
6968
+ }
6969
+ }
6970
+
6870
6971
  var commonjsGlobal$1 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
6871
6972
 
6872
6973
  var logger$1 = {exports: {}};
@@ -7153,26 +7254,6 @@ var logger$1 = {exports: {}};
7153
7254
 
7154
7255
  var Logger = logger$1.exports;
7155
7256
 
7156
- exports.WcmeErrorType = void 0;
7157
- (function (WcmeErrorType) {
7158
- WcmeErrorType["CREATE_OFFER_FAILED"] = "CREATE_OFFER_FAILED";
7159
- WcmeErrorType["SET_ANSWER_FAILED"] = "SET_ANSWER_FAILED";
7160
- WcmeErrorType["OFFER_ANSWER_MISMATCH"] = "OFFER_ANSWER_MISMATCH";
7161
- WcmeErrorType["SDP_MUNGE_FAILED"] = "SDP_MUNGE_FAILED";
7162
- WcmeErrorType["SDP_MUNGE_MISSING_CODECS"] = "SDP_MUNGE_MISSING_CODECS";
7163
- WcmeErrorType["INVALID_STREAM_REQUEST"] = "INVALID_STREAM_REQUEST";
7164
- WcmeErrorType["GET_TRANSCEIVER_FAILED"] = "GET_TRANSCEIVER_FAILED";
7165
- WcmeErrorType["GET_MAX_BITRATE_FAILED"] = "GET_MAX_BITRATE_FAILED";
7166
- WcmeErrorType["GET_PAYLOAD_TYPE_FAILED"] = "GET_PAYLOAD_TYPE_FAILED";
7167
- WcmeErrorType["SET_NMG_FAILED"] = "SET_NMG_FAILED";
7168
- })(exports.WcmeErrorType || (exports.WcmeErrorType = {}));
7169
- class WcmeError {
7170
- constructor(type, message = '') {
7171
- this.type = type;
7172
- this.message = message;
7173
- }
7174
- }
7175
-
7176
7257
  const DEFAULT_LOGGER_NAME = 'web-client-media-engine';
7177
7258
  const logger = Logger.get(DEFAULT_LOGGER_NAME);
7178
7259
  logger.setLevel(Logger.DEBUG);