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

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;
@@ -1360,55 +1363,110 @@ class _LocalStream extends Stream {
1360
1363
  /**
1361
1364
  * Adds an effect to a local stream.
1362
1365
  *
1363
- * @param name - The name of the effect.
1364
1366
  * @param effect - The effect to add.
1365
1367
  */
1366
- addEffect(name, effect) {
1368
+ addEffect(effect) {
1367
1369
  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)) {
1370
+ // Check if the effect has already been added.
1371
+ if (this.effects.some((e) => e.id === effect.id)) {
1372
+ return;
1373
+ }
1374
+ // Load the effect. Because loading is asynchronous, keep track of the loading effects.
1375
+ this.loadingEffects.set(effect.kind, effect);
1376
+ yield effect.load(this.outputTrack);
1377
+ // After loading, check whether or not we still want to use this effect. If another effect of
1378
+ // the same kind was added while this effect was loading, we only want to use the latest effect,
1379
+ // so dispose this one. If the effects list was cleared while this effect was loading, also
1380
+ // dispose it.
1381
+ if (effect !== this.loadingEffects.get(effect.kind)) {
1373
1382
  yield effect.dispose();
1374
- throw new Error(`Effect "${name}" not required after loading`);
1383
+ 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
1384
  }
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);
1385
+ this.loadingEffects.delete(effect.kind);
1386
+ /**
1387
+ * Handle when the effect's output track has been changed. This will update the input of the
1388
+ * next effect in the effects list of the output of the stream.
1389
+ *
1390
+ * @param track - The new output track of the effect.
1391
+ */
1392
+ const handleEffectTrackUpdated = (track) => {
1393
+ var _d;
1394
+ const effectIndex = this.effects.findIndex((e) => e.id === effect.id);
1387
1395
  if (effectIndex === this.effects.length - 1) {
1388
1396
  this.changeOutputTrack(track);
1389
1397
  }
1398
+ else if (effectIndex >= 0) {
1399
+ (_d = this.effects[effectIndex + 1]) === null || _d === void 0 ? void 0 : _d.replaceInputTrack(track);
1400
+ }
1390
1401
  else {
1391
- (_c = this.effects[effectIndex + 1]) === null || _c === void 0 ? void 0 : _c.effect.replaceInputTrack(track);
1402
+ logger$3.error(`Effect with ID ${effect.id} not found in effects list.`);
1392
1403
  }
1393
- });
1404
+ };
1405
+ /**
1406
+ * Handle when the effect has been disposed. This will remove all event listeners from the
1407
+ * effect.
1408
+ */
1409
+ const handleEffectDisposed = () => {
1410
+ effect.off('track-updated', handleEffectTrackUpdated);
1411
+ effect.off('disposed', handleEffectDisposed);
1412
+ };
1413
+ // TODO: using EffectEvent.TrackUpdated or EffectEvent.Disposed will cause the entire
1414
+ // web-media-effects lib to be rebuilt and inflates the size of the webrtc-core build, so
1415
+ // we use type assertion here as a temporary workaround.
1416
+ effect.on('track-updated', handleEffectTrackUpdated);
1417
+ effect.on('disposed', handleEffectDisposed);
1418
+ // Add the effect to the effects list. If an effect of the same kind has already been added,
1419
+ // dispose the existing effect and replace it with the new effect. If the existing effect was
1420
+ // enabled, also enable the new effect.
1421
+ const existingEffectIndex = this.effects.findIndex((e) => e.kind === effect.kind);
1422
+ if (existingEffectIndex >= 0) {
1423
+ const [existingEffect] = this.effects.splice(existingEffectIndex, 1, effect);
1424
+ if (existingEffect.isEnabled) {
1425
+ // If the existing effect is not the first effect in the effects list, then the input of the
1426
+ // new effect should be the output of the previous effect in the effects list. We know the
1427
+ // output track of the previous effect must exist because it must have been loaded (and all
1428
+ // loaded effects have an output track).
1429
+ const inputTrack = existingEffectIndex === 0
1430
+ ? this.inputTrack
1431
+ : this.effects[existingEffectIndex - 1].getOutputTrack();
1432
+ yield effect.replaceInputTrack(inputTrack);
1433
+ // Enabling the new effect will trigger the track-updated event, which will handle the new
1434
+ // effect's updated output track.
1435
+ yield effect.enable();
1436
+ }
1437
+ yield existingEffect.dispose();
1438
+ }
1439
+ else {
1440
+ this.effects.push(effect);
1441
+ }
1442
+ // Emit an event with the effect so others can listen to the effect events.
1443
+ this[exports.LocalStreamEventNames.EffectAdded].emit(effect);
1394
1444
  });
1395
1445
  }
1396
1446
  /**
1397
- * Get an effect from the effects list.
1447
+ * Get an effect from the effects list by ID.
1448
+ *
1449
+ * @param id - The id of the effect you want to get.
1450
+ * @returns The effect or undefined.
1451
+ */
1452
+ getEffectById(id) {
1453
+ return this.effects.find((effect) => effect.id === id);
1454
+ }
1455
+ /**
1456
+ * Get an effect from the effects list by kind.
1398
1457
  *
1399
- * @param name - The name of the effect you want to get.
1458
+ * @param kind - The kind of the effect you want to get.
1400
1459
  * @returns The effect or undefined.
1401
1460
  */
1402
- getEffect(name) {
1403
- var _c;
1404
- return (_c = this.effects.find((e) => e.name === name)) === null || _c === void 0 ? void 0 : _c.effect;
1461
+ getEffectByKind(kind) {
1462
+ return this.effects.find((effect) => effect.kind === kind);
1405
1463
  }
1406
1464
  /**
1407
1465
  * Get all the effects from the effects list.
1408
1466
  *
1409
- * @returns A list of effect items, each containing the name and the effect itself.
1467
+ * @returns A list of effects.
1410
1468
  */
1411
- getAllEffects() {
1469
+ getEffects() {
1412
1470
  return this.effects;
1413
1471
  }
1414
1472
  /**
@@ -1420,13 +1478,13 @@ class _LocalStream extends Stream {
1420
1478
  // Dispose of any effects currently in use
1421
1479
  if (this.effects.length > 0) {
1422
1480
  this.changeOutputTrack(this.inputTrack);
1423
- yield Promise.all(this.effects.map((item) => item.effect.dispose()));
1481
+ yield Promise.all(this.effects.map((effect) => effect.dispose()));
1424
1482
  this.effects = [];
1425
1483
  }
1426
1484
  });
1427
1485
  }
1428
1486
  }
1429
- _a$6 = exports.LocalStreamEventNames.ConstraintsChange, _b = exports.LocalStreamEventNames.OutputTrackChange;
1487
+ _a$6 = exports.LocalStreamEventNames.ConstraintsChange, _b = exports.LocalStreamEventNames.OutputTrackChange, _c = exports.LocalStreamEventNames.EffectAdded;
1430
1488
  const LocalStream = AddEvents(_LocalStream);
1431
1489
 
1432
1490
  /**