@webex/web-client-media-engine 3.21.0 → 3.22.0

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/esm/index.js CHANGED
@@ -326,149 +326,149 @@ var logger$1$1 = {exports: {}};
326
326
 
327
327
  var Logger$2 = logger$1$1.exports;
328
328
 
329
- const DEFAULT_LOGGER_NAME$1 = 'webrtc-core';
330
- const logger$3 = Logger$2.get(DEFAULT_LOGGER_NAME$1);
331
- Logger$2.useDefaults({
332
- defaultLevel: Logger$2.DEBUG,
333
- /* eslint-disable-next-line jsdoc/require-jsdoc */
334
- formatter: (messages, context) => {
335
- messages.unshift(`[${context.name}]`);
336
- },
329
+ const DEFAULT_LOGGER_NAME$1 = 'webrtc-core';
330
+ const logger$3 = Logger$2.get(DEFAULT_LOGGER_NAME$1);
331
+ Logger$2.useDefaults({
332
+ defaultLevel: Logger$2.DEBUG,
333
+ /* eslint-disable-next-line jsdoc/require-jsdoc */
334
+ formatter: (messages, context) => {
335
+ messages.unshift(`[${context.name}]`);
336
+ },
337
337
  });
338
338
 
339
- var DeviceKind$1;
340
- (function (DeviceKind) {
341
- DeviceKind["AudioInput"] = "audioinput";
342
- DeviceKind["AudioOutput"] = "audiooutput";
343
- DeviceKind["VideoInput"] = "videoinput";
344
- })(DeviceKind$1 || (DeviceKind$1 = {}));
345
- /**
346
- * Prompts the user for permission to use a media input which produces a MediaStream with tracks
347
- * containing the requested types of media.
348
- *
349
- * @param constraints - A MediaStreamConstraints object specifying the types of media to request,
350
- * along with any requirements for each type.
351
- * @returns A Promise whose fulfillment handler receives a MediaStream object when the requested
352
- * media has successfully been obtained.
353
- */
354
- function getUserMedia(constraints) {
355
- return __awaiter$2(this, void 0, void 0, function* () {
356
- return navigator.mediaDevices.getUserMedia(constraints);
357
- });
358
- }
359
- /**
360
- * Prompts the user for permission to use a user's display media and audio. If a video track is
361
- * absent from the constraints argument, one will still be provided.
362
- *
363
- * @param constraints - A MediaStreamConstraints object specifying the types of media to request,
364
- * along with any requirements for each type.
365
- * @returns A Promise whose fulfillment handler receives a MediaStream object when the requested
366
- * media has successfully been obtained.
367
- */
368
- function getDisplayMedia(constraints) {
369
- return navigator.mediaDevices.getDisplayMedia(constraints);
370
- }
371
- /**
372
- * Requests a list of the available media input and output devices, such as microphones, cameras,
373
- * headsets, and so forth.
374
- *
375
- * @returns A Promise that receives an array of MediaDeviceInfo objects when the promise is
376
- * fulfilled.
377
- */
378
- function enumerateDevices() {
379
- return __awaiter$2(this, void 0, void 0, function* () {
380
- return navigator.mediaDevices.enumerateDevices();
381
- });
382
- }
383
- /**
384
- * Adds the callback handler to be notified of a media device change (for example, a headset is
385
- * unplugged from the user's computer).
386
- *
387
- * @param handler - The callback function to execute.
388
- */
389
- function setOnDeviceChangeHandler$1(handler) {
390
- navigator.mediaDevices.ondevicechange = handler;
391
- }
392
- /**
393
- * Checks permissions using the navigator's permissions api.
394
- *
395
- * @param deviceKinds - Array of DeviceKind items.
396
- * @throws An error if camera or microphone aren't available options for query() (Firefox), or if
397
- * navigator.permissions is undefined (Safari and others).
398
- * @returns Array of Permission Status objects.
399
- */
400
- function checkNavigatorPermissions(deviceKinds) {
401
- return __awaiter$2(this, void 0, void 0, function* () {
402
- const permissionRequests = [];
403
- if (deviceKinds.includes(DeviceKind$1.VideoInput)) {
404
- permissionRequests.push(navigator.permissions.query({ name: 'camera' }));
405
- }
406
- if (deviceKinds.includes(DeviceKind$1.AudioInput)) {
407
- permissionRequests.push(navigator.permissions.query({ name: 'microphone' }));
408
- }
409
- return Promise.all(permissionRequests);
410
- });
411
- }
412
- /**
413
- * Check to see if the user has granted the application permission to use their devices.
414
- *
415
- * @param deviceKinds - Array of DeviceKind items.
416
- * @returns True if device permissions exist, false if otherwise.
417
- */
418
- function checkDevicePermissions(deviceKinds) {
419
- return __awaiter$2(this, void 0, void 0, function* () {
420
- try {
421
- const permissions = yield checkNavigatorPermissions(deviceKinds);
422
- if (permissions.every((permission) => permission.state === 'granted')) {
423
- return true;
424
- }
425
- // eslint-disable-next-line no-empty
426
- }
427
- catch (e) { }
428
- try {
429
- const devices = yield enumerateDevices();
430
- // If permissions are granted, the MediaDeviceInfo objects will have labels.
431
- return devices
432
- .filter((device) => deviceKinds.includes(device.kind))
433
- .every((device) => device.label);
434
- // eslint-disable-next-line no-empty
435
- }
436
- catch (e) { }
437
- return false;
438
- });
439
- }
440
- /**
441
- * Ensures that the user has granted permissions to the microphone and camera.
442
- *
443
- * @param deviceKinds - Array of DeviceKind items.
444
- * @param callback - Function that will be executed while device permissions are granted. After this
445
- * returns, permissions (for example device labels in Firefox) may not be available anymore.
446
- * @returns The callback's response.
447
- */
448
- function ensureDevicePermissions(deviceKinds, callback) {
449
- return __awaiter$2(this, void 0, void 0, function* () {
450
- try {
451
- const hasDevicePermissions = yield checkDevicePermissions(deviceKinds);
452
- if (!hasDevicePermissions) {
453
- const stream = yield getUserMedia({
454
- audio: deviceKinds.includes(DeviceKind$1.AudioInput),
455
- video: deviceKinds.includes(DeviceKind$1.VideoInput),
456
- });
457
- // Callback is here to call a function while an active capture exists, so that the browser
458
- // (Firefox) will allow the user to access device information.
459
- const callbackRes = yield callback();
460
- // Stop tracks in the stream so the browser (Safari) will know that there is not an active
461
- // stream running.
462
- stream.getTracks().forEach((track) => track.stop());
463
- return callbackRes;
464
- }
465
- return callback();
466
- }
467
- catch (e) {
468
- logger$3.error(e);
469
- throw new Error('Failed to ensure device permissions.');
470
- }
471
- });
339
+ var DeviceKind$1;
340
+ (function (DeviceKind) {
341
+ DeviceKind["AudioInput"] = "audioinput";
342
+ DeviceKind["AudioOutput"] = "audiooutput";
343
+ DeviceKind["VideoInput"] = "videoinput";
344
+ })(DeviceKind$1 || (DeviceKind$1 = {}));
345
+ /**
346
+ * Prompts the user for permission to use a media input which produces a MediaStream with tracks
347
+ * containing the requested types of media.
348
+ *
349
+ * @param constraints - A MediaStreamConstraints object specifying the types of media to request,
350
+ * along with any requirements for each type.
351
+ * @returns A Promise whose fulfillment handler receives a MediaStream object when the requested
352
+ * media has successfully been obtained.
353
+ */
354
+ function getUserMedia(constraints) {
355
+ return __awaiter$2(this, void 0, void 0, function* () {
356
+ return navigator.mediaDevices.getUserMedia(constraints);
357
+ });
358
+ }
359
+ /**
360
+ * Prompts the user for permission to use a user's display media and audio. If a video track is
361
+ * absent from the constraints argument, one will still be provided.
362
+ *
363
+ * @param constraints - A MediaStreamConstraints object specifying the types of media to request,
364
+ * along with any requirements for each type.
365
+ * @returns A Promise whose fulfillment handler receives a MediaStream object when the requested
366
+ * media has successfully been obtained.
367
+ */
368
+ function getDisplayMedia(constraints) {
369
+ return navigator.mediaDevices.getDisplayMedia(constraints);
370
+ }
371
+ /**
372
+ * Requests a list of the available media input and output devices, such as microphones, cameras,
373
+ * headsets, and so forth.
374
+ *
375
+ * @returns A Promise that receives an array of MediaDeviceInfo objects when the promise is
376
+ * fulfilled.
377
+ */
378
+ function enumerateDevices() {
379
+ return __awaiter$2(this, void 0, void 0, function* () {
380
+ return navigator.mediaDevices.enumerateDevices();
381
+ });
382
+ }
383
+ /**
384
+ * Adds the callback handler to be notified of a media device change (for example, a headset is
385
+ * unplugged from the user's computer).
386
+ *
387
+ * @param handler - The callback function to execute.
388
+ */
389
+ function setOnDeviceChangeHandler$1(handler) {
390
+ navigator.mediaDevices.ondevicechange = handler;
391
+ }
392
+ /**
393
+ * Checks permissions using the navigator's permissions api.
394
+ *
395
+ * @param deviceKinds - Array of DeviceKind items.
396
+ * @throws An error if camera or microphone aren't available options for query() (Firefox), or if
397
+ * navigator.permissions is undefined (Safari and others).
398
+ * @returns Array of Permission Status objects.
399
+ */
400
+ function checkNavigatorPermissions(deviceKinds) {
401
+ return __awaiter$2(this, void 0, void 0, function* () {
402
+ const permissionRequests = [];
403
+ if (deviceKinds.includes(DeviceKind$1.VideoInput)) {
404
+ permissionRequests.push(navigator.permissions.query({ name: 'camera' }));
405
+ }
406
+ if (deviceKinds.includes(DeviceKind$1.AudioInput)) {
407
+ permissionRequests.push(navigator.permissions.query({ name: 'microphone' }));
408
+ }
409
+ return Promise.all(permissionRequests);
410
+ });
411
+ }
412
+ /**
413
+ * Check to see if the user has granted the application permission to use their devices.
414
+ *
415
+ * @param deviceKinds - Array of DeviceKind items.
416
+ * @returns True if device permissions exist, false if otherwise.
417
+ */
418
+ function checkDevicePermissions(deviceKinds) {
419
+ return __awaiter$2(this, void 0, void 0, function* () {
420
+ try {
421
+ const permissions = yield checkNavigatorPermissions(deviceKinds);
422
+ if (permissions.every((permission) => permission.state === 'granted')) {
423
+ return true;
424
+ }
425
+ // eslint-disable-next-line no-empty
426
+ }
427
+ catch (e) { }
428
+ try {
429
+ const devices = yield enumerateDevices();
430
+ // If permissions are granted, the MediaDeviceInfo objects will have labels.
431
+ return devices
432
+ .filter((device) => deviceKinds.includes(device.kind))
433
+ .every((device) => device.label);
434
+ // eslint-disable-next-line no-empty
435
+ }
436
+ catch (e) { }
437
+ return false;
438
+ });
439
+ }
440
+ /**
441
+ * Ensures that the user has granted permissions to the microphone and camera.
442
+ *
443
+ * @param deviceKinds - Array of DeviceKind items.
444
+ * @param callback - Function that will be executed while device permissions are granted. After this
445
+ * returns, permissions (for example device labels in Firefox) may not be available anymore.
446
+ * @returns The callback's response.
447
+ */
448
+ function ensureDevicePermissions(deviceKinds, callback) {
449
+ return __awaiter$2(this, void 0, void 0, function* () {
450
+ try {
451
+ const hasDevicePermissions = yield checkDevicePermissions(deviceKinds);
452
+ if (!hasDevicePermissions) {
453
+ const stream = yield getUserMedia({
454
+ audio: deviceKinds.includes(DeviceKind$1.AudioInput),
455
+ video: deviceKinds.includes(DeviceKind$1.VideoInput),
456
+ });
457
+ // Callback is here to call a function while an active capture exists, so that the browser
458
+ // (Firefox) will allow the user to access device information.
459
+ const callbackRes = yield callback();
460
+ // Stop tracks in the stream so the browser (Safari) will know that there is not an active
461
+ // stream running.
462
+ stream.getTracks().forEach((track) => track.stop());
463
+ return callbackRes;
464
+ }
465
+ return callback();
466
+ }
467
+ catch (e) {
468
+ logger$3.error(e);
469
+ throw new Error('Failed to ensure device permissions.');
470
+ }
471
+ });
472
472
  }
473
473
 
474
474
  var media = /*#__PURE__*/Object.freeze({
@@ -482,175 +482,175 @@ var media = /*#__PURE__*/Object.freeze({
482
482
  ensureDevicePermissions: ensureDevicePermissions
483
483
  });
484
484
 
485
- var WebrtcCoreErrorType;
486
- (function (WebrtcCoreErrorType) {
487
- WebrtcCoreErrorType["DEVICE_PERMISSION_DENIED"] = "DEVICE_PERMISSION_DENIED";
488
- WebrtcCoreErrorType["CREATE_STREAM_FAILED"] = "CREATE_STREAM_FAILED";
489
- WebrtcCoreErrorType["ADD_EFFECT_FAILED"] = "ADD_EFFECT_FAILED";
490
- })(WebrtcCoreErrorType || (WebrtcCoreErrorType = {}));
491
- /**
492
- * Represents a WebRTC core error, which contains error type and error message.
493
- */
494
- class WebrtcCoreError {
495
- /**
496
- * Creates new error.
497
- *
498
- * @param type - Error type.
499
- * @param message - Error message.
500
- */
501
- constructor(type, message = '') {
502
- this.type = type;
503
- this.message = message;
504
- }
485
+ var WebrtcCoreErrorType;
486
+ (function (WebrtcCoreErrorType) {
487
+ WebrtcCoreErrorType["DEVICE_PERMISSION_DENIED"] = "DEVICE_PERMISSION_DENIED";
488
+ WebrtcCoreErrorType["CREATE_STREAM_FAILED"] = "CREATE_STREAM_FAILED";
489
+ WebrtcCoreErrorType["ADD_EFFECT_FAILED"] = "ADD_EFFECT_FAILED";
490
+ })(WebrtcCoreErrorType || (WebrtcCoreErrorType = {}));
491
+ /**
492
+ * Represents a WebRTC core error, which contains error type and error message.
493
+ */
494
+ class WebrtcCoreError {
495
+ /**
496
+ * Creates new error.
497
+ *
498
+ * @param type - Error type.
499
+ * @param message - Error message.
500
+ */
501
+ constructor(type, message = '') {
502
+ this.type = type;
503
+ this.message = message;
504
+ }
505
505
  }
506
506
 
507
- /**
508
- * Creates a camera stream. Please note that the constraint params in second getUserMedia call would NOT take effect when:
509
- *
510
- * 1. Previous captured video stream from the same device is not stopped.
511
- * 2. Previous createCameraStream() call for the same device is in progress.
512
- *
513
- * @param constructor - Constructor for the local camera stream.
514
- * @param constraints - Video device constraints.
515
- * @returns A LocalCameraStream object or an error.
516
- */
517
- function createCameraStream(constructor, constraints) {
518
- return __awaiter$2(this, void 0, void 0, function* () {
519
- let stream;
520
- try {
521
- stream = yield getUserMedia({ video: Object.assign({}, constraints) });
522
- }
523
- catch (error) {
524
- throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create camera stream: ${error}`);
525
- }
526
- return new constructor(stream);
527
- });
528
- }
529
- /**
530
- * Creates a LocalMicrophoneStream with the given constraints.
531
- *
532
- * @param constructor - Constructor for the local microphone stream.
533
- * @param constraints - Audio device constraints.
534
- * @returns A LocalMicrophoneStream object or an error.
535
- */
536
- function createMicrophoneStream(constructor, constraints) {
537
- return __awaiter$2(this, void 0, void 0, function* () {
538
- let stream;
539
- try {
540
- stream = yield getUserMedia({ audio: Object.assign({}, constraints) });
541
- }
542
- catch (error) {
543
- throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create microphone stream: ${error}`);
544
- }
545
- return new constructor(stream);
546
- });
547
- }
548
- /**
549
- * Creates a LocalDisplayStream with the given parameters.
550
- *
551
- * @param constructor - Constructor for the local display stream.
552
- * @param videoContentHint - An optional parameter to give a hint for the content of the stream.
553
- * @returns A Promise that resolves to a LocalDisplayStream or an error.
554
- */
555
- function createDisplayStream(constructor, videoContentHint) {
556
- return __awaiter$2(this, void 0, void 0, function* () {
557
- let stream;
558
- try {
559
- stream = yield getDisplayMedia({ video: true });
560
- }
561
- catch (error) {
562
- throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create display stream: ${error}`);
563
- }
564
- const localDisplayStream = new constructor(stream);
565
- if (videoContentHint) {
566
- localDisplayStream.contentHint = videoContentHint;
567
- }
568
- return localDisplayStream;
569
- });
570
- }
571
- /**
572
- * Creates a LocalDisplayStream and a LocalSystemAudioStream with the given parameters.
573
- *
574
- * @param displayStreamConstructor - Constructor for the local display stream.
575
- * @param systemAudioStreamConstructor - Constructor for the local system audio stream.
576
- * @param videoContentHint - An optional parameter to give a hint for the content of the stream.
577
- * @returns A Promise that resolves to a LocalDisplayStream and a LocalSystemAudioStream or an
578
- * error. If no system audio is available, the LocalSystemAudioStream will be resolved as null
579
- * instead.
580
- */
581
- function createDisplayStreamWithAudio(displayStreamConstructor, systemAudioStreamConstructor, videoContentHint) {
582
- return __awaiter$2(this, void 0, void 0, function* () {
583
- let stream;
584
- try {
585
- stream = yield getDisplayMedia({ video: true, audio: true });
586
- }
587
- catch (error) {
588
- throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create display and system audio streams: ${error}`);
589
- }
590
- // eslint-disable-next-line new-cap
591
- const localDisplayStream = new displayStreamConstructor(new MediaStream(stream.getVideoTracks()));
592
- if (videoContentHint) {
593
- localDisplayStream.contentHint = videoContentHint;
594
- }
595
- let localSystemAudioStream = null;
596
- if (stream.getAudioTracks().length > 0) {
597
- // eslint-disable-next-line new-cap
598
- localSystemAudioStream = new systemAudioStreamConstructor(new MediaStream(stream.getAudioTracks()));
599
- }
600
- return [localDisplayStream, localSystemAudioStream];
601
- });
602
- }
603
- /**
604
- * Enumerates the media input and output devices available.
605
- *
606
- * @param deviceKind - Optional filter to return a specific device kind.
607
- * @returns List of media devices in an array of MediaDeviceInfo objects.
608
- */
609
- function getDevices(deviceKind) {
610
- return __awaiter$2(this, void 0, void 0, function* () {
611
- let devices;
612
- try {
613
- devices = yield ensureDevicePermissions([DeviceKind$1.AudioInput, DeviceKind$1.VideoInput], enumerateDevices);
614
- }
615
- catch (error) {
616
- throw new WebrtcCoreError(WebrtcCoreErrorType.DEVICE_PERMISSION_DENIED, 'Failed to ensure device permissions');
617
- }
618
- return devices.filter((v) => (deviceKind ? v.kind === deviceKind : true));
619
- });
620
- }
621
- /**
622
- * Helper function to get a list of microphone devices.
623
- *
624
- * @returns List of microphone devices in an array of MediaDeviceInfo objects.
625
- */
626
- function getAudioInputDevices() {
627
- return __awaiter$2(this, void 0, void 0, function* () {
628
- return getDevices(DeviceKind$1.AudioInput);
629
- });
630
- }
631
- /**
632
- * Helper function to get a list of speaker devices.
633
- *
634
- * @returns List of speaker devices in an array of MediaDeviceInfo objects.
635
- */
636
- function getAudioOutputDevices() {
637
- return __awaiter$2(this, void 0, void 0, function* () {
638
- return getDevices(DeviceKind$1.AudioOutput);
639
- });
640
- }
641
- /**
642
- * Helper function to get a list of camera devices.
643
- *
644
- * @returns List of camera devices in an array of MediaDeviceInfo objects.
645
- */
646
- function getVideoInputDevices() {
647
- return __awaiter$2(this, void 0, void 0, function* () {
648
- return getDevices(DeviceKind$1.VideoInput);
649
- });
650
- }
651
- /**
652
- * Export the setOnDeviceChangeHandler method directly from the core lib.
653
- */
507
+ /**
508
+ * Creates a camera stream. Please note that the constraint params in second getUserMedia call would NOT take effect when:
509
+ *
510
+ * 1. Previous captured video stream from the same device is not stopped.
511
+ * 2. Previous createCameraStream() call for the same device is in progress.
512
+ *
513
+ * @param constructor - Constructor for the local camera stream.
514
+ * @param constraints - Video device constraints.
515
+ * @returns A LocalCameraStream object or an error.
516
+ */
517
+ function createCameraStream(constructor, constraints) {
518
+ return __awaiter$2(this, void 0, void 0, function* () {
519
+ let stream;
520
+ try {
521
+ stream = yield getUserMedia({ video: Object.assign({}, constraints) });
522
+ }
523
+ catch (error) {
524
+ throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create camera stream: ${error}`);
525
+ }
526
+ return new constructor(stream);
527
+ });
528
+ }
529
+ /**
530
+ * Creates a LocalMicrophoneStream with the given constraints.
531
+ *
532
+ * @param constructor - Constructor for the local microphone stream.
533
+ * @param constraints - Audio device constraints.
534
+ * @returns A LocalMicrophoneStream object or an error.
535
+ */
536
+ function createMicrophoneStream(constructor, constraints) {
537
+ return __awaiter$2(this, void 0, void 0, function* () {
538
+ let stream;
539
+ try {
540
+ stream = yield getUserMedia({ audio: Object.assign({}, constraints) });
541
+ }
542
+ catch (error) {
543
+ throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create microphone stream: ${error}`);
544
+ }
545
+ return new constructor(stream);
546
+ });
547
+ }
548
+ /**
549
+ * Creates a LocalDisplayStream with the given parameters.
550
+ *
551
+ * @param constructor - Constructor for the local display stream.
552
+ * @param videoContentHint - An optional parameter to give a hint for the content of the stream.
553
+ * @returns A Promise that resolves to a LocalDisplayStream or an error.
554
+ */
555
+ function createDisplayStream(constructor, videoContentHint) {
556
+ return __awaiter$2(this, void 0, void 0, function* () {
557
+ let stream;
558
+ try {
559
+ stream = yield getDisplayMedia({ video: true });
560
+ }
561
+ catch (error) {
562
+ throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create display stream: ${error}`);
563
+ }
564
+ const localDisplayStream = new constructor(stream);
565
+ if (videoContentHint) {
566
+ localDisplayStream.contentHint = videoContentHint;
567
+ }
568
+ return localDisplayStream;
569
+ });
570
+ }
571
+ /**
572
+ * Creates a LocalDisplayStream and a LocalSystemAudioStream with the given parameters.
573
+ *
574
+ * @param displayStreamConstructor - Constructor for the local display stream.
575
+ * @param systemAudioStreamConstructor - Constructor for the local system audio stream.
576
+ * @param videoContentHint - An optional parameter to give a hint for the content of the stream.
577
+ * @returns A Promise that resolves to a LocalDisplayStream and a LocalSystemAudioStream or an
578
+ * error. If no system audio is available, the LocalSystemAudioStream will be resolved as null
579
+ * instead.
580
+ */
581
+ function createDisplayStreamWithAudio(displayStreamConstructor, systemAudioStreamConstructor, videoContentHint) {
582
+ return __awaiter$2(this, void 0, void 0, function* () {
583
+ let stream;
584
+ try {
585
+ stream = yield getDisplayMedia({ video: true, audio: true });
586
+ }
587
+ catch (error) {
588
+ throw new WebrtcCoreError(WebrtcCoreErrorType.CREATE_STREAM_FAILED, `Failed to create display and system audio streams: ${error}`);
589
+ }
590
+ // eslint-disable-next-line new-cap
591
+ const localDisplayStream = new displayStreamConstructor(new MediaStream(stream.getVideoTracks()));
592
+ if (videoContentHint) {
593
+ localDisplayStream.contentHint = videoContentHint;
594
+ }
595
+ let localSystemAudioStream = null;
596
+ if (stream.getAudioTracks().length > 0) {
597
+ // eslint-disable-next-line new-cap
598
+ localSystemAudioStream = new systemAudioStreamConstructor(new MediaStream(stream.getAudioTracks()));
599
+ }
600
+ return [localDisplayStream, localSystemAudioStream];
601
+ });
602
+ }
603
+ /**
604
+ * Enumerates the media input and output devices available.
605
+ *
606
+ * @param deviceKind - Optional filter to return a specific device kind.
607
+ * @returns List of media devices in an array of MediaDeviceInfo objects.
608
+ */
609
+ function getDevices(deviceKind) {
610
+ return __awaiter$2(this, void 0, void 0, function* () {
611
+ let devices;
612
+ try {
613
+ devices = yield ensureDevicePermissions([DeviceKind$1.AudioInput, DeviceKind$1.VideoInput], enumerateDevices);
614
+ }
615
+ catch (error) {
616
+ throw new WebrtcCoreError(WebrtcCoreErrorType.DEVICE_PERMISSION_DENIED, 'Failed to ensure device permissions');
617
+ }
618
+ return devices.filter((v) => (deviceKind ? v.kind === deviceKind : true));
619
+ });
620
+ }
621
+ /**
622
+ * Helper function to get a list of microphone devices.
623
+ *
624
+ * @returns List of microphone devices in an array of MediaDeviceInfo objects.
625
+ */
626
+ function getAudioInputDevices() {
627
+ return __awaiter$2(this, void 0, void 0, function* () {
628
+ return getDevices(DeviceKind$1.AudioInput);
629
+ });
630
+ }
631
+ /**
632
+ * Helper function to get a list of speaker devices.
633
+ *
634
+ * @returns List of speaker devices in an array of MediaDeviceInfo objects.
635
+ */
636
+ function getAudioOutputDevices() {
637
+ return __awaiter$2(this, void 0, void 0, function* () {
638
+ return getDevices(DeviceKind$1.AudioOutput);
639
+ });
640
+ }
641
+ /**
642
+ * Helper function to get a list of camera devices.
643
+ *
644
+ * @returns List of camera devices in an array of MediaDeviceInfo objects.
645
+ */
646
+ function getVideoInputDevices() {
647
+ return __awaiter$2(this, void 0, void 0, function* () {
648
+ return getDevices(DeviceKind$1.VideoInput);
649
+ });
650
+ }
651
+ /**
652
+ * Export the setOnDeviceChangeHandler method directly from the core lib.
653
+ */
654
654
  const { setOnDeviceChangeHandler } = media;
655
655
 
656
656
  var events$1$1 = {exports: {}};
@@ -1163,627 +1163,627 @@ function AddEvents(Base) {
1163
1163
  };
1164
1164
  }
1165
1165
 
1166
- var _a$2$1;
1167
- var StreamEventNames;
1168
- (function (StreamEventNames) {
1169
- StreamEventNames["Ended"] = "stream-ended";
1170
- })(StreamEventNames || (StreamEventNames = {}));
1171
- /**
1172
- * Base stream class.
1173
- */
1174
- class _Stream {
1175
- /**
1176
- * Create a Stream from the given values.
1177
- *
1178
- * @param stream - The initial output MediaStream for this Stream.
1179
- */
1180
- constructor(stream) {
1181
- // TODO: these should be protected, but we need the helper type in ts-events
1182
- // to hide the 'emit' method from TypedEvent.
1183
- this[_a$2$1] = new TypedEvent$1();
1184
- this.outputStream = stream;
1185
- this.handleTrackEnded = this.handleTrackEnded.bind(this);
1186
- this.addTrackHandlersForStreamEvents(this.outputTrack);
1187
- }
1188
- /**
1189
- * Handler which is called when a track's ended event fires.
1190
- */
1191
- handleTrackEnded() {
1192
- this[StreamEventNames.Ended].emit();
1193
- }
1194
- /**
1195
- * Helper function to add event handlers to a MediaStreamTrack. Unlike the virtual
1196
- * {@link addTrackHandlers} function, which can be overridden, this function is internal to this
1197
- * class and will only add the event handlers relevant to this class. It prevents, for example,
1198
- * accidentally adding the same event handlers multiple times, which could happen if the virtual
1199
- * `addTrackHandlers` method was called from a subclass's constructor.
1200
- *
1201
- * @param track - The MediaStreamTrack.
1202
- */
1203
- addTrackHandlersForStreamEvents(track) {
1204
- track.addEventListener('ended', this.handleTrackEnded);
1205
- }
1206
- /**
1207
- * Add event handlers to a MediaStreamTrack.
1208
- *
1209
- * @param track - The MediaStreamTrack.
1210
- */
1211
- addTrackHandlers(track) {
1212
- this.addTrackHandlersForStreamEvents(track);
1213
- }
1214
- /**
1215
- * Remove event handlers from a MediaStreamTrack.
1216
- *
1217
- * @param track - The MediaStreamTrack.
1218
- */
1219
- removeTrackHandlers(track) {
1220
- track.removeEventListener('ended', this.handleTrackEnded);
1221
- }
1222
- /**
1223
- * Get the ID of the output stream.
1224
- *
1225
- * @returns The ID of the output stream.
1226
- */
1227
- get id() {
1228
- return this.outputStream.id;
1229
- }
1230
- /**
1231
- * Get the track of the output stream.
1232
- *
1233
- * @returns The output track.
1234
- */
1235
- get outputTrack() {
1236
- return this.outputStream.getTracks()[0];
1237
- }
1238
- }
1239
- _a$2$1 = StreamEventNames.Ended;
1166
+ var _a$2$1;
1167
+ var StreamEventNames;
1168
+ (function (StreamEventNames) {
1169
+ StreamEventNames["Ended"] = "stream-ended";
1170
+ })(StreamEventNames || (StreamEventNames = {}));
1171
+ /**
1172
+ * Base stream class.
1173
+ */
1174
+ class _Stream {
1175
+ /**
1176
+ * Create a Stream from the given values.
1177
+ *
1178
+ * @param stream - The initial output MediaStream for this Stream.
1179
+ */
1180
+ constructor(stream) {
1181
+ // TODO: these should be protected, but we need the helper type in ts-events
1182
+ // to hide the 'emit' method from TypedEvent.
1183
+ this[_a$2$1] = new TypedEvent$1();
1184
+ this.outputStream = stream;
1185
+ this.handleTrackEnded = this.handleTrackEnded.bind(this);
1186
+ this.addTrackHandlersForStreamEvents(this.outputTrack);
1187
+ }
1188
+ /**
1189
+ * Handler which is called when a track's ended event fires.
1190
+ */
1191
+ handleTrackEnded() {
1192
+ this[StreamEventNames.Ended].emit();
1193
+ }
1194
+ /**
1195
+ * Helper function to add event handlers to a MediaStreamTrack. Unlike the virtual
1196
+ * {@link addTrackHandlers} function, which can be overridden, this function is internal to this
1197
+ * class and will only add the event handlers relevant to this class. It prevents, for example,
1198
+ * accidentally adding the same event handlers multiple times, which could happen if the virtual
1199
+ * `addTrackHandlers` method was called from a subclass's constructor.
1200
+ *
1201
+ * @param track - The MediaStreamTrack.
1202
+ */
1203
+ addTrackHandlersForStreamEvents(track) {
1204
+ track.addEventListener('ended', this.handleTrackEnded);
1205
+ }
1206
+ /**
1207
+ * Add event handlers to a MediaStreamTrack.
1208
+ *
1209
+ * @param track - The MediaStreamTrack.
1210
+ */
1211
+ addTrackHandlers(track) {
1212
+ this.addTrackHandlersForStreamEvents(track);
1213
+ }
1214
+ /**
1215
+ * Remove event handlers from a MediaStreamTrack.
1216
+ *
1217
+ * @param track - The MediaStreamTrack.
1218
+ */
1219
+ removeTrackHandlers(track) {
1220
+ track.removeEventListener('ended', this.handleTrackEnded);
1221
+ }
1222
+ /**
1223
+ * Get the ID of the output stream.
1224
+ *
1225
+ * @returns The ID of the output stream.
1226
+ */
1227
+ get id() {
1228
+ return this.outputStream.id;
1229
+ }
1230
+ /**
1231
+ * Get the track of the output stream.
1232
+ *
1233
+ * @returns The output track.
1234
+ */
1235
+ get outputTrack() {
1236
+ return this.outputStream.getTracks()[0];
1237
+ }
1238
+ }
1239
+ _a$2$1 = StreamEventNames.Ended;
1240
1240
  const Stream = AddEvents(_Stream);
1241
1241
 
1242
- var _a$1$1, _b, _c, _d, _e;
1243
- var LocalStreamEventNames;
1244
- (function (LocalStreamEventNames) {
1245
- LocalStreamEventNames["UserMuteStateChange"] = "user-mute-state-change";
1246
- LocalStreamEventNames["SystemMuteStateChange"] = "system-mute-state-change";
1247
- LocalStreamEventNames["ConstraintsChange"] = "constraints-change";
1248
- LocalStreamEventNames["OutputTrackChange"] = "output-track-change";
1249
- LocalStreamEventNames["EffectAdded"] = "effect-added";
1250
- })(LocalStreamEventNames || (LocalStreamEventNames = {}));
1251
- /**
1252
- * A stream which originates on the local device.
1253
- */
1254
- class _LocalStream extends Stream {
1255
- /**
1256
- * Create a LocalStream from the given values.
1257
- *
1258
- * @param stream - The initial output MediaStream for this Stream.
1259
- */
1260
- constructor(stream) {
1261
- super(stream);
1262
- this[_a$1$1] = new TypedEvent$1();
1263
- this[_b] = new TypedEvent$1();
1264
- this[_c] = new TypedEvent$1();
1265
- this[_d] = new TypedEvent$1();
1266
- this[_e] = new TypedEvent$1();
1267
- this.effects = [];
1268
- this.loadingEffects = new Map();
1269
- this.inputStream = stream;
1270
- this.handleTrackMutedBySystem = this.handleTrackMutedBySystem.bind(this);
1271
- this.handleTrackUnmutedBySystem = this.handleTrackUnmutedBySystem.bind(this);
1272
- this.addTrackHandlersForLocalStreamEvents(this.inputTrack);
1273
- }
1274
- /**
1275
- * Handler which is called when a track's mute event fires.
1276
- */
1277
- handleTrackMutedBySystem() {
1278
- this[LocalStreamEventNames.SystemMuteStateChange].emit(true);
1279
- }
1280
- /**
1281
- * Handler which is called when a track's unmute event fires.
1282
- */
1283
- handleTrackUnmutedBySystem() {
1284
- this[LocalStreamEventNames.SystemMuteStateChange].emit(false);
1285
- }
1286
- /**
1287
- * Helper function to add event handlers to a MediaStreamTrack. See
1288
- * {@link Stream.addTrackHandlersForStreamEvents} for why this is useful.
1289
- *
1290
- * @param track - The MediaStreamTrack.
1291
- */
1292
- addTrackHandlersForLocalStreamEvents(track) {
1293
- track.addEventListener('mute', this.handleTrackMutedBySystem);
1294
- track.addEventListener('unmute', this.handleTrackUnmutedBySystem);
1295
- }
1296
- /**
1297
- * @inheritdoc
1298
- */
1299
- addTrackHandlers(track) {
1300
- super.addTrackHandlers(track);
1301
- this.addTrackHandlersForLocalStreamEvents(track);
1302
- }
1303
- /**
1304
- * @inheritdoc
1305
- */
1306
- removeTrackHandlers(track) {
1307
- super.removeTrackHandlers(track);
1308
- track.removeEventListener('mute', this.handleTrackMutedBySystem);
1309
- track.removeEventListener('unmute', this.handleTrackUnmutedBySystem);
1310
- }
1311
- /**
1312
- * Get the track within the MediaStream with which this LocalStream was created.
1313
- *
1314
- * @returns The track within the MediaStream with which this LocalStream
1315
- * was created.
1316
- */
1317
- get inputTrack() {
1318
- return this.inputStream.getTracks()[0];
1319
- }
1320
- /**
1321
- * Check whether or not this stream is muted. This considers both whether the stream has been
1322
- * muted by the user (see {@link userMuted}) and whether the stream has been muted by the system
1323
- * (see {@link systemMuted}).
1324
- *
1325
- * @returns True if the stream is muted, false otherwise.
1326
- */
1327
- get muted() {
1328
- return this.userMuted || this.systemMuted;
1329
- }
1330
- /**
1331
- * Check whether or not this stream has been muted by the user. This is equivalent to checking the
1332
- * MediaStreamTrack "enabled" state.
1333
- *
1334
- * @returns True if the stream has been muted by the user, false otherwise.
1335
- */
1336
- get userMuted() {
1337
- return !this.inputTrack.enabled;
1338
- }
1339
- /**
1340
- * Check whether or not this stream has been muted by the user. This is equivalent to checking the
1341
- * MediaStreamTrack "muted" state.
1342
- *
1343
- * @returns True if the stream has been muted by the system, false otherwise.
1344
- */
1345
- get systemMuted() {
1346
- return this.inputTrack.muted;
1347
- }
1348
- /**
1349
- * Set the user mute state of this stream.
1350
- *
1351
- * Note: This sets the user-toggled mute state, equivalent to changing the "enabled" state of the
1352
- * track. It is separate from the system-toggled mute state.
1353
- *
1354
- * @param isMuted - True to mute, false to unmute.
1355
- */
1356
- setUserMuted(isMuted) {
1357
- if (this.inputTrack.enabled === isMuted) {
1358
- this.inputTrack.enabled = !isMuted;
1359
- this[LocalStreamEventNames.UserMuteStateChange].emit(isMuted);
1360
- }
1361
- }
1362
- /**
1363
- * @inheritdoc
1364
- */
1365
- getSettings() {
1366
- return this.inputTrack.getSettings();
1367
- }
1368
- /**
1369
- * Get the label of the input track on this stream.
1370
- *
1371
- * @returns The label of the track.
1372
- */
1373
- get label() {
1374
- return this.inputTrack.label;
1375
- }
1376
- /**
1377
- * Get the readyState of the input track on this stream.
1378
- *
1379
- * @returns The readyState of the track.
1380
- */
1381
- get readyState() {
1382
- return this.inputTrack.readyState;
1383
- }
1384
- /**
1385
- * Change the track of the output stream to a different track.
1386
- *
1387
- * Note: this method assumes and enforces that if both input and output streams have the same
1388
- * track, then they must also be the same stream.
1389
- *
1390
- * @param newTrack - The track to be used in the output stream.
1391
- */
1392
- changeOutputTrack(newTrack) {
1393
- if (this.outputTrack.id !== newTrack.id) {
1394
- // If the input track and the *old* output track are currently the same, then the streams must
1395
- // be the same too. We want to apply the new track to the output stream without affecting the
1396
- // input stream, so we separate them by setting the input stream to be its own stream.
1397
- if (this.inputTrack.id === this.outputTrack.id) {
1398
- this.inputStream = new MediaStream(this.inputStream);
1399
- }
1400
- this.outputStream.removeTrack(this.outputTrack);
1401
- this.outputStream.addTrack(newTrack);
1402
- // If the input track and the *new* output track are now the same, then we want the streams to
1403
- // be the same too.
1404
- if (this.inputTrack.id === this.outputTrack.id) {
1405
- this.inputStream = this.outputStream;
1406
- }
1407
- this[LocalStreamEventNames.OutputTrackChange].emit(newTrack);
1408
- }
1409
- }
1410
- /**
1411
- * @inheritdoc
1412
- */
1413
- stop() {
1414
- this.inputTrack.stop();
1415
- this.outputTrack.stop();
1416
- this.disposeEffects();
1417
- // calling stop() will not automatically emit Ended, so we emit it here
1418
- this[StreamEventNames.Ended].emit();
1419
- }
1420
- /**
1421
- * Adds an effect to a local stream.
1422
- *
1423
- * @param effect - The effect to add.
1424
- */
1425
- addEffect(effect) {
1426
- return __awaiter$2(this, void 0, void 0, function* () {
1427
- // Check if the effect has already been added.
1428
- if (this.effects.some((e) => e.id === effect.id)) {
1429
- return;
1430
- }
1431
- // Load the effect. Because loading is asynchronous, keep track of the loading effects.
1432
- this.loadingEffects.set(effect.kind, effect);
1433
- yield effect.load(this.outputTrack);
1434
- // After loading, check whether or not we still want to use this effect. If another effect of
1435
- // the same kind was added while this effect was loading, we only want to use the latest effect,
1436
- // so dispose this one. If the effects list was cleared while this effect was loading, also
1437
- // dispose it.
1438
- if (effect !== this.loadingEffects.get(effect.kind)) {
1439
- yield effect.dispose();
1440
- throw new WebrtcCoreError(WebrtcCoreErrorType.ADD_EFFECT_FAILED, `Another effect with kind ${effect.kind} was added while effect ${effect.id} was loading, or the effects list was cleared.`);
1441
- }
1442
- this.loadingEffects.delete(effect.kind);
1443
- /**
1444
- * Handle when the effect's output track has been changed. This will update the input of the
1445
- * next effect in the effects list of the output of the stream.
1446
- *
1447
- * @param track - The new output track of the effect.
1448
- */
1449
- const handleEffectTrackUpdated = (track) => {
1450
- var _f;
1451
- const effectIndex = this.effects.findIndex((e) => e.id === effect.id);
1452
- if (effectIndex === this.effects.length - 1) {
1453
- this.changeOutputTrack(track);
1454
- }
1455
- else if (effectIndex >= 0) {
1456
- (_f = this.effects[effectIndex + 1]) === null || _f === void 0 ? void 0 : _f.replaceInputTrack(track);
1457
- }
1458
- else {
1459
- logger$3.error(`Effect with ID ${effect.id} not found in effects list.`);
1460
- }
1461
- };
1462
- /**
1463
- * Handle when the effect has been disposed. This will remove all event listeners from the
1464
- * effect.
1465
- */
1466
- const handleEffectDisposed = () => {
1467
- effect.off('track-updated', handleEffectTrackUpdated);
1468
- effect.off('disposed', handleEffectDisposed);
1469
- };
1470
- // TODO: using EffectEvent.TrackUpdated or EffectEvent.Disposed will cause the entire
1471
- // web-media-effects lib to be rebuilt and inflates the size of the webrtc-core build, so
1472
- // we use type assertion here as a temporary workaround.
1473
- effect.on('track-updated', handleEffectTrackUpdated);
1474
- effect.on('disposed', handleEffectDisposed);
1475
- // Add the effect to the effects list. If an effect of the same kind has already been added,
1476
- // dispose the existing effect and replace it with the new effect. If the existing effect was
1477
- // enabled, also enable the new effect.
1478
- const existingEffectIndex = this.effects.findIndex((e) => e.kind === effect.kind);
1479
- if (existingEffectIndex >= 0) {
1480
- const [existingEffect] = this.effects.splice(existingEffectIndex, 1, effect);
1481
- if (existingEffect.isEnabled) {
1482
- // If the existing effect is not the first effect in the effects list, then the input of the
1483
- // new effect should be the output of the previous effect in the effects list. We know the
1484
- // output track of the previous effect must exist because it must have been loaded (and all
1485
- // loaded effects have an output track).
1486
- const inputTrack = existingEffectIndex === 0
1487
- ? this.inputTrack
1488
- : this.effects[existingEffectIndex - 1].getOutputTrack();
1489
- yield effect.replaceInputTrack(inputTrack);
1490
- // Enabling the new effect will trigger the track-updated event, which will handle the new
1491
- // effect's updated output track.
1492
- yield effect.enable();
1493
- }
1494
- yield existingEffect.dispose();
1495
- }
1496
- else {
1497
- this.effects.push(effect);
1498
- }
1499
- // Emit an event with the effect so others can listen to the effect events.
1500
- this[LocalStreamEventNames.EffectAdded].emit(effect);
1501
- });
1502
- }
1503
- /**
1504
- * Get an effect from the effects list by ID.
1505
- *
1506
- * @param id - The id of the effect you want to get.
1507
- * @returns The effect or undefined.
1508
- */
1509
- getEffectById(id) {
1510
- return this.effects.find((effect) => effect.id === id);
1511
- }
1512
- /**
1513
- * Get an effect from the effects list by kind.
1514
- *
1515
- * @param kind - The kind of the effect you want to get.
1516
- * @returns The effect or undefined.
1517
- */
1518
- getEffectByKind(kind) {
1519
- return this.effects.find((effect) => effect.kind === kind);
1520
- }
1521
- /**
1522
- * Get all the effects from the effects list.
1523
- *
1524
- * @returns A list of effects.
1525
- */
1526
- getEffects() {
1527
- return this.effects;
1528
- }
1529
- /**
1530
- * Method to serialize data about input, output streams
1531
- * and also effects from LocalStream.
1532
- *
1533
- * @returns - A JSON-compatible object representation with data from LocalStream.
1534
- */
1535
- toJSON() {
1536
- return {
1537
- muted: this.muted,
1538
- label: this.label,
1539
- readyState: this.readyState,
1540
- inputStream: {
1541
- active: this.inputStream.active,
1542
- id: this.inputStream.id,
1543
- enabled: this.inputTrack.enabled,
1544
- muted: this.inputTrack.muted,
1545
- },
1546
- outputStream: {
1547
- active: this.outputStream.active,
1548
- id: this.outputStream.id,
1549
- },
1550
- effects: this.effects.map((effect) => {
1551
- return {
1552
- id: effect.id,
1553
- kind: effect.kind,
1554
- isEnabled: effect.isEnabled,
1555
- };
1556
- }),
1557
- };
1558
- }
1559
- /**
1560
- * Cleanup the local effects.
1561
- */
1562
- disposeEffects() {
1563
- return __awaiter$2(this, void 0, void 0, function* () {
1564
- this.loadingEffects.clear();
1565
- // Dispose of any effects currently in use
1566
- if (this.effects.length > 0) {
1567
- this.changeOutputTrack(this.inputTrack);
1568
- yield Promise.all(this.effects.map((effect) => effect.dispose()));
1569
- this.effects = [];
1570
- }
1571
- });
1572
- }
1573
- }
1574
- _a$1$1 = LocalStreamEventNames.UserMuteStateChange, _b = LocalStreamEventNames.SystemMuteStateChange, _c = LocalStreamEventNames.ConstraintsChange, _d = LocalStreamEventNames.OutputTrackChange, _e = LocalStreamEventNames.EffectAdded;
1242
+ var _a$1$1, _b, _c, _d, _e;
1243
+ var LocalStreamEventNames;
1244
+ (function (LocalStreamEventNames) {
1245
+ LocalStreamEventNames["UserMuteStateChange"] = "user-mute-state-change";
1246
+ LocalStreamEventNames["SystemMuteStateChange"] = "system-mute-state-change";
1247
+ LocalStreamEventNames["ConstraintsChange"] = "constraints-change";
1248
+ LocalStreamEventNames["OutputTrackChange"] = "output-track-change";
1249
+ LocalStreamEventNames["EffectAdded"] = "effect-added";
1250
+ })(LocalStreamEventNames || (LocalStreamEventNames = {}));
1251
+ /**
1252
+ * A stream which originates on the local device.
1253
+ */
1254
+ class _LocalStream extends Stream {
1255
+ /**
1256
+ * Create a LocalStream from the given values.
1257
+ *
1258
+ * @param stream - The initial output MediaStream for this Stream.
1259
+ */
1260
+ constructor(stream) {
1261
+ super(stream);
1262
+ this[_a$1$1] = new TypedEvent$1();
1263
+ this[_b] = new TypedEvent$1();
1264
+ this[_c] = new TypedEvent$1();
1265
+ this[_d] = new TypedEvent$1();
1266
+ this[_e] = new TypedEvent$1();
1267
+ this.effects = [];
1268
+ this.loadingEffects = new Map();
1269
+ this.inputStream = stream;
1270
+ this.handleTrackMutedBySystem = this.handleTrackMutedBySystem.bind(this);
1271
+ this.handleTrackUnmutedBySystem = this.handleTrackUnmutedBySystem.bind(this);
1272
+ this.addTrackHandlersForLocalStreamEvents(this.inputTrack);
1273
+ }
1274
+ /**
1275
+ * Handler which is called when a track's mute event fires.
1276
+ */
1277
+ handleTrackMutedBySystem() {
1278
+ this[LocalStreamEventNames.SystemMuteStateChange].emit(true);
1279
+ }
1280
+ /**
1281
+ * Handler which is called when a track's unmute event fires.
1282
+ */
1283
+ handleTrackUnmutedBySystem() {
1284
+ this[LocalStreamEventNames.SystemMuteStateChange].emit(false);
1285
+ }
1286
+ /**
1287
+ * Helper function to add event handlers to a MediaStreamTrack. See
1288
+ * {@link Stream.addTrackHandlersForStreamEvents} for why this is useful.
1289
+ *
1290
+ * @param track - The MediaStreamTrack.
1291
+ */
1292
+ addTrackHandlersForLocalStreamEvents(track) {
1293
+ track.addEventListener('mute', this.handleTrackMutedBySystem);
1294
+ track.addEventListener('unmute', this.handleTrackUnmutedBySystem);
1295
+ }
1296
+ /**
1297
+ * @inheritdoc
1298
+ */
1299
+ addTrackHandlers(track) {
1300
+ super.addTrackHandlers(track);
1301
+ this.addTrackHandlersForLocalStreamEvents(track);
1302
+ }
1303
+ /**
1304
+ * @inheritdoc
1305
+ */
1306
+ removeTrackHandlers(track) {
1307
+ super.removeTrackHandlers(track);
1308
+ track.removeEventListener('mute', this.handleTrackMutedBySystem);
1309
+ track.removeEventListener('unmute', this.handleTrackUnmutedBySystem);
1310
+ }
1311
+ /**
1312
+ * Get the track within the MediaStream with which this LocalStream was created.
1313
+ *
1314
+ * @returns The track within the MediaStream with which this LocalStream
1315
+ * was created.
1316
+ */
1317
+ get inputTrack() {
1318
+ return this.inputStream.getTracks()[0];
1319
+ }
1320
+ /**
1321
+ * Check whether or not this stream is muted. This considers both whether the stream has been
1322
+ * muted by the user (see {@link userMuted}) and whether the stream has been muted by the system
1323
+ * (see {@link systemMuted}).
1324
+ *
1325
+ * @returns True if the stream is muted, false otherwise.
1326
+ */
1327
+ get muted() {
1328
+ return this.userMuted || this.systemMuted;
1329
+ }
1330
+ /**
1331
+ * Check whether or not this stream has been muted by the user. This is equivalent to checking the
1332
+ * MediaStreamTrack "enabled" state.
1333
+ *
1334
+ * @returns True if the stream has been muted by the user, false otherwise.
1335
+ */
1336
+ get userMuted() {
1337
+ return !this.inputTrack.enabled;
1338
+ }
1339
+ /**
1340
+ * Check whether or not this stream has been muted by the user. This is equivalent to checking the
1341
+ * MediaStreamTrack "muted" state.
1342
+ *
1343
+ * @returns True if the stream has been muted by the system, false otherwise.
1344
+ */
1345
+ get systemMuted() {
1346
+ return this.inputTrack.muted;
1347
+ }
1348
+ /**
1349
+ * Set the user mute state of this stream.
1350
+ *
1351
+ * Note: This sets the user-toggled mute state, equivalent to changing the "enabled" state of the
1352
+ * track. It is separate from the system-toggled mute state.
1353
+ *
1354
+ * @param isMuted - True to mute, false to unmute.
1355
+ */
1356
+ setUserMuted(isMuted) {
1357
+ if (this.inputTrack.enabled === isMuted) {
1358
+ this.inputTrack.enabled = !isMuted;
1359
+ this[LocalStreamEventNames.UserMuteStateChange].emit(isMuted);
1360
+ }
1361
+ }
1362
+ /**
1363
+ * @inheritdoc
1364
+ */
1365
+ getSettings() {
1366
+ return this.inputTrack.getSettings();
1367
+ }
1368
+ /**
1369
+ * Get the label of the input track on this stream.
1370
+ *
1371
+ * @returns The label of the track.
1372
+ */
1373
+ get label() {
1374
+ return this.inputTrack.label;
1375
+ }
1376
+ /**
1377
+ * Get the readyState of the input track on this stream.
1378
+ *
1379
+ * @returns The readyState of the track.
1380
+ */
1381
+ get readyState() {
1382
+ return this.inputTrack.readyState;
1383
+ }
1384
+ /**
1385
+ * Change the track of the output stream to a different track.
1386
+ *
1387
+ * Note: this method assumes and enforces that if both input and output streams have the same
1388
+ * track, then they must also be the same stream.
1389
+ *
1390
+ * @param newTrack - The track to be used in the output stream.
1391
+ */
1392
+ changeOutputTrack(newTrack) {
1393
+ if (this.outputTrack.id !== newTrack.id) {
1394
+ // If the input track and the *old* output track are currently the same, then the streams must
1395
+ // be the same too. We want to apply the new track to the output stream without affecting the
1396
+ // input stream, so we separate them by setting the input stream to be its own stream.
1397
+ if (this.inputTrack.id === this.outputTrack.id) {
1398
+ this.inputStream = new MediaStream(this.inputStream);
1399
+ }
1400
+ this.outputStream.removeTrack(this.outputTrack);
1401
+ this.outputStream.addTrack(newTrack);
1402
+ // If the input track and the *new* output track are now the same, then we want the streams to
1403
+ // be the same too.
1404
+ if (this.inputTrack.id === this.outputTrack.id) {
1405
+ this.inputStream = this.outputStream;
1406
+ }
1407
+ this[LocalStreamEventNames.OutputTrackChange].emit(newTrack);
1408
+ }
1409
+ }
1410
+ /**
1411
+ * @inheritdoc
1412
+ */
1413
+ stop() {
1414
+ this.inputTrack.stop();
1415
+ this.outputTrack.stop();
1416
+ this.disposeEffects();
1417
+ // calling stop() will not automatically emit Ended, so we emit it here
1418
+ this[StreamEventNames.Ended].emit();
1419
+ }
1420
+ /**
1421
+ * Adds an effect to a local stream.
1422
+ *
1423
+ * @param effect - The effect to add.
1424
+ */
1425
+ addEffect(effect) {
1426
+ return __awaiter$2(this, void 0, void 0, function* () {
1427
+ // Check if the effect has already been added.
1428
+ if (this.effects.some((e) => e.id === effect.id)) {
1429
+ return;
1430
+ }
1431
+ // Load the effect. Because loading is asynchronous, keep track of the loading effects.
1432
+ this.loadingEffects.set(effect.kind, effect);
1433
+ yield effect.load(this.outputTrack);
1434
+ // After loading, check whether or not we still want to use this effect. If another effect of
1435
+ // the same kind was added while this effect was loading, we only want to use the latest effect,
1436
+ // so dispose this one. If the effects list was cleared while this effect was loading, also
1437
+ // dispose it.
1438
+ if (effect !== this.loadingEffects.get(effect.kind)) {
1439
+ yield effect.dispose();
1440
+ throw new WebrtcCoreError(WebrtcCoreErrorType.ADD_EFFECT_FAILED, `Another effect with kind ${effect.kind} was added while effect ${effect.id} was loading, or the effects list was cleared.`);
1441
+ }
1442
+ this.loadingEffects.delete(effect.kind);
1443
+ /**
1444
+ * Handle when the effect's output track has been changed. This will update the input of the
1445
+ * next effect in the effects list of the output of the stream.
1446
+ *
1447
+ * @param track - The new output track of the effect.
1448
+ */
1449
+ const handleEffectTrackUpdated = (track) => {
1450
+ var _f;
1451
+ const effectIndex = this.effects.findIndex((e) => e.id === effect.id);
1452
+ if (effectIndex === this.effects.length - 1) {
1453
+ this.changeOutputTrack(track);
1454
+ }
1455
+ else if (effectIndex >= 0) {
1456
+ (_f = this.effects[effectIndex + 1]) === null || _f === void 0 ? void 0 : _f.replaceInputTrack(track);
1457
+ }
1458
+ else {
1459
+ logger$3.error(`Effect with ID ${effect.id} not found in effects list.`);
1460
+ }
1461
+ };
1462
+ /**
1463
+ * Handle when the effect has been disposed. This will remove all event listeners from the
1464
+ * effect.
1465
+ */
1466
+ const handleEffectDisposed = () => {
1467
+ effect.off('track-updated', handleEffectTrackUpdated);
1468
+ effect.off('disposed', handleEffectDisposed);
1469
+ };
1470
+ // TODO: using EffectEvent.TrackUpdated or EffectEvent.Disposed will cause the entire
1471
+ // web-media-effects lib to be rebuilt and inflates the size of the webrtc-core build, so
1472
+ // we use type assertion here as a temporary workaround.
1473
+ effect.on('track-updated', handleEffectTrackUpdated);
1474
+ effect.on('disposed', handleEffectDisposed);
1475
+ // Add the effect to the effects list. If an effect of the same kind has already been added,
1476
+ // dispose the existing effect and replace it with the new effect. If the existing effect was
1477
+ // enabled, also enable the new effect.
1478
+ const existingEffectIndex = this.effects.findIndex((e) => e.kind === effect.kind);
1479
+ if (existingEffectIndex >= 0) {
1480
+ const [existingEffect] = this.effects.splice(existingEffectIndex, 1, effect);
1481
+ if (existingEffect.isEnabled) {
1482
+ // If the existing effect is not the first effect in the effects list, then the input of the
1483
+ // new effect should be the output of the previous effect in the effects list. We know the
1484
+ // output track of the previous effect must exist because it must have been loaded (and all
1485
+ // loaded effects have an output track).
1486
+ const inputTrack = existingEffectIndex === 0
1487
+ ? this.inputTrack
1488
+ : this.effects[existingEffectIndex - 1].getOutputTrack();
1489
+ yield effect.replaceInputTrack(inputTrack);
1490
+ // Enabling the new effect will trigger the track-updated event, which will handle the new
1491
+ // effect's updated output track.
1492
+ yield effect.enable();
1493
+ }
1494
+ yield existingEffect.dispose();
1495
+ }
1496
+ else {
1497
+ this.effects.push(effect);
1498
+ }
1499
+ // Emit an event with the effect so others can listen to the effect events.
1500
+ this[LocalStreamEventNames.EffectAdded].emit(effect);
1501
+ });
1502
+ }
1503
+ /**
1504
+ * Get an effect from the effects list by ID.
1505
+ *
1506
+ * @param id - The id of the effect you want to get.
1507
+ * @returns The effect or undefined.
1508
+ */
1509
+ getEffectById(id) {
1510
+ return this.effects.find((effect) => effect.id === id);
1511
+ }
1512
+ /**
1513
+ * Get an effect from the effects list by kind.
1514
+ *
1515
+ * @param kind - The kind of the effect you want to get.
1516
+ * @returns The effect or undefined.
1517
+ */
1518
+ getEffectByKind(kind) {
1519
+ return this.effects.find((effect) => effect.kind === kind);
1520
+ }
1521
+ /**
1522
+ * Get all the effects from the effects list.
1523
+ *
1524
+ * @returns A list of effects.
1525
+ */
1526
+ getEffects() {
1527
+ return this.effects;
1528
+ }
1529
+ /**
1530
+ * Method to serialize data about input, output streams
1531
+ * and also effects from LocalStream.
1532
+ *
1533
+ * @returns - A JSON-compatible object representation with data from LocalStream.
1534
+ */
1535
+ toJSON() {
1536
+ return {
1537
+ muted: this.muted,
1538
+ label: this.label,
1539
+ readyState: this.readyState,
1540
+ inputStream: {
1541
+ active: this.inputStream.active,
1542
+ id: this.inputStream.id,
1543
+ enabled: this.inputTrack.enabled,
1544
+ muted: this.inputTrack.muted,
1545
+ },
1546
+ outputStream: {
1547
+ active: this.outputStream.active,
1548
+ id: this.outputStream.id,
1549
+ },
1550
+ effects: this.effects.map((effect) => {
1551
+ return {
1552
+ id: effect.id,
1553
+ kind: effect.kind,
1554
+ isEnabled: effect.isEnabled,
1555
+ };
1556
+ }),
1557
+ };
1558
+ }
1559
+ /**
1560
+ * Cleanup the local effects.
1561
+ */
1562
+ disposeEffects() {
1563
+ return __awaiter$2(this, void 0, void 0, function* () {
1564
+ this.loadingEffects.clear();
1565
+ // Dispose of any effects currently in use
1566
+ if (this.effects.length > 0) {
1567
+ this.changeOutputTrack(this.inputTrack);
1568
+ yield Promise.all(this.effects.map((effect) => effect.dispose()));
1569
+ this.effects = [];
1570
+ }
1571
+ });
1572
+ }
1573
+ }
1574
+ _a$1$1 = LocalStreamEventNames.UserMuteStateChange, _b = LocalStreamEventNames.SystemMuteStateChange, _c = LocalStreamEventNames.ConstraintsChange, _d = LocalStreamEventNames.OutputTrackChange, _e = LocalStreamEventNames.EffectAdded;
1575
1575
  const LocalStream = AddEvents(_LocalStream);
1576
1576
 
1577
- /**
1578
- * An audio LocalStream.
1579
- */
1580
- class LocalAudioStream extends LocalStream {
1581
- /**
1582
- * Apply constraints to the stream.
1583
- *
1584
- * @param constraints - The constraints to apply.
1585
- * @returns A promise which resolves when the constraints have been successfully applied.
1586
- */
1587
- applyConstraints(constraints) {
1588
- return __awaiter$2(this, void 0, void 0, function* () {
1589
- logger$3.log(`Applying constraints to local track:`, constraints);
1590
- return this.inputTrack.applyConstraints(constraints).then(() => {
1591
- this[LocalStreamEventNames.ConstraintsChange].emit();
1592
- });
1593
- });
1594
- }
1577
+ /**
1578
+ * An audio LocalStream.
1579
+ */
1580
+ class LocalAudioStream extends LocalStream {
1581
+ /**
1582
+ * Apply constraints to the stream.
1583
+ *
1584
+ * @param constraints - The constraints to apply.
1585
+ * @returns A promise which resolves when the constraints have been successfully applied.
1586
+ */
1587
+ applyConstraints(constraints) {
1588
+ return __awaiter$2(this, void 0, void 0, function* () {
1589
+ logger$3.log(`Applying constraints to local track:`, constraints);
1590
+ return this.inputTrack.applyConstraints(constraints).then(() => {
1591
+ this[LocalStreamEventNames.ConstraintsChange].emit();
1592
+ });
1593
+ });
1594
+ }
1595
+ }
1596
+
1597
+ /**
1598
+ * A video LocalStream.
1599
+ */
1600
+ class LocalVideoStream extends LocalStream {
1601
+ /**
1602
+ * Apply constraints to the stream.
1603
+ *
1604
+ * @param constraints - The constraints to apply.
1605
+ * @returns A promise which resolves when the constraints have been successfully applied.
1606
+ */
1607
+ applyConstraints(constraints) {
1608
+ return __awaiter$2(this, void 0, void 0, function* () {
1609
+ logger$3.log(`Applying constraints to local track:`, constraints);
1610
+ return this.inputTrack.applyConstraints(constraints).then(() => {
1611
+ this[LocalStreamEventNames.ConstraintsChange].emit();
1612
+ });
1613
+ });
1614
+ }
1615
+ /**
1616
+ * Get the content hint for this stream.
1617
+ *
1618
+ * @returns The content hint setting for this stream, or undefined if none has been set.
1619
+ */
1620
+ get contentHint() {
1621
+ return this.inputTrack.contentHint;
1622
+ }
1623
+ /**
1624
+ * Set the content hint for this stream.
1625
+ *
1626
+ * @param hint - The content hint to set.
1627
+ */
1628
+ set contentHint(hint) {
1629
+ this.inputTrack.contentHint = hint;
1630
+ }
1631
+ /**
1632
+ * Check the resolution and then return how many layers will be active.
1633
+ *
1634
+ * @returns The active layers count.
1635
+ */
1636
+ getNumActiveSimulcastLayers() {
1637
+ let activeSimulcastLayersNumber = 0;
1638
+ const videoHeight = this.inputTrack.getSettings().height;
1639
+ if (videoHeight <= 180) {
1640
+ activeSimulcastLayersNumber = 1;
1641
+ }
1642
+ else if (videoHeight <= 360) {
1643
+ activeSimulcastLayersNumber = 2;
1644
+ }
1645
+ else {
1646
+ activeSimulcastLayersNumber = 3;
1647
+ }
1648
+ return activeSimulcastLayersNumber;
1649
+ }
1650
+ }
1651
+
1652
+ /**
1653
+ * A local camera stream.
1654
+ */
1655
+ class LocalCameraStream extends LocalVideoStream {
1656
+ }
1657
+
1658
+ /**
1659
+ * A local display stream.
1660
+ */
1661
+ class LocalDisplayStream extends LocalVideoStream {
1662
+ }
1663
+
1664
+ /**
1665
+ * A local microphone stream.
1666
+ */
1667
+ class LocalMicrophoneStream extends LocalAudioStream {
1668
+ }
1669
+
1670
+ /**
1671
+ * A local system audio stream.
1672
+ */
1673
+ class LocalSystemAudioStream extends LocalAudioStream {
1674
+ }
1675
+
1676
+ var _a$6;
1677
+ var RemoteMediaState;
1678
+ (function (RemoteMediaState) {
1679
+ RemoteMediaState["Started"] = "started";
1680
+ RemoteMediaState["Stopped"] = "stopped";
1681
+ })(RemoteMediaState || (RemoteMediaState = {}));
1682
+ var RemoteStreamEventNames;
1683
+ (function (RemoteStreamEventNames) {
1684
+ RemoteStreamEventNames["MediaStateChange"] = "media-state-change";
1685
+ })(RemoteStreamEventNames || (RemoteStreamEventNames = {}));
1686
+ /**
1687
+ * A stream originating from a remote peer.
1688
+ */
1689
+ class _RemoteStream extends Stream {
1690
+ /**
1691
+ * Create a RemoteStream from the given values.
1692
+ *
1693
+ * @param stream - The initial output MediaStream for this Stream.
1694
+ */
1695
+ constructor(stream) {
1696
+ super(stream);
1697
+ this[_a$6] = new TypedEvent$1();
1698
+ this.handleMediaStarted = this.handleMediaStarted.bind(this);
1699
+ this.handleMediaStopped = this.handleMediaStopped.bind(this);
1700
+ this.outputTrack.addEventListener('mute', this.handleMediaStopped);
1701
+ this.outputTrack.addEventListener('unmute', this.handleMediaStarted);
1702
+ }
1703
+ /**
1704
+ * @inheritdoc
1705
+ */
1706
+ handleMediaStarted() {
1707
+ this[RemoteStreamEventNames.MediaStateChange].emit(RemoteMediaState.Started);
1708
+ }
1709
+ /**
1710
+ * @inheritdoc
1711
+ */
1712
+ handleMediaStopped() {
1713
+ this[RemoteStreamEventNames.MediaStateChange].emit(RemoteMediaState.Stopped);
1714
+ }
1715
+ /**
1716
+ * Helper function to add event handlers to a MediaStreamTrack. See
1717
+ * {@link Stream.addTrackHandlersForStreamEvents} for why this is useful.
1718
+ *
1719
+ * @param track - The MediaStreamTrack.
1720
+ */
1721
+ addTrackHandlersForRemoteStreamEvents(track) {
1722
+ track.addEventListener('mute', this.handleMediaStopped);
1723
+ track.addEventListener('unmute', this.handleMediaStarted);
1724
+ }
1725
+ /**
1726
+ * @inheritdoc
1727
+ */
1728
+ addTrackHandlers(track) {
1729
+ super.addTrackHandlers(track);
1730
+ this.addTrackHandlersForRemoteStreamEvents(track);
1731
+ }
1732
+ /**
1733
+ * @inheritdoc
1734
+ */
1735
+ removeTrackHandlers(track) {
1736
+ super.removeTrackHandlers(track);
1737
+ track.removeEventListener('mute', this.handleMediaStopped);
1738
+ track.removeEventListener('unmute', this.handleMediaStarted);
1739
+ }
1740
+ /**
1741
+ * Get whether the media on this stream has started or stopped.
1742
+ *
1743
+ * @returns The state of the media.
1744
+ */
1745
+ get mediaState() {
1746
+ return this.outputTrack.muted ? RemoteMediaState.Stopped : RemoteMediaState.Started;
1747
+ }
1748
+ /**
1749
+ * @inheritdoc
1750
+ */
1751
+ getSettings() {
1752
+ return this.outputTrack.getSettings();
1753
+ }
1754
+ /**
1755
+ * Replace the existing track on the output stream for a new track.
1756
+ *
1757
+ * @param newTrack - The track to add to the stream.
1758
+ */
1759
+ replaceTrack(newTrack) {
1760
+ const oldTrack = this.outputTrack;
1761
+ this.removeTrackHandlers(oldTrack);
1762
+ this.outputStream.removeTrack(oldTrack);
1763
+ this.outputStream.addTrack(newTrack);
1764
+ this.addTrackHandlers(newTrack);
1765
+ if (oldTrack.muted !== newTrack.muted) {
1766
+ if (newTrack.muted) {
1767
+ this.handleMediaStopped();
1768
+ }
1769
+ else {
1770
+ this.handleMediaStarted();
1771
+ }
1772
+ }
1773
+ // TODO: Chrome/React may not automatically refresh the media element with the new track when
1774
+ // the output track has changed, so we may need to emit an event here if this is the case.
1775
+ // this[StreamEventNames.OutputTrackChange].emit(newTrack);
1776
+ }
1777
+ /**
1778
+ * @inheritdoc
1779
+ */
1780
+ stop() {
1781
+ this.outputTrack.stop();
1782
+ // calling stop() will not automatically emit Ended, so we emit it here
1783
+ this[StreamEventNames.Ended].emit();
1784
+ }
1595
1785
  }
1596
-
1597
- /**
1598
- * A video LocalStream.
1599
- */
1600
- class LocalVideoStream extends LocalStream {
1601
- /**
1602
- * Apply constraints to the stream.
1603
- *
1604
- * @param constraints - The constraints to apply.
1605
- * @returns A promise which resolves when the constraints have been successfully applied.
1606
- */
1607
- applyConstraints(constraints) {
1608
- return __awaiter$2(this, void 0, void 0, function* () {
1609
- logger$3.log(`Applying constraints to local track:`, constraints);
1610
- return this.inputTrack.applyConstraints(constraints).then(() => {
1611
- this[LocalStreamEventNames.ConstraintsChange].emit();
1612
- });
1613
- });
1614
- }
1615
- /**
1616
- * Get the content hint for this stream.
1617
- *
1618
- * @returns The content hint setting for this stream, or undefined if none has been set.
1619
- */
1620
- get contentHint() {
1621
- return this.inputTrack.contentHint;
1622
- }
1623
- /**
1624
- * Set the content hint for this stream.
1625
- *
1626
- * @param hint - The content hint to set.
1627
- */
1628
- set contentHint(hint) {
1629
- this.inputTrack.contentHint = hint;
1630
- }
1631
- /**
1632
- * Check the resolution and then return how many layers will be active.
1633
- *
1634
- * @returns The active layers count.
1635
- */
1636
- getNumActiveSimulcastLayers() {
1637
- let activeSimulcastLayersNumber = 0;
1638
- const videoHeight = this.inputTrack.getSettings().height;
1639
- if (videoHeight <= 180) {
1640
- activeSimulcastLayersNumber = 1;
1641
- }
1642
- else if (videoHeight <= 360) {
1643
- activeSimulcastLayersNumber = 2;
1644
- }
1645
- else {
1646
- activeSimulcastLayersNumber = 3;
1647
- }
1648
- return activeSimulcastLayersNumber;
1649
- }
1650
- }
1651
-
1652
- /**
1653
- * A local camera stream.
1654
- */
1655
- class LocalCameraStream extends LocalVideoStream {
1656
- }
1657
-
1658
- /**
1659
- * A local display stream.
1660
- */
1661
- class LocalDisplayStream extends LocalVideoStream {
1662
- }
1663
-
1664
- /**
1665
- * A local microphone stream.
1666
- */
1667
- class LocalMicrophoneStream extends LocalAudioStream {
1668
- }
1669
-
1670
- /**
1671
- * A local system audio stream.
1672
- */
1673
- class LocalSystemAudioStream extends LocalAudioStream {
1674
- }
1675
-
1676
- var _a$6;
1677
- var RemoteMediaState;
1678
- (function (RemoteMediaState) {
1679
- RemoteMediaState["Started"] = "started";
1680
- RemoteMediaState["Stopped"] = "stopped";
1681
- })(RemoteMediaState || (RemoteMediaState = {}));
1682
- var RemoteStreamEventNames;
1683
- (function (RemoteStreamEventNames) {
1684
- RemoteStreamEventNames["MediaStateChange"] = "media-state-change";
1685
- })(RemoteStreamEventNames || (RemoteStreamEventNames = {}));
1686
- /**
1687
- * A stream originating from a remote peer.
1688
- */
1689
- class _RemoteStream extends Stream {
1690
- /**
1691
- * Create a RemoteStream from the given values.
1692
- *
1693
- * @param stream - The initial output MediaStream for this Stream.
1694
- */
1695
- constructor(stream) {
1696
- super(stream);
1697
- this[_a$6] = new TypedEvent$1();
1698
- this.handleMediaStarted = this.handleMediaStarted.bind(this);
1699
- this.handleMediaStopped = this.handleMediaStopped.bind(this);
1700
- this.outputTrack.addEventListener('mute', this.handleMediaStopped);
1701
- this.outputTrack.addEventListener('unmute', this.handleMediaStarted);
1702
- }
1703
- /**
1704
- * @inheritdoc
1705
- */
1706
- handleMediaStarted() {
1707
- this[RemoteStreamEventNames.MediaStateChange].emit(RemoteMediaState.Started);
1708
- }
1709
- /**
1710
- * @inheritdoc
1711
- */
1712
- handleMediaStopped() {
1713
- this[RemoteStreamEventNames.MediaStateChange].emit(RemoteMediaState.Stopped);
1714
- }
1715
- /**
1716
- * Helper function to add event handlers to a MediaStreamTrack. See
1717
- * {@link Stream.addTrackHandlersForStreamEvents} for why this is useful.
1718
- *
1719
- * @param track - The MediaStreamTrack.
1720
- */
1721
- addTrackHandlersForRemoteStreamEvents(track) {
1722
- track.addEventListener('mute', this.handleMediaStopped);
1723
- track.addEventListener('unmute', this.handleMediaStarted);
1724
- }
1725
- /**
1726
- * @inheritdoc
1727
- */
1728
- addTrackHandlers(track) {
1729
- super.addTrackHandlers(track);
1730
- this.addTrackHandlersForRemoteStreamEvents(track);
1731
- }
1732
- /**
1733
- * @inheritdoc
1734
- */
1735
- removeTrackHandlers(track) {
1736
- super.removeTrackHandlers(track);
1737
- track.removeEventListener('mute', this.handleMediaStopped);
1738
- track.removeEventListener('unmute', this.handleMediaStarted);
1739
- }
1740
- /**
1741
- * Get whether the media on this stream has started or stopped.
1742
- *
1743
- * @returns The state of the media.
1744
- */
1745
- get mediaState() {
1746
- return this.outputTrack.muted ? RemoteMediaState.Stopped : RemoteMediaState.Started;
1747
- }
1748
- /**
1749
- * @inheritdoc
1750
- */
1751
- getSettings() {
1752
- return this.outputTrack.getSettings();
1753
- }
1754
- /**
1755
- * Replace the existing track on the output stream for a new track.
1756
- *
1757
- * @param newTrack - The track to add to the stream.
1758
- */
1759
- replaceTrack(newTrack) {
1760
- const oldTrack = this.outputTrack;
1761
- this.removeTrackHandlers(oldTrack);
1762
- this.outputStream.removeTrack(oldTrack);
1763
- this.outputStream.addTrack(newTrack);
1764
- this.addTrackHandlers(newTrack);
1765
- if (oldTrack.muted !== newTrack.muted) {
1766
- if (newTrack.muted) {
1767
- this.handleMediaStopped();
1768
- }
1769
- else {
1770
- this.handleMediaStarted();
1771
- }
1772
- }
1773
- // TODO: Chrome/React may not automatically refresh the media element with the new track when
1774
- // the output track has changed, so we may need to emit an event here if this is the case.
1775
- // this[StreamEventNames.OutputTrackChange].emit(newTrack);
1776
- }
1777
- /**
1778
- * @inheritdoc
1779
- */
1780
- stop() {
1781
- this.outputTrack.stop();
1782
- // calling stop() will not automatically emit Ended, so we emit it here
1783
- this[StreamEventNames.Ended].emit();
1784
- }
1785
- }
1786
- _a$6 = RemoteStreamEventNames.MediaStateChange;
1786
+ _a$6 = RemoteStreamEventNames.MediaStateChange;
1787
1787
  const RemoteStream = AddEvents(_RemoteStream);
1788
1788
 
1789
1789
  var commonjsGlobal$3 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -2343,114 +2343,114 @@ function eventTargetAgnosticAddListener$2(emitter, name, listener, flags) {
2343
2343
  }
2344
2344
  }
2345
2345
 
2346
- /**
2347
- * Typed event emitter class.
2348
- */
2349
- class EventEmitter$4 extends events$2.exports.EventEmitter {
2350
- }
2351
-
2352
- // Overall connection state (based on the ICE and DTLS connection states)
2353
- var ConnectionState;
2354
- (function (ConnectionState) {
2355
- ConnectionState["New"] = "New";
2356
- ConnectionState["Closed"] = "Closed";
2357
- ConnectionState["Connected"] = "Connected";
2358
- ConnectionState["Connecting"] = "Connecting";
2359
- ConnectionState["Disconnected"] = "Disconnected";
2360
- ConnectionState["Failed"] = "Failed";
2361
- })(ConnectionState || (ConnectionState = {}));
2362
- var ConnectionStateEvents;
2363
- (function (ConnectionStateEvents) {
2364
- ConnectionStateEvents["PeerConnectionStateChanged"] = "PeerConnectionStateChanged";
2365
- ConnectionStateEvents["IceConnectionStateChanged"] = "IceConnectionStateChanged";
2366
- })(ConnectionStateEvents || (ConnectionStateEvents = {}));
2367
- /**
2368
- * Listens on the connection's ICE and DTLS state changes and emits a single
2369
- * event that summarizes all the internal states into a single overall connection state.
2370
- */
2371
- class ConnectionStateHandler extends EventEmitter$4 {
2372
- /**
2373
- * Creates an instance of ConnectionStateHandler.
2374
- *
2375
- * @param getCurrentStatesCallback - Callback for getting the connection state information
2376
- * from the peer connection.
2377
- */
2378
- constructor(getCurrentStatesCallback) {
2379
- super();
2380
- this.getCurrentStatesCallback = getCurrentStatesCallback;
2381
- }
2382
- /**
2383
- * Handler for connection state change.
2384
- */
2385
- onPeerConnectionStateChange() {
2386
- const state = this.getPeerConnectionState();
2387
- this.emit(ConnectionStateEvents.PeerConnectionStateChanged, state);
2388
- }
2389
- /**
2390
- * Handler for ice connection state change.
2391
- */
2392
- onIceConnectionStateChange() {
2393
- const state = this.getIceConnectionState();
2394
- this.emit(ConnectionStateEvents.IceConnectionStateChanged, state);
2395
- }
2396
- /**
2397
- * Evaluates the overall connection state based on peer connection's
2398
- * connectionState and iceConnectionState.
2399
- *
2400
- * @returns Current overall connection state.
2401
- */
2402
- evaluateMediaConnectionState() {
2403
- const { connectionState, iceState } = this.getCurrentStatesCallback();
2404
- const connectionStates = [connectionState, iceState];
2405
- let mediaConnectionState;
2406
- if (connectionStates.every((value) => value === 'new')) {
2407
- mediaConnectionState = ConnectionState.New;
2408
- }
2409
- else if (connectionStates.some((value) => value === 'closed')) {
2410
- mediaConnectionState = ConnectionState.Closed;
2411
- }
2412
- else if (connectionStates.some((value) => value === 'failed')) {
2413
- mediaConnectionState = ConnectionState.Failed;
2414
- }
2415
- else if (connectionStates.some((value) => value === 'disconnected')) {
2416
- mediaConnectionState = ConnectionState.Disconnected;
2417
- }
2418
- else if (connectionStates.every((value) => value === 'connected' || value === 'completed')) {
2419
- mediaConnectionState = ConnectionState.Connected;
2420
- }
2421
- else {
2422
- mediaConnectionState = ConnectionState.Connecting;
2423
- }
2424
- logger$3.log(`iceConnectionState=${iceState} connectionState=${connectionState} => ${mediaConnectionState}`);
2425
- return mediaConnectionState;
2426
- }
2427
- /**
2428
- * Gets current connection state.
2429
- *
2430
- * @returns Current connection state.
2431
- */
2432
- getPeerConnectionState() {
2433
- const { connectionState } = this.getCurrentStatesCallback();
2434
- return connectionState;
2435
- }
2436
- /**
2437
- * Gets current ice connection state.
2438
- *
2439
- * @returns Current ice connection state.
2440
- */
2441
- getIceConnectionState() {
2442
- const { iceState } = this.getCurrentStatesCallback();
2443
- return iceState;
2444
- }
2445
- /**
2446
- * Gets current overall connection state.
2447
- *
2448
- * @returns Current overall connection state.
2449
- */
2450
- getConnectionState() {
2451
- return this.evaluateMediaConnectionState();
2452
- }
2453
- }
2346
+ /**
2347
+ * Typed event emitter class.
2348
+ */
2349
+ class EventEmitter$4 extends events$2.exports.EventEmitter {
2350
+ }
2351
+
2352
+ // Overall connection state (based on the ICE and DTLS connection states)
2353
+ var ConnectionState;
2354
+ (function (ConnectionState) {
2355
+ ConnectionState["New"] = "New";
2356
+ ConnectionState["Closed"] = "Closed";
2357
+ ConnectionState["Connected"] = "Connected";
2358
+ ConnectionState["Connecting"] = "Connecting";
2359
+ ConnectionState["Disconnected"] = "Disconnected";
2360
+ ConnectionState["Failed"] = "Failed";
2361
+ })(ConnectionState || (ConnectionState = {}));
2362
+ var ConnectionStateEvents;
2363
+ (function (ConnectionStateEvents) {
2364
+ ConnectionStateEvents["PeerConnectionStateChanged"] = "PeerConnectionStateChanged";
2365
+ ConnectionStateEvents["IceConnectionStateChanged"] = "IceConnectionStateChanged";
2366
+ })(ConnectionStateEvents || (ConnectionStateEvents = {}));
2367
+ /**
2368
+ * Listens on the connection's ICE and DTLS state changes and emits a single
2369
+ * event that summarizes all the internal states into a single overall connection state.
2370
+ */
2371
+ class ConnectionStateHandler extends EventEmitter$4 {
2372
+ /**
2373
+ * Creates an instance of ConnectionStateHandler.
2374
+ *
2375
+ * @param getCurrentStatesCallback - Callback for getting the connection state information
2376
+ * from the peer connection.
2377
+ */
2378
+ constructor(getCurrentStatesCallback) {
2379
+ super();
2380
+ this.getCurrentStatesCallback = getCurrentStatesCallback;
2381
+ }
2382
+ /**
2383
+ * Handler for connection state change.
2384
+ */
2385
+ onPeerConnectionStateChange() {
2386
+ const state = this.getPeerConnectionState();
2387
+ this.emit(ConnectionStateEvents.PeerConnectionStateChanged, state);
2388
+ }
2389
+ /**
2390
+ * Handler for ice connection state change.
2391
+ */
2392
+ onIceConnectionStateChange() {
2393
+ const state = this.getIceConnectionState();
2394
+ this.emit(ConnectionStateEvents.IceConnectionStateChanged, state);
2395
+ }
2396
+ /**
2397
+ * Evaluates the overall connection state based on peer connection's
2398
+ * connectionState and iceConnectionState.
2399
+ *
2400
+ * @returns Current overall connection state.
2401
+ */
2402
+ evaluateMediaConnectionState() {
2403
+ const { connectionState, iceState } = this.getCurrentStatesCallback();
2404
+ const connectionStates = [connectionState, iceState];
2405
+ let mediaConnectionState;
2406
+ if (connectionStates.every((value) => value === 'new')) {
2407
+ mediaConnectionState = ConnectionState.New;
2408
+ }
2409
+ else if (connectionStates.some((value) => value === 'closed')) {
2410
+ mediaConnectionState = ConnectionState.Closed;
2411
+ }
2412
+ else if (connectionStates.some((value) => value === 'failed')) {
2413
+ mediaConnectionState = ConnectionState.Failed;
2414
+ }
2415
+ else if (connectionStates.some((value) => value === 'disconnected')) {
2416
+ mediaConnectionState = ConnectionState.Disconnected;
2417
+ }
2418
+ else if (connectionStates.every((value) => value === 'connected' || value === 'completed')) {
2419
+ mediaConnectionState = ConnectionState.Connected;
2420
+ }
2421
+ else {
2422
+ mediaConnectionState = ConnectionState.Connecting;
2423
+ }
2424
+ logger$3.log(`iceConnectionState=${iceState} connectionState=${connectionState} => ${mediaConnectionState}`);
2425
+ return mediaConnectionState;
2426
+ }
2427
+ /**
2428
+ * Gets current connection state.
2429
+ *
2430
+ * @returns Current connection state.
2431
+ */
2432
+ getPeerConnectionState() {
2433
+ const { connectionState } = this.getCurrentStatesCallback();
2434
+ return connectionState;
2435
+ }
2436
+ /**
2437
+ * Gets current ice connection state.
2438
+ *
2439
+ * @returns Current ice connection state.
2440
+ */
2441
+ getIceConnectionState() {
2442
+ const { iceState } = this.getCurrentStatesCallback();
2443
+ return iceState;
2444
+ }
2445
+ /**
2446
+ * Gets current overall connection state.
2447
+ *
2448
+ * @returns Current overall connection state.
2449
+ */
2450
+ getConnectionState() {
2451
+ return this.evaluateMediaConnectionState();
2452
+ }
2453
+ }
2454
2454
  ConnectionStateHandler.Events = ConnectionStateEvents;
2455
2455
 
2456
2456
  /*
@@ -5808,341 +5808,345 @@ function adapterFactory({window} = {}, options = {
5808
5808
 
5809
5809
  adapterFactory({window: typeof window === 'undefined' ? undefined : window});
5810
5810
 
5811
- /**
5812
- * Creates an RTCPeerConnection.
5813
- *
5814
- * @param configuration - Config to the RTCPeerConnection constructor.
5815
- * @returns An RTCPeerConnection instance.
5816
- */
5817
- function createRTCPeerConnection(configuration) {
5818
- return new RTCPeerConnection(configuration);
5819
- }
5820
-
5821
- /**
5822
- * A type-safe form of the DOMString used in the MediaStreamTrack.kind field.
5823
- */
5824
- var MediaStreamTrackKind;
5825
- (function (MediaStreamTrackKind) {
5826
- MediaStreamTrackKind["Audio"] = "audio";
5827
- MediaStreamTrackKind["Video"] = "video";
5828
- })(MediaStreamTrackKind || (MediaStreamTrackKind = {}));
5829
- var PeerConnectionEvents;
5830
- (function (PeerConnectionEvents) {
5831
- PeerConnectionEvents["IceGatheringStateChange"] = "icegatheringstatechange";
5832
- PeerConnectionEvents["IceCandidate"] = "icecandidate";
5833
- PeerConnectionEvents["PeerConnectionStateChange"] = "peerconnectionstatechange";
5834
- PeerConnectionEvents["IceConnectionStateChange"] = "iceconnectionstatechange";
5835
- PeerConnectionEvents["CreateOfferOnSuccess"] = "createofferonsuccess";
5836
- PeerConnectionEvents["CreateAnswerOnSuccess"] = "createansweronsuccess";
5837
- PeerConnectionEvents["SetLocalDescriptionOnSuccess"] = "setlocaldescriptiononsuccess";
5838
- PeerConnectionEvents["SetRemoteDescriptionOnSuccess"] = "setremotedescriptiononsuccess";
5839
- })(PeerConnectionEvents || (PeerConnectionEvents = {}));
5840
- /**
5841
- * Manages a single RTCPeerConnection with the server.
5842
- */
5843
- class PeerConnection extends EventEmitter$4 {
5844
- /**
5845
- * Creates an instance of the RTCPeerConnection.
5846
- *
5847
- * @param configuration - Config to the RTCPeerConnection constructor.
5848
- */
5849
- constructor(configuration) {
5850
- super();
5851
- logger$3.log('PeerConnection init');
5852
- this.pc = createRTCPeerConnection(configuration);
5853
- this.connectionStateHandler = new ConnectionStateHandler(() => {
5854
- return {
5855
- connectionState: this.pc.connectionState,
5856
- iceState: this.pc.iceConnectionState,
5857
- };
5858
- });
5859
- this.connectionStateHandler.on(ConnectionStateHandler.Events.PeerConnectionStateChanged, (state) => {
5860
- this.emit(PeerConnection.Events.PeerConnectionStateChange, state);
5861
- });
5862
- this.connectionStateHandler.on(ConnectionStateHandler.Events.IceConnectionStateChanged, (state) => {
5863
- this.emit(PeerConnection.Events.IceConnectionStateChange, state);
5864
- });
5865
- // Forward the connection state related events to connection state handler
5866
- // eslint-disable-next-line jsdoc/require-jsdoc
5867
- this.pc.oniceconnectionstatechange = () => this.connectionStateHandler.onIceConnectionStateChange();
5868
- // eslint-disable-next-line jsdoc/require-jsdoc
5869
- this.pc.onconnectionstatechange = () => this.connectionStateHandler.onPeerConnectionStateChange();
5870
- // Subscribe to underlying PeerConnection events and emit them via the EventEmitter
5871
- /* eslint-disable jsdoc/require-jsdoc */
5872
- this.pc.onicegatheringstatechange = (ev) => {
5873
- this.emit(PeerConnection.Events.IceGatheringStateChange, ev);
5874
- };
5875
- /* eslint-disable jsdoc/require-jsdoc */
5876
- this.pc.onicecandidate = (ev) => {
5877
- this.emit(PeerConnection.Events.IceCandidate, ev);
5878
- };
5879
- }
5880
- /**
5881
- * Get the underlying RTCPeerConnection.
5882
- *
5883
- * @returns The underlying RTCPeerConnection.
5884
- */
5885
- getUnderlyingRTCPeerConnection() {
5886
- return this.pc;
5887
- }
5888
- /**
5889
- * Gets the overall connection state of the underlying RTCPeerConnection.
5890
- *
5891
- * @returns The underlying connection's overall state.
5892
- */
5893
- getConnectionState() {
5894
- return this.connectionStateHandler.getConnectionState();
5895
- }
5896
- /**
5897
- * Gets the connection state of the underlying RTCPeerConnection.
5898
- *
5899
- * @returns The underlying RTCPeerConnection connection state.
5900
- */
5901
- getPeerConnectionState() {
5902
- return this.connectionStateHandler.getPeerConnectionState();
5903
- }
5904
- /**
5905
- * Gets the ICE connection state of the underlying RTCPeerConnection.
5906
- *
5907
- * @returns The underlying RTCPeerConnection ICE connection state.
5908
- */
5909
- getIceConnectionState() {
5910
- return this.connectionStateHandler.getIceConnectionState();
5911
- }
5912
- /**
5913
- * Adds a new media track to the set of tracks which will be transmitted to the other peer.
5914
- *
5915
- * @param track - A MediaStreamTrack object representing the media track to add to the peer connection.
5916
- * @param streams - (Optional) One or more local MediaStream objects to which the track should be
5917
- * added.
5918
- * @returns The RTCRtpSender object which will be used to transmit the media data, or null if
5919
- * there is no underlying track when a track is added.
5920
- */
5921
- addTrack(track, ...streams) {
5922
- return this.pc.addTrack(track, ...streams);
5923
- }
5924
- /**
5925
- * Creates a new RTCRtpTransceiver and adds it to the set of transceivers associated with the
5926
- * PeerConnection. Each transceiver represents a bidirectional stream, with both an RTCRtpSender
5927
- * and an RTCRtpReceiver associated with it.
5928
- *
5929
- * @param trackOrKind - A MediaStreamTrack to associate with the transceiver, or a string which is used
5930
- * as the kind of the receiver's track, and by extension the RTCRtpReceiver itself.
5931
- * @param init - Options that you may wish to specify when creating the new transceiver.
5932
- * @returns - The created RTCRtpTransceiver object.
5933
- */
5934
- addTransceiver(trackOrKind, init) {
5935
- return this.pc.addTransceiver(trackOrKind, init);
5936
- }
5937
- /**
5938
- * Tell the local end of the connection to stop sending media from the specified track, without
5939
- * actually removing the corresponding RTCRtpSender from the list of senders as reported by
5940
- * RTCPeerConnection.getSenders(). If the track is already stopped, or is not in the connection's
5941
- * senders list, the method has no effect.
5942
- *
5943
- * If the connection has already been negotiated (signalingState is set to 'stable'), it is marked
5944
- * as needing to be negotiated again; the remote peer won't experience the change until this
5945
- * negotiation occurs. A negotiatedneeded event is sent to the RTCPeerConnection to let the local
5946
- * end know this negotiation must occur.
5947
- *
5948
- * @param sender - An RTCRtpSender specifying the sender to remove from the connection.
5949
- */
5950
- removeTrack(sender) {
5951
- this.pc.removeTrack(sender);
5952
- }
5953
- /**
5954
- * Creates a new data channel linked with the remote peer.
5955
- *
5956
- * @param label - A human-readable name for the channel. May not be longer than 65,535 bytes.
5957
- * @param options - An object providing configuration options for the data channel.
5958
- * @returns An RTCDataChannel object.
5959
- */
5960
- createDataChannel(label, options) {
5961
- return this.pc.createDataChannel(label, options);
5962
- }
5963
- /**
5964
- * Creates an SDP answer to an offer received from a remote peer during the offer/answer
5965
- * negotiation of a WebRTC connection.
5966
- *
5967
- * @param options - (Optional) An object which contains options which customize the answer; this
5968
- * is based on the RTCAnswerOptions dictionary.
5969
- * @returns A Promise whose fulfillment handler is called with an object conforming to the
5970
- * RTCSessionDescriptionInit dictionary which contains the SDP answer to be delivered to the
5971
- * other peer.
5972
- */
5973
- createAnswer(options) {
5974
- return __awaiter$2(this, void 0, void 0, function* () {
5975
- return this.pc.createAnswer(options).then((answer) => {
5976
- this.emit(PeerConnection.Events.CreateAnswerOnSuccess, answer);
5977
- return answer;
5978
- });
5979
- });
5980
- }
5981
- /**
5982
- * Initiates the creation of an SDP offer for the purpose of starting a new WebRTC connection to a
5983
- * remote peer.
5984
- *
5985
- * @param options - (Optional) An RTCOfferOptions dictionary providing options requested for the
5986
- * offer.
5987
- * @returns A Promise whose fulfillment handler will receive an object conforming to the
5988
- * RTCSessionDescriptionInit dictionary which contains the SDP describing the generated offer.
5989
- * That received offer should be delivered through the signaling server to a remote peer.
5990
- */
5991
- createOffer(options) {
5992
- return __awaiter$2(this, void 0, void 0, function* () {
5993
- return this.pc.createOffer(options).then((offer) => {
5994
- this.emit(PeerConnection.Events.CreateOfferOnSuccess, offer);
5995
- return offer;
5996
- });
5997
- });
5998
- }
5999
- /**
6000
- * Changes the local description associated with the connection.
6001
- *
6002
- * @param description - An RTCSessionDescriptionInit or RTCSessionDescription which specifies the
6003
- * configuration to be applied to the local end of the connection.
6004
- * @returns A Promise which is fulfilled once the value of RTCPeerConnection.localDescription is
6005
- * successfully changed or rejected if the change cannot be applied.
6006
- */
6007
- setLocalDescription(description) {
6008
- var _a;
6009
- return __awaiter$2(this, void 0, void 0, function* () {
6010
- // In Firefox, setLocalDescription will not throw an error if an m-line has no codecs, even
6011
- // though it violates https://datatracker.ietf.org/doc/html/rfc8866. See
6012
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1857612. So, we check the media lines here to
6013
- // preemptively throw an error on Firefox.
6014
- if (BrowserInfo$1.isFirefox()) {
6015
- (_a = description === null || description === void 0 ? void 0 : description.sdp) === null || _a === void 0 ? void 0 : _a.split(/(\r\n|\r|\n)/).filter((line) => line.startsWith('m')).forEach((mediaLine) => {
6016
- if (mediaLine.trim().split(' ').length < 4) {
6017
- throw new Error(`Invalid media line ${mediaLine}, expected at least 4 fields`);
6018
- }
6019
- });
6020
- }
6021
- return this.pc.setLocalDescription(description).then(() => {
6022
- if (description) {
6023
- this.emit(PeerConnection.Events.SetLocalDescriptionOnSuccess, description);
6024
- }
6025
- });
6026
- });
6027
- }
6028
- /**
6029
- * Sets the specified session description as the remote peer's current offer or answer.
6030
- *
6031
- * @param description - An RTCSessionDescriptionInit or RTCSessionDescription which specifies the
6032
- * remote peer's current offer or answer.
6033
- * @returns A Promise which is fulfilled once the value of the connection's remoteDescription is
6034
- * successfully changed or rejected if the change cannot be applied (for example, if the
6035
- * specified description is incompatible with one or both of the peers on the connection).
6036
- */
6037
- setRemoteDescription(description) {
6038
- return __awaiter$2(this, void 0, void 0, function* () {
6039
- return this.pc.setRemoteDescription(description).then(() => {
6040
- this.emit(PeerConnection.Events.SetRemoteDescriptionOnSuccess, description);
6041
- });
6042
- });
6043
- }
6044
- /**
6045
- * Closes the current peer connection.
6046
- */
6047
- close() {
6048
- this.pc.close();
6049
- }
6050
- /**
6051
- * Get the local description from this PeerConnection.
6052
- *
6053
- * @returns An RTCSessionDescription representing the local description, or null if none has been set.
6054
- */
6055
- getLocalDescription() {
6056
- return this.pc.localDescription;
6057
- }
6058
- /**
6059
- * Get the remote description from this PeerConnection.
6060
- *
6061
- * @returns An RTCSessionDescription representing the remote description, or null if none has been set.
6062
- */
6063
- getRemoteDescription() {
6064
- return this.pc.remoteDescription;
6065
- }
6066
- /**
6067
- * Returns an array of RTCRtpSender objects, each of which represents the RTP sender responsible
6068
- * for transmitting one track's data. A sender object provides methods and properties for
6069
- * examining and controlling the encoding and transmission of the track's data.
6070
- *
6071
- * @returns An array of RTCRtpSender objects, one for each track on the connection. The array is
6072
- * empty if there are no RTP senders on the connection.
6073
- */
6074
- getSenders() {
6075
- return this.pc.getSenders();
6076
- }
6077
- /**
6078
- * Get the list of RTCRtpTransceiver objects being used to send and receive data on the
6079
- * connection.
6080
- *
6081
- * @returns - An array of the RTCRtpTransceiver objects representing the transceivers handling
6082
- * sending and receiving all media on the PeerConnection. The list is in the order in which the
6083
- * transceivers were added to the connection.
6084
- */
6085
- getTransceivers() {
6086
- return this.pc.getTransceivers();
6087
- }
6088
- /**
6089
- * Get statistics about either the overall connection or about the specified MediaStreamTrack.
6090
- *
6091
- * @param selector - An optional MediaStreamTrack for which to gather statistics. If not provided,
6092
- * statistics will be gathered for the entire underlying RTCPeerConnection.
6093
- * @returns - A Promise which resolves with an RTCStatsReport object providing connection
6094
- * statistics.
6095
- */
6096
- getStats(selector) {
6097
- return this.pc.getStats(selector);
6098
- }
6099
- /**
6100
- * Returns a string that describes the connections' ICE gathering state.
6101
- *
6102
- * @returns - The ICE gathering state.
6103
- */
6104
- get iceGatheringState() {
6105
- return this.pc.iceGatheringState;
6106
- }
6107
- /**
6108
- * Returns the type of a connection that has been established.
6109
- *
6110
- * @returns The connection type which would be `ConnectionType`.
6111
- */
6112
- getCurrentConnectionType() {
6113
- var _a;
6114
- return __awaiter$2(this, void 0, void 0, function* () {
6115
- // make sure this method only can be called when the ice connection is established;
6116
- const isIceConnected = this.pc.iceConnectionState === 'connected' || this.pc.iceConnectionState === 'completed';
6117
- if (!isIceConnected) {
6118
- throw new Error('Ice connection is not established');
6119
- }
6120
- const succeededLocalCandidateIds = new Set();
6121
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6122
- const localCandidateStatsReports = [];
6123
- (yield this.pc.getStats()).forEach((report) => {
6124
- var _a;
6125
- // collect all local candidate ids from `candidate-pair` stats reports with `succeeded` state.
6126
- if (report.type === 'candidate-pair' && ((_a = report.state) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'succeeded') {
6127
- succeededLocalCandidateIds.add(report.localCandidateId);
6128
- }
6129
- // collect all `local-candidate` stats.
6130
- if (report.type === 'local-candidate') {
6131
- localCandidateStatsReports.push(report);
6132
- }
6133
- });
6134
- // find the `local-candidate` stats which report id contains in `succeededLocalCandidateIds`.
6135
- const localCandidate = localCandidateStatsReports.find((report) => succeededLocalCandidateIds.has(report.id));
6136
- if (!localCandidate) {
6137
- return 'unknown';
6138
- }
6139
- if (localCandidate.relayProtocol) {
6140
- return `TURN-${localCandidate.relayProtocol.toUpperCase()}`;
6141
- }
6142
- return (_a = localCandidate.protocol) === null || _a === void 0 ? void 0 : _a.toUpperCase();
6143
- });
6144
- }
6145
- }
5811
+ /**
5812
+ * Creates an RTCPeerConnection.
5813
+ *
5814
+ * @param configuration - Config to the RTCPeerConnection constructor.
5815
+ * @returns An RTCPeerConnection instance.
5816
+ */
5817
+ function createRTCPeerConnection(configuration) {
5818
+ return new RTCPeerConnection(configuration);
5819
+ }
5820
+
5821
+ /**
5822
+ * A type-safe form of the DOMString used in the MediaStreamTrack.kind field.
5823
+ */
5824
+ var MediaStreamTrackKind;
5825
+ (function (MediaStreamTrackKind) {
5826
+ MediaStreamTrackKind["Audio"] = "audio";
5827
+ MediaStreamTrackKind["Video"] = "video";
5828
+ })(MediaStreamTrackKind || (MediaStreamTrackKind = {}));
5829
+ var PeerConnectionEvents;
5830
+ (function (PeerConnectionEvents) {
5831
+ PeerConnectionEvents["IceGatheringStateChange"] = "icegatheringstatechange";
5832
+ PeerConnectionEvents["IceCandidate"] = "icecandidate";
5833
+ PeerConnectionEvents["IceCandidateError"] = "icecandidateerror";
5834
+ PeerConnectionEvents["PeerConnectionStateChange"] = "peerconnectionstatechange";
5835
+ PeerConnectionEvents["IceConnectionStateChange"] = "iceconnectionstatechange";
5836
+ PeerConnectionEvents["CreateOfferOnSuccess"] = "createofferonsuccess";
5837
+ PeerConnectionEvents["CreateAnswerOnSuccess"] = "createansweronsuccess";
5838
+ PeerConnectionEvents["SetLocalDescriptionOnSuccess"] = "setlocaldescriptiononsuccess";
5839
+ PeerConnectionEvents["SetRemoteDescriptionOnSuccess"] = "setremotedescriptiononsuccess";
5840
+ })(PeerConnectionEvents || (PeerConnectionEvents = {}));
5841
+ /**
5842
+ * Manages a single RTCPeerConnection with the server.
5843
+ */
5844
+ class PeerConnection extends EventEmitter$4 {
5845
+ /**
5846
+ * Creates an instance of the RTCPeerConnection.
5847
+ *
5848
+ * @param configuration - Config to the RTCPeerConnection constructor.
5849
+ */
5850
+ constructor(configuration) {
5851
+ super();
5852
+ logger$3.log('PeerConnection init');
5853
+ this.pc = createRTCPeerConnection(configuration);
5854
+ this.connectionStateHandler = new ConnectionStateHandler(() => {
5855
+ return {
5856
+ connectionState: this.pc.connectionState,
5857
+ iceState: this.pc.iceConnectionState,
5858
+ };
5859
+ });
5860
+ this.connectionStateHandler.on(ConnectionStateHandler.Events.PeerConnectionStateChanged, (state) => {
5861
+ this.emit(PeerConnection.Events.PeerConnectionStateChange, state);
5862
+ });
5863
+ this.connectionStateHandler.on(ConnectionStateHandler.Events.IceConnectionStateChanged, (state) => {
5864
+ this.emit(PeerConnection.Events.IceConnectionStateChange, state);
5865
+ });
5866
+ // Forward the connection state related events to connection state handler
5867
+ // eslint-disable-next-line jsdoc/require-jsdoc
5868
+ this.pc.oniceconnectionstatechange = () => this.connectionStateHandler.onIceConnectionStateChange();
5869
+ // eslint-disable-next-line jsdoc/require-jsdoc
5870
+ this.pc.onconnectionstatechange = () => this.connectionStateHandler.onPeerConnectionStateChange();
5871
+ // Subscribe to underlying PeerConnection events and emit them via the EventEmitter
5872
+ /* eslint-disable jsdoc/require-jsdoc */
5873
+ this.pc.onicegatheringstatechange = (ev) => {
5874
+ this.emit(PeerConnection.Events.IceGatheringStateChange, ev);
5875
+ };
5876
+ /* eslint-disable jsdoc/require-jsdoc */
5877
+ this.pc.onicecandidate = (ev) => {
5878
+ this.emit(PeerConnection.Events.IceCandidate, ev);
5879
+ };
5880
+ this.pc.onicecandidateerror = (ev) => {
5881
+ this.emit(PeerConnection.Events.IceCandidateError, ev);
5882
+ };
5883
+ }
5884
+ /**
5885
+ * Get the underlying RTCPeerConnection.
5886
+ *
5887
+ * @returns The underlying RTCPeerConnection.
5888
+ */
5889
+ getUnderlyingRTCPeerConnection() {
5890
+ return this.pc;
5891
+ }
5892
+ /**
5893
+ * Gets the overall connection state of the underlying RTCPeerConnection.
5894
+ *
5895
+ * @returns The underlying connection's overall state.
5896
+ */
5897
+ getConnectionState() {
5898
+ return this.connectionStateHandler.getConnectionState();
5899
+ }
5900
+ /**
5901
+ * Gets the connection state of the underlying RTCPeerConnection.
5902
+ *
5903
+ * @returns The underlying RTCPeerConnection connection state.
5904
+ */
5905
+ getPeerConnectionState() {
5906
+ return this.connectionStateHandler.getPeerConnectionState();
5907
+ }
5908
+ /**
5909
+ * Gets the ICE connection state of the underlying RTCPeerConnection.
5910
+ *
5911
+ * @returns The underlying RTCPeerConnection ICE connection state.
5912
+ */
5913
+ getIceConnectionState() {
5914
+ return this.connectionStateHandler.getIceConnectionState();
5915
+ }
5916
+ /**
5917
+ * Adds a new media track to the set of tracks which will be transmitted to the other peer.
5918
+ *
5919
+ * @param track - A MediaStreamTrack object representing the media track to add to the peer connection.
5920
+ * @param streams - (Optional) One or more local MediaStream objects to which the track should be
5921
+ * added.
5922
+ * @returns The RTCRtpSender object which will be used to transmit the media data, or null if
5923
+ * there is no underlying track when a track is added.
5924
+ */
5925
+ addTrack(track, ...streams) {
5926
+ return this.pc.addTrack(track, ...streams);
5927
+ }
5928
+ /**
5929
+ * Creates a new RTCRtpTransceiver and adds it to the set of transceivers associated with the
5930
+ * PeerConnection. Each transceiver represents a bidirectional stream, with both an RTCRtpSender
5931
+ * and an RTCRtpReceiver associated with it.
5932
+ *
5933
+ * @param trackOrKind - A MediaStreamTrack to associate with the transceiver, or a string which is used
5934
+ * as the kind of the receiver's track, and by extension the RTCRtpReceiver itself.
5935
+ * @param init - Options that you may wish to specify when creating the new transceiver.
5936
+ * @returns - The created RTCRtpTransceiver object.
5937
+ */
5938
+ addTransceiver(trackOrKind, init) {
5939
+ return this.pc.addTransceiver(trackOrKind, init);
5940
+ }
5941
+ /**
5942
+ * Tell the local end of the connection to stop sending media from the specified track, without
5943
+ * actually removing the corresponding RTCRtpSender from the list of senders as reported by
5944
+ * RTCPeerConnection.getSenders(). If the track is already stopped, or is not in the connection's
5945
+ * senders list, the method has no effect.
5946
+ *
5947
+ * If the connection has already been negotiated (signalingState is set to 'stable'), it is marked
5948
+ * as needing to be negotiated again; the remote peer won't experience the change until this
5949
+ * negotiation occurs. A negotiatedneeded event is sent to the RTCPeerConnection to let the local
5950
+ * end know this negotiation must occur.
5951
+ *
5952
+ * @param sender - An RTCRtpSender specifying the sender to remove from the connection.
5953
+ */
5954
+ removeTrack(sender) {
5955
+ this.pc.removeTrack(sender);
5956
+ }
5957
+ /**
5958
+ * Creates a new data channel linked with the remote peer.
5959
+ *
5960
+ * @param label - A human-readable name for the channel. May not be longer than 65,535 bytes.
5961
+ * @param options - An object providing configuration options for the data channel.
5962
+ * @returns An RTCDataChannel object.
5963
+ */
5964
+ createDataChannel(label, options) {
5965
+ return this.pc.createDataChannel(label, options);
5966
+ }
5967
+ /**
5968
+ * Creates an SDP answer to an offer received from a remote peer during the offer/answer
5969
+ * negotiation of a WebRTC connection.
5970
+ *
5971
+ * @param options - (Optional) An object which contains options which customize the answer; this
5972
+ * is based on the RTCAnswerOptions dictionary.
5973
+ * @returns A Promise whose fulfillment handler is called with an object conforming to the
5974
+ * RTCSessionDescriptionInit dictionary which contains the SDP answer to be delivered to the
5975
+ * other peer.
5976
+ */
5977
+ createAnswer(options) {
5978
+ return __awaiter$2(this, void 0, void 0, function* () {
5979
+ return this.pc.createAnswer(options).then((answer) => {
5980
+ this.emit(PeerConnection.Events.CreateAnswerOnSuccess, answer);
5981
+ return answer;
5982
+ });
5983
+ });
5984
+ }
5985
+ /**
5986
+ * Initiates the creation of an SDP offer for the purpose of starting a new WebRTC connection to a
5987
+ * remote peer.
5988
+ *
5989
+ * @param options - (Optional) An RTCOfferOptions dictionary providing options requested for the
5990
+ * offer.
5991
+ * @returns A Promise whose fulfillment handler will receive an object conforming to the
5992
+ * RTCSessionDescriptionInit dictionary which contains the SDP describing the generated offer.
5993
+ * That received offer should be delivered through the signaling server to a remote peer.
5994
+ */
5995
+ createOffer(options) {
5996
+ return __awaiter$2(this, void 0, void 0, function* () {
5997
+ return this.pc.createOffer(options).then((offer) => {
5998
+ this.emit(PeerConnection.Events.CreateOfferOnSuccess, offer);
5999
+ return offer;
6000
+ });
6001
+ });
6002
+ }
6003
+ /**
6004
+ * Changes the local description associated with the connection.
6005
+ *
6006
+ * @param description - An RTCSessionDescriptionInit or RTCSessionDescription which specifies the
6007
+ * configuration to be applied to the local end of the connection.
6008
+ * @returns A Promise which is fulfilled once the value of RTCPeerConnection.localDescription is
6009
+ * successfully changed or rejected if the change cannot be applied.
6010
+ */
6011
+ setLocalDescription(description) {
6012
+ return __awaiter$2(this, void 0, void 0, function* () {
6013
+ var _a;
6014
+ // In Firefox, setLocalDescription will not throw an error if an m-line has no codecs, even
6015
+ // though it violates https://datatracker.ietf.org/doc/html/rfc8866. See
6016
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1857612. So, we check the media lines here to
6017
+ // preemptively throw an error on Firefox.
6018
+ if (BrowserInfo$1.isFirefox()) {
6019
+ (_a = description === null || description === void 0 ? void 0 : description.sdp) === null || _a === void 0 ? void 0 : _a.split(/(\r\n|\r|\n)/).filter((line) => line.startsWith('m')).forEach((mediaLine) => {
6020
+ if (mediaLine.trim().split(' ').length < 4) {
6021
+ throw new Error(`Invalid media line ${mediaLine}, expected at least 4 fields`);
6022
+ }
6023
+ });
6024
+ }
6025
+ return this.pc.setLocalDescription(description).then(() => {
6026
+ if (description) {
6027
+ this.emit(PeerConnection.Events.SetLocalDescriptionOnSuccess, description);
6028
+ }
6029
+ });
6030
+ });
6031
+ }
6032
+ /**
6033
+ * Sets the specified session description as the remote peer's current offer or answer.
6034
+ *
6035
+ * @param description - An RTCSessionDescriptionInit or RTCSessionDescription which specifies the
6036
+ * remote peer's current offer or answer.
6037
+ * @returns A Promise which is fulfilled once the value of the connection's remoteDescription is
6038
+ * successfully changed or rejected if the change cannot be applied (for example, if the
6039
+ * specified description is incompatible with one or both of the peers on the connection).
6040
+ */
6041
+ setRemoteDescription(description) {
6042
+ return __awaiter$2(this, void 0, void 0, function* () {
6043
+ return this.pc.setRemoteDescription(description).then(() => {
6044
+ this.emit(PeerConnection.Events.SetRemoteDescriptionOnSuccess, description);
6045
+ });
6046
+ });
6047
+ }
6048
+ /**
6049
+ * Closes the current peer connection.
6050
+ */
6051
+ close() {
6052
+ this.pc.close();
6053
+ }
6054
+ /**
6055
+ * Get the local description from this PeerConnection.
6056
+ *
6057
+ * @returns An RTCSessionDescription representing the local description, or null if none has been set.
6058
+ */
6059
+ getLocalDescription() {
6060
+ return this.pc.localDescription;
6061
+ }
6062
+ /**
6063
+ * Get the remote description from this PeerConnection.
6064
+ *
6065
+ * @returns An RTCSessionDescription representing the remote description, or null if none has been set.
6066
+ */
6067
+ getRemoteDescription() {
6068
+ return this.pc.remoteDescription;
6069
+ }
6070
+ /**
6071
+ * Returns an array of RTCRtpSender objects, each of which represents the RTP sender responsible
6072
+ * for transmitting one track's data. A sender object provides methods and properties for
6073
+ * examining and controlling the encoding and transmission of the track's data.
6074
+ *
6075
+ * @returns An array of RTCRtpSender objects, one for each track on the connection. The array is
6076
+ * empty if there are no RTP senders on the connection.
6077
+ */
6078
+ getSenders() {
6079
+ return this.pc.getSenders();
6080
+ }
6081
+ /**
6082
+ * Get the list of RTCRtpTransceiver objects being used to send and receive data on the
6083
+ * connection.
6084
+ *
6085
+ * @returns - An array of the RTCRtpTransceiver objects representing the transceivers handling
6086
+ * sending and receiving all media on the PeerConnection. The list is in the order in which the
6087
+ * transceivers were added to the connection.
6088
+ */
6089
+ getTransceivers() {
6090
+ return this.pc.getTransceivers();
6091
+ }
6092
+ /**
6093
+ * Get statistics about either the overall connection or about the specified MediaStreamTrack.
6094
+ *
6095
+ * @param selector - An optional MediaStreamTrack for which to gather statistics. If not provided,
6096
+ * statistics will be gathered for the entire underlying RTCPeerConnection.
6097
+ * @returns - A Promise which resolves with an RTCStatsReport object providing connection
6098
+ * statistics.
6099
+ */
6100
+ getStats(selector) {
6101
+ return this.pc.getStats(selector);
6102
+ }
6103
+ /**
6104
+ * Returns a string that describes the connections' ICE gathering state.
6105
+ *
6106
+ * @returns - The ICE gathering state.
6107
+ */
6108
+ get iceGatheringState() {
6109
+ return this.pc.iceGatheringState;
6110
+ }
6111
+ /**
6112
+ * Returns the type of a connection that has been established.
6113
+ *
6114
+ * @returns The connection type which would be `ConnectionType`.
6115
+ */
6116
+ getCurrentConnectionType() {
6117
+ return __awaiter$2(this, void 0, void 0, function* () {
6118
+ var _a;
6119
+ // make sure this method only can be called when the ice connection is established;
6120
+ const isIceConnected = this.pc.iceConnectionState === 'connected' || this.pc.iceConnectionState === 'completed';
6121
+ if (!isIceConnected) {
6122
+ throw new Error('Ice connection is not established');
6123
+ }
6124
+ const succeededLocalCandidateIds = new Set();
6125
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6126
+ const localCandidateStatsReports = [];
6127
+ (yield this.pc.getStats()).forEach((report) => {
6128
+ var _a;
6129
+ // collect all local candidate ids from `candidate-pair` stats reports with `succeeded` state.
6130
+ if (report.type === 'candidate-pair' && ((_a = report.state) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'succeeded') {
6131
+ succeededLocalCandidateIds.add(report.localCandidateId);
6132
+ }
6133
+ // collect all `local-candidate` stats.
6134
+ if (report.type === 'local-candidate') {
6135
+ localCandidateStatsReports.push(report);
6136
+ }
6137
+ });
6138
+ // find the `local-candidate` stats which report id contains in `succeededLocalCandidateIds`.
6139
+ const localCandidate = localCandidateStatsReports.find((report) => succeededLocalCandidateIds.has(report.id));
6140
+ if (!localCandidate) {
6141
+ return 'unknown';
6142
+ }
6143
+ if (localCandidate.relayProtocol) {
6144
+ return `TURN-${localCandidate.relayProtocol.toUpperCase()}`;
6145
+ }
6146
+ return (_a = localCandidate.protocol) === null || _a === void 0 ? void 0 : _a.toUpperCase();
6147
+ });
6148
+ }
6149
+ }
6146
6150
  PeerConnection.Events = PeerConnectionEvents;
6147
6151
 
6148
6152
  var commonjsGlobal$2 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -9532,10 +9536,6 @@ const simulcastMaxFrameSizes = {
9532
9536
  };
9533
9537
 
9534
9538
  class JmpLine extends Line {
9535
- constructor(versions) {
9536
- super();
9537
- this.versions = versions;
9538
- }
9539
9539
  static fromSdpLine(line) {
9540
9540
  if (!JmpLine.regex.test(line)) {
9541
9541
  return undefined;
@@ -9544,6 +9544,10 @@ class JmpLine extends Line {
9544
9544
  const versions = tokens[1].split(',').filter((v) => v.length);
9545
9545
  return new JmpLine(versions);
9546
9546
  }
9547
+ constructor(versions) {
9548
+ super();
9549
+ this.versions = versions;
9550
+ }
9547
9551
  toSdpLine() {
9548
9552
  return `a=jmp:${this.versions.join(',')}`;
9549
9553
  }
@@ -14737,6 +14741,7 @@ var MultistreamConnectionEventNames;
14737
14741
  MultistreamConnectionEventNames["CreateAnswerOnSuccess"] = "createansweronsuccess";
14738
14742
  MultistreamConnectionEventNames["SetLocalDescriptionOnSuccess"] = "setlocaldescriptiononsuccess";
14739
14743
  MultistreamConnectionEventNames["SetRemoteDescriptionOnSuccess"] = "setremotedescriptiononsuccess";
14744
+ MultistreamConnectionEventNames["IceCandidateError"] = "icecandidateerror";
14740
14745
  })(MultistreamConnectionEventNames || (MultistreamConnectionEventNames = {}));
14741
14746
  const defaultMultistreamConnectionOptions = {
14742
14747
  disableSimulcast: BrowserInfo.isFirefox(),
@@ -14805,6 +14810,9 @@ class MultistreamConnection extends EventEmitter$2 {
14805
14810
  this.pc.on(PeerConnection.Events.IceGatheringStateChange, () => {
14806
14811
  this.emit(MultistreamConnectionEventNames.IceGatheringStateUpdate, this.getIceGatheringState());
14807
14812
  });
14813
+ this.pc.on(PeerConnection.Events.IceCandidateError, (error) => {
14814
+ this.emit(MultistreamConnectionEventNames.IceCandidateError, error);
14815
+ });
14808
14816
  }
14809
14817
  getConnectionState() {
14810
14818
  return this.pc.getConnectionState();