@webex/web-client-media-engine 3.13.0 → 3.14.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
@@ -1167,10 +1167,9 @@ function AddEvents(Base) {
1167
1167
  };
1168
1168
  }
1169
1169
 
1170
- var _a$1$1, _b$1;
1170
+ var _a$2$1;
1171
1171
  exports.StreamEventNames = void 0;
1172
1172
  (function (StreamEventNames) {
1173
- StreamEventNames["MuteStateChange"] = "mute-state-change";
1174
1173
  StreamEventNames["Ended"] = "stream-ended";
1175
1174
  })(exports.StreamEventNames || (exports.StreamEventNames = {}));
1176
1175
  /**
@@ -1185,25 +1184,10 @@ class _Stream {
1185
1184
  constructor(stream) {
1186
1185
  // TODO: these should be protected, but we need the helper type in ts-events
1187
1186
  // to hide the 'emit' method from TypedEvent.
1188
- this[_a$1$1] = new TypedEvent$1();
1189
- this[_b$1] = new TypedEvent$1();
1187
+ this[_a$2$1] = new TypedEvent$1();
1190
1188
  this.outputStream = stream;
1191
- this.handleTrackMuted = this.handleTrackMuted.bind(this);
1192
- this.handleTrackUnmuted = this.handleTrackUnmuted.bind(this);
1193
1189
  this.handleTrackEnded = this.handleTrackEnded.bind(this);
1194
- this.addTrackHandlers(this.outputTrack);
1195
- }
1196
- /**
1197
- * Handler which is called when a track's mute event fires.
1198
- */
1199
- handleTrackMuted() {
1200
- this[exports.StreamEventNames.MuteStateChange].emit(true);
1201
- }
1202
- /**
1203
- * Handler which is called when a track's unmute event fires.
1204
- */
1205
- handleTrackUnmuted() {
1206
- this[exports.StreamEventNames.MuteStateChange].emit(false);
1190
+ this.addTrackHandlersForStreamEvents(this.outputTrack);
1207
1191
  }
1208
1192
  /**
1209
1193
  * Handler which is called when a track's ended event fires.
@@ -1211,15 +1195,25 @@ class _Stream {
1211
1195
  handleTrackEnded() {
1212
1196
  this[exports.StreamEventNames.Ended].emit();
1213
1197
  }
1198
+ /**
1199
+ * Helper function to add event handlers to a MediaStreamTrack. Unlike the virtual
1200
+ * {@link addTrackHandlers} function, which can be overridden, this function is internal to this
1201
+ * class and will only add the event handlers relevant to this class. It prevents, for example,
1202
+ * accidentally adding the same event handlers multiple times, which could happen if the virtual
1203
+ * `addTrackHandlers` method was called from a subclass's constructor.
1204
+ *
1205
+ * @param track - The MediaStreamTrack.
1206
+ */
1207
+ addTrackHandlersForStreamEvents(track) {
1208
+ track.addEventListener('ended', this.handleTrackEnded);
1209
+ }
1214
1210
  /**
1215
1211
  * Add event handlers to a MediaStreamTrack.
1216
1212
  *
1217
1213
  * @param track - The MediaStreamTrack.
1218
1214
  */
1219
1215
  addTrackHandlers(track) {
1220
- track.addEventListener('mute', this.handleTrackMuted);
1221
- track.addEventListener('unmute', this.handleTrackUnmuted);
1222
- track.addEventListener('ended', this.handleTrackEnded);
1216
+ this.addTrackHandlersForStreamEvents(track);
1223
1217
  }
1224
1218
  /**
1225
1219
  * Remove event handlers from a MediaStreamTrack.
@@ -1227,8 +1221,6 @@ class _Stream {
1227
1221
  * @param track - The MediaStreamTrack.
1228
1222
  */
1229
1223
  removeTrackHandlers(track) {
1230
- track.removeEventListener('mute', this.handleTrackMuted);
1231
- track.removeEventListener('unmute', this.handleTrackUnmuted);
1232
1224
  track.removeEventListener('ended', this.handleTrackEnded);
1233
1225
  }
1234
1226
  /**
@@ -1248,12 +1240,14 @@ class _Stream {
1248
1240
  return this.outputStream.getTracks()[0];
1249
1241
  }
1250
1242
  }
1251
- _a$1$1 = exports.StreamEventNames.MuteStateChange, _b$1 = exports.StreamEventNames.Ended;
1243
+ _a$2$1 = exports.StreamEventNames.Ended;
1252
1244
  const Stream = AddEvents(_Stream);
1253
1245
 
1254
- var _a$6, _b, _c;
1246
+ var _a$1$1, _b, _c, _d, _e;
1255
1247
  exports.LocalStreamEventNames = void 0;
1256
1248
  (function (LocalStreamEventNames) {
1249
+ LocalStreamEventNames["UserMuteStateChange"] = "user-mute-state-change";
1250
+ LocalStreamEventNames["SystemMuteStateChange"] = "system-mute-state-change";
1257
1251
  LocalStreamEventNames["ConstraintsChange"] = "constraints-change";
1258
1252
  LocalStreamEventNames["OutputTrackChange"] = "output-track-change";
1259
1253
  LocalStreamEventNames["EffectAdded"] = "effect-added";
@@ -1269,12 +1263,54 @@ class _LocalStream extends Stream {
1269
1263
  */
1270
1264
  constructor(stream) {
1271
1265
  super(stream);
1272
- this[_a$6] = new TypedEvent$1();
1266
+ this[_a$1$1] = new TypedEvent$1();
1273
1267
  this[_b] = new TypedEvent$1();
1274
1268
  this[_c] = new TypedEvent$1();
1269
+ this[_d] = new TypedEvent$1();
1270
+ this[_e] = new TypedEvent$1();
1275
1271
  this.effects = [];
1276
1272
  this.loadingEffects = new Map();
1277
1273
  this.inputStream = stream;
1274
+ this.handleTrackMutedBySystem = this.handleTrackMutedBySystem.bind(this);
1275
+ this.handleTrackUnmutedBySystem = this.handleTrackUnmutedBySystem.bind(this);
1276
+ this.addTrackHandlersForLocalStreamEvents(this.inputTrack);
1277
+ }
1278
+ /**
1279
+ * Handler which is called when a track's mute event fires.
1280
+ */
1281
+ handleTrackMutedBySystem() {
1282
+ this[exports.LocalStreamEventNames.SystemMuteStateChange].emit(true);
1283
+ }
1284
+ /**
1285
+ * Handler which is called when a track's unmute event fires.
1286
+ */
1287
+ handleTrackUnmutedBySystem() {
1288
+ this[exports.LocalStreamEventNames.SystemMuteStateChange].emit(false);
1289
+ }
1290
+ /**
1291
+ * Helper function to add event handlers to a MediaStreamTrack. See
1292
+ * {@link Stream.addTrackHandlersForStreamEvents} for why this is useful.
1293
+ *
1294
+ * @param track - The MediaStreamTrack.
1295
+ */
1296
+ addTrackHandlersForLocalStreamEvents(track) {
1297
+ track.addEventListener('mute', this.handleTrackMutedBySystem);
1298
+ track.addEventListener('unmute', this.handleTrackUnmutedBySystem);
1299
+ }
1300
+ /**
1301
+ * @inheritdoc
1302
+ */
1303
+ addTrackHandlers(track) {
1304
+ super.addTrackHandlers(track);
1305
+ this.addTrackHandlersForLocalStreamEvents(track);
1306
+ }
1307
+ /**
1308
+ * @inheritdoc
1309
+ */
1310
+ removeTrackHandlers(track) {
1311
+ super.removeTrackHandlers(track);
1312
+ track.removeEventListener('mute', this.handleTrackMutedBySystem);
1313
+ track.removeEventListener('unmute', this.handleTrackUnmutedBySystem);
1278
1314
  }
1279
1315
  /**
1280
1316
  * Get the track within the MediaStream with which this LocalStream was created.
@@ -1286,42 +1322,45 @@ class _LocalStream extends Stream {
1286
1322
  return this.inputStream.getTracks()[0];
1287
1323
  }
1288
1324
  /**
1289
- * @inheritdoc
1325
+ * Check whether or not this stream is muted. This considers both whether the stream has been
1326
+ * muted by the user (see {@link userMuted}) and whether the stream has been muted by the system
1327
+ * (see {@link systemMuted}).
1328
+ *
1329
+ * @returns True if the stream is muted, false otherwise.
1290
1330
  */
1291
- handleTrackMuted() {
1292
- if (this.inputTrack.enabled) {
1293
- super.handleTrackMuted();
1294
- }
1331
+ get muted() {
1332
+ return this.userMuted || this.systemMuted;
1295
1333
  }
1296
1334
  /**
1297
- * @inheritdoc
1335
+ * Check whether or not this stream has been muted by the user. This is equivalent to checking the
1336
+ * MediaStreamTrack "enabled" state.
1337
+ *
1338
+ * @returns True if the stream has been muted by the user, false otherwise.
1298
1339
  */
1299
- handleTrackUnmuted() {
1300
- if (this.inputTrack.enabled) {
1301
- super.handleTrackUnmuted();
1302
- }
1340
+ get userMuted() {
1341
+ return !this.inputTrack.enabled;
1303
1342
  }
1304
1343
  /**
1305
- * @inheritdoc
1344
+ * Check whether or not this stream has been muted by the user. This is equivalent to checking the
1345
+ * MediaStreamTrack "muted" state.
1346
+ *
1347
+ * @returns True if the stream has been muted by the system, false otherwise.
1306
1348
  */
1307
- get muted() {
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;
1349
+ get systemMuted() {
1350
+ return this.inputTrack.muted;
1312
1351
  }
1313
1352
  /**
1314
- * Set the mute state of this stream.
1353
+ * Set the user mute state of this stream.
1354
+ *
1355
+ * Note: This sets the user-toggled mute state, equivalent to changing the "enabled" state of the
1356
+ * track. It is separate from the system-toggled mute state.
1315
1357
  *
1316
1358
  * @param isMuted - True to mute, false to unmute.
1317
1359
  */
1318
- setMuted(isMuted) {
1360
+ setUserMuted(isMuted) {
1319
1361
  if (this.inputTrack.enabled === isMuted) {
1320
1362
  this.inputTrack.enabled = !isMuted;
1321
- // setting `enabled` will not automatically emit MuteStateChange, so we emit it here
1322
- if (!this.inputTrack.muted) {
1323
- this[exports.StreamEventNames.MuteStateChange].emit(isMuted);
1324
- }
1363
+ this[exports.LocalStreamEventNames.UserMuteStateChange].emit(isMuted);
1325
1364
  }
1326
1365
  }
1327
1366
  /**
@@ -1411,13 +1450,13 @@ class _LocalStream extends Stream {
1411
1450
  * @param track - The new output track of the effect.
1412
1451
  */
1413
1452
  const handleEffectTrackUpdated = (track) => {
1414
- var _d;
1453
+ var _f;
1415
1454
  const effectIndex = this.effects.findIndex((e) => e.id === effect.id);
1416
1455
  if (effectIndex === this.effects.length - 1) {
1417
1456
  this.changeOutputTrack(track);
1418
1457
  }
1419
1458
  else if (effectIndex >= 0) {
1420
- (_d = this.effects[effectIndex + 1]) === null || _d === void 0 ? void 0 : _d.replaceInputTrack(track);
1459
+ (_f = this.effects[effectIndex + 1]) === null || _f === void 0 ? void 0 : _f.replaceInputTrack(track);
1421
1460
  }
1422
1461
  else {
1423
1462
  logger$3.error(`Effect with ID ${effect.id} not found in effects list.`);
@@ -1535,7 +1574,7 @@ class _LocalStream extends Stream {
1535
1574
  });
1536
1575
  }
1537
1576
  }
1538
- _a$6 = exports.LocalStreamEventNames.ConstraintsChange, _b = exports.LocalStreamEventNames.OutputTrackChange, _c = exports.LocalStreamEventNames.EffectAdded;
1577
+ _a$1$1 = exports.LocalStreamEventNames.UserMuteStateChange, _b = exports.LocalStreamEventNames.SystemMuteStateChange, _c = exports.LocalStreamEventNames.ConstraintsChange, _d = exports.LocalStreamEventNames.OutputTrackChange, _e = exports.LocalStreamEventNames.EffectAdded;
1539
1578
  const LocalStream = AddEvents(_LocalStream);
1540
1579
 
1541
1580
  /**
@@ -1637,15 +1676,77 @@ class LocalMicrophoneStream extends LocalAudioStream {
1637
1676
  class LocalSystemAudioStream extends LocalAudioStream {
1638
1677
  }
1639
1678
 
1679
+ var _a$6;
1680
+ exports.RemoteMediaState = void 0;
1681
+ (function (RemoteMediaState) {
1682
+ RemoteMediaState["Started"] = "started";
1683
+ RemoteMediaState["Stopped"] = "stopped";
1684
+ })(exports.RemoteMediaState || (exports.RemoteMediaState = {}));
1685
+ exports.RemoteStreamEventNames = void 0;
1686
+ (function (RemoteStreamEventNames) {
1687
+ RemoteStreamEventNames["MediaStateChange"] = "media-state-change";
1688
+ })(exports.RemoteStreamEventNames || (exports.RemoteStreamEventNames = {}));
1640
1689
  /**
1641
1690
  * A stream originating from a remote peer.
1642
1691
  */
1643
- class RemoteStream extends Stream {
1692
+ class _RemoteStream extends Stream {
1693
+ /**
1694
+ * Create a RemoteStream from the given values.
1695
+ *
1696
+ * @param stream - The initial output MediaStream for this Stream.
1697
+ */
1698
+ constructor(stream) {
1699
+ super(stream);
1700
+ this[_a$6] = new TypedEvent$1();
1701
+ this.handleMediaStarted = this.handleMediaStarted.bind(this);
1702
+ this.handleMediaStopped = this.handleMediaStopped.bind(this);
1703
+ this.outputTrack.addEventListener('mute', this.handleMediaStopped);
1704
+ this.outputTrack.addEventListener('unmute', this.handleMediaStarted);
1705
+ }
1644
1706
  /**
1645
1707
  * @inheritdoc
1646
1708
  */
1647
- get muted() {
1648
- return !this.outputTrack.enabled;
1709
+ handleMediaStarted() {
1710
+ this[exports.RemoteStreamEventNames.MediaStateChange].emit(exports.RemoteMediaState.Started);
1711
+ }
1712
+ /**
1713
+ * @inheritdoc
1714
+ */
1715
+ handleMediaStopped() {
1716
+ this[exports.RemoteStreamEventNames.MediaStateChange].emit(exports.RemoteMediaState.Stopped);
1717
+ }
1718
+ /**
1719
+ * Helper function to add event handlers to a MediaStreamTrack. See
1720
+ * {@link Stream.addTrackHandlersForStreamEvents} for why this is useful.
1721
+ *
1722
+ * @param track - The MediaStreamTrack.
1723
+ */
1724
+ addTrackHandlersForRemoteStreamEvents(track) {
1725
+ track.addEventListener('mute', this.handleMediaStopped);
1726
+ track.addEventListener('unmute', this.handleMediaStarted);
1727
+ }
1728
+ /**
1729
+ * @inheritdoc
1730
+ */
1731
+ addTrackHandlers(track) {
1732
+ super.addTrackHandlers(track);
1733
+ this.addTrackHandlersForRemoteStreamEvents(track);
1734
+ }
1735
+ /**
1736
+ * @inheritdoc
1737
+ */
1738
+ removeTrackHandlers(track) {
1739
+ super.removeTrackHandlers(track);
1740
+ track.removeEventListener('mute', this.handleMediaStopped);
1741
+ track.removeEventListener('unmute', this.handleMediaStarted);
1742
+ }
1743
+ /**
1744
+ * Get whether the media on this stream has started or stopped.
1745
+ *
1746
+ * @returns The state of the media.
1747
+ */
1748
+ get mediaState() {
1749
+ return this.outputTrack.muted ? exports.RemoteMediaState.Stopped : exports.RemoteMediaState.Started;
1649
1750
  }
1650
1751
  /**
1651
1752
  * @inheritdoc
@@ -1664,6 +1765,14 @@ class RemoteStream extends Stream {
1664
1765
  this.outputStream.removeTrack(oldTrack);
1665
1766
  this.outputStream.addTrack(newTrack);
1666
1767
  this.addTrackHandlers(newTrack);
1768
+ if (oldTrack.muted !== newTrack.muted) {
1769
+ if (newTrack.muted) {
1770
+ this.handleMediaStopped();
1771
+ }
1772
+ else {
1773
+ this.handleMediaStarted();
1774
+ }
1775
+ }
1667
1776
  // TODO: Chrome/React may not automatically refresh the media element with the new track when
1668
1777
  // the output track has changed, so we may need to emit an event here if this is the case.
1669
1778
  // this[StreamEventNames.OutputTrackChange].emit(newTrack);
@@ -1676,7 +1785,9 @@ class RemoteStream extends Stream {
1676
1785
  // calling stop() will not automatically emit Ended, so we emit it here
1677
1786
  this[exports.StreamEventNames.Ended].emit();
1678
1787
  }
1679
- }
1788
+ }
1789
+ _a$6 = exports.RemoteStreamEventNames.MediaStateChange;
1790
+ const RemoteStream = AddEvents(_RemoteStream);
1680
1791
 
1681
1792
  var commonjsGlobal$3 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
1682
1793
 
@@ -9626,11 +9737,11 @@ class EgressSdpMunger {
9626
9737
  this.streamIds.forEach((streamId) => {
9627
9738
  const rtpSsrc = streamId.ssrc;
9628
9739
  mediaDescription.addLine(new SsrcLine(rtpSsrc, 'cname', `${rtpSsrc}-cname`));
9629
- mediaDescription.addLine(new SsrcLine(rtpSsrc, 'msid', '-', '1'));
9740
+ mediaDescription.addLine(new SsrcLine(rtpSsrc, 'msid', '-', `${mediaDescription.mid}`));
9630
9741
  if (options.rtxEnabled) {
9631
9742
  const rtxSsrc = streamId.rtxSsrc;
9632
9743
  mediaDescription.addLine(new SsrcLine(rtxSsrc, 'cname', `${rtpSsrc}-cname`));
9633
- mediaDescription.addLine(new SsrcLine(rtxSsrc, 'msid', '-', '1'));
9744
+ mediaDescription.addLine(new SsrcLine(rtxSsrc, 'msid', '-', `${mediaDescription.mid}`));
9634
9745
  mediaDescription.addLine(new SsrcGroupLine('FID', [rtpSsrc, rtxSsrc]));
9635
9746
  }
9636
9747
  });
@@ -10181,13 +10292,13 @@ class IngressSdpMunger {
10181
10292
  mungeRemoteDescription(mediaDescription) {
10182
10293
  if (!mediaDescription.ssrcs.length) {
10183
10294
  mediaDescription.addLine(new SsrcLine(this.ssrc, 'cname', `${this.ssrc}-cname`));
10184
- mediaDescription.addLine(new SsrcLine(this.ssrc, 'msid', '-', '1'));
10295
+ mediaDescription.addLine(new SsrcLine(this.ssrc, 'msid', '-', `${mediaDescription.mid}`));
10185
10296
  if (hasCodec('rtx', mediaDescription)) {
10186
10297
  if (!this.rtxSsrc) {
10187
10298
  this.rtxSsrc = generateSsrc();
10188
10299
  }
10189
10300
  mediaDescription.addLine(new SsrcLine(this.rtxSsrc, 'cname', `${this.ssrc}-cname`));
10190
- mediaDescription.addLine(new SsrcLine(this.rtxSsrc, 'msid', '-', '1'));
10301
+ mediaDescription.addLine(new SsrcLine(this.rtxSsrc, 'msid', '-', `${mediaDescription.mid}`));
10191
10302
  mediaDescription.addLine(new SsrcGroupLine('FID', [this.ssrc, this.rtxSsrc]));
10192
10303
  }
10193
10304
  }
@@ -10280,15 +10391,15 @@ class ReceiveSlot extends EventEmitter$2 {
10280
10391
  constructor(idGetter, track) {
10281
10392
  super();
10282
10393
  this._idGetter = idGetter;
10283
- this.handleStreamMuteStateChange = this.handleStreamMuteStateChange.bind(this);
10394
+ this.handleStreamMediaStateChange = this.handleStreamMediaStateChange.bind(this);
10284
10395
  this.handleStreamEnded = this.handleStreamEnded.bind(this);
10285
10396
  this._stream = new RemoteStream(new MediaStream([track]));
10286
10397
  this._sourceState = 'no source';
10287
- this._stream.on(exports.StreamEventNames.MuteStateChange, this.handleStreamMuteStateChange);
10398
+ this._stream.on(exports.RemoteStreamEventNames.MediaStateChange, this.handleStreamMediaStateChange);
10288
10399
  this._stream.on(exports.StreamEventNames.Ended, this.handleStreamEnded);
10289
10400
  }
10290
- handleStreamMuteStateChange(muted) {
10291
- if (muted) {
10401
+ handleStreamMediaStateChange(state) {
10402
+ if (state === exports.RemoteMediaState.Stopped) {
10292
10403
  this.emit(exports.ReceiveSlotEvents.MediaStopped);
10293
10404
  }
10294
10405
  else {
@@ -10309,7 +10420,7 @@ class ReceiveSlot extends EventEmitter$2 {
10309
10420
  }
10310
10421
  }
10311
10422
  close() {
10312
- this._stream.off(exports.StreamEventNames.MuteStateChange, this.handleStreamMuteStateChange);
10423
+ this._stream.off(exports.RemoteStreamEventNames.MediaStateChange, this.handleStreamMediaStateChange);
10313
10424
  this._stream.off(exports.StreamEventNames.Ended, this.handleStreamEnded);
10314
10425
  }
10315
10426
  get id() {
@@ -14157,14 +14268,16 @@ class SendOnlyTransceiver extends Transceiver {
14157
14268
  const oldStream = this.publishedStream;
14158
14269
  oldStream === null || oldStream === void 0 ? void 0 : oldStream.off(exports.LocalStreamEventNames.OutputTrackChange, this.handleTrackChange);
14159
14270
  oldStream === null || oldStream === void 0 ? void 0 : oldStream.off(exports.LocalStreamEventNames.ConstraintsChange, this.handleStreamConstraintsChange);
14160
- oldStream === null || oldStream === void 0 ? void 0 : oldStream.off(exports.StreamEventNames.MuteStateChange, this.handleStreamMuteStateChange);
14271
+ oldStream === null || oldStream === void 0 ? void 0 : oldStream.off(exports.LocalStreamEventNames.UserMuteStateChange, this.handleStreamMuteStateChange);
14272
+ oldStream === null || oldStream === void 0 ? void 0 : oldStream.off(exports.LocalStreamEventNames.SystemMuteStateChange, this.handleStreamMuteStateChange);
14161
14273
  if (this.requested) {
14162
14274
  yield this.replaceSenderSource(newStream);
14163
14275
  }
14164
14276
  this.publishedStream = newStream;
14165
14277
  newStream === null || newStream === void 0 ? void 0 : newStream.on(exports.LocalStreamEventNames.OutputTrackChange, this.handleTrackChange);
14166
14278
  newStream === null || newStream === void 0 ? void 0 : newStream.on(exports.LocalStreamEventNames.ConstraintsChange, this.handleStreamConstraintsChange);
14167
- newStream === null || newStream === void 0 ? void 0 : newStream.on(exports.StreamEventNames.MuteStateChange, this.handleStreamMuteStateChange);
14279
+ newStream === null || newStream === void 0 ? void 0 : newStream.on(exports.LocalStreamEventNames.UserMuteStateChange, this.handleStreamMuteStateChange);
14280
+ newStream === null || newStream === void 0 ? void 0 : newStream.on(exports.LocalStreamEventNames.SystemMuteStateChange, this.handleStreamMuteStateChange);
14168
14281
  if ((!oldStream && newStream && !newStream.muted) ||
14169
14282
  (oldStream && !newStream && !oldStream.muted)) {
14170
14283
  this.streamPublishStateChange.emit();