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