sip-connector 19.8.3 → 20.0.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.
Files changed (44) hide show
  1. package/README.md +131 -138
  2. package/dist/@SipConnector-CZiURTVf.cjs +1 -0
  3. package/dist/{@SipConnector-BmkeKEDD.js → @SipConnector-D4DfiZRM.js} +1117 -977
  4. package/dist/ApiManager/@ApiManager.d.ts +0 -1
  5. package/dist/ApiManager/constants.d.ts +3 -8
  6. package/dist/ApiManager/eventNames.d.ts +15 -6
  7. package/dist/ApiManager/index.d.ts +0 -1
  8. package/dist/ApiManager/types.d.ts +0 -6
  9. package/dist/CallManager/@CallManager.d.ts +44 -15
  10. package/dist/CallManager/MCUSession.d.ts +0 -2
  11. package/dist/CallManager/RecvSession.d.ts +29 -0
  12. package/dist/CallManager/RemoteStreamsManager.d.ts +20 -5
  13. package/dist/CallManager/RoleManager.d.ts +31 -0
  14. package/dist/CallManager/eventNames.d.ts +9 -2
  15. package/dist/CallManager/index.d.ts +1 -2
  16. package/dist/CallManager/types.d.ts +29 -35
  17. package/dist/ConnectionManager/@ConnectionManager.d.ts +2 -2
  18. package/dist/ConnectionManager/ConfigurationManager.d.ts +6 -1
  19. package/dist/ConnectionManager/ConnectionFlow.d.ts +5 -4
  20. package/dist/ConnectionManager/SipOperations.d.ts +2 -2
  21. package/dist/ConnectionManager/UAFactory.d.ts +4 -4
  22. package/dist/SipConnector/@SipConnector.d.ts +4 -4
  23. package/dist/SipConnector/eventNames.d.ts +1 -1
  24. package/dist/SipConnectorFacade/@SipConnectorFacade.d.ts +0 -2
  25. package/dist/VideoSendingBalancer/__fixtures__/createMockTrack.d.ts +1 -1
  26. package/dist/__fixtures__/RTCPeerConnectionMock.d.ts +14 -18
  27. package/dist/__fixtures__/index.d.ts +4 -4
  28. package/dist/doMock.cjs +1 -1
  29. package/dist/doMock.js +134 -131
  30. package/dist/index.cjs +1 -1
  31. package/dist/index.js +156 -171
  32. package/dist/tools/__fixtures__/connectToServer.d.ts +15 -15
  33. package/dist/tools/__fixtures__/permissions.d.ts +2 -2
  34. package/dist/tools/__fixtures__/processRequest.d.ts +2 -2
  35. package/dist/tools/index.d.ts +1 -0
  36. package/dist/tools/sendOffer.d.ts +39 -0
  37. package/dist/utils/utils.d.ts +1 -1
  38. package/package.json +13 -5
  39. package/dist/@SipConnector-BHakZWEK.cjs +0 -1
  40. package/dist/CallManager/AbstractCallStrategy.d.ts +0 -54
  41. package/dist/CallManager/MCUCallStrategy.d.ts +0 -31
  42. package/dist/TransceiverManager/@TransceiverManager.d.ts +0 -70
  43. package/dist/TransceiverManager/index.d.ts +0 -1
  44. package/dist/TransceiverManager/types.d.ts +0 -11
package/README.md CHANGED
@@ -31,8 +31,6 @@ SDK предоставляет комплексное решение для:
31
31
  - **Обработка смены треков**: Автоматическая адаптация балансировки при изменении видеотреков
32
32
  - **Улучшенная статистика**: Расширенные возможности сбора и анализа WebRTC статистики
33
33
  - **Автоматический перезапуск ICE**: Обработка событий `restart` от сервера с автоматическим вызовом `restartIce`
34
- - **Управление transceiver'ами**: Новый `TransceiverManager` для отслеживания и управления RTCRtpTransceiver'ами
35
- - **Автоматическое добавление transceiver'ов**: Умное добавление презентационных transceiver'ов при событиях restart
36
34
  |
37
35
 
38
36
  ### 🏗️ Архитектура
@@ -97,11 +95,11 @@ const facade = new SipConnectorFacade(sipConnector);
97
95
  // Подключение с объектом параметров
98
96
  await facade.connectToServer({
99
97
  userAgent: tools.getUserAgent({ appName: 'MyApp' }),
100
- sipWebSocketServerURL: 'wss://sip.example.com/ws',
101
- sipServerUrl: 'sip:example.com',
102
- name: '1001', // SIP URI user part
98
+ sipServerUrl: 'sip.example.com', // WebSocket URL (путь /webrtc/wss/ добавляется автоматически)
99
+ sipServerIp: 'sip.example.com', // SIP сервер IP
100
+ user: '1001', // SIP URI user part
103
101
  password: 'secret',
104
- isRegisteredUser: true, // Включить SIP REGISTER
102
+ register: true, // Включить SIP REGISTER
105
103
  });
106
104
 
107
105
  // Или с функцией для динамического получения параметров
@@ -110,11 +108,11 @@ await facade.connectToServer(async () => {
110
108
  const config = await fetchConnectionConfig();
111
109
  return {
112
110
  userAgent: tools.getUserAgent({ appName: 'MyApp' }),
113
- sipWebSocketServerURL: config.websocketUrl,
114
- sipServerUrl: config.sipUrl,
115
- name: config.username,
111
+ sipServerUrl: config.websocketUrl, // Без пути /webrtc/wss/ - он добавляется автоматически
112
+ sipServerIp: config.sipServerIp,
113
+ user: config.username,
116
114
  password: config.password,
117
- isRegisteredUser: true,
115
+ register: true,
118
116
  };
119
117
  });
120
118
  ```
@@ -128,14 +126,23 @@ const localStream = await navigator.mediaDevices.getUserMedia({
128
126
  video: true,
129
127
  });
130
128
 
129
+ // Подписка на изменения удаленных потоков
130
+ const unsubscribeRemoteStreams = sipConnector.on('call:remote-streams-changed', (event) => {
131
+ console.log('Изменение удаленных потоков:', {
132
+ participantId: event.participantId,
133
+ changeType: event.changeType, // 'added' | 'removed'
134
+ trackId: event.trackId,
135
+ streams: event.streams, // Актуальный массив всех удаленных потоков
136
+ });
137
+
138
+ // Обновление UI с новыми потоками
139
+ updateRemoteStreamsDisplay(event.streams);
140
+ });
141
+
131
142
  // Инициация звонка
132
143
  const pc = await facade.callToServer({
133
144
  conference: '12345',
134
145
  mediaStream: localStream,
135
- setRemoteStreams: (streams) => {
136
- // Обработка удаленных потоков
137
- console.log('Получены удаленные потоки:', streams);
138
- },
139
146
  });
140
147
 
141
148
  // Подписка на WebRTC-статистику
@@ -150,6 +157,7 @@ const unsubscribeStats = facade.onStats(({ outbound, inbound }) => {
150
157
  ```typescript
151
158
  await facade.disconnectFromServer();
152
159
  unsubscribeStats();
160
+ unsubscribeRemoteStreams();
153
161
  ```
154
162
 
155
163
  ---
@@ -159,15 +167,17 @@ unsubscribeStats();
159
167
  ### Обработка входящих вызовов
160
168
 
161
169
  ```typescript
170
+ // Подписка на изменения удаленных потоков (до ответа на звонок)
171
+ const unsubscribeRemoteStreams = sipConnector.on('call:remote-streams-changed', (event) => {
172
+ console.log('Изменение удаленных потоков:', event);
173
+ displayRemoteStreams(event.streams);
174
+ });
175
+
162
176
  // Подписка на входящие события
163
177
  sipConnector.on('incoming-call:incomingCall', () => {
164
178
  // Автоматический ответ с локальным потоком
165
179
  facade.answerToIncomingCall({
166
180
  mediaStream: localStream,
167
- setRemoteStreams: (streams) => {
168
- // Отображение удаленных потоков
169
- displayRemoteStreams(streams);
170
- },
171
181
  });
172
182
  });
173
183
  ```
@@ -279,20 +289,40 @@ await facade.startPresentation({
279
289
  ### Отслеживание перемещений
280
290
 
281
291
  ```typescript
282
- // Подписка на перемещение в зрители
283
- const unsubscribeMoveToSpectators = facade.onMoveToSpectators(() => {
284
- console.log('Участник перемещен в зрители');
285
- updateParticipantRole('spectator');
286
- });
292
+ // Подписка на перемещение в зрители (новый формат с audioId)
293
+ const unsubscribeMoveToSpectators = sipConnector.on(
294
+ 'api:participant:move-request-to-spectators',
295
+ (data) => {
296
+ if (data.isSynthetic) {
297
+ console.log('Участник перемещен в зрители (синтетическое событие)');
298
+ } else {
299
+ console.log('Участник перемещен в зрители с audioId:', data.audioId);
300
+ }
301
+ updateParticipantRole('spectator');
302
+ },
303
+ );
304
+
305
+ // Подписка на перемещение в зрители (старый формат для обратной совместимости)
306
+ const unsubscribeMoveToSpectatorsSynthetic = sipConnector.on(
307
+ 'api:participant:move-request-to-spectators-synthetic',
308
+ () => {
309
+ console.log('Участник перемещен в зрители (старый формат)');
310
+ updateParticipantRole('spectator');
311
+ },
312
+ );
287
313
 
288
314
  // Подписка на перемещение в участники
289
- const unsubscribeMoveToParticipants = facade.onMoveToParticipants(() => {
290
- console.log('Участник перемещен в участники');
291
- updateParticipantRole('participant');
292
- });
315
+ const unsubscribeMoveToParticipants = sipConnector.on(
316
+ 'api:participant:move-request-to-participants',
317
+ () => {
318
+ console.log('Участник перемещен в участники');
319
+ updateParticipantRole('participant');
320
+ },
321
+ );
293
322
 
294
323
  // Отписка при необходимости
295
324
  unsubscribeMoveToSpectators();
325
+ unsubscribeMoveToSpectatorsSynthetic();
296
326
  unsubscribeMoveToParticipants();
297
327
  ```
298
328
 
@@ -319,7 +349,24 @@ facade.onUseLicense((license) => {
319
349
  ### Работа с удаленными потоками
320
350
 
321
351
  ```typescript
322
- // Получение текущих удаленных потоков
352
+ // Подписка на изменения удаленных потоков
353
+ let currentRemoteStreams: MediaStream[] = [];
354
+
355
+ const unsubscribeRemoteStreams = sipConnector.on('call:remote-streams-changed', (event) => {
356
+ console.log('Изменение удаленных потоков:', {
357
+ participantId: event.participantId,
358
+ changeType: event.changeType, // 'added' | 'removed'
359
+ trackId: event.trackId,
360
+ });
361
+
362
+ // Обновляем текущие потоки
363
+ currentRemoteStreams = event.streams;
364
+
365
+ // Обновляем UI
366
+ updateStreamsDisplay(event.streams);
367
+ });
368
+
369
+ // Получение текущих удаленных потоков (синхронный метод)
323
370
  const remoteStreams = facade.getRemoteStreams();
324
371
  if (remoteStreams) {
325
372
  console.log('Активные удаленные потоки:', remoteStreams.length);
@@ -428,115 +475,21 @@ sipConnector.on('api:restart', (data) => {
428
475
 
429
476
  ---
430
477
 
431
- ## 🎛️ Управление RTCRtpTransceiver'ами
432
-
433
- ### Обзор TransceiverManager
434
-
435
- SDK автоматически отслеживает и управляет RTCRtpTransceiver'ами через новый класс `TransceiverManager`:
436
-
437
- ```typescript
438
- // Получение текущих transceiver'ов
439
- const transceivers = sipConnector.callManager.getTransceivers();
440
-
441
- console.log('Основной аудио transceiver:', transceivers.mainAudio);
442
- console.log('Основной видео transceiver:', transceivers.mainVideo);
443
- console.log('Презентационный видео transceiver:', transceivers.presentationVideo);
444
- ```
445
-
446
- ### Типы transceiver'ов
447
-
448
- SDK автоматически классифицирует transceiver'ы по их `mid` значению:
449
-
450
- | Тип transceiver'а | mid | Назначение |
451
- | ------------------- | --- | --------------------------- |
452
- | `mainAudio` | '0' | Основной аудио поток |
453
- | `mainVideo` | '1' | Основной видео поток |
454
- | `presentationVideo` | '2' | Презентационный видео поток |
455
-
456
- ### Автоматическое добавление transceiver'ов
457
-
458
- При получении события `restart` с `videoTrackCount === 2`, SDK автоматически добавляет презентационный transceiver если он отсутствует:
459
-
460
- ```typescript
461
- // SDK автоматически обрабатывает события restart
462
- sipConnector.on('api:restart', (data) => {
463
- if (data.videoTrackCount === 2) {
464
- // SDK проверит наличие presentationVideo transceiver'а
465
- // и добавит его автоматически если необходимо
466
- console.log('Будет добавлен презентационный transceiver');
467
- }
468
- });
469
- ```
470
-
471
- ### Ручное управление transceiver'ами
472
-
473
- ```typescript
474
- // Добавление нового transceiver'а
475
- try {
476
- const audioTransceiver = await sipConnector.callManager.addTransceiver('audio', {
477
- direction: 'sendrecv',
478
- });
479
-
480
- const videoTransceiver = await sipConnector.callManager.addTransceiver('video', {
481
- direction: 'sendonly',
482
- sendEncodings: [
483
- { rid: 'low', maxBitrate: 500_000, scaleResolutionDownBy: 4 },
484
- { rid: 'high', maxBitrate: 2_000_000, scaleResolutionDownBy: 1 },
485
- ],
486
- });
487
-
488
- console.log('Transceiver'ы добавлены:', { audioTransceiver, videoTransceiver });
489
- } catch (error) {
490
- console.error('Ошибка добавления transceiver'а:', error);
491
- }
492
- ```
493
-
494
- ### Мониторинг transceiver'ов
495
-
496
- ```typescript
497
- // Проверка состояния transceiver'ов
498
- const checkTransceivers = () => {
499
- const transceivers = sipConnector.callManager.getTransceivers();
500
-
501
- console.log('Статус transceiver'ов:', {
502
- hasAudio: transceivers.mainAudio !== undefined,
503
- hasVideo: transceivers.mainVideo !== undefined,
504
- hasPresentation: transceivers.presentationVideo !== undefined,
505
- });
506
-
507
- // Детальная информация
508
- if (transceivers.mainVideo) {
509
- console.log('Основное видео:', {
510
- mid: transceivers.mainVideo.mid,
511
- direction: transceivers.mainVideo.direction,
512
- currentDirection: transceivers.mainVideo.currentDirection,
513
- });
514
- }
515
- };
516
-
517
- // Проверка после установки соединения
518
- sipConnector.on('call:confirmed', () => {
519
- checkTransceivers();
520
- });
521
- ```
522
-
523
- ---
524
-
525
478
  ## 📡 События и их обработка
526
479
 
527
480
  ### Архитектура событий
528
481
 
529
482
  SDK использует **событийно-ориентированную архитектуру** с префиксами для группировки:
530
483
 
531
- | Префикс | Описание | Примеры событий |
532
- | ------------------ | ------------------------ | ----------------------------------------- |
533
- | `connection:*` | События подключения | `connected`, `disconnected` |
534
- | `call:*` | События звонков | `accepted`, `ended`, `failed` |
535
- | `api:*` | События от сервера | `enterRoom`, `useLicense`, `restart` |
536
- | `incoming-call:*` | События входящих звонков | `incomingCall` |
537
- | `presentation:*` | События презентаций | `started`, `stopped` |
538
- | `stats:*` | События статистики | `collected` |
539
- | `video-balancer:*` | События балансировки | `balancing-started`, `parameters-updated` |
484
+ | Префикс | Описание | Примеры событий |
485
+ | ------------------ | ------------------------ | ------------------------------------------------------------------------------ |
486
+ | `connection:*` | События подключения | `connected`, `disconnected` |
487
+ | `call:*` | События звонков | `accepted`, `ended`, `failed`, `remote-streams-changed` |
488
+ | `api:*` | События от сервера | `enterRoom`, `useLicense`, `restart`, `participant:move-request-to-spectators` |
489
+ | `incoming-call:*` | События входящих звонков | `incomingCall` |
490
+ | `presentation:*` | События презентаций | `started`, `stopped` |
491
+ | `stats:*` | События статистики | `collected` |
492
+ | `video-balancer:*` | События балансировки | `balancing-started`, `parameters-updated` |
540
493
 
541
494
  ### Основные события
542
495
 
@@ -571,8 +524,50 @@ sipConnector.on('api:useLicense', (license) => {
571
524
  sipConnector.on('api:restart', (data) => {
572
525
  console.log('Событие restart от сервера:', data);
573
526
  });
527
+
528
+ // Изменения удаленных потоков
529
+ sipConnector.on('call:remote-streams-changed', (event) => {
530
+ console.log('Изменение удаленных потоков:', {
531
+ participantId: event.participantId,
532
+ changeType: event.changeType, // 'added' | 'removed'
533
+ trackId: event.trackId,
534
+ streams: event.streams,
535
+ });
536
+ });
537
+
538
+ // Перемещение участников
539
+ sipConnector.on('api:participant:move-request-to-spectators', (data) => {
540
+ if (data.isSynthetic) {
541
+ console.log('Перемещение в зрители (синтетическое)');
542
+ } else {
543
+ console.log('Перемещение в зрители с audioId:', data.audioId);
544
+ }
545
+ });
546
+
547
+ sipConnector.on('api:participant:move-request-to-spectators-synthetic', () => {
548
+ console.log('Перемещение в зрители (старый формат для обратной совместимости)');
549
+ });
574
550
  ```
575
551
 
552
+ ### Детальная таблица событий
553
+
554
+ #### События звонков (`call:*`)
555
+
556
+ | Событие | Описание | Данные |
557
+ | ----------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------ |
558
+ | `call:accepted` | Звонок принят | - |
559
+ | `call:ended` | Звонок завершен | `EndEvent` |
560
+ | `call:failed` | Звонок завершился с ошибкой | `EndEvent` |
561
+ | `call:remote-streams-changed` | Изменение удаленных потоков | `{ participantId: string, changeType: 'added' \| 'removed', trackId: string, streams: MediaStream[] }` |
562
+
563
+ #### События участников (`api:participant:*`)
564
+
565
+ | Событие | Описание | Данные |
566
+ | ------------------------------------------------------ | ------------------------------ | ------------------------------------------------------------------ |
567
+ | `api:participant:move-request-to-spectators` | Перемещение в зрители (новый) | `{ isSynthetic: true } \| { isSynthetic: false, audioId: string }` |
568
+ | `api:participant:move-request-to-spectators-synthetic` | Перемещение в зрители (старый) | - |
569
+ | `api:participant:move-request-to-participants` | Перемещение в участники | - |
570
+
576
571
  ### Продвинутые паттерны
577
572
 
578
573
  ```typescript
@@ -855,8 +850,11 @@ sipConnector.startAutoConnect({
855
850
  getParameters: async () => {
856
851
  return {
857
852
  displayName: 'displayName',
858
- sipWebSocketServerURL: 'wss://example.com/ws',
859
- sipServerUrl: 'sipServerUrl',
853
+ sipServerUrl: 'example.com', // Путь /webrtc/wss/ добавляется автоматически
854
+ sipServerIp: 'sip.example.com',
855
+ user: 'user',
856
+ password: 'password',
857
+ register: true,
860
858
  };
861
859
  },
862
860
  // Проверяет готовность к подключению
@@ -924,7 +922,6 @@ import {
924
922
  SipConnector, // Низкоуровневый API
925
923
  SipConnectorFacade, // Высокоуровневый фасад
926
924
  StatsPeerConnection, // Сбор статистики
927
- TransceiverManager, // Управление transceiver'ами
928
925
  // ... другие экспорты
929
926
  } from 'sip-connector';
930
927
  ```
@@ -941,10 +938,6 @@ await facade.replaceMediaStream(mediaStream, options);
941
938
  // Получение удаленных потоков
942
939
  const streams = facade.getRemoteStreams();
943
940
 
944
- // Управление transceiver'ами (низкоуровневый API)
945
- const transceivers = sipConnector.callManager.getTransceivers();
946
- await sipConnector.callManager.addTransceiver('video', { direction: 'sendrecv' });
947
-
948
941
  // Перезапуск ICE-соединения (низкоуровневый API)
949
942
  await sipConnector.callManager.restartIce(options);
950
943
  ```
@@ -0,0 +1 @@
1
+ "use strict";const O=require("events-constructor"),Q=require("debug"),$=require("@krivega/cancelable-promise"),w=require("@krivega/timeout-requester"),Y=require("repeated-calls"),oe=require("xstate"),z=require("stack-promises");require("ua-parser-js");require("sequent-promises");const X="sip-connector",h=Q(X),Be=()=>{Q.enable(X)},ke=()=>{Q.enable(`-${X}`)},Fe="Error decline with 603",$e=1006,qe=n=>typeof n=="object"&&n!==null&&"code"in n&&n.code===$e,We=n=>n.message===Fe;var u=(n=>(n.CONTENT_TYPE="content-type",n.CONTENT_ENTER_ROOM="x-webrtc-enter-room",n.CONTENT_USE_LICENSE="X-WEBRTC-USE-LICENSE",n.PARTICIPANT_NAME="X-WEBRTC-PARTICIPANT-NAME",n.INPUT_CHANNELS="X-WEBRTC-INPUT-CHANNELS",n.OUTPUT_CHANNELS="X-WEBRTC-OUTPUT-CHANNELS",n.MAIN_CAM="X-WEBRTC-MAINCAM",n.MIC="X-WEBRTC-MIC",n.MEDIA_SYNC="X-WEBRTC-SYNC",n.MAIN_CAM_RESOLUTION="X-WEBRTC-MAINCAM-RESOLUTION",n.MEDIA_STATE="X-WEBRTC-MEDIA-STATE",n.MEDIA_TYPE="X-Vinteo-Media-Type",n.MAIN_CAM_STATE="X-Vinteo-MainCam-State",n.MIC_STATE="X-Vinteo-Mic-State",n.CONTENT_PARTICIPANT_STATE="X-WEBRTC-PARTSTATE",n.NOTIFY="X-VINTEO-NOTIFY",n.CONTENT_ENABLE_MEDIA_DEVICE="X-WEBRTC-REQUEST-ENABLE-MEDIA-DEVICE",n.CONTENT_SHARE_STATE="x-webrtc-share-state",n.MUST_STOP_PRESENTATION_P2P="x-webrtc-share-state: YOUMUSTSTOPSENDCONTENT",n.START_PRESENTATION_P2P="x-webrtc-share-state: YOUCANRECEIVECONTENT",n.STOP_PRESENTATION_P2P="x-webrtc-share-state: CONTENTEND",n.STOP_PRESENTATION="x-webrtc-share-state: STOPPRESENTATION",n.START_PRESENTATION="x-webrtc-share-state: LETMESTARTPRESENTATION",n.ENABLE_MAIN_CAM="X-WEBRTC-REQUEST-ENABLE-MEDIA-DEVICE: LETMESTARTMAINCAM",n.AVAILABLE_INCOMING_BITRATE="X-WEBRTC-AVAILABLE-INCOMING-BITRATE",n.AUDIO_TRACK_COUNT="X-WEBRTC-AUDIO-TRACK-COUNT",n.VIDEO_TRACK_COUNT="X-WEBRTC-VIDEO-TRACK-COUNT",n.TRACKS_DIRECTION="X-WEBRTC-TRACKS-DIRECTION",n.AUDIO_ID="X-WEBRTC-AUDIOID",n))(u||{}),F=(n=>(n.AVAILABLE_SECOND_REMOTE_STREAM="YOUCANRECEIVECONTENT",n.NOT_AVAILABLE_SECOND_REMOTE_STREAM="CONTENTEND",n.MUST_STOP_PRESENTATION="YOUMUSTSTOPSENDCONTENT",n))(F||{}),G=(n=>(n.SPECTATOR="SPECTATOR",n.PARTICIPANT="PARTICIPANT",n))(G||{}),y=(n=>(n.ENTER_ROOM="application/vinteo.webrtc.roomname",n.MIC="application/vinteo.webrtc.mic",n.USE_LICENSE="application/vinteo.webrtc.uselic",n.PARTICIPANT_STATE="application/vinteo.webrtc.partstate",n.NOTIFY="application/vinteo.webrtc.notify",n.SHARE_STATE="application/vinteo.webrtc.sharedesktop",n.MAIN_CAM="application/vinteo.webrtc.maincam",n))(y||{}),m=(n=>(n.CHANNELS="application/vinteo.webrtc.channels",n.MEDIA_STATE="application/vinteo.webrtc.mediastate",n.REFUSAL="application/vinteo.webrtc.refusal",n.SHARE_STATE="application/vinteo.webrtc.sharedesktop",n.MAIN_CAM="application/vinteo.webrtc.maincam",n.STATS="application/vinteo.webrtc.stats",n))(m||{}),M=(n=>(n.PAUSE_MAIN_CAM="PAUSEMAINCAM",n.RESUME_MAIN_CAM="RESUMEMAINCAM",n.MAX_MAIN_CAM_RESOLUTION="MAXMAINCAMRESOLUTION",n.ADMIN_STOP_MAIN_CAM="ADMINSTOPMAINCAM",n.ADMIN_START_MAIN_CAM="ADMINSTARTMAINCAM",n))(M||{}),V=(n=>(n.ADMIN_STOP_MIC="ADMINSTOPMIC",n.ADMIN_START_MIC="ADMINSTARTMIC",n))(V||{}),x=(n=>(n.ADMIN_SYNC_FORCED="1",n.ADMIN_SYNC_NOT_FORCED="0",n))(x||{}),ce=(n=>(n.AUDIO="AUDIO",n.VIDEO="VIDEO",n.AUDIOPLUSPRESENTATION="AUDIOPLUSPRESENTATION",n))(ce||{}),l=(n=>(n.CHANNELS_NOTIFY="channels:notify",n.PARTICIPANT_ADDED_TO_LIST_MODERATORS="participant:added-to-list-moderators",n.PARTICIPANT_REMOVED_FROM_LIST_MODERATORS="participant:removed-from-list-moderators",n.PARTICIPANT_MOVE_REQUEST_TO_STREAM="participant:move-request-to-stream",n.PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS="participant:move-request-to-spectators",n.PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS_SYNTHETIC="participant:move-request-to-spectators-synthetic",n.PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS_WITH_AUDIO_ID="participant:move-request-to-spectators-with-audio-id",n.PARTICIPANT_MOVE_REQUEST_TO_PARTICIPANTS="participant:move-request-to-participants",n.PARTICIPATION_ACCEPTING_WORD_REQUEST="participation:accepting-word-request",n.PARTICIPATION_CANCELLING_WORD_REQUEST="participation:cancelling-word-request",n.WEBCAST_STARTED="webcast:started",n.WEBCAST_STOPPED="webcast:stopped",n.ACCOUNT_CHANGED="account:changed",n.ACCOUNT_DELETED="account:deleted",n.CONFERENCE_PARTICIPANT_TOKEN_ISSUED="conference:participant-token-issued",n.CHANNELS="channels",n.ENTER_ROOM="enterRoom",n.SHARE_STATE="shareState",n.MAIN_CAM_CONTROL="main-cam-control",n.USE_LICENSE="useLicense",n.ADMIN_START_MAIN_CAM="admin-start-main-cam",n.ADMIN_STOP_MAIN_CAM="admin-stop-main-cam",n.ADMIN_START_MIC="admin-start-mic",n.ADMIN_STOP_MIC="admin-stop-mic",n.ADMIN_FORCE_SYNC_MEDIA_STATE="admin-force-sync-media-state",n.AVAILABLE_SECOND_REMOTE_STREAM="availableSecondRemoteStream",n.NOT_AVAILABLE_SECOND_REMOTE_STREAM="notAvailableSecondRemoteStream",n.MUST_STOP_PRESENTATION="mustStopPresentation",n.NEW_DTMF="newDTMF",n))(l||{});const he=["participation:accepting-word-request","participation:cancelling-word-request","participant:move-request-to-stream","channels:notify","conference:participant-token-issued","account:changed","account:deleted","webcast:started","webcast:stopped","participant:added-to-list-moderators","participant:removed-from-list-moderators","participant:move-request-to-spectators","participant:move-request-to-spectators-synthetic","participant:move-request-to-spectators-with-audio-id","participant:move-request-to-participants","channels","enterRoom","shareState","main-cam-control","useLicense","admin-start-main-cam","admin-stop-main-cam","admin-start-mic","admin-stop-mic","admin-force-sync-media-state","availableSecondRemoteStream","notAvailableSecondRemoteStream","mustStopPresentation","newDTMF"];var N=(n=>(n.CHANNELS="channels",n.WEBCAST_STARTED="WebcastStarted",n.WEBCAST_STOPPED="WebcastStopped",n.ACCOUNT_CHANGED="accountChanged",n.ACCOUNT_DELETED="accountDeleted",n.ADDED_TO_LIST_MODERATORS="addedToListModerators",n.REMOVED_FROM_LIST_MODERATORS="removedFromListModerators",n.ACCEPTING_WORD_REQUEST="ParticipationRequestAccepted",n.CANCELLING_WORD_REQUEST="ParticipationRequestRejected",n.MOVE_REQUEST_TO_STREAM="ParticipantMovedToWebcast",n.CONFERENCE_PARTICIPANT_TOKEN_ISSUED="ConferenceParticipantTokenIssued",n))(N||{});class He{events;connectionManager;callManager;constructor({connectionManager:e,callManager:t}){this.connectionManager=e,this.callManager=t,this.events=new O.TypedEvents(he),this.subscribe()}async waitChannels(){return this.wait(l.CHANNELS)}async waitSyncMediaState(){return this.wait(l.ADMIN_FORCE_SYNC_MEDIA_STATE)}async sendDTMF(e){return new Promise((t,s)=>{let i;try{i=this.getEstablishedRTCSessionProtected()}catch(r){s(r)}i&&(this.callManager.once("newDTMF",({originator:r})=>{r==="local"&&t()}),i.sendDTMF(e,{duration:120,interToneGap:600}))})}async sendChannels({inputChannels:e,outputChannels:t}){const s=this.getEstablishedRTCSessionProtected(),i=`${u.INPUT_CHANNELS}: ${e}`,r=`${u.OUTPUT_CHANNELS}: ${t}`,a=[i,r];return s.sendInfo(m.CHANNELS,void 0,{extraHeaders:a})}async sendMediaState({cam:e,mic:t},s={}){const i=this.getEstablishedRTCSessionProtected(),r=`${u.MEDIA_STATE}: currentstate`,a=`${u.MAIN_CAM_STATE}: ${Number(e)}`,o=`${u.MIC_STATE}: ${Number(t)}`,c=[r,a,o];return i.sendInfo(m.MEDIA_STATE,void 0,{noTerminateWhenError:!0,...s,extraHeaders:c})}async sendStats({availableIncomingBitrate:e}){const t=this.getEstablishedRTCSessionProtected(),i=[`${u.AVAILABLE_INCOMING_BITRATE}: ${e}`];return t.sendInfo(m.STATS,void 0,{noTerminateWhenError:!0,extraHeaders:i})}async sendRefusalToTurnOn(e,t={}){const s=this.getEstablishedRTCSessionProtected(),a=e==="mic"?0:1,c=[`${u.MEDIA_TYPE}: ${a}`];return s.sendInfo(m.REFUSAL,void 0,{noTerminateWhenError:!0,...t,extraHeaders:c})}async sendRefusalToTurnOnMic(e={}){return this.sendRefusalToTurnOn("mic",{noTerminateWhenError:!0,...e})}async sendRefusalToTurnOnCam(e={}){return this.sendRefusalToTurnOn("cam",{noTerminateWhenError:!0,...e})}async sendMustStopPresentationP2P(){await this.getEstablishedRTCSessionProtected().sendInfo(m.SHARE_STATE,void 0,{extraHeaders:[u.MUST_STOP_PRESENTATION_P2P]})}async sendStoppedPresentationP2P(){await this.getEstablishedRTCSessionProtected().sendInfo(m.SHARE_STATE,void 0,{extraHeaders:[u.STOP_PRESENTATION_P2P]})}async sendStoppedPresentation(){await this.getEstablishedRTCSessionProtected().sendInfo(m.SHARE_STATE,void 0,{extraHeaders:[u.STOP_PRESENTATION]})}async askPermissionToStartPresentationP2P(){await this.getEstablishedRTCSessionProtected().sendInfo(m.SHARE_STATE,void 0,{extraHeaders:[u.START_PRESENTATION_P2P]})}async askPermissionToStartPresentation(){await this.getEstablishedRTCSessionProtected().sendInfo(m.SHARE_STATE,void 0,{extraHeaders:[u.START_PRESENTATION]})}async askPermissionToEnableCam(e={}){const t=this.getEstablishedRTCSessionProtected(),s=[u.ENABLE_MAIN_CAM];return t.sendInfo(m.MAIN_CAM,void 0,{noTerminateWhenError:!0,...e,extraHeaders:s}).catch(i=>{if(We(i))throw i})}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}getEstablishedRTCSessionProtected=()=>{const e=this.callManager.getEstablishedRTCSession();if(!e)throw new Error("No rtcSession established");return e};subscribe(){this.connectionManager.on("sipEvent",this.handleSipEvent),this.callManager.on("newInfo",this.handleNewInfo),this.callManager.on("newDTMF",e=>{this.events.trigger("newDTMF",e)})}handleSipEvent=({request:e})=>{this.maybeHandleNotify(e)};maybeHandleNotify=e=>{try{const t=e.getHeader(u.NOTIFY);if(t){const s=JSON.parse(t);this.handleNotify(s)}}catch(t){h("error parse notify",t)}};handleNotify=e=>{switch(e.cmd){case N.CHANNELS:{const t=e;this.triggerChannelsNotify(t);break}case N.WEBCAST_STARTED:{const t=e;this.triggerWebcastStartedNotify(t);break}case N.WEBCAST_STOPPED:{const t=e;this.triggerWebcastStoppedNotify(t);break}case N.ADDED_TO_LIST_MODERATORS:{const t=e;this.triggerAddedToListModeratorsNotify(t);break}case N.REMOVED_FROM_LIST_MODERATORS:{const t=e;this.triggerRemovedFromListModeratorsNotify(t);break}case N.ACCEPTING_WORD_REQUEST:{const t=e;this.triggerParticipationAcceptingWordRequest(t);break}case N.CANCELLING_WORD_REQUEST:{const t=e;this.triggerParticipationCancellingWordRequest(t);break}case N.MOVE_REQUEST_TO_STREAM:{const t=e;this.triggerParticipantMoveRequestToStream(t);break}case N.ACCOUNT_CHANGED:{this.triggerAccountChangedNotify();break}case N.ACCOUNT_DELETED:{this.triggerAccountDeletedNotify();break}case N.CONFERENCE_PARTICIPANT_TOKEN_ISSUED:{const t=e;this.triggerConferenceParticipantTokenIssued(t);break}default:h("unknown cmd",e)}};handleNewInfo=e=>{const{originator:t}=e;if(t!=="remote")return;const{request:s}=e,i=s,r=i.getHeader(u.CONTENT_TYPE);if(r!==void 0)switch(r){case y.ENTER_ROOM:{this.triggerEnterRoom(i),this.maybeTriggerChannels(i);break}case y.NOTIFY:{this.maybeHandleNotify(i);break}case y.SHARE_STATE:{this.triggerShareState(i);break}case y.MAIN_CAM:{this.triggerMainCamControl(i);break}case y.MIC:{this.triggerMicControl(i);break}case y.USE_LICENSE:{this.triggerUseLicense(i);break}case y.PARTICIPANT_STATE:{this.maybeTriggerParticipantMoveRequest(i);break}}};triggerChannelsNotify=e=>{const t=e.input,s=e.output,i={inputChannels:t,outputChannels:s};this.events.trigger(l.CHANNELS_NOTIFY,i)};triggerWebcastStartedNotify=({body:{conference:e,type:t}})=>{const s={conference:e,type:t};this.events.trigger(l.WEBCAST_STARTED,s)};triggerWebcastStoppedNotify=({body:{conference:e,type:t}})=>{const s={conference:e,type:t};this.events.trigger(l.WEBCAST_STOPPED,s)};triggerAddedToListModeratorsNotify=({conference:e})=>{const t={conference:e};this.events.trigger(l.PARTICIPANT_ADDED_TO_LIST_MODERATORS,t)};triggerRemovedFromListModeratorsNotify=({conference:e})=>{const t={conference:e};this.events.trigger(l.PARTICIPANT_REMOVED_FROM_LIST_MODERATORS,t)};triggerParticipationAcceptingWordRequest=({body:{conference:e}})=>{const t={conference:e};this.events.trigger(l.PARTICIPATION_ACCEPTING_WORD_REQUEST,t)};triggerParticipationCancellingWordRequest=({body:{conference:e}})=>{const t={conference:e};this.events.trigger(l.PARTICIPATION_CANCELLING_WORD_REQUEST,t)};triggerParticipantMoveRequestToStream=({body:{conference:e}})=>{const t={conference:e};this.events.trigger(l.PARTICIPANT_MOVE_REQUEST_TO_STREAM,t)};triggerAccountChangedNotify=()=>{this.events.trigger(l.ACCOUNT_CHANGED,{})};triggerAccountDeletedNotify=()=>{this.events.trigger(l.ACCOUNT_DELETED,{})};triggerConferenceParticipantTokenIssued=({body:{conference:e,participant:t,jwt:s}})=>{const i={conference:e,participant:t,jwt:s};this.events.trigger(l.CONFERENCE_PARTICIPANT_TOKEN_ISSUED,i)};maybeTriggerChannels=e=>{const t=e.getHeader(u.INPUT_CHANNELS),s=e.getHeader(u.OUTPUT_CHANNELS);if(t&&s){const i={inputChannels:t,outputChannels:s};this.events.trigger(l.CHANNELS,i)}};triggerEnterRoom=e=>{const t=e.getHeader(u.CONTENT_ENTER_ROOM),s=e.getHeader(u.PARTICIPANT_NAME);this.events.trigger(l.ENTER_ROOM,{room:t,participantName:s})};triggerShareState=e=>{const t=e.getHeader(u.CONTENT_SHARE_STATE);if(t!==void 0)switch(t){case F.AVAILABLE_SECOND_REMOTE_STREAM:{this.events.trigger(l.AVAILABLE_SECOND_REMOTE_STREAM,{});break}case F.NOT_AVAILABLE_SECOND_REMOTE_STREAM:{this.events.trigger(l.NOT_AVAILABLE_SECOND_REMOTE_STREAM,{});break}case F.MUST_STOP_PRESENTATION:{this.events.trigger(l.MUST_STOP_PRESENTATION,{});break}}};maybeTriggerParticipantMoveRequest=e=>{const t=e.getHeader(u.CONTENT_PARTICIPANT_STATE),s=e.getHeader(u.AUDIO_ID);t===G.SPECTATOR&&(s?(this.events.trigger(l.PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS_WITH_AUDIO_ID,{audioId:s}),this.events.trigger(l.PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS,{isSynthetic:!1,audioId:s})):(this.events.trigger(l.PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS_SYNTHETIC,{}),this.events.trigger(l.PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS,{isSynthetic:!0}))),t===G.PARTICIPANT&&this.events.trigger(l.PARTICIPANT_MOVE_REQUEST_TO_PARTICIPANTS,{})};triggerMainCamControl=e=>{const t=e.getHeader(u.MAIN_CAM),s=e.getHeader(u.MEDIA_SYNC),i=s===x.ADMIN_SYNC_FORCED;if(t===M.ADMIN_START_MAIN_CAM){this.events.trigger(l.ADMIN_START_MAIN_CAM,{isSyncForced:i});return}if(t===M.ADMIN_STOP_MAIN_CAM){this.events.trigger(l.ADMIN_STOP_MAIN_CAM,{isSyncForced:i});return}(t===M.RESUME_MAIN_CAM||t===M.PAUSE_MAIN_CAM)&&s!==void 0&&this.events.trigger(l.ADMIN_FORCE_SYNC_MEDIA_STATE,{isSyncForced:i});const r=e.getHeader(u.MAIN_CAM_RESOLUTION);this.events.trigger(l.MAIN_CAM_CONTROL,{mainCam:t,resolutionMainCam:r})};triggerMicControl=e=>{const t=e.getHeader(u.MIC),i=e.getHeader(u.MEDIA_SYNC)===x.ADMIN_SYNC_FORCED;t===V.ADMIN_START_MIC?this.events.trigger(l.ADMIN_START_MIC,{isSyncForced:i}):t===V.ADMIN_STOP_MIC&&this.events.trigger(l.ADMIN_STOP_MIC,{isSyncForced:i})};triggerUseLicense=e=>{const t=e.getHeader(u.CONTENT_USE_LICENSE);this.events.trigger(l.USE_LICENSE,t)}}var R=(n=>(n.PEER_CONNECTION="peerconnection",n.CONNECTING="connecting",n.SENDING="sending",n.PROGRESS="progress",n.ACCEPTED="accepted",n.CONFIRMED="confirmed",n.ENDED="ended",n.FAILED="failed",n.NEW_DTMF="newDTMF",n.NEW_INFO="newInfo",n.HOLD="hold",n.UNHOLD="unhold",n.MUTED="muted",n.UNMUTED="unmuted",n.REINVITE="reinvite",n.UPDATE="update",n.REFER="refer",n.REPLACES="replaces",n.SDP="sdp",n.ICE_CANDIDATE="icecandidate",n.GET_USER_MEDIA_FAILED="getusermediafailed",n.PEER_CONNECTION_CREATE_OFFER_FAILED="peerconnection:createofferfailed",n.PEER_CONNECTION_CREATE_ANSWER_FAILED="peerconnection:createanswerfailed",n.PEER_CONNECTION_SET_LOCAL_DESCRIPTION_FAILED="peerconnection:setlocaldescriptionfailed",n.PEER_CONNECTION_SET_REMOTE_DESCRIPTION_FAILED="peerconnection:setremotedescriptionfailed",n.START_PRESENTATION="presentation:start",n.STARTED_PRESENTATION="presentation:started",n.END_PRESENTATION="presentation:end",n.ENDED_PRESENTATION="presentation:ended",n.FAILED_PRESENTATION="presentation:failed",n.PEER_CONNECTION_CONFIRMED="peerconnection:confirmed",n.PEER_CONNECTION_ONTRACK="peerconnection:ontrack",n.ENDED_FROM_SERVER="ended:fromserver",n.CALL_STATUS_CHANGED="call-status-changed",n.REMOTE_STREAMS_CHANGED="remote-streams-changed",n))(R||{}),de=(n=>(n.LOCAL="local",n.REMOTE="remote",n.SYSTEM="system",n))(de||{});const le=["peerconnection","connecting","sending","progress","accepted","confirmed","ended","failed","newInfo","newDTMF","presentation:start","presentation:started","presentation:end","presentation:ended","presentation:failed","reinvite","update","refer","replaces","sdp","icecandidate","getusermediafailed","peerconnection:createofferfailed","peerconnection:createanswerfailed","peerconnection:setlocaldescriptionfailed","peerconnection:setremotedescriptionfailed"],Ge=["peerconnection:confirmed","peerconnection:ontrack","ended:fromserver","call-status-changed","remote-streams-changed"],ue=[...le,...Ge],Ve=(n,e)=>{n.getVideoTracks().forEach(s=>{"contentHint"in s&&s.contentHint!==e&&(s.contentHint=e)})},B=(n,{directionVideo:e,directionAudio:t,contentHint:s}={})=>{if(!n||e==="recvonly"&&t==="recvonly")return;const i=t==="recvonly"?[]:n.getAudioTracks(),r=e==="recvonly"?[]:n.getVideoTracks(),a=[...i,...r],o=new MediaStream(a);return o.getTracks=()=>[...o.getAudioTracks(),...o.getVideoTracks()],s&&s!=="none"&&Ve(o,s),o};var J=(n=>(n.BYE="Terminated",n.WEBRTC_ERROR="WebRTC Error",n.CANCELED="Canceled",n.REQUEST_TIMEOUT="Request Timeout",n.REJECTED="Rejected",n.REDIRECTED="Redirected",n.UNAVAILABLE="Unavailable",n.NOT_FOUND="Not Found",n.ADDRESS_INCOMPLETE="Address Incomplete",n.INCOMPATIBLE_SDP="Incompatible SDP",n.BAD_MEDIA_DESCRIPTION="Bad Media Description",n))(J||{});class xe{events;rtcSession;disposers=new Set;onReset;constructor(e,{onReset:t}){this.events=e,this.onReset=t,e.on(R.FAILED,this.handleEnded),e.on(R.ENDED,this.handleEnded)}get connection(){return this.rtcSession?.connection}get isCallActive(){return this.rtcSession?.isEstablished()===!0}getEstablishedRTCSession=()=>this.rtcSession?.isEstablished()===!0?this.rtcSession:void 0;startCall=async(e,t,{number:s,mediaStream:i,extraHeaders:r=[],iceServers:a,directionVideo:o,directionAudio:c,contentHint:d,offerToReceiveAudio:S=!0,offerToReceiveVideo:g=!0,degradationPreference:T,sendEncodings:p,onAddedTransceiver:v})=>new Promise((A,D)=>{this.handleCall().then(A).catch(q=>{D(q)}),this.rtcSession=e.call(t(s),{mediaStream:B(i,{directionVideo:o,directionAudio:c,contentHint:d}),pcConfig:{iceServers:a},rtcOfferConstraints:{offerToReceiveAudio:S,offerToReceiveVideo:g},eventHandlers:this.events.triggers,extraHeaders:r,directionVideo:o,directionAudio:c,degradationPreference:T,sendEncodings:p,onAddedTransceiver:v})});async endCall(){const{rtcSession:e}=this;if(e&&!e.isEnded())return e.terminateAsync({cause:J.CANCELED}).finally(()=>{this.reset()});this.reset()}answerToIncomingCall=async(e,{mediaStream:t,extraHeaders:s=[],iceServers:i,directionVideo:r,directionAudio:a,offerToReceiveAudio:o,offerToReceiveVideo:c,contentHint:d,degradationPreference:S,sendEncodings:g,onAddedTransceiver:T})=>new Promise((p,v)=>{try{this.rtcSession=e,this.subscribeToSessionEvents(e),this.handleCall().then(p).catch(A=>{v(A)}),e.answer({pcConfig:{iceServers:i},rtcOfferConstraints:{offerToReceiveAudio:o,offerToReceiveVideo:c},mediaStream:B(t,{directionVideo:r,directionAudio:a,contentHint:d}),extraHeaders:s,directionVideo:r,directionAudio:a,degradationPreference:S,sendEncodings:g,onAddedTransceiver:T})}catch(A){v(A)}});async replaceMediaStream(e,t){if(!this.rtcSession)throw new Error("No rtcSession established");const{contentHint:s}=t??{},i=B(e,{contentHint:s});if(i===void 0)throw new Error("No preparedMediaStream");return this.rtcSession.replaceMediaStream(i,t)}async restartIce(e){if(!this.rtcSession)throw new Error("No rtcSession established");return this.rtcSession.restartIce(e)}handleCall=async()=>new Promise((e,t)=>{const s=()=>{this.events.on(R.PEER_CONNECTION,d),this.events.on(R.CONFIRMED,S)},i=()=>{this.events.off(R.PEER_CONNECTION,d),this.events.off(R.CONFIRMED,S)},r=()=>{this.events.on(R.FAILED,o),this.events.on(R.ENDED,o)},a=()=>{this.events.off(R.FAILED,o),this.events.off(R.ENDED,o)},o=g=>{i(),a(),t(g)};let c;const d=({peerconnection:g})=>{c=g;const T=p=>{this.events.trigger(R.PEER_CONNECTION_ONTRACK,p)};g.addEventListener("track",T),this.disposers.add(()=>{g.removeEventListener("track",T)})},S=()=>{c!==void 0&&this.events.trigger(R.PEER_CONNECTION_CONFIRMED,c),i(),a(),e(c)};s(),r()});subscribeToSessionEvents(e){this.events.eachTriggers((t,s)=>{const i=le.find(r=>r===s);i&&(e.on(i,t),this.disposers.add(()=>{e.off(i,t)}))})}unsubscribeFromSessionEvents(){this.disposers.forEach(e=>{e()}),this.disposers.clear()}handleEnded=e=>{const{originator:t}=e;t==="remote"&&this.events.trigger(R.ENDED_FROM_SERVER,e),this.reset()};reset=()=>{delete this.rtcSession,this.unsubscribeFromSessionEvents(),this.onReset()}}class Qe{config;tools;connection;constructor(e,t){this.config=e,this.tools=t,this.connection=new RTCPeerConnection(e.pcConfig),this.addTransceivers()}get settings(){return this.config}get peerConnection(){return this.connection}close(){this.connection.close()}async call(e){const t=this.waitForTracks(),s=await this.createOffer(),i=await this.tools.sendOffer({conferenceNumber:e,quality:this.config.quality,audioChannel:this.config.audioChannel},s);await this.setRemoteDescription(i),await t}async createOffer(){const e=await this.connection.createOffer();return await this.connection.setLocalDescription(e),e}async setRemoteDescription(e){return this.connection.setRemoteDescription(e)}async waitForTracks(){return new Promise(e=>{const t=new Set,s=i=>{const{track:r}=i;t.add(r.kind),t.has("audio")&&t.has("video")&&(this.connection.removeEventListener("track",s),e())};this.connection.addEventListener("track",s)})}addTransceivers(){this.addRecvOnlyTransceiver("audio"),this.addRecvOnlyTransceiver("video"),this.addRecvOnlyTransceiver("video"),this.addRecvOnlyTransceiver("video"),this.addRecvOnlyTransceiver("video")}addRecvOnlyTransceiver(e){const t={direction:"recvonly"};return this.connection.addTransceiver(e,t)}}const ge=n=>n.getSettings(),Ye=(n,e)=>{const t=ge(n);let s=e;s??=n.label;let i=t?.msid;return i??=s,i??=n.id,i},ze=(n,e)=>{const t=ge(n);let s=e;return s??=t?.msid,s??=n.label,(s&&s.length>0?s:void 0)??n.id};class Z{participantGroups=new Map;trackToGroup=new Map;trackDisposers=new Map;reset(){this.participantGroups.clear(),this.trackToGroup.clear(),this.trackDisposers.forEach(e=>{e()}),this.trackDisposers.clear()}addTrack(e,{onRemoved:t,streamHint:s}={}){const i=ze(e,s),r=Ye(e,s);if(this.trackToGroup.has(e.id))return{isAdded:!1};const a=this.getParticipantGroups(i);let o=a.get(r);o||(o={participantId:i,groupId:r,stream:new MediaStream,trackIds:new Set},a.set(r,o)),o.stream.addTrack(e),o.trackIds.add(e.id),this.trackToGroup.set(e.id,{participantId:i,groupId:r});const c=()=>{this.disposeTrackListener(e.id),this.removeTrack(e.id)&&t?.({trackId:e.id,participantId:i})};return e.addEventListener("ended",c),this.trackDisposers.set(e.id,()=>{e.removeEventListener("ended",c)}),{isAdded:!0,participantId:i}}removeTrack(e){this.disposeTrackListener(e);const t=this.trackToGroup.get(e);if(!t)return!1;const{participantId:s,groupId:i}=t,r=this.participantGroups.get(s),a=r?.get(i);if(!a)return this.trackToGroup.delete(e),!1;const o=a.stream.getTracks().find(c=>c.id===e);return o&&a.stream.removeTrack(o),a.trackIds.delete(e),this.trackToGroup.delete(e),a.trackIds.size===0&&(r?.delete(i),r?.size===0&&this.participantGroups.delete(s)),!0}removeStaleTracks(e,t){const s=this.participantGroups.get(e);if(!s)return!1;let i=!1;return[...s.values()].forEach(a=>{[...a.trackIds].filter(c=>!t.includes(c)).forEach(c=>{const d=this.removeTrack(c);i||=d})}),i}getStreams(e){if(e!==void 0){const t=this.participantGroups.get(e);return t?[...t.values()].map(s=>s.stream):[]}return[...this.participantGroups.values()].flatMap(t=>[...t.values()]).map(t=>t.stream)}disposeTrackListener(e){const t=this.trackDisposers.get(e);t&&(t(),this.trackDisposers.delete(e))}getParticipantGroups(e){const t=this.participantGroups.get(e);if(t)return t;const s=new Map;return this.participantGroups.set(e,s),s}}const W={type:"participant"},Xe={type:"spectator_synthetic"},Je=n=>({type:"spectator",recvParams:n});class f{role=W;mainManager;recvManager;onRoleChanged;constructor({mainManager:e,recvManager:t},s){this.mainManager=e,this.recvManager=t,this.onRoleChanged=s}static hasParticipant(e){return e.type==="participant"}static hasSpectatorSynthetic(e){return e.type==="spectator_synthetic"}static hasSpectator(e){return e.type==="spectator"}getRole(){return this.role}setCallRoleParticipant(){this.changeRole(W)}setCallRoleSpectatorSynthetic(){this.changeRole(Xe)}setCallRoleSpectator(e){this.changeRole(Je(e))}changeRole(e){const t=this.role;if(t.type!==e.type){this.setRole(e);return}f.hasSpectator(e)&&f.hasSpectator(t)&&t.recvParams.audioId!==e.recvParams.audioId&&this.setRole(e)}reset(){this.role=W,this.recvManager.reset()}getActiveManager(){return this.hasSpectator()?this.recvManager:this.mainManager}hasParticipant(){return f.hasParticipant(this.role)}hasSpectatorSynthetic(){return f.hasSpectatorSynthetic(this.role)}hasSpectator(){return f.hasSpectator(this.role)}setRole(e){const t=this.role;this.role=e,this.onRoleChanged?.({previous:t,next:e})}}const ee=n=>n.streams[0]?.id;class Ke{events;isPendingCall=!1;isPendingAnswer=!1;rtcSession;callConfiguration={};mainRemoteStreamsManager=new Z;recvRemoteStreamsManager=new Z;roleManager=new f({mainManager:this.mainRemoteStreamsManager,recvManager:this.recvRemoteStreamsManager},e=>{this.onRoleChanged(e)});mcuSession;recvSession;disposeRecvSessionTrackListener;constructor(){this.events=new O.TypedEvents(ue),this.mcuSession=new xe(this.events,{onReset:this.reset}),this.subscribeCallStatusChange(),this.subscribeMcuRemoteTrackEvents()}get requested(){return this.isPendingCall||this.isPendingAnswer}get connection(){return this.mcuSession.connection}get isCallActive(){return this.mcuSession.isCallActive}getEstablishedRTCSession=()=>this.mcuSession.getEstablishedRTCSession();on(e,t){return this.events.on(e,t)}onRace(e,t){return this.events.onRace(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}startCall=async(e,t,s)=>(this.isPendingCall=!0,this.callConfiguration.number=s.number,this.callConfiguration.answer=!1,this.mcuSession.startCall(e,t,s).finally(()=>{this.isPendingCall=!1}));async endCall(){return this.mcuSession.endCall()}answerToIncomingCall=async(e,t)=>{this.isPendingAnswer=!0;const s=e();return this.callConfiguration.answer=!0,this.callConfiguration.number=s.remote_identity.uri.user,this.mcuSession.answerToIncomingCall(s,t).finally(()=>{this.isPendingAnswer=!1})};getCallConfiguration(){return{...this.callConfiguration}}getRemoteStreams(){return this.getActiveStreamsManager().getStreams()}setCallRoleParticipant(){this.roleManager.setCallRoleParticipant()}setCallRoleSpectatorSynthetic(){this.roleManager.setCallRoleSpectatorSynthetic()}setCallRoleSpectator(e){this.roleManager.setCallRoleSpectator(e)}async replaceMediaStream(e,t){return this.mcuSession.replaceMediaStream(e,t)}async restartIce(e){return this.mcuSession.restartIce(e)}reset=()=>{this.mainRemoteStreamsManager.reset(),this.callConfiguration.number=void 0,this.callConfiguration.answer=!1,this.roleManager.reset(),this.stopRecvSession()};subscribeCallStatusChange(){let{isCallActive:e}=this;const{ACCEPTED:t,CONFIRMED:s,ENDED:i,FAILED:r}=R;this.onRace([t,s,i,r],()=>{e=this.maybeTriggerCallStatus(e)})}maybeTriggerCallStatus(e){const t=this.isCallActive;return t!==e&&this.events.trigger(R.CALL_STATUS_CHANGED,{isCallActive:t}),t}subscribeMcuRemoteTrackEvents(){this.on(R.PEER_CONNECTION_ONTRACK,e=>{this.addRemoteTrack(this.mainRemoteStreamsManager,e.track,ee(e))})}addRemoteTrack(e,t,s){const i=e.addTrack(t,{streamHint:s,onRemoved:r=>{this.emitRemoteStreamsChanged(e,"removed",{trackId:r.trackId,participantId:r.participantId})}});i.isAdded&&this.emitRemoteStreamsChanged(e,"added",{trackId:t.id,participantId:i.participantId})}emitRemoteStreamsChanged(e,t,{trackId:s,participantId:i}){const r=this.getActiveStreamsManager();if(e!==r)return;const a=[...r.getStreams()];this.events.trigger(R.REMOTE_STREAMS_CHANGED,{participantId:i,changeType:t,trackId:s,streams:a})}getActiveStreamsManager(){return this.roleManager.getActiveManager()}attachRecvSessionTracks(e){const{peerConnection:t}=e,s=i=>{this.addRemoteTrack(this.recvRemoteStreamsManager,i.track,ee(i))};t.addEventListener("track",s),this.disposeRecvSessionTrackListener=()=>{t.removeEventListener("track",s)}}startRecvSession(e,t){const{number:s}=this.callConfiguration;if(s===void 0)return;this.stopRecvSession();const i={quality:"high",audioChannel:e},r=new Qe(i,{sendOffer:t});this.recvSession=r,this.recvRemoteStreamsManager.reset(),this.attachRecvSessionTracks(r),r.call(s).catch(()=>{this.stopRecvSession()})}stopRecvSession(){this.recvSession?.close(),this.recvSession=void 0,this.disposeRecvSessionTrackListener?.(),this.disposeRecvSessionTrackListener=void 0,this.recvRemoteStreamsManager.reset()}onRoleChanged=({previous:e,next:t})=>{if(f.hasSpectator(e)&&!f.hasSpectator(t)&&this.stopRecvSession(),f.hasSpectator(t)){const s=t.recvParams;this.startRecvSession(s.audioId,s.sendOffer)}}}const je=(n,e)=>(n.degradationPreference=e.degradationPreference,n),Ze=(n,e)=>{n.encodings??=[];for(let t=n.encodings.length;t<e;t+=1)n.encodings.push({});return n},Te=n=>(e,t)=>t!==void 0&&e!==t||t===void 0&&e!==n,et=Te(),tt=(n,e)=>{if(et(n,e))return n},nt=(n,e)=>{const t=n.maxBitrate,s=tt(e,t);return s!==void 0&&(n.maxBitrate=s),n},Se=1,st=Te(Se),it=(n,e)=>{const t=n===void 0?void 0:Math.max(n,Se);if(t!==void 0&&st(t,e))return t},rt=(n,e)=>{const t=n.scaleResolutionDownBy,s=it(e,t);return s!==void 0&&(n.scaleResolutionDownBy=s),n},at=(n,e)=>{const t=e.encodings?.length??0;return Ze(n,t),n.encodings.forEach((s,i)=>{const r=(e?.encodings??[])[i],a=r?.maxBitrate,o=r?.scaleResolutionDownBy;nt(s,a),rt(s,o)}),n},ot=(n,e)=>{if(n.codecs?.length!==e.codecs?.length)return!0;for(let t=0;t<(n.codecs?.length??0);t++)if(JSON.stringify(n.codecs[t])!==JSON.stringify(e.codecs[t]))return!0;if(n.headerExtensions?.length!==e.headerExtensions?.length)return!0;for(let t=0;t<(n.headerExtensions?.length??0);t++)if(JSON.stringify(n.headerExtensions[t])!==JSON.stringify(e.headerExtensions[t]))return!0;if(n.encodings?.length!==e.encodings?.length)return!0;for(let t=0;t<(n.encodings?.length??0);t++)if(JSON.stringify(n.encodings[t])!==JSON.stringify(e.encodings[t]))return!0;return n.rtcp?.cname!==e.rtcp?.cname||n.rtcp?.reducedSize!==e.rtcp?.reducedSize||n.degradationPreference!==e.degradationPreference},Ce=async(n,e)=>{const t=n.getParameters(),s=JSON.parse(JSON.stringify(t));at(t,e),je(t,e);const i=ot(s,t);return i&&await n.setParameters(t),{parameters:t,isChanged:i}},K=async(n,e,t)=>{const{isChanged:s,parameters:i}=await Ce(n,{encodings:[{scaleResolutionDownBy:e.scaleResolutionDownBy,maxBitrate:e.maxBitrate}]});return s&&t&&t(i),{isChanged:s,parameters:i}},ct=(n,e)=>n.find(t=>t.track!==null&&e.getTracks().includes(t.track)),ht=async(n,e,t)=>{const s=ct(n,e);if(s)return K(s,{maxBitrate:t})};var P=(n=>(n.START_PRESENTATION="presentation:start",n.STARTED_PRESENTATION="presentation:started",n.END_PRESENTATION="presentation:end",n.ENDED_PRESENTATION="presentation:ended",n.FAILED_PRESENTATION="presentation:failed",n))(P||{});const Ee=["presentation:start","presentation:started","presentation:end","presentation:ended","presentation:failed"],dt=1,lt=n=>Y.hasCanceledError(n);class ut{events;promisePendingStartPresentation;promisePendingStopPresentation;streamPresentationCurrent;maxBitrate;cancelableSendPresentationWithRepeatedCalls;callManager;constructor({callManager:e,maxBitrate:t}){this.callManager=e,this.maxBitrate=t,this.events=new O.TypedEvents(Ee),this.subscribe()}get isPendingPresentation(){return!!this.promisePendingStartPresentation||!!this.promisePendingStopPresentation}async startPresentation(e,t,{isNeedReinvite:s,contentHint:i,sendEncodings:r,onAddedTransceiver:a}={},o){const c=this.getRtcSessionProtected();if(this.streamPresentationCurrent)throw new Error("Presentation is already started");return this.sendPresentationWithDuplicatedCalls(e,{rtcSession:c,stream:t,presentationOptions:{isNeedReinvite:s,contentHint:i,sendEncodings:r,onAddedTransceiver:a},options:o})}async stopPresentation(e){this.cancelSendPresentationWithRepeatedCalls();const t=this.streamPresentationCurrent;let s=this.promisePendingStartPresentation??Promise.resolve(void 0);this.promisePendingStartPresentation&&await this.promisePendingStartPresentation.catch(()=>{});const i=this.callManager.getEstablishedRTCSession();return i&&t?s=e().then(async()=>i.stopPresentation(t)).catch(r=>{const a=r instanceof Error?r:new Error(String(r));throw this.events.trigger(P.FAILED_PRESENTATION,a),r}):t&&this.events.trigger(P.ENDED_PRESENTATION,t),this.promisePendingStopPresentation=s,s.finally(()=>{this.resetPresentation()})}async updatePresentation(e,t,{contentHint:s,sendEncodings:i,onAddedTransceiver:r}={}){const a=this.getRtcSessionProtected();if(!this.streamPresentationCurrent)throw new Error("Presentation has not started yet");return this.promisePendingStartPresentation&&await this.promisePendingStartPresentation,this.sendPresentation(e,a,t,{contentHint:s,isNeedReinvite:!1,sendEncodings:i,onAddedTransceiver:r}).then(async o=>(await this.setMaxBitrate(),o))}cancelSendPresentationWithRepeatedCalls(){this.cancelableSendPresentationWithRepeatedCalls?.stopRepeatedCalls()}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}subscribe(){this.callManager.on("presentation:start",e=>{this.events.trigger(P.START_PRESENTATION,e)}),this.callManager.on("presentation:started",e=>{this.events.trigger(P.STARTED_PRESENTATION,e)}),this.callManager.on("presentation:end",e=>{this.events.trigger(P.END_PRESENTATION,e)}),this.callManager.on("presentation:ended",e=>{this.events.trigger(P.ENDED_PRESENTATION,e)}),this.callManager.on("presentation:failed",e=>{this.events.trigger(P.FAILED_PRESENTATION,e)}),this.callManager.on("failed",this.handleEnded),this.callManager.on("ended",this.handleEnded)}async sendPresentationWithDuplicatedCalls(e,{rtcSession:t,stream:s,presentationOptions:i,options:r={callLimit:dt}}){const a=async()=>this.sendPresentation(e,t,s,i),o=()=>!!this.streamPresentationCurrent;return this.cancelableSendPresentationWithRepeatedCalls=Y.repeatedCallsAsync({targetFunction:a,isComplete:o,isRejectAsValid:!0,...r}),this.cancelableSendPresentationWithRepeatedCalls.then(c=>c)}async sendPresentation(e,t,s,{isNeedReinvite:i=!0,contentHint:r="detail",degradationPreference:a,sendEncodings:o,onAddedTransceiver:c}){const d=B(s,{contentHint:r});if(d===void 0)throw new Error("No streamPresentationTarget");this.streamPresentationCurrent=d;const S=e().then(async()=>t.startPresentation(d,i,{degradationPreference:a,sendEncodings:o,onAddedTransceiver:c})).then(this.setMaxBitrate).then(()=>s).catch(g=>{this.removeStreamPresentationCurrent();const T=g instanceof Error?g:new Error(String(g));throw this.events.trigger(P.FAILED_PRESENTATION,T),g});return this.promisePendingStartPresentation=S,S.finally(()=>{this.promisePendingStartPresentation=void 0})}setMaxBitrate=async()=>{const{connection:e}=this.callManager,{streamPresentationCurrent:t}=this,{maxBitrate:s}=this;if(!e||!t||s===void 0)return;const i=e.getSenders();await ht(i,t,s)};getRtcSessionProtected=()=>{const e=this.callManager.getEstablishedRTCSession();if(!e)throw new Error("No rtcSession established");return e};handleEnded=()=>{this.reset()};reset(){this.cancelSendPresentationWithRepeatedCalls(),this.resetPresentation()}resetPresentation(){this.removeStreamPresentationCurrent(),this.promisePendingStartPresentation=void 0,this.promisePendingStopPresentation=void 0}removeStreamPresentationCurrent(){delete this.streamPresentationCurrent}}class gt{data;getUa;constructor(e){this.getUa=e.getUa}isConfigured(){return this.getUa()!==void 0}get(){if(this.data!==void 0)return{...this.data}}set(e){if(e===void 0){this.data=void 0;return}this.data={...e}}update(e,t){if(this.data===void 0)throw new Error("data is not exist");this.data[e]=t}clear(){this.data=void 0}isRegister(){return this.data?.register===!0}getSipServerIp(){return this.data?.sipServerIp}getSipServerUrl(){return this.data?.sipServerUrl}getDisplayName(){return this.data?.displayName}getUser(){return this.data?.user}getPassword(){return this.data?.password}isRegisterEnabled(){return this.data?.register===!0}}var C=(n=>(n.CONNECTING="connecting",n.CONNECTED="connected",n.DISCONNECTED="disconnected",n.DISCONNECTING="disconnecting",n.NEW_RTC_SESSION="newRTCSession",n.REGISTERED="registered",n.UNREGISTERED="unregistered",n.REGISTRATION_FAILED="registrationFailed",n.NEW_MESSAGE="newMessage",n.SIP_EVENT="sipEvent",n.CONNECT_STARTED="connect-started",n.CONNECT_SUCCEEDED="connect-succeeded",n.CONNECT_FAILED="connect-failed",n.CONNECT_PARAMETERS_RESOLVE_SUCCESS="connect-parameters-resolve-success",n.CONNECT_PARAMETERS_RESOLVE_FAILED="connect-parameters-resolve-failed",n.CONNECTED_WITH_CONFIGURATION="connected-with-configuration",n))(C||{});const pe=["connecting","connected","disconnected","newRTCSession","registered","unregistered","registrationFailed","newMessage","sipEvent"],Tt=["disconnecting","connect-started","connect-succeeded","connect-failed","connect-parameters-resolve-success","connect-parameters-resolve-failed","connected-with-configuration"],Re=[...pe,...Tt];function St(n){return e=>`sip:${e}@${n}`}const Ct=(n,e)=>()=>Math.floor(Math.random()*(e-n))+n,Ae=n=>n.trim().replaceAll(" ","_"),Et=Ct(1e5,99999999),pt=3;class Rt{cancelableConnectWithRepeatedCalls;JsSIP;events;uaFactory;stateMachine;registrationManager;getUa;setUa;getConnectionConfiguration;setConnectionConfiguration;updateConnectionConfiguration;setGetUri;setSocket;constructor(e){this.JsSIP=e.JsSIP,this.events=e.events,this.uaFactory=e.uaFactory,this.stateMachine=e.stateMachine,this.registrationManager=e.registrationManager,this.getUa=e.getUa,this.setUa=e.setUa,this.getConnectionConfiguration=e.getConnectionConfiguration,this.setConnectionConfiguration=e.setConnectionConfiguration,this.updateConnectionConfiguration=e.updateConnectionConfiguration,this.setGetUri=e.setGetUri,this.setSocket=e.setSocket,this.proxyEvents()}connect=async(e,t)=>(this.cancelRequests(),this.connectWithDuplicatedCalls(e,t));set=async({displayName:e})=>new Promise((t,s)=>{const i=this.getUa();if(!i){s(new Error("this.ua is not initialized"));return}let r=!1;const a=this.getConnectionConfiguration();e!==void 0&&e!==a?.displayName&&(r=i.set("display_name",Ae(e)),this.updateConnectionConfiguration("displayName",e));const o=r;o?t(o):s(new Error("nothing changed"))});disconnect=async()=>{this.events.trigger(C.DISCONNECTING,{});const e=new Promise(s=>{this.events.once(C.DISCONNECTED,()=>{s()})}),t=this.getUa();return t?t.stop():this.events.trigger(C.DISCONNECTED,{socket:{},error:!1}),e.finally(()=>{t?.removeAllListeners(),this.setUa(void 0),this.stateMachine.reset()})};cancelRequests(){this.cancelConnectWithRepeatedCalls()}connectWithDuplicatedCalls=async(e,{callLimit:t=pt}={})=>{const s=async()=>this.connectInner(e),i=r=>{const c=this.getUa()?.isConnected()===!0&&this.hasEqualConnectionConfiguration(e),d=r!=null&&!qe(r);return c||d};return this.stateMachine.startConnect(),this.cancelableConnectWithRepeatedCalls=Y.repeatedCallsAsync({targetFunction:s,isComplete:i,callLimit:t,isRejectAsValid:!0,isCheckBeforeCall:!1}),this.cancelableConnectWithRepeatedCalls.then(r=>{if("ua"in r&&r.ua instanceof this.JsSIP.UA)return r;throw r})};hasEqualConnectionConfiguration(e){const{configuration:t}=this.uaFactory.createConfiguration(e),i=this.getUa()?.configuration;return i?i.password===t.password&&i.register===t.register&&i.uri.toString()===t.uri&&i.display_name===t.display_name&&i.user_agent===t.user_agent&&i.sockets===t.sockets&&i.session_timers===t.session_timers&&i.register_expires===t.register_expires&&i.connection_recovery_min_interval===t.connection_recovery_min_interval&&i.connection_recovery_max_interval===t.connection_recovery_max_interval:!1}connectInner=async e=>this.initUa(e).then(async()=>this.start()).then(t=>{const s=this.getConnectionConfiguration();if(s===void 0)throw new Error("connectionConfiguration has not defined");return{...s,ua:t}});initUa=async({user:e,password:t,sipServerIp:s,sipServerUrl:i,remoteAddress:r,sessionTimers:a,registerExpires:o,connectionRecoveryMinInterval:c,connectionRecoveryMaxInterval:d,userAgent:S,displayName:g="",register:T=!1,extraHeaders:p=[]})=>{this.stateMachine.startInitUa(),this.setConnectionConfiguration({sipServerIp:s,sipServerUrl:i,displayName:g,register:T,user:e,password:t}),this.getUa()&&await this.disconnect();const{ua:A,helpers:D}=this.uaFactory.createUAWithConfiguration({user:e,password:t,sipServerIp:s,sipServerUrl:i,displayName:g,register:T,sessionTimers:a,registerExpires:o,connectionRecoveryMinInterval:c,connectionRecoveryMaxInterval:d,userAgent:S,remoteAddress:r,extraHeaders:p},this.events);return this.setUa(A),this.setGetUri(D.getUri),this.setSocket(D.socket),A};start=async()=>new Promise((e,t)=>{const s=this.getUa();if(!s){t(new Error("this.ua is not initialized"));return}let i;i=((c,d)=>{if(this.getConnectionConfiguration()?.register===!0)return this.registrationManager.subscribeToStartEvents(c,d);const g=C.CONNECTED,T=[C.DISCONNECTED];return this.events.on(g,c),T.forEach(p=>{this.events.on(p,d)}),()=>{this.events.off(g,c),T.forEach(p=>{this.events.off(p,d)})}})(()=>{i?.(),e(s)},c=>{i?.(),t(c)}),s.start()});cancelConnectWithRepeatedCalls(){this.cancelableConnectWithRepeatedCalls?.cancel()}proxyEvents(){this.events.on(C.CONNECTED,()=>{const e=this.getConnectionConfiguration(),t=this.getUa();e!==void 0&&t!==void 0&&this.events.trigger(C.CONNECTED_WITH_CONFIGURATION,{...e,ua:t})})}}var Ne=(n=>(n.START_CONNECT="START_CONNECT",n.START_INIT_UA="START_INIT_UA",n.UA_CONNECTED="UA_CONNECTED",n.UA_REGISTERED="UA_REGISTERED",n.UA_UNREGISTERED="UA_UNREGISTERED",n.UA_DISCONNECTED="UA_DISCONNECTED",n.CONNECTION_FAILED="CONNECTION_FAILED",n.RESET="RESET",n))(Ne||{});const At=oe.setup({types:{context:{},events:{}},actions:{logTransition:(n,e)=>{h(`State transition: ${e.from} -> ${e.to} (${e.event})`)},logStateChange:(n,e)=>{h("ConnectionStateMachine state changed",e.state)}}}).createMachine({id:"connection",initial:"idle",context:{},states:{idle:{entry:{type:"logStateChange",params:{state:"idle"}},on:{START_CONNECT:{target:"connecting",actions:{type:"logTransition",params:{from:"idle",to:"connecting",event:"START_CONNECT"}}}}},connecting:{entry:{type:"logStateChange",params:{state:"connecting"}},on:{START_INIT_UA:{target:"initializing",actions:{type:"logTransition",params:{from:"connecting",to:"initializing",event:"START_INIT_UA"}}},UA_DISCONNECTED:{target:"disconnected",actions:{type:"logTransition",params:{from:"connecting",to:"disconnected",event:"UA_DISCONNECTED"}}},CONNECTION_FAILED:{target:"failed",actions:{type:"logTransition",params:{from:"connecting",to:"failed",event:"CONNECTION_FAILED"}}}}},initializing:{entry:{type:"logStateChange",params:{state:"initializing"}},on:{UA_CONNECTED:{target:"connected",actions:{type:"logTransition",params:{from:"initializing",to:"connected",event:"UA_CONNECTED"}}},UA_REGISTERED:{target:"registered",actions:{type:"logTransition",params:{from:"initializing",to:"registered",event:"UA_REGISTERED"}}},UA_DISCONNECTED:{target:"disconnected",actions:{type:"logTransition",params:{from:"initializing",to:"disconnected",event:"UA_DISCONNECTED"}}},CONNECTION_FAILED:{target:"failed",actions:{type:"logTransition",params:{from:"initializing",to:"failed",event:"CONNECTION_FAILED"}}}}},connected:{entry:{type:"logStateChange",params:{state:"connected"}},on:{UA_REGISTERED:{target:"registered",actions:{type:"logTransition",params:{from:"connected",to:"registered",event:"UA_REGISTERED"}}},UA_DISCONNECTED:{target:"disconnected",actions:{type:"logTransition",params:{from:"connected",to:"disconnected",event:"UA_DISCONNECTED"}}},CONNECTION_FAILED:{target:"failed",actions:{type:"logTransition",params:{from:"connected",to:"failed",event:"CONNECTION_FAILED"}}}}},registered:{entry:{type:"logStateChange",params:{state:"registered"}},on:{UA_UNREGISTERED:{target:"connected",actions:{type:"logTransition",params:{from:"registered",to:"connected",event:"UA_UNREGISTERED"}}},UA_DISCONNECTED:{target:"disconnected",actions:{type:"logTransition",params:{from:"registered",to:"disconnected",event:"UA_DISCONNECTED"}}},CONNECTION_FAILED:{target:"failed",actions:{type:"logTransition",params:{from:"registered",to:"failed",event:"CONNECTION_FAILED"}}}}},disconnected:{entry:{type:"logStateChange",params:{state:"disconnected"}},on:{RESET:{target:"idle",actions:{type:"logTransition",params:{from:"disconnected",to:"idle",event:"RESET"}}},START_CONNECT:{target:"connecting",actions:{type:"logTransition",params:{from:"disconnected",to:"connecting",event:"START_CONNECT"}}}}},failed:{entry:{type:"logStateChange",params:{state:"failed"}},on:{RESET:{target:"idle",actions:{type:"logTransition",params:{from:"failed",to:"idle",event:"RESET"}}},START_CONNECT:{target:"connecting",actions:{type:"logTransition",params:{from:"failed",to:"connecting",event:"START_CONNECT"}}}}}}});class Nt{actor;stateChangeListeners=new Set;events;unsubscribeFromEvents;actorSubscription;constructor(e){this.events=e,this.actor=oe.createActor(At),this.actorSubscription=this.actor.subscribe(t=>{const s=t.value;this.stateChangeListeners.forEach(i=>{i(s)})}),this.actor.start(),this.subscribeToEvents()}get state(){return this.actor.getSnapshot().value}get isIdle(){return this.hasState("idle")}get isConnecting(){return this.hasState("connecting")}get isInitializing(){return this.hasState("initializing")}get isConnected(){return this.hasState("connected")}get isRegistered(){return this.hasState("registered")}get isDisconnected(){return this.hasState("disconnected")}get isFailed(){return this.hasState("failed")}get isPending(){return this.isConnecting||this.isInitializing}get isPendingConnect(){return this.isConnecting}get isPendingInitUa(){return this.isInitializing}get isActiveConnection(){return this.isConnected||this.isRegistered}startConnect(){this.toStartConnect()}startInitUa(){this.toStartInitUa()}reset(){this.toIdle()}destroy(){this.unsubscribeFromEvents?.(),this.actorSubscription?.unsubscribe(),this.actor.stop()}onStateChange(e){return this.stateChangeListeners.add(e),()=>{this.stateChangeListeners.delete(e)}}canTransition(e){return this.actor.getSnapshot().can({type:e})}getValidEvents(){return Object.values(Ne).filter(e=>this.canTransition(e))}hasState(e){return this.actor.getSnapshot().matches(e)}sendEvent(e){const t=this.actor.getSnapshot(),s={type:e};if(!t.can(s)){h(`Invalid transition: ${s.type} from ${this.state}. Event cannot be processed in current state.`);return}this.actor.send(s)}toStartConnect=()=>{this.sendEvent("START_CONNECT")};toStartInitUa=()=>{this.sendEvent("START_INIT_UA")};toConnected=()=>{this.sendEvent("UA_CONNECTED")};toRegistered=()=>{this.sendEvent("UA_REGISTERED")};toUnregistered=()=>{this.sendEvent("UA_UNREGISTERED")};toDisconnected=()=>{this.sendEvent("UA_DISCONNECTED")};toFailed=()=>{this.sendEvent("CONNECTION_FAILED")};toIdle=()=>{this.sendEvent("RESET")};subscribeToEvents(){this.events.on("connected",this.toConnected),this.events.on("registered",this.toRegistered),this.events.on("unregistered",this.toUnregistered),this.events.on("disconnected",this.toDisconnected),this.events.on("registrationFailed",this.toFailed),this.unsubscribeFromEvents=()=>{this.events.off("connected",this.toConnected),this.events.off("registered",this.toRegistered),this.events.off("unregistered",this.toUnregistered),this.events.off("disconnected",this.toDisconnected),this.events.off("registrationFailed",this.toFailed)}}}class mt{events;getUaProtected;constructor(e){this.events=e.events,this.getUaProtected=e.getUaProtected}async register(){const e=this.getUaProtected();return new Promise((t,s)=>{e.on(C.REGISTERED,t),e.on(C.REGISTRATION_FAILED,s),e.register()})}async unregister(){const e=this.getUaProtected();return new Promise(t=>{e.on(C.UNREGISTERED,t),e.unregister()})}async tryRegister(){try{await this.unregister()}catch(e){h("tryRegister",e)}return this.register()}subscribeToStartEvents(e,t){const s=C.REGISTERED,i=[C.REGISTRATION_FAILED,C.DISCONNECTED];return this.events.on(s,e),i.forEach(r=>{this.events.on(r,t)}),()=>{this.events.off(s,e),i.forEach(r=>{this.events.off(r,t)})}}}class It{uaFactory;getUaProtected;constructor(e){this.uaFactory=e.uaFactory,this.getUaProtected=e.getUaProtected}async sendOptions(e,t,s){const i=this.getUaProtected();return new Promise((r,a)=>{try{i.sendOptions(e,t,{extraHeaders:s,eventHandlers:{succeeded:()=>{r()},failed:a}})}catch(o){a(o)}})}async ping(e,t){const i=this.getUaProtected().configuration.uri;return this.sendOptions(i,e,t)}async checkTelephony({userAgent:e,displayName:t,sipServerIp:s,sipServerUrl:i,remoteAddress:r,extraHeaders:a}){return new Promise((o,c)=>{const{configuration:d}=this.uaFactory.createConfiguration({sipServerUrl:i,displayName:t,userAgent:e,sipServerIp:s}),S=this.uaFactory.createUA({...d,remoteAddress:r,extraHeaders:a}),g=()=>{const p=new Error("Telephony is not available");c(p)};S.once(C.DISCONNECTED,g);const T=()=>{S.removeAllListeners(),S.once(C.DISCONNECTED,()=>{o()}),S.stop()};S.once(C.CONNECTED,T),S.start()})}}const _t=n=>{const e=[];return n!==void 0&&n!==""&&e.push(`X-Vinteo-Remote: ${n}`),e};class b{JsSIP;constructor(e){this.JsSIP=e}static isRegisteredUA(e){return!!e&&e.isRegistered()}static validateParametersConnection({register:e,password:t,user:s,sipServerIp:i,sipServerUrl:r}){if(!i)throw new Error("sipServerIp is required");if(!r)throw new Error("sipServerUrl is required");if(e&&(t===void 0||t===""))throw new Error("password is required for authorized connection");if(e&&(s===void 0||s===""))throw new Error("user is required for authorized connection")}static resolveAuthorizationUser(e,t){return e&&t!==void 0&&t.trim()!==""?t.trim():`${Et()}`}static buildExtraHeaders(e,t){const s=e!==void 0&&e!==""?_t(e):[];return t===void 0?s:[...s,...t]}createConfiguration({user:e,password:t,sipServerUrl:s,displayName:i="",sipServerIp:r,register:a=!1,sessionTimers:o=!1,registerExpires:c=300,connectionRecoveryMinInterval:d=2,connectionRecoveryMaxInterval:S=6,userAgent:g}){b.validateParametersConnection({register:a,password:t,user:e,sipServerIp:r,sipServerUrl:s});const T=b.resolveAuthorizationUser(a,e),p=St(r),v=p(T),A=new this.JsSIP.WebSocketInterface(`wss://${s}/webrtc/wss/`);return{configuration:{password:t,register:a,uri:v,display_name:Ae(i),user_agent:g,sdpSemantics:"unified-plan",sockets:[A],session_timers:o,register_expires:c,connection_recovery_min_interval:d,connection_recovery_max_interval:S},helpers:{socket:A,getUri:p}}}createUA({remoteAddress:e,extraHeaders:t,...s}){const i=new this.JsSIP.UA(s),r=b.buildExtraHeaders(e,t);return r.length>0&&i.registrator().setExtraHeaders(r),i}createUAWithConfiguration(e,t){const{configuration:s,helpers:i}=this.createConfiguration(e),r=this.createUA({...s,remoteAddress:e.remoteAddress,extraHeaders:e.extraHeaders});return t.eachTriggers((a,o)=>{const c=pe.find(d=>d===o);c&&r.on(c,a)}),{ua:r,helpers:i}}}const me="Not ready for connection",Ie=n=>n instanceof Error&&n.message===me,Mt=()=>new Error(me),ft=async n=>typeof n=="function"?n():n;class vt{events;ua;socket;uaFactory;registrationManager;stateMachine;connectionFlow;sipOperations;configurationManager;JsSIP;constructor({JsSIP:e}){this.JsSIP=e,this.events=new O.TypedEvents(Re),this.uaFactory=new b(e),this.registrationManager=new mt({events:this.events,getUaProtected:this.getUaProtected}),this.stateMachine=new Nt(this.events),this.configurationManager=new gt({getUa:this.getUa}),this.sipOperations=new It({uaFactory:this.uaFactory,getUaProtected:this.getUaProtected}),this.connectionFlow=new Rt({JsSIP:this.JsSIP,events:this.events,uaFactory:this.uaFactory,stateMachine:this.stateMachine,registrationManager:this.registrationManager,getUa:this.getUa,getConnectionConfiguration:this.getConnectionConfiguration,setConnectionConfiguration:t=>{this.configurationManager.set(t)},updateConnectionConfiguration:(t,s)=>{this.configurationManager.update(t,s)},setUa:t=>{this.ua=t},setGetUri:t=>{this.getUri=t},setSocket:t=>{this.socket=t}})}get requested(){return this.stateMachine.isPending}get isPendingConnect(){return this.stateMachine.isPendingConnect}get isPendingInitUa(){return this.stateMachine.isPendingInitUa}get isIdle(){return this.stateMachine.isIdle}get isDisconnected(){return this.stateMachine.isDisconnected}get isFailed(){return this.stateMachine.isFailed}get connectionState(){return this.stateMachine.state}get isRegistered(){return b.isRegisteredUA(this.ua)}get isRegisterConfig(){return this.configurationManager.isRegister()}connect=async(e,t)=>this.disconnect().catch(s=>{h("connect: disconnect error",s)}).then(async()=>this.connectWithProcessError(e,t));set=async({displayName:e})=>this.connectionFlow.set({displayName:e});disconnect=async()=>{if(this.isConfigured())return this.connectionFlow.disconnect()};async register(){return this.registrationManager.register()}async unregister(){return this.registrationManager.unregister()}tryRegister=async()=>this.registrationManager.tryRegister();sendOptions=async(e,t,s)=>this.sipOperations.sendOptions(e,t,s);ping=async(e,t)=>this.sipOperations.ping(e,t);checkTelephony=async e=>this.sipOperations.checkTelephony(e);on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}isConfigured(){return this.configurationManager.isConfigured()}getConnectionConfiguration=()=>this.configurationManager.get();destroy(){this.stateMachine.destroy()}getUri=e=>e;getUaProtected=()=>{if(!this.ua)throw new Error("UA not initialized");return this.ua};getUa=()=>this.ua;connectWithProcessError=async(e,t)=>{if(!(t?.hasReadyForConnection?.()??!0))throw Mt();return this.processConnect(e,t).catch(async i=>{const r=i;return this.disconnect().then(()=>{throw r}).catch(()=>{throw r})})};processConnect=async(e,t)=>(this.events.trigger(C.CONNECT_STARTED,{}),ft(e).then(s=>(this.events.trigger(C.CONNECT_PARAMETERS_RESOLVE_SUCCESS,s),s)).catch(s=>{throw this.events.trigger(C.CONNECT_PARAMETERS_RESOLVE_FAILED,s),s}).then(async s=>this.connectionFlow.connect(s,t)).then(s=>(this.events.trigger(C.CONNECT_SUCCEEDED,{...s}),s)).catch(s=>{const i=s??new Error("Failed to connect to server");throw this.events.trigger(C.CONNECT_FAILED,i),i}))}class Pt{connectionManager;stackPromises=z.createStackPromises({noRunIsNotActual:!0});constructor({connectionManager:e}){this.connectionManager=e}connect=async(...e)=>this.stackPromises.run(async()=>this.connectionManager.connect(...e));disconnect=async()=>this.stackPromises.run(async()=>this.connectionManager.disconnect());stop(){this.stackPromises.stop()}}const te=0,Ot=30;class yt{countInner=te;initialCount=te;limitInner=Ot;isInProgress=!1;onStatusChange;constructor({onStatusChange:e}){this.onStatusChange=e}get count(){return this.countInner}get limit(){return this.limitInner}get isAttemptInProgress(){return this.isInProgress}hasLimitReached(){return this.countInner>=this.limitInner}startAttempt(){this.isInProgress||(this.isInProgress=!0,this.onStatusChange({isInProgress:this.isInProgress}))}finishAttempt(){this.isInProgress&&(this.isInProgress=!1,this.onStatusChange({isInProgress:this.isInProgress}))}increment(){this.count<this.limit&&(this.countInner+=1)}reset(){this.countInner=this.initialCount,this.finishAttempt()}}class Dt{connectionManager;interval;checkTelephonyByTimeout=void 0;cancelableBeforeRequest=void 0;constructor({connectionManager:e,interval:t}){this.connectionManager=e,this.interval=t}start({onBeforeRequest:e,onSuccessRequest:t,onFailRequest:s}){this.stop(),this.cancelableBeforeRequest=new $.CancelableRequest(e),this.checkTelephonyByTimeout=w.resolveRequesterByTimeout({isDontStopOnFail:!0,requestInterval:this.interval,request:async()=>{if(!this.cancelableBeforeRequest)throw new Error("cancelableBeforeRequest is not defined");const i=await this.cancelableBeforeRequest.request();return this.connectionManager.checkTelephony(i)}}),this.checkTelephonyByTimeout.start(void 0,{onFailRequest:s,onSuccessRequest:()=>{this.stop(),t()}})}stop(){this.checkTelephonyByTimeout?.stop(),this.checkTelephonyByTimeout=void 0,this.cancelableBeforeRequest?.cancelRequest(),this.cancelableBeforeRequest=void 0}}var I=(n=>(n.BEFORE_ATTEMPT="before-attempt",n.SUCCESS="success",n.FAILED_ALL_ATTEMPTS="failed-all-attempts",n.CANCELLED_ATTEMPTS="cancelled-attempts",n.CHANGED_ATTEMPT_STATUS="changed-attempt-status",n.STOP_ATTEMPTS_BY_ERROR="stop-attempts-by-error",n.LIMIT_REACHED_ATTEMPTS="limit-reached-attempts",n))(I||{});const _e=["before-attempt","success","failed-all-attempts","cancelled-attempts","changed-attempt-status","stop-attempts-by-error","limit-reached-attempts"],bt=15e3,wt=2;class Ut{connectionManager;pingServerByTimeoutWithFailCalls;constructor({connectionManager:e}){this.connectionManager=e,this.pingServerByTimeoutWithFailCalls=w.requesterByTimeoutsWithFailCalls(wt,{whenPossibleRequest:async()=>{},requestInterval:bt,request:async()=>(h("ping"),this.connectionManager.ping().then(()=>{h("ping success")}))})}start({onFailRequest:e}){this.pingServerByTimeoutWithFailCalls.start(void 0,{onFailRequest:e}).catch(h)}stop(){this.pingServerByTimeoutWithFailCalls.stop()}}class Lt{callManager;pingServerRequester;disposeCallStatusChange;constructor({connectionManager:e,callManager:t}){this.callManager=t,this.pingServerRequester=new Ut({connectionManager:e})}start({onFailRequest:e}){h("start"),this.disposeCallStatusChange=this.callManager.on("call-status-changed",()=>{this.handleCallStatusChange({onFailRequest:e})}),this.handleCallStatusChange({onFailRequest:e})}stop(){h("stop"),this.pingServerRequester.stop(),this.unsubscribeCallStatusChange()}unsubscribeCallStatusChange(){this.disposeCallStatusChange?.(),this.disposeCallStatusChange=void 0}handleCallStatusChange({onFailRequest:e}){this.callManager.isCallActive?this.pingServerRequester.stop():this.pingServerRequester.start({onFailRequest:e})}}class Bt{connectionManager;callManager;isRegistrationFailed=!1;disposers=[];constructor({connectionManager:e,callManager:t}){this.connectionManager=e,this.callManager=t}subscribe(e){this.unsubscribe(),this.disposers.push(this.connectionManager.on("registrationFailed",()=>{this.setIsRegistrationFailed()})),this.disposers.push(this.callManager.on("call-status-changed",({isCallActive:t})=>{!t&&this.isRegistrationFailed&&e()}))}unsubscribe(){this.disposers.forEach(e=>{e()}),this.disposers=[],this.resetIsRegistrationFailed()}setIsRegistrationFailed(){this.isRegistrationFailed=!0}resetIsRegistrationFailed(){this.isRegistrationFailed=!1}}const kt=3e3,Ft=15e3,ne={LIMIT_REACHED:"Limit reached",FAILED_TO_RECONNECT:"Failed to reconnect"},$t=async()=>{},qt=n=>!0;class Wt{events;connectionManager;connectionQueueManager;checkTelephonyRequester;pingServerIfNotActiveCallRequester;registrationFailedOutOfCallSubscriber;attemptsState;delayBetweenAttempts;cancelableRequestBeforeRetry;onBeforeRetry;canRetryOnError;networkInterfacesSubscriber;resumeFromSleepModeSubscriber;constructor({connectionQueueManager:e,connectionManager:t,callManager:s},i){const r=i?.onBeforeRetry??$t,a=i?.canRetryOnError??qt;this.connectionQueueManager=e,this.connectionManager=t,this.onBeforeRetry=r,this.canRetryOnError=a,this.networkInterfacesSubscriber=i?.networkInterfacesSubscriber,this.resumeFromSleepModeSubscriber=i?.resumeFromSleepModeSubscriber,this.events=new O.TypedEvents(_e),this.checkTelephonyRequester=new Dt({connectionManager:t,interval:i?.checkTelephonyRequestInterval??Ft}),this.pingServerIfNotActiveCallRequester=new Lt({connectionManager:t,callManager:s}),this.registrationFailedOutOfCallSubscriber=new Bt({connectionManager:t,callManager:s}),this.attemptsState=new yt({onStatusChange:this.emitStatusChange}),this.cancelableRequestBeforeRetry=new $.CancelableRequest(r),this.delayBetweenAttempts=new w.DelayRequester(i?.timeoutBetweenAttempts??kt)}start(e){h("auto connector start"),this.restartConnectionAttempts(e),this.subscribeToHardwareTriggers(e)}stop(){h("auto connector stop"),this.unsubscribeFromHardwareTriggers(),this.stopConnectionFlow().catch(e=>{h("auto connector stop from stop method: error",e)})}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}restartConnectionAttempts(e){h("auto connector restart connection attempts"),this.stopConnectionFlow().then(async()=>this.attemptConnection(e)).catch(t=>{h("auto connector failed to restart connection attempts:",t)})}async stopConnectionFlow(){h("stopConnectionFlow"),this.stopAttempts(),this.stopConnectTriggers(),await this.connectionQueueManager.disconnect()}stopAttempts(){this.attemptsState.isAttemptInProgress&&this.connectionQueueManager.stop(),this.delayBetweenAttempts.cancelRequest(),this.cancelableRequestBeforeRetry.cancelRequest(),this.attemptsState.reset()}stopConnectTriggers(){h("stopConnectTriggers"),this.stopPingRequester(),this.checkTelephonyRequester.stop(),this.registrationFailedOutOfCallSubscriber.unsubscribe()}startCheckTelephony(e){h("startCheckTelephony"),this.checkTelephonyRequester.start({onBeforeRequest:async()=>(await this.onBeforeRetry(),e.getParameters()),onSuccessRequest:()=>{h("startCheckTelephony: onSuccessRequest"),this.connectIfDisconnected(e)},onFailRequest:t=>{h("startCheckTelephony: onFailRequest",t.message)}})}async attemptConnection(e){if(h("attemptConnection: attempts.count",this.attemptsState.count),this.events.trigger(I.BEFORE_ATTEMPT,{}),this.stopConnectTriggers(),this.attemptsState.hasLimitReached()){h("attemptConnection: limit reached"),this.handleLimitReached(e);return}return this.attemptsState.startAttempt(),this.attemptsState.increment(),this.executeConnectionAttempt(e)}async executeConnectionAttempt(e){try{await this.connectionQueueManager.connect(e.getParameters,e.options),h("executeConnectionAttempt: success"),this.handleSucceededAttempt(e)}catch(t){this.handleConnectionError(t,e)}}handleConnectionError(e,t){if(Ie(e)){this.attemptsState.finishAttempt(),this.events.trigger(I.STOP_ATTEMPTS_BY_ERROR,e);return}if(!this.canRetryOnError(e)){h("executeConnectionAttempt: error does not allow retry",e),this.attemptsState.finishAttempt(),this.events.trigger(I.STOP_ATTEMPTS_BY_ERROR,e);return}if(z.isPromiseIsNotActualError(e)){h("executeConnectionAttempt: not actual error",e),this.attemptsState.finishAttempt(),this.events.trigger(I.CANCELLED_ATTEMPTS,e);return}h("executeConnectionAttempt: error",e),this.scheduleReconnect(t)}handleLimitReached(e){this.attemptsState.finishAttempt(),this.events.trigger(I.LIMIT_REACHED_ATTEMPTS,new Error(ne.LIMIT_REACHED)),this.startCheckTelephony(e)}handleSucceededAttempt(e){h("handleSucceededAttempt"),this.subscribeToConnectTriggers(e),this.events.trigger(I.SUCCESS)}subscribeToConnectTriggers(e){this.startPingRequester(e),this.registrationFailedOutOfCallSubscriber.subscribe(()=>{h("registrationFailedOutOfCallListener callback"),this.restartConnectionAttempts(e)})}subscribeToHardwareTriggers(e){this.unsubscribeFromHardwareTriggers(),h("subscribeToHardwareTriggers"),this.networkInterfacesSubscriber?.subscribe({onChange:()=>{h("networkInterfacesSubscriber onChange"),this.restartConnectionAttempts(e)},onUnavailable:()=>{h("networkInterfacesSubscriber onUnavailable"),this.stopConnectionFlow().catch(t=>{h("auto connector stop from networkInterfacesSubscriber onUnavailable: error",t)})}}),this.resumeFromSleepModeSubscriber?.subscribe({onResume:()=>{h("resumeFromSleepModeSubscriber onResume"),this.restartConnectionAttempts(e)}})}unsubscribeFromHardwareTriggers(){h("unsubscribeFromHardwareTriggers"),this.networkInterfacesSubscriber?.unsubscribe(),this.resumeFromSleepModeSubscriber?.unsubscribe()}stopPingRequester(){this.pingServerIfNotActiveCallRequester.stop()}startPingRequester(e){this.pingServerIfNotActiveCallRequester.start({onFailRequest:()=>{h("pingRequester: onFailRequest"),this.restartConnectionAttempts(e)}})}connectIfDisconnected(e){const t=this.isConnectionUnavailable();h("connectIfDisconnected: isUnavailable",t),t?this.restartConnectionAttempts(e):(this.stopConnectTriggers(),this.events.trigger(I.SUCCESS))}scheduleReconnect(e){h("scheduleReconnect"),this.delayBetweenAttempts.request().then(async()=>(h("scheduleReconnect: delayBetweenAttempts success"),this.cancelableRequestBeforeRetry.request())).then(async()=>(h("scheduleReconnect: onBeforeRetry success"),this.attemptConnection(e))).catch(t=>{const s=t instanceof Error?t:new Error(ne.FAILED_TO_RECONNECT);this.attemptsState.finishAttempt(),$.isCanceledError(t)||w.hasCanceledError(t)?this.events.trigger(I.CANCELLED_ATTEMPTS,s):this.events.trigger(I.FAILED_ALL_ATTEMPTS,s),h("scheduleReconnect: error",t)})}isConnectionUnavailable(){const{isFailed:e,isDisconnected:t,isIdle:s}=this.connectionManager;return e||t||s}emitStatusChange=({isInProgress:e})=>{this.events.trigger(I.CHANGED_ATTEMPT_STATUS,{isInProgress:e})}}var L=(n=>(n.INCOMING_CALL="incomingCall",n.DECLINED_INCOMING_CALL="declinedIncomingCall",n.TERMINATED_INCOMING_CALL="terminatedIncomingCall",n.FAILED_INCOMING_CALL="failedIncomingCall",n))(L||{});const Me=["incomingCall","declinedIncomingCall","terminatedIncomingCall","failedIncomingCall"],Ht=486,Gt=487;class Vt{events;incomingRTCSession;connectionManager;constructor(e){this.connectionManager=e,this.events=new O.TypedEvents(Me),this.start()}get remoteCallerData(){return{displayName:this.incomingRTCSession?.remote_identity.display_name,host:this.incomingRTCSession?.remote_identity.uri.host,incomingNumber:this.incomingRTCSession?.remote_identity.uri.user,rtcSession:this.incomingRTCSession}}get isAvailableIncomingCall(){return!!this.incomingRTCSession}start(){this.subscribe()}stop(){this.unsubscribe(),this.removeIncomingSession()}getIncomingRTCSession=()=>{const{incomingRTCSession:e}=this;if(!e)throw new Error("No incomingRTCSession");return e};extractIncomingRTCSession=()=>{const e=this.getIncomingRTCSession();return this.removeIncomingSession(),e};async declineToIncomingCall({statusCode:e=Gt}={}){return new Promise((t,s)=>{try{const i=this.getIncomingRTCSession(),r=this.remoteCallerData;this.removeIncomingSession(),this.events.trigger(L.DECLINED_INCOMING_CALL,r),i.terminate({status_code:e}),t()}catch(i){s(i)}})}async busyIncomingCall(){return this.declineToIncomingCall({statusCode:Ht})}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}subscribe(){this.connectionManager.on("newRTCSession",this.handleNewRTCSession)}unsubscribe(){this.connectionManager.off("newRTCSession",this.handleNewRTCSession)}handleNewRTCSession=({originator:e,session:t})=>{e==="remote"&&this.setIncomingSession(t)};setIncomingSession(e){this.incomingRTCSession=e;const t=this.remoteCallerData;e.on("failed",s=>{this.removeIncomingSession(),s.originator==="local"?this.events.trigger(L.TERMINATED_INCOMING_CALL,t):this.events.trigger(L.FAILED_INCOMING_CALL,t)}),this.events.trigger(L.INCOMING_CALL,t)}removeIncomingSession(){delete this.incomingRTCSession}}const U=1e3;var E=(n=>(n.INBOUND_RTP="inbound-rtp",n.REMOTE_OUTBOUND_RTP="remote-outbound-rtp",n.MEDIA_SOURCE="media-source",n.OUTBOUND_RTP="outbound-rtp",n.REMOTE_INBOUND_RTP="remote-inbound-rtp",n.CODEC="codec",n.CANDIDATE_PAIR="candidate-pair",n.CERTIFICATE="certificate",n.TRANSPORT="transport",n.LOCAL_CANDIDATE="local-candidate",n.REMOTE_CANDIDATE="remote-candidate",n))(E||{});const fe=["collected"],xt="api/v2/rtp2webrtc/offer",ve=async({serverUrl:n,conferenceNumber:e,quality:t,audio:s,offer:i})=>{const r=new URL(`https://${n.replace(/\/$/,"")}/${xt}/${encodeURIComponent(e)}`);r.searchParams.set("quality",t),r.searchParams.set("audio",String(s));const a=await fetch(r.toString(),{method:"POST",headers:{"Content-Type":"application/json"},referrerPolicy:"no-referrer",credentials:"same-origin",body:JSON.stringify(i)});if(!a.ok)throw new Error(`sendOffer failed with status ${a.status}`);const o=await a.json();return{type:o.type,sdp:o.sdp,toJSON(){return o}}},se=()=>"performance"in window?performance.now():Date.now(),k=n=>[...n.keys()].reduce((e,t)=>{const s=n.get(t);return s===void 0?e:{...e,[s.type]:s}},{}),Qt=n=>{if(!n)return{outboundRtp:void 0,codec:void 0,mediaSource:void 0,remoteInboundRtp:void 0};const e=k(n);return{outboundRtp:e[E.OUTBOUND_RTP],codec:e[E.CODEC],mediaSource:e[E.MEDIA_SOURCE],remoteInboundRtp:e[E.REMOTE_INBOUND_RTP]}},ie=n=>{if(!n)return{outboundRtp:void 0,codec:void 0,mediaSource:void 0,remoteInboundRtp:void 0};const e=k(n);return{outboundRtp:e[E.OUTBOUND_RTP],codec:e[E.CODEC],mediaSource:e[E.MEDIA_SOURCE],remoteInboundRtp:e[E.REMOTE_INBOUND_RTP]}},re=({videoReceiversStats:n,synchronizationSourcesVideo:e})=>{if(!n)return{inboundRtp:void 0,codec:void 0,synchronizationSources:e};const t=k(n);return{inboundRtp:t[E.INBOUND_RTP],codec:t[E.CODEC],synchronizationSources:e}},Yt=({audioReceiverStats:n,synchronizationSourcesAudio:e})=>{if(!n)return{inboundRtp:void 0,codec:void 0,remoteOutboundRtp:void 0,synchronizationSources:e};const t=k(n);return{inboundRtp:t[E.INBOUND_RTP],codec:t[E.CODEC],remoteOutboundRtp:t[E.REMOTE_OUTBOUND_RTP],synchronizationSources:e}},Pe=n=>{if(!n)return{candidatePair:void 0,certificate:void 0,localCandidate:void 0,remoteCandidate:void 0,transport:void 0};const e=k(n);return{candidatePair:e[E.CANDIDATE_PAIR],certificate:e[E.CERTIFICATE],localCandidate:e[E.LOCAL_CANDIDATE],remoteCandidate:e[E.REMOTE_CANDIDATE],transport:e[E.TRANSPORT]}},zt=({audioSenderStats:n,videoSenderFirstStats:e,videoSenderSecondStats:t})=>({video:ie(e),secondVideo:ie(t),audio:Qt(n),additional:Pe(n??e??t)}),Xt=({audioReceiverStats:n,videoReceiverFirstStats:e,videoReceiverSecondStats:t,synchronizationSources:s})=>({video:re({videoReceiversStats:e,synchronizationSourcesVideo:s.video}),secondVideo:re({videoReceiversStats:t,synchronizationSourcesVideo:s.video}),audio:Yt({audioReceiverStats:n,synchronizationSourcesAudio:s.audio}),additional:Pe(n??e??t)}),Jt=({audioSenderStats:n,videoSenderFirstStats:e,videoSenderSecondStats:t,audioReceiverStats:s,videoReceiverFirstStats:i,videoReceiverSecondStats:r,synchronizationSources:a})=>{const o=zt({audioSenderStats:n,videoSenderFirstStats:e,videoSenderSecondStats:t}),c=Xt({audioReceiverStats:s,videoReceiverFirstStats:i,videoReceiverSecondStats:r,synchronizationSources:a});return{outbound:o,inbound:c}},Kt=async n=>{const e="audio",t="video",s=n.getSenders(),i=s.find(T=>T.track?.kind===e),r=s.filter(T=>T.track?.kind===t),a=n.getReceivers(),o=a.find(T=>T.track.kind===e),c=a.filter(T=>T.track.kind===t),d={trackIdentifier:o?.track.id,item:o?.getSynchronizationSources()[0]},S={trackIdentifier:c[0]?.track.id,item:c[0]?.getSynchronizationSources()[0]},g={audio:d,video:S};return Promise.all([i?.getStats()??Promise.resolve(void 0),r[0]?.getStats()??Promise.resolve(void 0),r[1]?.getStats()??Promise.resolve(void 0),o?.getStats()??Promise.resolve(void 0),c[0]?.getStats()??Promise.resolve(void 0),c[1]?.getStats()??Promise.resolve(void 0)]).then(T=>{const[p,v,A,D,q,Le]=T;return{synchronizationSources:g,audioSenderStats:p,videoSenderFirstStats:v,videoSenderSecondStats:A,audioReceiverStats:D,videoReceiverFirstStats:q,videoReceiverSecondStats:Le}})},jt=n=>{h(String(n))};class Oe{events;setTimeoutRequest;requesterAllStatistics=new $.CancelableRequest(Kt);constructor(){this.events=new O.TypedEvents(fe),this.setTimeoutRequest=new w.SetTimeoutRequest}get requested(){return this.setTimeoutRequest.requested}start(e,{interval:t=U,onError:s=jt}={}){this.stop(),this.setTimeoutRequest.request(()=>{this.collectStatistics(e,{onError:s})},t)}stop(){this.setTimeoutRequest.cancelRequest(),this.requesterAllStatistics.cancelRequest()}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}collectStatistics=(e,{onError:t})=>{const s=se();this.requesterAllStatistics.request(e).then(i=>{this.events.trigger("collected",Jt(i));const a=se()-s;let o=U;a>48?o=U*4:a>32?o=U*3:a>16&&(o=U*2),this.start(e,{onError:t,interval:o})}).catch(i=>{t&&t(i)})}}class Zt{availableIncomingBitrate;statsPeerConnection;callManager;apiManager;previousAvailableIncomingBitrate;constructor({callManager:e,apiManager:t}){this.callManager=e,this.apiManager=t,this.statsPeerConnection=new Oe,this.subscribe()}get events(){return this.statsPeerConnection.events}on(e,t){return this.statsPeerConnection.on(e,t)}once(e,t){return this.statsPeerConnection.once(e,t)}onceRace(e,t){return this.statsPeerConnection.onceRace(e,t)}async wait(e){return this.statsPeerConnection.wait(e)}off(e,t){this.statsPeerConnection.off(e,t)}hasAvailableIncomingBitrateChangedQuarter(){const e=this.previousAvailableIncomingBitrate,t=this.availableIncomingBitrate;return e===void 0||t===void 0?!1:e===0?t>0:Math.abs(t-e)/e>=.25}subscribe(){this.callManager.on("peerconnection:confirmed",this.handleStarted),this.callManager.on("failed",this.handleEnded),this.callManager.on("ended",this.handleEnded),this.statsPeerConnection.on("collected",this.handleStatsCollected)}handleStatsCollected=e=>{this.previousAvailableIncomingBitrate=this.availableIncomingBitrate,this.availableIncomingBitrate=e.inbound.additional.candidatePair?.availableIncomingBitrate,this.maybeSendStats()};handleStarted=e=>{this.statsPeerConnection.start(e)};handleEnded=()=>{this.statsPeerConnection.stop(),this.availableIncomingBitrate=void 0,this.previousAvailableIncomingBitrate=void 0};maybeSendStats(){this.availableIncomingBitrate!==void 0&&this.hasAvailableIncomingBitrateChangedQuarter()&&this.apiManager.sendStats({availableIncomingBitrate:this.availableIncomingBitrate}).catch(e=>{h("Failed to send stats",e)})}}const en=(n,e)=>n.filter(s=>e.some(i=>i.clockRate===s.clockRate&&i.mimeType===s.mimeType&&i.channels===s.channels&&i.sdpFmtpLine===s.sdpFmtpLine)),tn=n=>{const e=RTCRtpSender.getCapabilities(n),t=RTCRtpReceiver.getCapabilities(n),s=e===null?[]:e.codecs,i=t===null?[]:t.codecs;return en(s,i)},nn=(n,e)=>e===void 0||e.length===0?n:n.sort((t,s)=>{const i=e.indexOf(t.mimeType),r=e.indexOf(s.mimeType),a=i===-1?Number.MAX_VALUE:i,o=r===-1?Number.MAX_VALUE:r;return a-o}),sn=(n,e)=>e===void 0||e.length===0?n:n.filter(t=>!e.includes(t.mimeType)),rn=(n,{preferredMimeTypesVideoCodecs:e,excludeMimeTypesVideoCodecs:t})=>{try{if(typeof n.setCodecPreferences=="function"&&n.sender.track?.kind==="video"&&(e!==void 0&&e.length>0||t!==void 0&&t.length>0)){const s=tn("video"),i=sn(s,t),r=nn(i,e);n.setCodecPreferences(r)}}catch(s){h("setCodecPreferences error",s)}},an=n=>[...n.keys()].map(e=>n.get(e)),on=(n,e)=>an(n).find(t=>t?.type===e),ye=async n=>n.getStats().then(e=>on(e,"codec")?.mimeType);class cn{async getCodecFromSender(e){return await ye(e)??""}}class hn{stackPromises=z.createStackPromises({noRunIsNotActual:!0});async add(e){return this.stackPromises.add(e),this.run()}stop(){this.stackPromises.stop()}async run(){return this.stackPromises().catch(e=>{h("TaskQueue: error",e)})}}class dn{taskQueue;onSetParameters;constructor(e){this.onSetParameters=e,this.taskQueue=new hn}async setEncodingsToSender(e,t){return this.taskQueue.add(async()=>K(e,t,this.onSetParameters))}stop(){this.taskQueue.stop()}}const De=(n,e)=>n!==void 0&&e!==void 0&&n.toLowerCase().includes(e.toLowerCase()),ln=1e6,_=n=>n*ln,be=_(.06),we=_(4),un=n=>n<=64?be:n<=128?_(.12):n<=256?_(.25):n<=384?_(.32):n<=426?_(.38):n<=640?_(.5):n<=848?_(.7):n<=1280?_(1):n<=1920?_(2):we,gn="av1",Tn=n=>De(n,gn),Sn=.6,j=(n,e)=>Tn(e)?n*Sn:n,Cn=n=>j(be,n),En=n=>j(we,n),ae=(n,e)=>{const t=un(n);return j(t,e)},H=1,pn=({videoTrack:n,targetSize:e})=>{const t=n.getSettings(),s=t.width,i=t.height,r=s===void 0?H:s/e.width,a=i===void 0?H:i/e.height;return Math.max(r,a,H)};class Rn{ignoreForCodec;senderFinder;codecProvider;parametersSetter;resultNoChanged={isChanged:!1,parameters:{encodings:[{}],transactionId:"0",codecs:[],headerExtensions:[],rtcp:{}}};constructor({senderFinder:e,codecProvider:t,parametersSetter:s},i){this.senderFinder=e,this.codecProvider=t,this.parametersSetter=s,this.ignoreForCodec=i.ignoreForCodec}async balance(e,t){const s=e.getSenders(),i=this.senderFinder.findVideoSender(s);if(!i?.track)return{...this.resultNoChanged,sender:i};const r=await this.codecProvider.getCodecFromSender(i);if(De(r,this.ignoreForCodec))return{...this.resultNoChanged,sender:i};const{mainCam:a,resolutionMainCam:o}=t??{};return this.processSender({mainCam:a,resolutionMainCam:o},{sender:i,codec:r,videoTrack:i.track}).then(c=>({...c,sender:i}))}async processSender(e,t){const{mainCam:s,resolutionMainCam:i}=e;switch(s){case M.PAUSE_MAIN_CAM:return this.downgradeResolutionSender(t);case M.RESUME_MAIN_CAM:return this.setBitrateByTrackResolution(t);case M.MAX_MAIN_CAM_RESOLUTION:return i!==void 0?this.setResolutionSender(i,t):this.setBitrateByTrackResolution(t);case M.ADMIN_STOP_MAIN_CAM:case M.ADMIN_START_MAIN_CAM:case void 0:return this.setBitrateByTrackResolution(t);default:return this.setBitrateByTrackResolution(t)}}async downgradeResolutionSender(e){const{sender:t,codec:s}=e,i={scaleResolutionDownBy:200,maxBitrate:Cn(s)};return this.parametersSetter.setEncodingsToSender(t,i)}async setBitrateByTrackResolution(e){const{sender:t,videoTrack:s,codec:i}=e,a=s.getSettings().width,o=a===void 0?En(i):ae(a,i);return this.parametersSetter.setEncodingsToSender(t,{scaleResolutionDownBy:1,maxBitrate:o})}async setResolutionSender(e,t){const[s,i]=e.split("x"),{sender:r,videoTrack:a,codec:o}=t,c={width:Number(s),height:Number(i)},d=pn({videoTrack:a,targetSize:c}),S=ae(c.width,o),g={scaleResolutionDownBy:d,maxBitrate:S};return this.parametersSetter.setEncodingsToSender(r,g)}}const An=n=>n.find(e=>e.track?.kind==="video");class Nn{findVideoSender(e){return An(e)}}class mn{currentSender;originalReplaceTrack;lastWidth;lastHeight;maxPollIntervalMs;currentPollIntervalMs;pollIntervalMs;setTimeoutRequest;constructor({pollIntervalMs:e=1e3,maxPollIntervalMs:t}){this.pollIntervalMs=e,this.maxPollIntervalMs=t??e*16,this.currentPollIntervalMs=this.pollIntervalMs,this.setTimeoutRequest=new w.SetTimeoutRequest}subscribe(e,t){if(!e){this.detachSender();return}this.currentSender!==e&&(this.detachSender(),this.attachSender(e,t))}unsubscribe(){this.detachSender()}attachSender(e,t){this.currentSender=e;const s=e.replaceTrack.bind(e);this.originalReplaceTrack=s,e.replaceTrack=async i=>{await s(i),this.attachTrack(t,i??void 0),t()},this.attachTrack(t,e.track)}detachSender(){this.currentSender&&this.originalReplaceTrack&&(this.currentSender.replaceTrack=this.originalReplaceTrack),this.originalReplaceTrack=void 0,this.currentSender=void 0,this.detachTrack()}attachTrack(e,t){if(this.detachTrack(),!t)return;const{width:s,height:i}=t.getSettings();this.lastWidth=s,this.lastHeight=i,this.currentPollIntervalMs=this.pollIntervalMs,this.schedulePoll(t,e)}schedulePoll(e,t){const s=()=>{const{width:i,height:r}=e.getSettings();i!==this.lastWidth||r!==this.lastHeight?(this.lastWidth=i,this.lastHeight=r,this.currentPollIntervalMs=this.pollIntervalMs,t()):this.currentPollIntervalMs=Math.min(this.currentPollIntervalMs*2,this.maxPollIntervalMs),this.setTimeoutRequest.request(s,this.currentPollIntervalMs)};this.setTimeoutRequest.request(s,this.currentPollIntervalMs)}detachTrack(){this.setTimeoutRequest.cancelRequest(),this.lastWidth=void 0,this.lastHeight=void 0}}class In{apiManager;currentHandler;constructor(e){this.apiManager=e}subscribe(e){this.currentHandler=e,this.apiManager.on("main-cam-control",e)}unsubscribe(){this.currentHandler&&(this.apiManager.off("main-cam-control",this.currentHandler),this.currentHandler=void 0)}}class _n{eventHandler;senderBalancer;parametersSetterWithQueue;getConnection;serverHeaders;trackMonitor;constructor(e,t,{ignoreForCodec:s,onSetParameters:i,pollIntervalMs:r}={}){this.getConnection=t,this.eventHandler=new In(e),this.parametersSetterWithQueue=new dn(i),this.senderBalancer=new Rn({senderFinder:new Nn,codecProvider:new cn,parametersSetter:this.parametersSetterWithQueue},{ignoreForCodec:s}),this.trackMonitor=new mn({pollIntervalMs:r})}subscribe(){this.eventHandler.subscribe(this.handleMainCamControl)}unsubscribe(){this.eventHandler.unsubscribe(),this.parametersSetterWithQueue.stop(),this.reset()}reset(){delete this.serverHeaders,this.trackMonitor.unsubscribe()}async balance(){const e=this.getConnection();if(!e)throw new Error("connection is not exist");const t=await this.senderBalancer.balance(e,this.serverHeaders);return this.trackMonitor.subscribe(t.sender,()=>{this.balance().catch(s=>{h("balance on track change: error",s)})}),t}handleMainCamControl=e=>{this.serverHeaders=e,this.balance().catch(t=>{h("handleMainCamControl: error",t)})}}const Ue=["balancing-scheduled","balancing-started","balancing-stopped","parameters-updated"];class Mn{isBalancingActive=!1;events;callManager;balancingStartDelay;videoSendingBalancer;startBalancingTimer;constructor(e,t,s={}){this.events=new O.TypedEvents(Ue),this.callManager=e,this.balancingStartDelay=s.balancingStartDelay??1e4,this.videoSendingBalancer=new _n(t,()=>e.connection,{...s,onSetParameters:i=>{this.events.trigger("parameters-updated",i),s.onSetParameters?.(i)}}),this.subscribe()}get isBalancingScheduled(){return this.startBalancingTimer!==void 0}async startBalancing(){this.isBalancingActive||(this.clearStartTimer(),await this.videoSendingBalancer.balance(),this.videoSendingBalancer.subscribe(),this.isBalancingActive=!0,this.events.trigger("balancing-started",{delay:this.balancingStartDelay}))}stopBalancing(){this.clearStartTimer(),this.videoSendingBalancer.unsubscribe(),this.isBalancingActive=!1,this.events.trigger("balancing-stopped",{})}async balance(){return this.videoSendingBalancer.balance()}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}subscribe(){this.callManager.on("peerconnection:confirmed",this.handleCallStarted),this.callManager.on("ended",this.handleCallEnded),this.callManager.on("failed",this.handleCallEnded)}handleCallStarted=()=>{this.scheduleBalancingStart()};handleCallEnded=()=>{this.stopBalancing()};scheduleBalancingStart(){this.clearStartTimer(),this.startBalancingTimer=setTimeout(()=>{this.startBalancingTimer=void 0,this.startBalancing().catch(e=>{h("startBalancing: error",e)})},this.balancingStartDelay),this.events.trigger("balancing-scheduled",{delay:this.balancingStartDelay})}clearStartTimer(){this.startBalancingTimer&&(clearTimeout(this.startBalancingTimer),this.startBalancingTimer=void 0)}}const fn=1e6,vn=_e.map(n=>`auto-connect:${n}`),Pn=Re.map(n=>`connection:${n}`),On=ue.map(n=>`call:${n}`),yn=he.map(n=>`api:${n}`),Dn=Me.map(n=>`incoming-call:${n}`),bn=Ee.map(n=>`presentation:${n}`),wn=fe.map(n=>`stats:${n}`),Un=Ue.map(n=>`video-balancer:${n}`),Ln=[...vn,...Pn,...On,...yn,...Dn,...bn,...wn,...Un];class Bn{events;connectionManager;connectionQueueManager;callManager;autoConnectorManager;apiManager;incomingCallManager;presentationManager;statsManager;videoSendingBalancerManager;preferredMimeTypesVideoCodecs;excludeMimeTypesVideoCodecs;constructor({JsSIP:e},{preferredMimeTypesVideoCodecs:t,excludeMimeTypesVideoCodecs:s,videoBalancerOptions:i,autoConnectorOptions:r}={}){this.preferredMimeTypesVideoCodecs=t,this.excludeMimeTypesVideoCodecs=s,this.events=new O.TypedEvents(Ln),this.connectionManager=new vt({JsSIP:e}),this.connectionQueueManager=new Pt({connectionManager:this.connectionManager}),this.callManager=new Ke,this.apiManager=new He({connectionManager:this.connectionManager,callManager:this.callManager}),this.incomingCallManager=new Vt(this.connectionManager),this.presentationManager=new ut({callManager:this.callManager,maxBitrate:fn}),this.statsManager=new Zt({callManager:this.callManager,apiManager:this.apiManager}),this.autoConnectorManager=new Wt({connectionQueueManager:this.connectionQueueManager,connectionManager:this.connectionManager,callManager:this.callManager},r),this.videoSendingBalancerManager=new Mn(this.callManager,this.apiManager,i),this.subscribe()}get requestedConnection(){return this.connectionManager.requested}get isPendingConnect(){return this.connectionManager.isPendingConnect}get isPendingInitUa(){return this.connectionManager.isPendingInitUa}get connectionState(){return this.connectionManager.connectionState}get isRegistered(){return this.connectionManager.isRegistered}get isRegisterConfig(){return this.connectionManager.isRegisterConfig}get socket(){return this.connectionManager.socket}get requestedCall(){return this.callManager.requested}get connection(){return this.callManager.connection}get isCallActive(){return this.callManager.isCallActive}get remoteCallerData(){return this.incomingCallManager.remoteCallerData}get isAvailableIncomingCall(){return this.incomingCallManager.isAvailableIncomingCall}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}onceRace(e,t){return this.events.onceRace(e,t)}async wait(e){return this.events.wait(e)}off(e,t){this.events.off(e,t)}connect=async(...e)=>this.connectionQueueManager.connect(...e);disconnect=async()=>this.connectionQueueManager.disconnect();register=async()=>this.connectionManager.register();unregister=async()=>this.connectionManager.unregister();tryRegister=async()=>this.connectionManager.tryRegister();set=async(...e)=>this.connectionManager.set(...e);sendOptions=async(e,t,s)=>this.connectionManager.sendOptions(e,t,s);ping=async(e,t)=>this.connectionManager.ping(e,t);checkTelephony=async e=>this.connectionManager.checkTelephony(e);isConfigured=()=>this.connectionManager.isConfigured();getConnectionConfiguration=()=>this.connectionManager.getConnectionConfiguration();getUri=e=>this.connectionManager.getUri(e);startAutoConnect=(...e)=>{this.autoConnectorManager.start(...e)};stopAutoConnect=()=>{this.autoConnectorManager.stop()};call=async e=>{const{onAddedTransceiver:t,...s}=e;return this.callManager.startCall(this.connectionManager.getUaProtected(),this.getUri,{...s,onAddedTransceiver:this.resolveHandleAddTransceiver(t)})};hangUp=async()=>this.callManager.endCall();answerToIncomingCall=async e=>{const{onAddedTransceiver:t,...s}=e;return this.callManager.answerToIncomingCall(this.incomingCallManager.extractIncomingRTCSession,{...s,onAddedTransceiver:this.resolveHandleAddTransceiver(t)})};declineToIncomingCall=async(...e)=>this.incomingCallManager.declineToIncomingCall(...e);getEstablishedRTCSession=()=>this.callManager.getEstablishedRTCSession();getCallConfiguration=()=>this.callManager.getCallConfiguration();getRemoteStreams=()=>this.callManager.getRemoteStreams();replaceMediaStream=async(...e)=>this.callManager.replaceMediaStream(...e);async startPresentation(e,t={}){const{isP2P:s,callLimit:i,onAddedTransceiver:r,...a}=t;return this.presentationManager.startPresentation(async()=>{s===!0?(await this.apiManager.sendMustStopPresentationP2P(),await this.apiManager.askPermissionToStartPresentationP2P()):await this.apiManager.askPermissionToStartPresentation()},e,{...a,onAddedTransceiver:this.resolveHandleAddTransceiver(r)},i===void 0?void 0:{callLimit:i})}async stopPresentation(e={}){const{isP2P:t}=e;return this.presentationManager.stopPresentation(async()=>{await(t===!0?this.apiManager.sendMustStopPresentationP2P():this.apiManager.sendStoppedPresentation())})}async updatePresentation(e,t={}){const{isP2P:s,onAddedTransceiver:i,...r}=t;return this.presentationManager.updatePresentation(async()=>{s===!0?(await this.apiManager.sendMustStopPresentationP2P(),await this.apiManager.askPermissionToStartPresentationP2P()):await this.apiManager.askPermissionToStartPresentation()},e,{...r,onAddedTransceiver:this.resolveHandleAddTransceiver(i)})}async waitChannels(...e){return this.apiManager.waitChannels(...e)}async waitSyncMediaState(...e){return this.apiManager.waitSyncMediaState(...e)}async sendDTMF(...e){return this.apiManager.sendDTMF(...e)}async sendChannels(...e){return this.apiManager.sendChannels(...e)}async sendMediaState(...e){return this.apiManager.sendMediaState(...e)}async sendRefusalToTurnOn(...e){return this.apiManager.sendRefusalToTurnOn(...e)}async sendRefusalToTurnOnMic(...e){return this.apiManager.sendRefusalToTurnOnMic(...e)}async sendRefusalToTurnOnCam(...e){return this.apiManager.sendRefusalToTurnOnCam(...e)}async sendMustStopPresentationP2P(...e){return this.apiManager.sendMustStopPresentationP2P(...e)}async sendStoppedPresentationP2P(...e){return this.apiManager.sendStoppedPresentationP2P(...e)}async sendStoppedPresentation(...e){return this.apiManager.sendStoppedPresentation(...e)}async askPermissionToStartPresentationP2P(...e){return this.apiManager.askPermissionToStartPresentationP2P(...e)}async askPermissionToStartPresentation(...e){return this.apiManager.askPermissionToStartPresentation(...e)}async askPermissionToEnableCam(...e){return this.apiManager.askPermissionToEnableCam(...e)}subscribeChangeRole(){this.apiManager.on("participant:move-request-to-participants",()=>{this.callManager.setCallRoleParticipant()}),this.apiManager.on("participant:move-request-to-spectators-synthetic",()=>{this.callManager.setCallRoleSpectatorSynthetic()}),this.apiManager.on("participant:move-request-to-spectators-with-audio-id",({audioId:e})=>{this.callManager.setCallRoleSpectator({audioId:e,sendOffer:this.sendOffer})})}sendOffer=async(e,t)=>{const i=this.connectionManager.getConnectionConfiguration()?.sipServerUrl;if(i===void 0)throw new Error("No sipServerUrl for sendOffer");return ve({serverUrl:i,offer:t,conferenceNumber:e.conferenceNumber,quality:e.quality,audio:e.audioChannel})};setCodecPreferences(e){rn(e,{preferredMimeTypesVideoCodecs:this.preferredMimeTypesVideoCodecs,excludeMimeTypesVideoCodecs:this.excludeMimeTypesVideoCodecs})}subscribe(){this.bridgeEvents("auto-connect",this.autoConnectorManager),this.bridgeEvents("connection",this.connectionManager),this.bridgeEvents("call",this.callManager),this.bridgeEvents("api",this.apiManager),this.bridgeEvents("incoming-call",this.incomingCallManager),this.bridgeEvents("presentation",this.presentationManager),this.bridgeEvents("stats",this.statsManager),this.bridgeEvents("video-balancer",this.videoSendingBalancerManager),this.subscribeChangeRole()}bridgeEvents=(e,t)=>{t.events.eachTriggers((s,i)=>{t.on(i,r=>{this.events.trigger(`${e}:${i}`,r)})})};resolveHandleAddTransceiver=e=>async(t,s,i)=>{this.setCodecPreferences(t),await e?.(t,s,i)}}exports.ECallCause=J;exports.EStatsTypes=E;exports.EUseLicense=ce;exports.Originator=de;exports.SipConnector=Bn;exports.StatsPeerConnection=Oe;exports.disableDebug=ke;exports.enableDebug=Be;exports.getCodecFromSender=ye;exports.hasCanceledStartPresentationError=lt;exports.hasNotReadyForConnectionError=Ie;exports.logger=h;exports.prepareMediaStream=B;exports.sendOffer=ve;exports.setEncodingsToSender=K;exports.setParametersToSender=Ce;