@wazo/sdk 0.37.0 → 0.37.4

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 (144) hide show
  1. package/dist/wazo-sdk.js +5 -5
  2. package/esm/__tests__/api-client.test.js +91 -23
  3. package/esm/__tests__/web-rtc-client.test.js +165 -56
  4. package/esm/api/agentd.js +7 -1
  5. package/esm/api/amid.js +7 -1
  6. package/esm/api/application.js +7 -1
  7. package/esm/api/auth.js +7 -1
  8. package/esm/api/call-logd.js +17 -23
  9. package/esm/api/calld.js +10 -18
  10. package/esm/api/chatd.js +7 -1
  11. package/esm/api/confd.js +78 -1
  12. package/esm/api/ctid-ng.js +7 -1
  13. package/esm/api/dird.js +7 -1
  14. package/esm/api/webhookd.js +7 -1
  15. package/esm/api-client.js +91 -23
  16. package/esm/checker/Checker.js +169 -56
  17. package/esm/checker/checks/aor.js +91 -23
  18. package/esm/checker/checks/api.js +91 -23
  19. package/esm/checker/checks/index.js +169 -56
  20. package/esm/checker/checks/wazo-websocket.js +11 -1
  21. package/esm/checker/checks/webrtc-transport.js +165 -56
  22. package/esm/checker/checks/webrtc.js +165 -56
  23. package/esm/domain/AdHocAPIConference.js +1722 -1654
  24. package/esm/domain/CallLog.js +10 -22
  25. package/esm/domain/CallSession.js +1 -18
  26. package/esm/domain/Features.js +91 -23
  27. package/esm/domain/IndirectTransfer.js +0 -17
  28. package/esm/domain/Meeting.js +71 -0
  29. package/esm/domain/Phone/CTIPhone.js +98 -26
  30. package/esm/domain/Phone/Phone.js +0 -17
  31. package/esm/domain/Phone/WebRTCPhone.js +47 -27
  32. package/esm/domain/Room.js +0 -17
  33. package/esm/domain/SwitchboardCall.js +0 -17
  34. package/esm/domain/__tests__/CallLog.test.js +10 -22
  35. package/esm/domain/__tests__/CallSession.test.js +1 -18
  36. package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
  37. package/esm/domain/__tests__/Room.test.js +1 -18
  38. package/esm/index.js +3880 -3111
  39. package/esm/lib/WazoSessionDescriptionHandler.js +24 -10
  40. package/esm/service/CallApi.js +91 -23
  41. package/esm/service/IssueReporter.js +7 -1
  42. package/esm/service/__tests__/IssueReporter.test.js +9 -1
  43. package/esm/service/getApiClient.js +91 -23
  44. package/esm/simple/Auth.js +1126 -360
  45. package/esm/simple/Configuration.js +1126 -360
  46. package/esm/simple/Directory.js +91 -23
  47. package/esm/simple/Phone.js +3724 -2958
  48. package/esm/simple/Websocket.js +13 -1
  49. package/esm/simple/index.js +1128 -362
  50. package/esm/simple/room/LocalParticipant.js +1097 -331
  51. package/esm/simple/room/Participant.js +1097 -331
  52. package/esm/simple/room/RemoteParticipant.js +1097 -331
  53. package/esm/simple/room/Room.js +1097 -331
  54. package/esm/simple/room/SipRoom.js +12996 -0
  55. package/esm/simple/room/Stream.js +1128 -362
  56. package/esm/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
  57. package/esm/simple/utils.js +1128 -362
  58. package/esm/utils/__tests__/api-requester.test.js +7 -1
  59. package/esm/utils/api-requester.js +7 -1
  60. package/esm/web-rtc-client.js +165 -56
  61. package/esm/websocket-client.js +12 -2
  62. package/lib/__tests__/api-client.test.js +91 -23
  63. package/lib/__tests__/web-rtc-client.test.js +165 -56
  64. package/lib/api/agentd.js +7 -1
  65. package/lib/api/amid.js +7 -1
  66. package/lib/api/application.js +7 -1
  67. package/lib/api/auth.js +7 -1
  68. package/lib/api/call-logd.js +17 -23
  69. package/lib/api/calld.js +10 -18
  70. package/lib/api/chatd.js +7 -1
  71. package/lib/api/confd.js +78 -1
  72. package/lib/api/ctid-ng.js +7 -1
  73. package/lib/api/dird.js +7 -1
  74. package/lib/api/webhookd.js +7 -1
  75. package/lib/api-client.js +91 -23
  76. package/lib/checker/Checker.js +169 -56
  77. package/lib/checker/checks/aor.js +91 -23
  78. package/lib/checker/checks/api.js +91 -23
  79. package/lib/checker/checks/index.js +169 -56
  80. package/lib/checker/checks/wazo-websocket.js +11 -1
  81. package/lib/checker/checks/webrtc-transport.js +165 -56
  82. package/lib/checker/checks/webrtc.js +165 -56
  83. package/lib/domain/AdHocAPIConference.js +1722 -1654
  84. package/lib/domain/CallLog.js +10 -22
  85. package/lib/domain/CallSession.js +1 -18
  86. package/lib/domain/Features.js +91 -23
  87. package/lib/domain/IndirectTransfer.js +0 -17
  88. package/lib/domain/Meeting.js +73 -0
  89. package/lib/domain/Phone/CTIPhone.js +98 -26
  90. package/lib/domain/Phone/Phone.js +0 -16
  91. package/lib/domain/Phone/WebRTCPhone.js +47 -27
  92. package/lib/domain/Room.js +0 -17
  93. package/lib/domain/SwitchboardCall.js +0 -17
  94. package/lib/domain/__tests__/CallLog.test.js +10 -22
  95. package/lib/domain/__tests__/CallSession.test.js +1 -18
  96. package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
  97. package/lib/domain/__tests__/Room.test.js +1 -18
  98. package/lib/index.js +3880 -3111
  99. package/lib/lib/WazoSessionDescriptionHandler.js +24 -10
  100. package/lib/service/CallApi.js +91 -23
  101. package/lib/service/IssueReporter.js +7 -1
  102. package/lib/service/__tests__/IssueReporter.test.js +9 -1
  103. package/lib/service/getApiClient.js +91 -23
  104. package/lib/simple/Auth.js +1126 -360
  105. package/lib/simple/Configuration.js +1126 -360
  106. package/lib/simple/Directory.js +91 -23
  107. package/lib/simple/Phone.js +3724 -2958
  108. package/lib/simple/Websocket.js +13 -1
  109. package/lib/simple/index.js +1128 -362
  110. package/lib/simple/room/LocalParticipant.js +1097 -331
  111. package/lib/simple/room/Participant.js +1097 -331
  112. package/lib/simple/room/RemoteParticipant.js +1097 -331
  113. package/lib/simple/room/Room.js +1097 -331
  114. package/lib/simple/room/SipRoom.js +13006 -0
  115. package/lib/simple/room/Stream.js +1128 -362
  116. package/lib/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
  117. package/lib/simple/utils.js +1128 -362
  118. package/lib/utils/__tests__/api-requester.test.js +7 -1
  119. package/lib/utils/api-requester.js +7 -1
  120. package/lib/web-rtc-client.js +165 -56
  121. package/lib/websocket-client.js +13 -1
  122. package/package.json +1 -1
  123. package/src/api/calld.js +3 -0
  124. package/src/api/confd.js +13 -0
  125. package/src/domain/CallLog.js +10 -22
  126. package/src/domain/CallSession.js +1 -2
  127. package/src/domain/Meeting.js +59 -0
  128. package/src/domain/Phone/CTIPhone.js +6 -2
  129. package/src/domain/Phone/Phone.js +2 -0
  130. package/src/domain/Phone/WebRTCPhone.js +22 -8
  131. package/src/index.js +6 -0
  132. package/src/lib/WazoSessionDescriptionHandler.js +17 -9
  133. package/src/service/IssueReporter.js +7 -1
  134. package/src/service/__tests__/IssueReporter.test.js +2 -0
  135. package/src/simple/Phone.js +13 -4
  136. package/src/simple/index.js +8 -0
  137. package/src/simple/room/Participant.js +7 -0
  138. package/src/simple/room/Room.js +157 -79
  139. package/src/simple/room/SipRoom.js +147 -0
  140. package/src/simple/room/Stream.js +1 -3
  141. package/src/simple/room/__tests__/RemoteParticipant.test.js +3 -2
  142. package/src/types/WebSocketMessage.js +21 -0
  143. package/src/web-rtc-client.js +57 -24
  144. package/src/websocket-client.js +4 -0
@@ -338,7 +338,13 @@ class IssueReporter {
338
338
  }
339
339
 
340
340
  _isLevelAbove(level1 , level2 ) {
341
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
341
+ const index1 = LOG_LEVELS.indexOf(level1);
342
+ const index2 = LOG_LEVELS.indexOf(level2);
343
+ if (index1 === -1 || index2 === -1) {
344
+ return false;
345
+ }
346
+
347
+ return index1 > index2;
342
348
  }
343
349
 
344
350
  _makeCategory(category ) {
@@ -361,7 +367,7 @@ var IssueReporter$1 = new IssueReporter();
361
367
 
362
368
  const methods = ['head', 'get', 'post', 'put', 'delete'];
363
369
 
364
- const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
370
+ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
365
371
 
366
372
  // Use a function here to be able to mock it in tests
367
373
  const realFetch = () => {
@@ -500,7 +506,7 @@ class ApiRequester {
500
506
  };
501
507
 
502
508
  if (this.refreshTokenPromise) {
503
- logger$a.info('A token is already refreshing, waiting ...', { url });
509
+ logger$c.info('A token is already refreshing, waiting ...', { url });
504
510
  await this.refreshTokenPromise;
505
511
  }
506
512
 
@@ -520,7 +526,7 @@ class ApiRequester {
520
526
  return promise.then(async (err ) => {
521
527
  // Check if the token is still valid
522
528
  if (firstCall && this._checkTokenExpired(response, err)) {
523
- logger$a.warn('token expired', { error: err.reason });
529
+ logger$c.warn('token expired', { error: err.reason });
524
530
  // Replay the call after refreshing the token
525
531
  return this._replayWithNewToken(err, path, method, body, headers, parse);
526
532
  }
@@ -530,7 +536,7 @@ class ApiRequester {
530
536
  : exceptionClass.fromResponse(err, response.status);
531
537
 
532
538
  if (this.shouldLogErrors) {
533
- logger$a.error('API error', error);
539
+ logger$c.error('API error', error);
534
540
  }
535
541
 
536
542
  throw error;
@@ -540,7 +546,7 @@ class ApiRequester {
540
546
  return newParse(response, isJson);
541
547
  }).catch(error => {
542
548
  if (this.shouldLogErrors) {
543
- logger$a.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
549
+ logger$c.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
544
550
  }
545
551
 
546
552
  throw error;
@@ -568,13 +574,13 @@ class ApiRequester {
568
574
  ) {
569
575
  const isTokenNotFound = this._isTokenNotFound(err);
570
576
  let newPath = path;
571
- logger$a.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
577
+ logger$c.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
572
578
 
573
579
  this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
574
580
 
575
581
  return this.refreshTokenPromise.then(() => {
576
582
  this.refreshTokenPromise = null;
577
- logger$a.info('token refreshed', { isTokenNotFound });
583
+ logger$c.info('token refreshed', { isTokenNotFound });
578
584
  if (isTokenNotFound) {
579
585
  const pathParts = path.split('/');
580
586
  pathParts.pop();
@@ -2516,6 +2522,65 @@ class ExternalApp {
2516
2522
  }
2517
2523
  }
2518
2524
 
2525
+ //
2526
+
2527
+
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+ class Meeting {
2538
+
2539
+
2540
+
2541
+
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+ static parse(plain ) {
2549
+ return new Meeting({
2550
+ guestSipAuthorization: plain.guest_sip_authorization,
2551
+ hostname: plain.hostname,
2552
+ name: plain.name,
2553
+ ownerUuids: plain.owner_uuids,
2554
+ port: plain.port,
2555
+ uuid: plain.uuid,
2556
+ number: plain.number,
2557
+ });
2558
+ }
2559
+
2560
+ static newFrom(meeting ) {
2561
+ return newFrom(meeting, Meeting);
2562
+ }
2563
+
2564
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2565
+ this.guestSipAuthorization = guestSipAuthorization;
2566
+ this.hostname = hostname;
2567
+ this.name = name;
2568
+ this.ownerUuids = ownerUuids;
2569
+ this.port = port;
2570
+ this.uuid = uuid;
2571
+ this.number = number;
2572
+
2573
+ // Useful to compare instead of instanceof with minified code
2574
+ this.type = 'Meeting';
2575
+ }
2576
+
2577
+ getGuestSipCredentials() {
2578
+ // eslint-disable-next-line no-undef
2579
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2580
+ return { username, secret };
2581
+ }
2582
+ }
2583
+
2519
2584
  /* */
2520
2585
 
2521
2586
  var confdMethods = (client , baseUrl ) => ({
@@ -2580,6 +2645,18 @@ var confdMethods = (client , baseUrl ) => ({
2580
2645
  return null;
2581
2646
  }
2582
2647
  },
2648
+
2649
+ createMyMeeting: (name ) =>
2650
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2651
+
2652
+ deleteMyMeeting: (meetingUuid ) =>
2653
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2654
+
2655
+ getMeeting: (meetingUuid ) =>
2656
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2657
+
2658
+ guestGetMeeting: (meetingUuid ) =>
2659
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2583
2660
  });
2584
2661
 
2585
2662
  //
@@ -3337,7 +3414,7 @@ class CallSession {
3337
3414
  return newFrom(callSession, CallSession);
3338
3415
  }
3339
3416
 
3340
- static parseCall(session , call ) {
3417
+ static parseCall(call ) {
3341
3418
  return new CallSession({
3342
3419
  callId: call.id,
3343
3420
  sipCallId: call.sipCallId,
@@ -3522,7 +3599,11 @@ class CallLog {
3522
3599
  answered: plain.answered,
3523
3600
  callDirection: plain.call_direction,
3524
3601
  destination: {
3525
- extension: plain.requested_extension || plain.destination_extension,
3602
+ // @TEMP: Temporarily assuming empty numbers are meetings
3603
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3604
+ extension: plain.requested_extension
3605
+ || plain.destination_extension
3606
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3526
3607
  name: plain.requested_name || plain.destination_name || '',
3527
3608
  },
3528
3609
  source: {
@@ -3538,27 +3619,11 @@ class CallLog {
3538
3619
  }
3539
3620
 
3540
3621
  static parseNew(plain , session ) {
3541
- return new CallLog({
3542
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3543
- answered: plain.answered,
3544
- callDirection: plain.call_direction,
3545
- destination: {
3546
- extension: plain.requested_extension || plain.destination_extension,
3547
- name: plain.requested_name || plain.destination_name || '',
3548
- },
3549
- source: {
3550
- extension: plain.source_extension,
3551
- name: plain.source_name,
3552
- },
3553
- id: plain.id,
3554
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3555
- start: moment__default['default'](plain.start).toDate(),
3556
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3557
- recordings: Recording.parseMany(plain.recordings),
3558
- // @TODO: FIXME add verification declined vs missed call
3559
- newMissedCall: session
3560
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3561
- });
3622
+ const callLog = CallLog.parse(plain);
3623
+ // @TODO: FIXME add verification declined vs missed call
3624
+ callLog.newMissedCall = session
3625
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3626
+ return callLog;
3562
3627
  }
3563
3628
 
3564
3629
  static newFrom(profile ) {
@@ -3718,29 +3783,432 @@ class IndirectTransfer {
3718
3783
  });
3719
3784
  }
3720
3785
 
3721
- destinationIs(callSession ) {
3722
- return callSession.isId(this.destinationId);
3786
+ destinationIs(callSession ) {
3787
+ return callSession.isId(this.destinationId);
3788
+ }
3789
+
3790
+ sourceIs(callSession ) {
3791
+ return callSession.isId(this.sourceId);
3792
+ }
3793
+
3794
+ updateFrom(indirectTransfer ) {
3795
+ updateFrom(this, indirectTransfer);
3796
+ }
3797
+
3798
+ static newFrom(indirectTransfer ) {
3799
+ return newFrom(indirectTransfer, IndirectTransfer);
3800
+ }
3801
+ }
3802
+
3803
+ //
3804
+
3805
+ class CallApi {
3806
+ static async fetchCallLogs(offset , limit ) {
3807
+ return getApiClient().callLogd.listCallLogs(offset, limit);
3808
+ }
3809
+
3810
+ static async fetchDistinctCallLogs(offset , limit , distinct = 'peer_exten') {
3811
+ return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
3812
+ }
3813
+
3814
+ static async fetchActiveCalls() {
3815
+ return getApiClient().calld.listCalls();
3816
+ }
3817
+
3818
+ static async fetchCallLogsFromDate(from , number ) {
3819
+ return getApiClient().callLogd.listCallLogsFromDate(from, number);
3820
+ }
3821
+
3822
+ static async search(query , limit ) {
3823
+ return getApiClient().callLogd.search(query, limit);
3824
+ }
3825
+
3826
+ static async searchBy(field , value , limit ) {
3827
+ return getApiClient().callLogd.searchBy(field, value, limit);
3828
+ }
3829
+
3830
+ static async fetchSIP(session , line ) {
3831
+ const lineToUse = line || session.primaryLine();
3832
+ return getApiClient().confd.getUserLineSip(session.uuid, lineToUse ? lineToUse.id : null);
3833
+ }
3834
+
3835
+ static async cancelCall(callSession ) {
3836
+ return getApiClient().calld.cancelCall(callSession.callId);
3837
+ }
3838
+
3839
+ static async makeCall(callFromLine , extension , isMobile = false,
3840
+ callbackAllLines = false) {
3841
+ const lineId = callFromLine ? callFromLine.id : null;
3842
+
3843
+ const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
3844
+ return Call.parse(response);
3845
+ }
3846
+
3847
+ static async relocateCall(callId , line , contactIdentifier ) {
3848
+ return getApiClient().calld.relocateCall(callId, 'line', line, contactIdentifier);
3849
+ }
3850
+
3851
+ static async hold(callId ) {
3852
+ return getApiClient().calld.hold(callId);
3853
+ }
3854
+
3855
+ static async resume(callId ) {
3856
+ return getApiClient().calld.resume(callId);
3857
+ }
3858
+
3859
+ static async mute(callId ) {
3860
+ return getApiClient().calld.mute(callId);
3861
+ }
3862
+
3863
+ static async sendDTMF(callId , digits ) {
3864
+ return getApiClient().calld.sendDTMF(callId, digits);
3865
+ }
3866
+
3867
+ static async unmute(callId ) {
3868
+ return getApiClient().calld.unmute(callId);
3869
+ }
3870
+
3871
+ static async transferCall(callId , number , flow ) {
3872
+ return getApiClient().calld.transferCall(callId, number, flow);
3873
+ }
3874
+
3875
+ static async cancelCallTransfer(transferId ) {
3876
+ return getApiClient().calld.cancelCallTransfer(transferId);
3877
+ }
3878
+
3879
+ static async confirmCallTransfer(transferId ) {
3880
+ return getApiClient().calld.confirmCallTransfer(transferId);
3881
+ }
3882
+ }
3883
+
3884
+ //
3885
+
3886
+ const TRANSFER_FLOW_ATTENDED = 'attended';
3887
+ const TRANSFER_FLOW_BLIND = 'blind';
3888
+
3889
+ // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
3890
+
3891
+ const logger$b = IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
3892
+
3893
+ class CTIPhone extends Emitter {
3894
+
3895
+
3896
+
3897
+
3898
+
3899
+
3900
+
3901
+
3902
+ constructor(session , isMobile = false, callbackAllLines = false) {
3903
+ super();
3904
+ logger$b.info('CTI Phone created');
3905
+ this.session = session;
3906
+ this.isMobile = isMobile;
3907
+ this.callbackAllLines = callbackAllLines;
3908
+ }
3909
+
3910
+ getOptions() {
3911
+ // @FIXME: temporarily disabling this option
3912
+ // const hold = this.session.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD);
3913
+
3914
+ return {
3915
+ accept: false,
3916
+ decline: true,
3917
+ mute: true,
3918
+ hold: false,
3919
+ transfer: true,
3920
+ sendKey: true,
3921
+ addParticipant: false,
3922
+ record: true,
3923
+ merge: false,
3924
+ };
3925
+ }
3926
+
3927
+ hasAnActiveCall() {
3928
+ return !!this.currentCall;
3929
+ }
3930
+
3931
+ callCount() {
3932
+ return this.currentCall ? 1 : 0;
3933
+ }
3934
+
3935
+ isWebRTC() {
3936
+ return false;
3937
+ }
3938
+
3939
+ getUserAgent() {
3940
+ return 'cti-phone';
3941
+ }
3942
+
3943
+ startHeartbeat() {
3944
+ }
3945
+
3946
+ setOnHeartbeatTimeout() {
3947
+ }
3948
+
3949
+ setOnHeartbeatCallback() {
3950
+ }
3951
+
3952
+ stopHeartbeat() {
3953
+ }
3954
+
3955
+ bindClientEvents() {
3956
+ }
3957
+
3958
+ onConnect() {
3959
+ }
3960
+
3961
+ onDisconnect() {
3962
+ }
3963
+
3964
+ async makeCall(number , line ) {
3965
+ logger$b.info('make CTI call', { number });
3966
+
3967
+ if (!number) {
3968
+ return null;
3969
+ }
3970
+ try {
3971
+ this.currentCall = await CallApi.makeCall(line, number, this.isMobile, this.callbackAllLines);
3972
+ } catch (_) {
3973
+ // We have to deal with error like `User has no mobile phone number` error in the UI.
3974
+ }
3975
+ if (!this.currentCall) {
3976
+ return null;
3977
+ }
3978
+ const callSession = CallSession.parseCall(this.currentCall);
3979
+ this.eventEmitter.emit('onCallOutgoing', callSession);
3980
+
3981
+ return callSession;
3982
+ }
3983
+
3984
+ accept(callSession ) {
3985
+ if (!callSession) {
3986
+ return Promise.resolve(null);
3987
+ }
3988
+ logger$b.info('accept CTI call', { callId: callSession.getId(), number: callSession.number });
3989
+
3990
+ if (!this.currentCall) {
3991
+ this.currentCall = callSession.call;
3992
+ }
3993
+
3994
+ return Promise.resolve(callSession.getId());
3995
+ }
3996
+
3997
+ endCurrentCall(callSession ) {
3998
+ if (!callSession) {
3999
+ return;
4000
+ }
4001
+ logger$b.info('end current CTI call', { callId: callSession.getId(), number: callSession.number });
4002
+
4003
+ this.currentCall = undefined;
4004
+ this.eventEmitter.emit('onCallEnded', callSession);
4005
+ }
4006
+
4007
+ async hangup(callSession ) {
4008
+ if (!callSession) {
4009
+ return Promise.resolve(false);
4010
+ }
4011
+ logger$b.info('hangup CTI call', { callId: callSession.getId(), number: callSession.number });
4012
+
4013
+ try {
4014
+ await CallApi.cancelCall(callSession);
4015
+ if (this.currentCall && callSession.callId === this.currentCall.id) {
4016
+ this.endCurrentCall(callSession);
4017
+ }
4018
+
4019
+ this.eventEmitter.emit('onCallEnded', callSession);
4020
+ return true;
4021
+ } catch (e) {
4022
+ logger$b.error('hangup CTI call, error', e);
4023
+
4024
+ this.eventEmitter.emit('onCallFailed', callSession);
4025
+ return false;
4026
+ }
4027
+ }
4028
+
4029
+ ignore() {}
4030
+
4031
+ async reject(callSession ) {
4032
+ if (!callSession) {
4033
+ return;
4034
+ }
4035
+ logger$b.info('reject CTI call', { callId: callSession.getId(), number: callSession.number });
4036
+
4037
+ await CallApi.cancelCall(callSession);
4038
+ this.eventEmitter.emit('onCallEnded', callSession);
4039
+ }
4040
+
4041
+ async transfer(callSession , number ) {
4042
+ if (!callSession) {
4043
+ return;
4044
+ }
4045
+ logger$b.info('transfer CTI call', { callId: callSession.getId(), number: callSession.number, to: number });
4046
+
4047
+ await CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_BLIND);
4048
+ }
4049
+
4050
+ indirectTransfer() {}
4051
+
4052
+ async initiateCTIIndirectTransfer(callSession , number ) {
4053
+ if (!callSession) {
4054
+ return;
4055
+ }
4056
+ logger$b.info('indirect CTI transfer', { callId: callSession.getId(), number: callSession.number, to: number });
4057
+
4058
+ return CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_ATTENDED);
4059
+ }
4060
+
4061
+ async cancelCTIIndirectTransfer(transferId ) {
4062
+ logger$b.info('cancel CTI transfer', { transferId });
4063
+
4064
+ return CallApi.cancelCallTransfer(transferId);
4065
+ }
4066
+
4067
+ async confirmCTIIndirectTransfer(transferId ) {
4068
+ logger$b.info('confirm CTI transfer', { transferId });
4069
+
4070
+ return CallApi.confirmCallTransfer(transferId);
4071
+ }
4072
+
4073
+ sendKey(callSession , digits ) {
4074
+ if (!callSession) {
4075
+ return;
4076
+ }
4077
+ logger$b.info('send CTI key', { callId: callSession.getId(), number: callSession.number, digits });
4078
+
4079
+ return CallApi.sendDTMF(callSession.callId, digits);
4080
+ }
4081
+
4082
+ onConnectionMade() {
4083
+ logger$b.info('on CTI connection made');
4084
+
4085
+ this.eventEmitter.emit('onCallAccepted');
4086
+ }
4087
+
4088
+ async close() {
4089
+ logger$b.info('CTI close');
4090
+
4091
+ return Promise.resolve();
4092
+ }
4093
+
4094
+ async hold(callSession ) {
4095
+ if (!callSession) {
4096
+ return;
4097
+ }
4098
+ logger$b.info('CTI hold', { callId: callSession.getId(), number: callSession.number });
4099
+
4100
+ return CallApi.hold(callSession.callId);
4101
+ }
4102
+
4103
+ async resume(callSession ) {
4104
+ if (!callSession) {
4105
+ return;
4106
+ }
4107
+ logger$b.info('CTI resume', { callId: callSession.getId(), number: callSession.number });
4108
+
4109
+ return CallApi.resume(callSession.callId);
4110
+ }
4111
+
4112
+ async mute(callSession ) {
4113
+ if (!callSession) {
4114
+ return;
4115
+ }
4116
+ logger$b.info('CTI mute', { callId: callSession.getId(), number: callSession.number });
4117
+
4118
+ return CallApi.mute(callSession.callId);
4119
+ }
4120
+
4121
+ async unmute(callSession ) {
4122
+ if (!callSession) {
4123
+ return;
4124
+ }
4125
+ logger$b.info('CTI unmute', { callId: callSession.getId(), number: callSession.number });
4126
+
4127
+ return CallApi.unmute(callSession.callId);
4128
+ }
4129
+
4130
+ putOnSpeaker() {}
4131
+
4132
+ putOffSpeaker() {}
4133
+
4134
+ turnCameraOff() {}
4135
+
4136
+ turnCameraOn() {}
4137
+
4138
+ changeAudioInputDevice() {}
4139
+
4140
+ changeVideoInputDevice() {}
4141
+
4142
+ changeAudioDevice() {}
4143
+
4144
+ changeRingDevice() {}
4145
+
4146
+ changeAudioVolume() {}
4147
+
4148
+ changeRingVolume() {}
4149
+
4150
+ hasVideo() {
4151
+ return false;
4152
+ }
4153
+
4154
+ getLocalStreamForCall() {
4155
+ return null;
4156
+ }
4157
+
4158
+ getRemoteStreamForCall() {
4159
+ return null;
4160
+ }
4161
+
4162
+ getLocalVideoStream() {
4163
+ return null;
4164
+ }
4165
+
4166
+ setActiveSipSession() {}
4167
+
4168
+ isRegistered() {
4169
+ return true;
4170
+ }
4171
+
4172
+ hasIncomingCallSession() {
4173
+ return true;
4174
+ }
4175
+
4176
+ hasActiveRemoteVideoStream() {
4177
+ return false;
4178
+ }
4179
+
4180
+ getCurrentCallSession() {
4181
+ return this.currentCall ? CallSession.parseCall(this.currentCall) : null;
3723
4182
  }
3724
4183
 
3725
- sourceIs(callSession ) {
3726
- return callSession.isId(this.sourceId);
4184
+ enableRinging() {}
4185
+
4186
+ sendMessage() {}
4187
+
4188
+ disableRinging() {}
4189
+
4190
+ getLocalStream() {
4191
+ return null;
3727
4192
  }
3728
4193
 
3729
- updateFrom(indirectTransfer ) {
3730
- updateFrom(this, indirectTransfer);
4194
+ getRemoteStream() {
4195
+ return null;
3731
4196
  }
3732
4197
 
3733
- static newFrom(indirectTransfer ) {
3734
- return newFrom(indirectTransfer, IndirectTransfer);
4198
+ getRemoteVideoStream() {
4199
+ return null;
3735
4200
  }
3736
- }
3737
4201
 
3738
- //
3739
- const TRANSFER_FLOW_BLIND = 'blind';
4202
+ getRemoteAudioStream() {
4203
+ return null;
4204
+ }
3740
4205
 
3741
- // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
4206
+ hasLocalVideo() {
4207
+ return false;
4208
+ }
3742
4209
 
3743
- IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
4210
+ useLocalVideoElement() {}
4211
+ }
3744
4212
 
3745
4213
  /* */
3746
4214
 
@@ -4300,6 +4768,9 @@ var calldMethods = (client , baseUrl ) => ({
4300
4768
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4301
4769
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4302
4770
 
4771
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4772
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4773
+
4303
4774
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4304
4775
 
4305
4776
  mute: (callId ) =>
@@ -4653,7 +5124,7 @@ const AGENTD_VERSION = '1.0';
4653
5124
  const WEBHOOKD_VERSION = '1.0';
4654
5125
  const AMID_VERSION = '1.0';
4655
5126
 
4656
- const logger$9 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
5127
+ const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
4657
5128
 
4658
5129
  class ApiClient {
4659
5130
 
@@ -4705,12 +5176,12 @@ class ApiClient {
4705
5176
  }
4706
5177
 
4707
5178
  async forceRefreshToken() {
4708
- logger$9.info('forcing refresh token, calling callback');
5179
+ logger$a.info('forcing refresh token, calling callback');
4709
5180
  return this.refreshTokenCallback();
4710
5181
  }
4711
5182
 
4712
5183
  async refreshTokenCallback() {
4713
- logger$9.info('refresh token callback called', {
5184
+ logger$a.info('refresh token callback called', {
4714
5185
  refreshToken: this.refreshToken,
4715
5186
  refreshBackend: this.refreshBackend,
4716
5187
  refreshExpiration: this.refreshExpiration,
@@ -4728,7 +5199,7 @@ class ApiClient {
4728
5199
  this.isMobile,
4729
5200
  );
4730
5201
 
4731
- logger$9.info('token refreshed', { token: session.token });
5202
+ logger$a.info('token refreshed', { token: session.token });
4732
5203
 
4733
5204
  if (this.onRefreshToken) {
4734
5205
  this.onRefreshToken(session.token, session);
@@ -4869,7 +5340,7 @@ var getApiClient = (forServer ) => {
4869
5340
  class InvalidSubscription extends Error {}
4870
5341
  class InvalidAuthorization extends Error {}
4871
5342
 
4872
- const logger$8 = IssueReporter$1.loggerFor('simple-auth');
5343
+ const logger$9 = IssueReporter$1.loggerFor('simple-auth');
4873
5344
 
4874
5345
  class Auth {
4875
5346
 
@@ -4904,7 +5375,7 @@ class Auth {
4904
5375
  setApiClientId(this.clientId);
4905
5376
  setRefreshExpiration(this.expiration);
4906
5377
  setOnRefreshToken((token , session ) => {
4907
- logger$8.info('on refresh token done', { token });
5378
+ logger$9.info('on refresh token done', { token });
4908
5379
  setApiToken(token);
4909
5380
  Wazo.Websocket.updateToken(token);
4910
5381
 
@@ -5463,7 +5934,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5463
5934
  .then(() => {
5464
5935
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5465
5936
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5466
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5937
+ if (this.peerConnection.addTransceiver) {
5938
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5939
+ }
5467
5940
  }
5468
5941
  })
5469
5942
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5490,12 +5963,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5490
5963
  };
5491
5964
  })
5492
5965
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5493
- .then((sessionDescription) => {
5494
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5495
- this.localMediaStreamConstraints = options.constraints;
5496
-
5497
- return sessionDescription;
5498
- })
5499
5966
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5500
5967
  .catch((error) => {
5501
5968
  wazoLogger.error('error when creating media', error);
@@ -5690,6 +6157,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5690
6157
 
5691
6158
  // set the transceiver direction to the answer direction
5692
6159
  this._peerConnection.getTransceivers().forEach((transceiver) => {
6160
+ if (transceiver.stopped) {
6161
+ return;
6162
+ }
5693
6163
  if (transceiver.direction /* guarding, but should always be true */) {
5694
6164
  const { receiver } = transceiver;
5695
6165
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5734,10 +6204,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5734
6204
  if (kind !== 'audio' && kind !== 'video') {
5735
6205
  throw new Error(`Unknown new track kind ${kind}.`);
5736
6206
  }
5737
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
6207
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
6208
+ otherSender.track && otherSender.track.kind === kind);
5738
6209
 
5739
6210
  // Do not reuse sender video tracks in SFU
5740
6211
  if (sender && (!sfu || newTrack.kind === 'audio')) {
6212
+ if (sender.track) {
6213
+ // eslint-disable-next-line no-param-reassign
6214
+ newTrack.enabled = sender.track.enabled;
6215
+ }
5741
6216
  trackUpdates.push(
5742
6217
  new Promise((resolve) => {
5743
6218
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5771,7 +6246,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5771
6246
  // Review: could make streamless tracks a configurable option?
5772
6247
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5773
6248
  try {
5774
- pc.addTrack(newTrack, localStream);
6249
+ if (pc.addTrack) {
6250
+ pc.addTrack(newTrack, localStream);
6251
+ } else {
6252
+ pc.addStream(localStream);
6253
+ }
5775
6254
  } catch (error) {
5776
6255
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5777
6256
  throw error;
@@ -5907,7 +6386,7 @@ const DEFAULT_ICE_TIMEOUT = 3000;
5907
6386
  const SEND_STATS_DELAY = 5000;
5908
6387
 
5909
6388
  const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
5910
- const logger$7 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
6389
+ const logger$8 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
5911
6390
  const statsLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-stats') : console;
5912
6391
 
5913
6392
  // events
@@ -5953,6 +6432,7 @@ const MAX_REGISTER_TRIES = 10;
5953
6432
 
5954
6433
 
5955
6434
 
6435
+
5956
6436
 
5957
6437
 
5958
6438
 
@@ -5979,6 +6459,7 @@ class WebRTCClient extends Emitter {
5979
6459
 
5980
6460
 
5981
6461
 
6462
+
5982
6463
 
5983
6464
  // sugar
5984
6465
 
@@ -6017,6 +6498,8 @@ class WebRTCClient extends Emitter {
6017
6498
  super();
6018
6499
  this.uaConfigOverrides = uaConfigOverrides;
6019
6500
  this.config = config;
6501
+ this.skipRegister = config.skipRegister;
6502
+
6020
6503
  this._buildConfig(config, session).then((newConfig ) => {
6021
6504
  this.config = newConfig;
6022
6505
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -6072,13 +6555,13 @@ class WebRTCClient extends Emitter {
6072
6555
 
6073
6556
  createUserAgent(configOverrides ) {
6074
6557
  const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
6075
- logger$7.info('sdk webrtc, creating UA', { webRTCConfiguration });
6558
+ logger$8.info('sdk webrtc, creating UA', { webRTCConfiguration });
6076
6559
 
6077
6560
  webRTCConfiguration.delegate = {
6078
6561
  onConnect: this.onConnect.bind(this),
6079
6562
  onDisconnect: this.onDisconnect.bind(this),
6080
6563
  onInvite: (invitation ) => {
6081
- logger$7.info('sdk webrtc on invite', {
6564
+ logger$8.info('sdk webrtc on invite', {
6082
6565
  method: 'delegate.onInvite',
6083
6566
  id: invitation.id,
6084
6567
  remoteURI: invitation.remoteURI,
@@ -6121,7 +6604,7 @@ class WebRTCClient extends Emitter {
6121
6604
  }
6122
6605
 
6123
6606
  onConnect() {
6124
- logger$7.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6607
+ logger$8.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6125
6608
  this.eventEmitter.emit(CONNECTED);
6126
6609
  if (!this.isRegistered() && this.registerer && this.registerer.waiting) {
6127
6610
  this.registerer.waitingToggle(false);
@@ -6130,7 +6613,7 @@ class WebRTCClient extends Emitter {
6130
6613
  }
6131
6614
 
6132
6615
  async onDisconnect(error ) {
6133
- logger$7.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6616
+ logger$8.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6134
6617
  this.connectionPromise = null;
6135
6618
  // The UA will attempt to reconnect automatically when an error occurred
6136
6619
  this.eventEmitter.emit(DISCONNECTED, error);
@@ -6144,40 +6627,48 @@ class WebRTCClient extends Emitter {
6144
6627
  }
6145
6628
 
6146
6629
  register(tries = 0) {
6147
- logger$7.info('sdk webrtc registering...', {
6630
+ const logInfo = {
6148
6631
  userAgent: !!this.userAgent,
6149
6632
  registered: this.isRegistered(),
6150
6633
  connectionPromise: !!this.connectionPromise,
6151
6634
  registerer: !!this.registerer,
6152
6635
  waiting: this.registerer && this.registerer.waiting,
6153
6636
  tries,
6154
- });
6637
+ skipRegister: this.skipRegister,
6638
+ };
6639
+
6640
+ if (this.skipRegister) {
6641
+ logger$8.info('sdk webrtc skip register...', logInfo);
6642
+ return Promise.resolve();
6643
+ }
6644
+
6645
+ logger$8.info('sdk webrtc registering...', logInfo);
6155
6646
 
6156
6647
  if (!this.userAgent) {
6157
- logger$7.info('sdk webrtc recreating User Agent');
6648
+ logger$8.info('sdk webrtc recreating User Agent');
6158
6649
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6159
6650
  }
6160
6651
  if (!this.userAgent || this.isRegistered()) {
6161
- logger$7.info('sdk webrtc registering aborted, already registered or no UA can be created');
6652
+ logger$8.info('sdk webrtc registering aborted, already registered or no UA can be created');
6162
6653
  return Promise.resolve();
6163
6654
  }
6164
6655
 
6165
6656
  if (this.connectionPromise || (this.registerer && this.registerer.waiting)) {
6166
- logger$7.info('sdk webrtc registering aborted due to a registration in progress.');
6657
+ logger$8.info('sdk webrtc registering aborted due to a registration in progress.');
6167
6658
  return Promise.resolve();
6168
6659
  }
6169
6660
 
6170
6661
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6171
6662
 
6172
6663
  const onRegisterFailed = () => {
6173
- logger$7.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6664
+ logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6174
6665
  this.connectionPromise = null;
6175
6666
  if (this.registerer && this.registerer.waiting) {
6176
6667
  this.registerer.waitingToggle(false);
6177
6668
  }
6178
6669
 
6179
6670
  if (tries <= MAX_REGISTER_TRIES) {
6180
- logger$7.info('sdk webrtc registering, retrying...', { tries });
6671
+ logger$8.info('sdk webrtc registering, retrying...', { tries });
6181
6672
  setTimeout(() => this.register(tries + 1), 300);
6182
6673
  }
6183
6674
  };
@@ -6186,18 +6677,18 @@ class WebRTCClient extends Emitter {
6186
6677
  // Avoid race condition with the close method called just before register and setting userAgent to null
6187
6678
  // during the resolution of the primise.
6188
6679
  if (!this.userAgent) {
6189
- logger$7.info('sdk webrtc recreating User Agent after connection');
6680
+ logger$8.info('sdk webrtc recreating User Agent after connection');
6190
6681
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6191
6682
  }
6192
6683
 
6193
- logger$7.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6684
+ logger$8.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6194
6685
  this.registerer = new registerer.Registerer(this.userAgent, registerOptions);
6195
6686
  this.connectionPromise = null;
6196
6687
  this._monkeyPatchRegisterer(this.registerer);
6197
6688
 
6198
6689
  // Bind registerer events
6199
6690
  this.registerer.stateChange.addListener(newState => {
6200
- logger$7.info('sdk webrtc registering, state changed', { newState });
6691
+ logger$8.info('sdk webrtc registering, state changed', { newState });
6201
6692
 
6202
6693
  if (newState === registererState.RegistererState.Registered && this.registerer
6203
6694
  && this.registerer.state === registererState.RegistererState.Registered) {
@@ -6210,7 +6701,7 @@ class WebRTCClient extends Emitter {
6210
6701
  const options = {
6211
6702
  requestDelegate: {
6212
6703
  onReject: response => {
6213
- logger$7.error('sdk webrtc registering, rejected', { response });
6704
+ logger$8.error('sdk webrtc registering, rejected', { response });
6214
6705
 
6215
6706
  onRegisterFailed();
6216
6707
  },
@@ -6218,13 +6709,13 @@ class WebRTCClient extends Emitter {
6218
6709
  };
6219
6710
 
6220
6711
  return this.registerer.register(options).catch((e) => {
6221
- logger$7.error('sdk webrtc registering, error', e);
6712
+ logger$8.error('sdk webrtc registering, error', e);
6222
6713
 
6223
6714
  this.eventEmitter.emit(REGISTRATION_FAILED);
6224
6715
  return e;
6225
6716
  });
6226
6717
  }).catch(error => {
6227
- logger$7.error('sdk webrtc registering, transport error', error);
6718
+ logger$8.error('sdk webrtc registering, transport error', error);
6228
6719
  onRegisterFailed();
6229
6720
  });
6230
6721
  }
@@ -6253,21 +6744,21 @@ class WebRTCClient extends Emitter {
6253
6744
  }
6254
6745
 
6255
6746
  unregister() {
6256
- logger$7.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6747
+ logger$8.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6257
6748
  if (!this.registerer) {
6258
6749
  return Promise.resolve();
6259
6750
  }
6260
6751
 
6261
6752
  try {
6262
6753
  return this.registerer.unregister().then(() => {
6263
- logger$7.info('sdk webrtc unregistered');
6754
+ logger$8.info('sdk webrtc unregistered');
6264
6755
  this._cleanupRegister();
6265
6756
  }).catch(e => {
6266
- logger$7.error('sdk webrtc unregistering, promise error', e);
6757
+ logger$8.error('sdk webrtc unregistering, promise error', e);
6267
6758
  this._cleanupRegister();
6268
6759
  });
6269
6760
  } catch (e) {
6270
- logger$7.error('sdk webrtc unregistering, error', e);
6761
+ logger$8.error('sdk webrtc unregistering, error', e);
6271
6762
  // Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
6272
6763
  // error when the registerer is in a bad state
6273
6764
  this._cleanupRegister();
@@ -6275,7 +6766,7 @@ class WebRTCClient extends Emitter {
6275
6766
  }
6276
6767
 
6277
6768
  stop() {
6278
- logger$7.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6769
+ logger$8.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6279
6770
  if (!this.userAgent) {
6280
6771
  return Promise.resolve();
6281
6772
  }
@@ -6283,12 +6774,12 @@ class WebRTCClient extends Emitter {
6283
6774
  return this.userAgent.stop().then(() => {
6284
6775
  return this._cleanupRegister();
6285
6776
  }).catch(e => {
6286
- logger$7.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6777
+ logger$8.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6287
6778
  });
6288
6779
  }
6289
6780
 
6290
6781
  call(number , enableVideo , audioOnly = false, conference = false) {
6291
- logger$7.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6782
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6292
6783
  const inviterOptions = {
6293
6784
  sessionDescriptionHandlerOptionsReInvite: {
6294
6785
  conference,
@@ -6317,7 +6808,7 @@ class WebRTCClient extends Emitter {
6317
6808
  this._onAccepted(session, response.session, true);
6318
6809
  },
6319
6810
  onReject: (response ) => {
6320
- logger$7.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6811
+ logger$8.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6321
6812
  this._stopSendingStats(session);
6322
6813
 
6323
6814
  this.eventEmitter.emit(REJECTED, session, response);
@@ -6339,11 +6830,11 @@ class WebRTCClient extends Emitter {
6339
6830
  }
6340
6831
 
6341
6832
  answer(session , enableVideo ) {
6342
- logger$7.info('sdk webrtc answer call', { id: session.id, enableVideo });
6833
+ logger$8.info('sdk webrtc answer call', { id: session.id, enableVideo });
6343
6834
 
6344
6835
  if (!session || !session.accept) {
6345
6836
  const error = 'No session to answer, or not an invitation';
6346
- logger$7.warn(error);
6837
+ logger$8.warn(error);
6347
6838
  return Promise.reject(new Error(error));
6348
6839
  }
6349
6840
  const options = {
@@ -6353,15 +6844,15 @@ class WebRTCClient extends Emitter {
6353
6844
  return session.accept(options).then(() => {
6354
6845
  if (session.isCanceled) {
6355
6846
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
6356
- logger$7.error(message, { id: session.id });
6847
+ logger$8.error(message, { id: session.id });
6357
6848
  this.onCallEnded(session);
6358
6849
 
6359
6850
  throw new CanceledCallError(message);
6360
6851
  }
6361
- logger$7.info('sdk webrtc answer, accepted.');
6852
+ logger$8.info('sdk webrtc answer, accepted.');
6362
6853
  this._onAccepted(session);
6363
6854
  }).catch(e => {
6364
- logger$7.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6855
+ logger$8.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6365
6856
 
6366
6857
  throw e;
6367
6858
  });
@@ -6369,7 +6860,7 @@ class WebRTCClient extends Emitter {
6369
6860
 
6370
6861
  hangup(session ) {
6371
6862
  const { state, id } = session;
6372
- logger$7.info('sdk webrtc hangup call', { id, state });
6863
+ logger$8.info('sdk webrtc hangup call', { id, state });
6373
6864
 
6374
6865
  try {
6375
6866
  this._stopSendingStats(session);
@@ -6398,24 +6889,24 @@ class WebRTCClient extends Emitter {
6398
6889
 
6399
6890
  return bye();
6400
6891
  } catch (error) {
6401
- logger$7.warn('sdk webrtc hangup, error', error);
6892
+ logger$8.warn('sdk webrtc hangup, error', error);
6402
6893
  }
6403
6894
 
6404
6895
  return null;
6405
6896
  }
6406
6897
 
6407
6898
  reject(session ) {
6408
- logger$7.info('sdk webrtc reject call', { id: session.id });
6899
+ logger$8.info('sdk webrtc reject call', { id: session.id });
6409
6900
 
6410
6901
  try {
6411
6902
  return session.reject ? session.reject() : session.cancel();
6412
6903
  } catch (e) {
6413
- logger$7.warn('Error when rejecting call', e.message, e.stack);
6904
+ logger$8.warn('Error when rejecting call', e.message, e.stack);
6414
6905
  }
6415
6906
  }
6416
6907
 
6417
6908
  async close() {
6418
- logger$7.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6909
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6419
6910
  this._cleanupMedia();
6420
6911
  this.connectionPromise = null;
6421
6912
 
@@ -6446,7 +6937,7 @@ class WebRTCClient extends Emitter {
6446
6937
  // eg: "INVITE not rejectable in state Completed"
6447
6938
  }
6448
6939
  this.userAgent = null;
6449
- logger$7.info('sdk webrtc client closed');
6940
+ logger$8.info('sdk webrtc client closed');
6450
6941
  }
6451
6942
 
6452
6943
  getNumber(session ) {
@@ -6459,13 +6950,13 @@ class WebRTCClient extends Emitter {
6459
6950
  }
6460
6951
 
6461
6952
  mute(session ) {
6462
- logger$7.info('sdk webrtc mute', { id: session.id });
6953
+ logger$8.info('sdk webrtc mute', { id: session.id });
6463
6954
 
6464
6955
  this._toggleAudio(session, true);
6465
6956
  }
6466
6957
 
6467
6958
  unmute(session ) {
6468
- logger$7.info('sdk webrtc unmute', { id: session.id });
6959
+ logger$8.info('sdk webrtc unmute', { id: session.id });
6469
6960
 
6470
6961
  this._toggleAudio(session, false);
6471
6962
  }
@@ -6482,12 +6973,18 @@ class WebRTCClient extends Emitter {
6482
6973
  }
6483
6974
 
6484
6975
  if (pc.getSenders) {
6976
+ if (!pc.getSenders().length) {
6977
+ return false;
6978
+ }
6485
6979
  pc.getSenders().forEach(sender => {
6486
6980
  if (sender && sender.track && sender.track.kind === 'audio') {
6487
6981
  muted = muted && !sender.track.enabled;
6488
6982
  }
6489
6983
  });
6490
6984
  } else {
6985
+ if (!pc.getLocalStreams().length) {
6986
+ return false;
6987
+ }
6491
6988
  pc.getLocalStreams().forEach(stream => {
6492
6989
  stream.getAudioTracks().forEach(track => {
6493
6990
  muted = muted && !track.enabled;
@@ -6499,20 +6996,20 @@ class WebRTCClient extends Emitter {
6499
6996
  }
6500
6997
 
6501
6998
  toggleCameraOn(session ) {
6502
- logger$7.info('sdk webrtc toggle camera on', { id: session.id });
6999
+ logger$8.info('sdk webrtc toggle camera on', { id: session.id });
6503
7000
 
6504
7001
  this._toggleVideo(session, false);
6505
7002
  }
6506
7003
 
6507
7004
  toggleCameraOff(session ) {
6508
- logger$7.info('sdk webrtc toggle camera off', { id: session.id });
7005
+ logger$8.info('sdk webrtc toggle camera off', { id: session.id });
6509
7006
 
6510
7007
  this._toggleVideo(session, true);
6511
7008
  }
6512
7009
 
6513
7010
  hold(session , isConference = false) {
6514
7011
  const sessionId = this.getSipSessionId(session);
6515
- logger$7.info('sdk webrtc hold', {
7012
+ logger$8.info('sdk webrtc hold', {
6516
7013
  sessionId,
6517
7014
  keys: Object.keys(this.heldSessions),
6518
7015
  pendingReinvite: !!session.pendingReinvite,
@@ -6544,6 +7041,9 @@ class WebRTCClient extends Emitter {
6544
7041
  if (!this._isWeb()) {
6545
7042
  options.sessionDescriptionHandlerModifiers = [modifiers.holdModifier];
6546
7043
  }
7044
+ options.sessionDescriptionHandlerOptions = {
7045
+ constraints: options.constraints,
7046
+ };
6547
7047
 
6548
7048
  // Send re-INVITE
6549
7049
  return session.invite(options);
@@ -6552,7 +7052,7 @@ class WebRTCClient extends Emitter {
6552
7052
  unhold(session , isConference = false) {
6553
7053
  const sessionId = this.getSipSessionId(session);
6554
7054
 
6555
- logger$7.info('sdk webrtc unhold', {
7055
+ logger$8.info('sdk webrtc unhold', {
6556
7056
  sessionId,
6557
7057
  keys: Object.keys(this.heldSessions),
6558
7058
  pendingReinvite: !!session.pendingReinvite,
@@ -6583,6 +7083,9 @@ class WebRTCClient extends Emitter {
6583
7083
  // (eg: holdModifier)
6584
7084
  options.sessionDescriptionHandlerModifiers = [];
6585
7085
  }
7086
+ options.sessionDescriptionHandlerOptions = {
7087
+ constraints: options.constraints,
7088
+ };
6586
7089
 
6587
7090
  // Send re-INVITE
6588
7091
  return session.invite(options);
@@ -6640,7 +7143,7 @@ class WebRTCClient extends Emitter {
6640
7143
  return;
6641
7144
  }
6642
7145
 
6643
- logger$7.info('send WebRTC message', { sipId: sipSession.id, contentType });
7146
+ logger$8.info('send WebRTC message', { sipId: sipSession.id, contentType });
6644
7147
 
6645
7148
  try {
6646
7149
  sipSession.message({
@@ -6765,7 +7268,8 @@ class WebRTCClient extends Emitter {
6765
7268
  }
6766
7269
  const sdh = session.sessionDescriptionHandler;
6767
7270
  const pc = sdh.peerConnection;
6768
- const localStream = this.getLocalStream(this.getSipSessionId(session));
7271
+ const sessionId = this.getSipSessionId(session);
7272
+ const localStream = this.getLocalStream(sessionId);
6769
7273
 
6770
7274
  // Release old video stream
6771
7275
  if (localStream) {
@@ -6791,11 +7295,8 @@ class WebRTCClient extends Emitter {
6791
7295
 
6792
7296
  // let's update the local stream
6793
7297
  this.eventEmitter.emit('onVideoInputChange', stream);
6794
- try {
6795
- await sdh.setLocalMediaStream(stream);
6796
- } catch (_) {
6797
- // Nothing to do
6798
- }
7298
+ this.setLocalMediaStream(sessionId, stream);
7299
+
6799
7300
  return stream;
6800
7301
  });
6801
7302
  }
@@ -7007,7 +7508,7 @@ class WebRTCClient extends Emitter {
7007
7508
  }
7008
7509
 
7009
7510
  startHeartbeat() {
7010
- logger$7.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7511
+ logger$8.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7011
7512
  if (!this.userAgent) {
7012
7513
  this.heartbeat.stop();
7013
7514
  return;
@@ -7020,7 +7521,7 @@ class WebRTCClient extends Emitter {
7020
7521
  }
7021
7522
 
7022
7523
  stopHeartbeat() {
7023
- logger$7.info('sdk webrtc stop heartbeat');
7524
+ logger$8.info('sdk webrtc stop heartbeat');
7024
7525
  this.heartbeat.stop();
7025
7526
  }
7026
7527
 
@@ -7040,7 +7541,7 @@ class WebRTCClient extends Emitter {
7040
7541
  }
7041
7542
 
7042
7543
  attemptReconnection() {
7043
- logger$7.info('attempt reconnection', { userAgent: !!this.userAgent });
7544
+ logger$8.info('attempt reconnection', { userAgent: !!this.userAgent });
7044
7545
  if (!this.userAgent) {
7045
7546
  return;
7046
7547
  }
@@ -7097,9 +7598,11 @@ class WebRTCClient extends Emitter {
7097
7598
  remoteStream.removeTrack(track);
7098
7599
  });
7099
7600
 
7100
- pc.getReceivers().forEach(receiver => {
7101
- remoteStream.addTrack(receiver.track);
7102
- });
7601
+ if (pc.getReceivers) {
7602
+ pc.getReceivers().forEach(receiver => {
7603
+ remoteStream.addTrack(receiver.track);
7604
+ });
7605
+ }
7103
7606
  }
7104
7607
 
7105
7608
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -7134,6 +7637,25 @@ class WebRTCClient extends Emitter {
7134
7637
  return sessionId in this.conferences;
7135
7638
  }
7136
7639
 
7640
+ createAudioElementFor(sessionId ) {
7641
+ const audio = document.createElement('audio');
7642
+ audio.setAttribute('id', `audio-${sessionId}`);
7643
+
7644
+ if (audio.setSinkId && this.audioOutputDeviceId) {
7645
+ audio.setSinkId(this.audioOutputDeviceId);
7646
+ }
7647
+
7648
+ if (document.body) {
7649
+ document.body.appendChild(audio);
7650
+ }
7651
+ this.audioElements[sessionId] = audio;
7652
+
7653
+ audio.volume = this.audioOutputVolume;
7654
+ audio.autoplay = true;
7655
+
7656
+ return audio;
7657
+ }
7658
+
7137
7659
  _onTransportError() {
7138
7660
  this.eventEmitter.emit(TRANSPORT_ERROR);
7139
7661
  this.attemptReconnection();
@@ -7143,7 +7665,7 @@ class WebRTCClient extends Emitter {
7143
7665
  const body = message && typeof message === 'object' ? message.data : message;
7144
7666
  if (body && body.indexOf('200 OK') !== -1) {
7145
7667
  if (this.hasHeartbeat()) {
7146
- logger$7.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7668
+ logger$8.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7147
7669
 
7148
7670
  this.heartbeat.onHeartbeat();
7149
7671
  if (this.heartbeatCb) {
@@ -7154,7 +7676,7 @@ class WebRTCClient extends Emitter {
7154
7676
  }
7155
7677
 
7156
7678
  async _onHeartbeatTimeout() {
7157
- logger$7.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7679
+ logger$8.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7158
7680
 
7159
7681
  if (this.heartbeatTimeoutCb) {
7160
7682
  this.heartbeatTimeoutCb();
@@ -7166,7 +7688,7 @@ class WebRTCClient extends Emitter {
7166
7688
  try {
7167
7689
  await this.userAgent.transport.disconnect();
7168
7690
  } catch (e) {
7169
- logger$7.error('Transport disconnection after heartbeat timeout, error', e);
7691
+ logger$8.error('Transport disconnection after heartbeat timeout, error', e);
7170
7692
  }
7171
7693
  }
7172
7694
 
@@ -7199,31 +7721,31 @@ class WebRTCClient extends Emitter {
7199
7721
  }
7200
7722
 
7201
7723
  _connectIfNeeded() {
7202
- logger$7.info('connect if needed, checking', { connected: this.isConnected() });
7724
+ logger$8.info('connect if needed, checking', { connected: this.isConnected() });
7203
7725
  if (!this.userAgent) {
7204
- logger$7.info('need to recreate User Agent');
7726
+ logger$8.info('need to recreate User Agent');
7205
7727
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
7206
7728
  }
7207
7729
 
7208
7730
  if (this.isConnected()) {
7209
- logger$7.info('webrtc sdk, already connected');
7731
+ logger$8.info('webrtc sdk, already connected');
7210
7732
  return Promise.resolve();
7211
7733
  }
7212
7734
 
7213
7735
  if (this.isConnecting()) {
7214
- logger$7.info('webrtc sdk, already connecting...');
7736
+ logger$8.info('webrtc sdk, already connecting...');
7215
7737
 
7216
7738
  this.connectionPromise = this.userAgent.transport.connectPromise;
7217
7739
  return this.connectionPromise;
7218
7740
  }
7219
7741
 
7220
7742
  if (this.connectionPromise) {
7221
- logger$7.info('webrtc sdk, connection promise connecting...');
7743
+ logger$8.info('webrtc sdk, connection promise connecting...');
7222
7744
  // $FlowFixMe
7223
7745
  return this.connectionPromise;
7224
7746
  }
7225
7747
 
7226
- logger$7.info('WebRTC UA needs to connect');
7748
+ logger$8.info('WebRTC UA needs to connect');
7227
7749
 
7228
7750
  // Force UA to reconnect
7229
7751
  if (this.userAgent && this.userAgent.state !== userAgentState.UserAgentState.Stopped) {
@@ -7348,7 +7870,7 @@ class WebRTCClient extends Emitter {
7348
7870
 
7349
7871
  sdh.peerConnectionDelegate = {
7350
7872
  onicecandidateerror: (error ) => {
7351
- logger$7.error('on icecandidate error', {
7873
+ logger$8.error('on icecandidate error', {
7352
7874
  address: error.address,
7353
7875
  port: error.port,
7354
7876
  errorCode: error.errorCode,
@@ -7363,7 +7885,7 @@ class WebRTCClient extends Emitter {
7363
7885
  let hadRemoteVideo = false;
7364
7886
 
7365
7887
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7366
- // Becase when `onInvite` is called we already got the video track
7888
+ // Because when `onInvite` is called we already got the video track
7367
7889
  session.onInviteRequest = (request) => {
7368
7890
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7369
7891
 
@@ -7377,7 +7899,7 @@ class WebRTCClient extends Emitter {
7377
7899
  updatedNumber = session.assertedIdentity.uri.normal.user;
7378
7900
  updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
7379
7901
  }
7380
- logger$7.info('re-invite received', { updatedCalleeName, updatedNumber });
7902
+ logger$8.info('re-invite received', { updatedCalleeName, updatedNumber });
7381
7903
 
7382
7904
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
7383
7905
 
@@ -7398,7 +7920,7 @@ class WebRTCClient extends Emitter {
7398
7920
  }
7399
7921
 
7400
7922
  _onAccepted(session , sessionDialog , withEvent = true) {
7401
- logger$7.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7923
+ logger$8.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7402
7924
 
7403
7925
  this.storeSipSession(session);
7404
7926
 
@@ -7438,20 +7960,10 @@ class WebRTCClient extends Emitter {
7438
7960
  const isConference = this.isConference(sessionId);
7439
7961
 
7440
7962
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7441
- const audio = document.createElement('audio');
7442
- audio.setAttribute('id', `audio-${sessionId}`);
7443
-
7444
- if (audio.setSinkId && this.audioOutputDeviceId) {
7445
- audio.setSinkId(this.audioOutputDeviceId);
7446
- }
7447
-
7448
- if (document.body) {
7449
- document.body.appendChild(audio);
7450
- }
7451
- this.audioElements[sessionId] = audio;
7963
+ this.createAudioElementFor(sessionId);
7452
7964
  }
7453
7965
 
7454
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7966
+ const audioElement = this.audioElements[sessionId];
7455
7967
  const stream = newStream || this.getRemoteStream(sessionId);
7456
7968
 
7457
7969
  if (!this._isWeb() || !stream) {
@@ -7598,10 +8110,10 @@ class WebRTCClient extends Emitter {
7598
8110
 
7599
8111
  _stopSendingStats(session ) {
7600
8112
  const sessionId = this.getSipSessionId(session);
7601
- logger$7.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
8113
+ logger$8.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7602
8114
 
7603
8115
  if (sessionId in this.statsIntervals) {
7604
- logger$7.trace('Stop sending stats for call', { sessionId });
8116
+ logger$8.trace('Stop sending stats for call', { sessionId });
7605
8117
  this.statsIntervals[sessionId]();
7606
8118
  delete this.statsIntervals[sessionId];
7607
8119
  }
@@ -7617,7 +8129,7 @@ class WebRTCClient extends Emitter {
7617
8129
  try {
7618
8130
  await this.userAgent.transport.disconnect();
7619
8131
  } catch (e) {
7620
- logger$7.error('WebRTC transport disconnect, error', e);
8132
+ logger$8.error('WebRTC transport disconnect, error', e);
7621
8133
  }
7622
8134
  }
7623
8135
  }
@@ -7704,7 +8216,7 @@ const events = [
7704
8216
  ON_SIGNAL,
7705
8217
  ];
7706
8218
 
7707
- const logger$6 = IssueReporter$1.loggerFor('webrtc-phone');
8219
+ const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
7708
8220
 
7709
8221
  class WebRTCPhone extends Emitter {
7710
8222
 
@@ -7775,7 +8287,7 @@ class WebRTCPhone extends Emitter {
7775
8287
  }).catch(error => {
7776
8288
  // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
7777
8289
  console.error('register error', error, error.message, error.stack);
7778
- logger$6.error('WebRTC register error', { message: error.message, stack: error.stack });
8290
+ logger$7.error('WebRTC register error', { message: error.message, stack: error.stack });
7779
8291
  });
7780
8292
  }
7781
8293
 
@@ -7790,7 +8302,7 @@ class WebRTCPhone extends Emitter {
7790
8302
  if (!this.client) {
7791
8303
  return;
7792
8304
  }
7793
- logger$6.info('WebRTC phone stop');
8305
+ logger$7.info('WebRTC phone stop');
7794
8306
  this.client.stop();
7795
8307
  }
7796
8308
 
@@ -7805,14 +8317,14 @@ class WebRTCPhone extends Emitter {
7805
8317
  async sendReinvite(callSession , constraints = null, conference = false,
7806
8318
  audioOnly = false) {
7807
8319
  const sipSession = this.findSipSession(callSession);
7808
- logger$6.info('WebRTC phone - send reinvite', {
8320
+ logger$7.info('WebRTC phone - send reinvite', {
7809
8321
  sessionId: sipSession ? sipSession.id : null,
7810
8322
  constraints,
7811
8323
  audioOnly,
7812
8324
  });
7813
8325
 
7814
8326
  if (!sipSession) {
7815
- return null;
8327
+ return false;
7816
8328
  }
7817
8329
 
7818
8330
  // $FlowFixMe
@@ -7822,19 +8334,17 @@ class WebRTCPhone extends Emitter {
7822
8334
  // Downgrade
7823
8335
  if (constraints && !isUpgrade) {
7824
8336
  // No reinvite needed
7825
- return this._downgradeToAudio(callSession);
8337
+ this._downgradeToAudio(callSession);
8338
+ return false;
7826
8339
  }
7827
8340
 
7828
8341
  if (isUpgrade) {
7829
8342
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
7830
8343
  if (!shouldReinvite) {
7831
- return;
8344
+ return false;
7832
8345
  }
7833
8346
  }
7834
8347
 
7835
- // Force reinvite in SDH
7836
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
7837
-
7838
8348
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
7839
8349
  }
7840
8350
 
@@ -7843,7 +8353,7 @@ class WebRTCPhone extends Emitter {
7843
8353
  }
7844
8354
 
7845
8355
  startHeartbeat() {
7846
- logger$6.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
8356
+ logger$7.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
7847
8357
  if (!this.client || this.client.hasHeartbeat()) {
7848
8358
  return;
7849
8359
  }
@@ -7852,7 +8362,7 @@ class WebRTCPhone extends Emitter {
7852
8362
  }
7853
8363
 
7854
8364
  stopHeartbeat() {
7855
- logger$6.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
8365
+ logger$7.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
7856
8366
  if (!this.client) {
7857
8367
  return;
7858
8368
  }
@@ -7869,7 +8379,7 @@ class WebRTCPhone extends Emitter {
7869
8379
  }
7870
8380
 
7871
8381
  reconnect() {
7872
- logger$6.info('WebRTC phone - reconnect', { client: !!this.client });
8382
+ logger$7.info('WebRTC phone - reconnect', { client: !!this.client });
7873
8383
  if (!this.client) {
7874
8384
  return;
7875
8385
  }
@@ -7907,7 +8417,7 @@ class WebRTCPhone extends Emitter {
7907
8417
  _downgradeToAudio(callSession ) {
7908
8418
  const sipSession = this.findSipSession(callSession);
7909
8419
  if (!sipSession) {
7910
- return;
8420
+ return false;
7911
8421
  }
7912
8422
 
7913
8423
  // Release local video stream when downgrading to audio
@@ -8020,7 +8530,7 @@ class WebRTCPhone extends Emitter {
8020
8530
  // Monkey patch to know when canceled with the CANCEL message
8021
8531
  const onCancel = sipSession._onCancel.bind(sipSession);
8022
8532
  sipSession._onCancel = (message ) => {
8023
- logger$6.trace('on sip session canceled', { callId: message.callId });
8533
+ logger$7.trace('on sip session canceled', { callId: message.callId });
8024
8534
 
8025
8535
  onCancel(message);
8026
8536
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
@@ -8045,13 +8555,13 @@ class WebRTCPhone extends Emitter {
8045
8555
  this.audioOutputVolume,
8046
8556
  );
8047
8557
  case sessionState.SessionState.Terminating:
8048
- logger$6.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8558
+ logger$7.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8049
8559
 
8050
8560
  this.eventEmitter.emit(ON_CALL_ENDING, this._createCallSession(sipSession));
8051
8561
 
8052
8562
  break;
8053
8563
  case sessionState.SessionState.Terminated:
8054
- logger$6.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8564
+ logger$7.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8055
8565
 
8056
8566
  this._onCallTerminated(sipSession);
8057
8567
 
@@ -8087,7 +8597,7 @@ class WebRTCPhone extends Emitter {
8087
8597
  }
8088
8598
 
8089
8599
  async startScreenSharing(constraints , callSession ) {
8090
- logger$6.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8600
+ logger$7.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8091
8601
 
8092
8602
  const screenShareStream = await this._getStreamFromConstraints(constraints);
8093
8603
  if (!screenShareStream) {
@@ -8109,6 +8619,10 @@ class WebRTCPhone extends Emitter {
8109
8619
  localStream.removeTrack(videoTrack);
8110
8620
  }
8111
8621
 
8622
+ if (localStream) {
8623
+ localStream.addTrack(screenTrack);
8624
+ }
8625
+
8112
8626
  if (sender) {
8113
8627
  sender.replaceTrack(screenTrack);
8114
8628
  }
@@ -8123,7 +8637,8 @@ class WebRTCPhone extends Emitter {
8123
8637
  return;
8124
8638
  }
8125
8639
 
8126
- logger$6.info('WebRTC phone - stop screen sharing');
8640
+ logger$7.info('WebRTC phone - stop screen sharing');
8641
+ let reinvited = false;
8127
8642
 
8128
8643
  try {
8129
8644
  if (this.currentScreenShare.stream) {
@@ -8138,7 +8653,8 @@ class WebRTCPhone extends Emitter {
8138
8653
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
8139
8654
  // We have to downgrade to audio.
8140
8655
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
8141
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
8656
+ const constraints = { audio: false, video: screenshareStopped };
8657
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
8142
8658
  }
8143
8659
  } catch (e) {
8144
8660
  console.warn(e);
@@ -8152,6 +8668,8 @@ class WebRTCPhone extends Emitter {
8152
8668
  );
8153
8669
 
8154
8670
  this.currentScreenShare = null;
8671
+
8672
+ return reinvited;
8155
8673
  }
8156
8674
 
8157
8675
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -8189,7 +8707,7 @@ class WebRTCPhone extends Emitter {
8189
8707
  }
8190
8708
 
8191
8709
  _onCallAccepted(sipSession , cameraEnabled ) {
8192
- logger$6.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8710
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8193
8711
 
8194
8712
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
8195
8713
  this.currentSipSession = sipSession;
@@ -8207,11 +8725,15 @@ class WebRTCPhone extends Emitter {
8207
8725
  }
8208
8726
 
8209
8727
  changeAudioDevice(id ) {
8210
- logger$6.info('WebRTC phone - change audio device', { deviceId: id });
8728
+ logger$7.info('WebRTC phone - change audio device', { deviceId: id });
8211
8729
  this.audioOutputDeviceId = id;
8212
8730
  this.client.changeAudioOutputDevice(id);
8213
8731
  }
8214
8732
 
8733
+ createAudioElementFor(sessionId ) {
8734
+ return this.client.createAudioElementFor(sessionId);
8735
+ }
8736
+
8215
8737
  changeRingDevice(id ) {
8216
8738
  this.audioRingDeviceId = id;
8217
8739
  }
@@ -8228,25 +8750,25 @@ class WebRTCPhone extends Emitter {
8228
8750
  }
8229
8751
 
8230
8752
  changeAudioInputDevice(id ) {
8231
- logger$6.info('WebRTC phone - changeAudio input device', { deviceId: id });
8753
+ logger$7.info('WebRTC phone - changeAudio input device', { deviceId: id });
8232
8754
 
8233
8755
  return this.client.changeAudioInputDevice(id, this.currentSipSession);
8234
8756
  }
8235
8757
 
8236
8758
  changeVideoInputDevice(id ) {
8237
- logger$6.info('WebRTC phone - change video input device', { deviceId: id });
8759
+ logger$7.info('WebRTC phone - change video input device', { deviceId: id });
8238
8760
 
8239
8761
  return this.client.changeVideoInputDevice(id, this.currentSipSession);
8240
8762
  }
8241
8763
 
8242
8764
  changeSessionVideoInputDevice(id ) {
8243
- logger$6.info('WebRTC phone - change session video input device', { deviceId: id });
8765
+ logger$7.info('WebRTC phone - change session video input device', { deviceId: id });
8244
8766
 
8245
8767
  return this.client.changeSessionVideoInputDevice(id, this.currentSipSession);
8246
8768
  }
8247
8769
 
8248
8770
  _onCallTerminated(sipSession ) {
8249
- logger$6.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8771
+ logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8250
8772
 
8251
8773
  const callSession = this._createCallSession(sipSession);
8252
8774
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
@@ -8280,7 +8802,7 @@ class WebRTCPhone extends Emitter {
8280
8802
  const hasIncomingCallSession = this.hasIncomingCallSession();
8281
8803
 
8282
8804
  // Re-trigger incoming call event for remaining incoming calls
8283
- logger$6.info('WebRTC phone - check to re-trigger incoming call', {
8805
+ logger$7.info('WebRTC phone - check to re-trigger incoming call', {
8284
8806
  sipId: sipSession.id,
8285
8807
  shouldRetrigger,
8286
8808
  hasIncomingCallSession,
@@ -8369,37 +8891,37 @@ class WebRTCPhone extends Emitter {
8369
8891
 
8370
8892
  // Deprecated
8371
8893
  getLocalStreamForCall(callSession ) {
8372
- logger$6.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8894
+ logger$7.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8373
8895
 
8374
8896
  return this.getLocalStream(callSession);
8375
8897
  }
8376
8898
 
8377
8899
  // Deprecated
8378
8900
  getRemoteStreamForCall(callSession ) {
8379
- logger$6.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8901
+ logger$7.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8380
8902
 
8381
8903
  return this.getRemoteVideoStream(callSession);
8382
8904
  }
8383
8905
 
8384
8906
  getRemoteStreamsForCall(callSession ) {
8385
- logger$6.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8907
+ logger$7.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8386
8908
 
8387
8909
  return this.getRemoteStream(callSession);
8388
8910
  }
8389
8911
 
8390
8912
  accept(callSession , cameraEnabled ) {
8391
- logger$6.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8913
+ logger$7.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8392
8914
  if (this.currentSipSession) {
8393
8915
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
8394
8916
  }
8395
8917
 
8396
8918
  if (!callSession) {
8397
- logger$6.warn('no CallSession to accept.');
8919
+ logger$7.warn('no CallSession to accept.');
8398
8920
  return Promise.resolve(null);
8399
8921
  }
8400
8922
 
8401
8923
  if (callSession.getId() in this.acceptedSessions) {
8402
- logger$6.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8924
+ logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8403
8925
  return Promise.resolve(callSession.sipCallId);
8404
8926
  }
8405
8927
 
@@ -8411,24 +8933,24 @@ class WebRTCPhone extends Emitter {
8411
8933
  const sipSession = this.client.getSipSession(callSession.getId());
8412
8934
  if (sipSession) {
8413
8935
  if (sipSession.state === sessionState.SessionState.Terminated || sipSession.state === sessionState.SessionState.Terminating) {
8414
- logger$6.warn('Trying to answer a terminated sipSession.');
8936
+ logger$7.warn('Trying to answer a terminated sipSession.');
8415
8937
 
8416
8938
  return Promise.resolve(null);
8417
8939
  }
8418
8940
 
8419
- logger$6.info('accept call, session found', { sipId: sipSession.id });
8941
+ logger$7.info('accept call, session found', { sipId: sipSession.id });
8420
8942
 
8421
8943
  // $FlowFixMe
8422
8944
  return this.client.answer(sipSession, this.allowVideo ? cameraEnabled : false).then(() => {
8423
8945
  return callSession.sipCallId;
8424
8946
  }).catch(e => {
8425
- logger$6.error(e);
8947
+ logger$7.error(e);
8426
8948
  this.endCurrentCall(callSession);
8427
8949
  throw e;
8428
8950
  });
8429
8951
  }
8430
8952
 
8431
- logger$6.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8953
+ logger$7.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8432
8954
 
8433
8955
  return Promise.resolve(null);
8434
8956
  }
@@ -8438,7 +8960,7 @@ class WebRTCPhone extends Emitter {
8438
8960
  }
8439
8961
 
8440
8962
  async reject(callSession ) {
8441
- logger$6.info('reject WebRTC called', { id: callSession.getId() });
8963
+ logger$7.info('reject WebRTC called', { id: callSession.getId() });
8442
8964
 
8443
8965
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call rejected locally');
8444
8966
  if (!callSession || callSession.getId() in this.rejectedSessions) {
@@ -8450,14 +8972,14 @@ class WebRTCPhone extends Emitter {
8450
8972
 
8451
8973
  const sipSession = this.findSipSession(callSession);
8452
8974
  if (sipSession) {
8453
- logger$6.info('WebRTC rejecting', { sipId: sipSession.id });
8975
+ logger$7.info('WebRTC rejecting', { sipId: sipSession.id });
8454
8976
 
8455
8977
  this.client.hangup(sipSession);
8456
8978
  }
8457
8979
  }
8458
8980
 
8459
8981
  async ignore(callSession ) {
8460
- logger$6.info('WebRTC ignore', { id: callSession.getId() });
8982
+ logger$7.info('WebRTC ignore', { id: callSession.getId() });
8461
8983
 
8462
8984
  // kill the ring
8463
8985
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'ignoring call');
@@ -8466,7 +8988,7 @@ class WebRTCPhone extends Emitter {
8466
8988
  }
8467
8989
 
8468
8990
  hold(callSession , withEvent = true, isConference = false) {
8469
- logger$6.info('WebRTC hold', { id: callSession.getId() });
8991
+ logger$7.info('WebRTC hold', { id: callSession.getId() });
8470
8992
 
8471
8993
  const sipSession = this.findSipSession(callSession);
8472
8994
 
@@ -8477,7 +8999,7 @@ class WebRTCPhone extends Emitter {
8477
8999
 
8478
9000
  // @Deprecated
8479
9001
  unhold(callSession , withEvent = true, isConference = false) {
8480
- logger$6.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
9002
+ logger$7.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8481
9003
 
8482
9004
  console.warn('Please note that `phone.unhold()` is being deprecated; `phone.resume()` is the preferred method');
8483
9005
 
@@ -8492,7 +9014,7 @@ class WebRTCPhone extends Emitter {
8492
9014
  const sipSession = this.findSipSession(callSession);
8493
9015
 
8494
9016
  if (sipSession) {
8495
- logger$6.info('WebRTC atxfer', { sipId: sipSession.id });
9017
+ logger$7.info('WebRTC atxfer', { sipId: sipSession.id });
8496
9018
 
8497
9019
  return this.client.atxfer(sipSession);
8498
9020
  }
@@ -8507,7 +9029,7 @@ class WebRTCPhone extends Emitter {
8507
9029
  if (!sipSession) {
8508
9030
  return new Promise((resolve, reject) => reject(new Error('No session to hold')));
8509
9031
  }
8510
- logger$6.info('WebRTC hold sip session', { sipId: sipSession.id });
9032
+ logger$7.info('WebRTC hold sip session', { sipId: sipSession.id });
8511
9033
 
8512
9034
  const promise = this.client.hold(sipSession, isConference);
8513
9035
  if (withEvent) {
@@ -8526,7 +9048,7 @@ class WebRTCPhone extends Emitter {
8526
9048
  if (!sipSession) {
8527
9049
  return new Promise((resolve, reject) => reject(new Error('No session to unhold')));
8528
9050
  }
8529
- logger$6.info('WebRTC unhold', { sipId: sipSession.id });
9051
+ logger$7.info('WebRTC unhold', { sipId: sipSession.id });
8530
9052
 
8531
9053
  const promise = this.client.unhold(sipSession, isConference);
8532
9054
  if (withEvent) {
@@ -8537,18 +9059,18 @@ class WebRTCPhone extends Emitter {
8537
9059
  }
8538
9060
 
8539
9061
  resume(callSession , isConference = false) {
8540
- logger$6.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
9062
+ logger$7.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8541
9063
 
8542
9064
  const sipSession = this.findSipSession(callSession);
8543
9065
  if (!sipSession) {
8544
9066
  return new Promise((resolve, reject) => reject(new Error('No session to resume')));
8545
9067
  }
8546
9068
 
8547
- logger$6.info('WebRTC resuming', { sipId: sipSession.id });
9069
+ logger$7.info('WebRTC resuming', { sipId: sipSession.id });
8548
9070
 
8549
9071
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
8550
9072
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
8551
- logger$6.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9073
+ logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8552
9074
  this.holdSipSession(this.currentSipSession, callSession);
8553
9075
  }
8554
9076
 
@@ -8563,14 +9085,14 @@ class WebRTCPhone extends Emitter {
8563
9085
  }
8564
9086
 
8565
9087
  mute(callSession , withEvent = true) {
8566
- logger$6.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
9088
+ logger$7.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8567
9089
 
8568
9090
  const sipSession = this.findSipSession(callSession);
8569
9091
  if (!sipSession) {
8570
9092
  return;
8571
9093
  }
8572
9094
 
8573
- logger$6.info('WebRTC muting', { sipId: sipSession.id });
9095
+ logger$7.info('WebRTC muting', { sipId: sipSession.id });
8574
9096
  this.client.mute(sipSession);
8575
9097
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: true });
8576
9098
 
@@ -8584,14 +9106,14 @@ class WebRTCPhone extends Emitter {
8584
9106
  }
8585
9107
 
8586
9108
  unmute(callSession , withEvent = true) {
8587
- logger$6.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
9109
+ logger$7.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8588
9110
 
8589
9111
  const sipSession = this.findSipSession(callSession);
8590
9112
  if (!sipSession) {
8591
9113
  return;
8592
9114
  }
8593
9115
 
8594
- logger$6.info('WebRTC unmuting', { sipId: sipSession.id });
9116
+ logger$7.info('WebRTC unmuting', { sipId: sipSession.id });
8595
9117
  this.client.unmute(sipSession);
8596
9118
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: false });
8597
9119
 
@@ -8618,7 +9140,7 @@ class WebRTCPhone extends Emitter {
8618
9140
  if (!sipSession) {
8619
9141
  return;
8620
9142
  }
8621
- logger$6.info('WebRTC turn camera on', { sipId: sipSession.id });
9143
+ logger$7.info('WebRTC turn camera on', { sipId: sipSession.id });
8622
9144
 
8623
9145
  this.client.toggleCameraOn(sipSession);
8624
9146
 
@@ -8630,7 +9152,7 @@ class WebRTCPhone extends Emitter {
8630
9152
  if (!sipSession) {
8631
9153
  return;
8632
9154
  }
8633
- logger$6.info('WebRTC turn camera off', { sipId: sipSession.id });
9155
+ logger$7.info('WebRTC turn camera off', { sipId: sipSession.id });
8634
9156
 
8635
9157
  this.client.toggleCameraOff(sipSession);
8636
9158
  this.eventEmitter.emit(ON_CAMERA_DISABLED, this._createCameraDisabledCallSession(sipSession, callSession));
@@ -8642,7 +9164,7 @@ class WebRTCPhone extends Emitter {
8642
9164
  return;
8643
9165
  }
8644
9166
 
8645
- logger$6.info('WebRTC send key', { sipId: sipSession.id, tone });
9167
+ logger$7.info('WebRTC send key', { sipId: sipSession.id, tone });
8646
9168
  this.client.sendDTMF(sipSession, tone);
8647
9169
  }
8648
9170
 
@@ -8650,7 +9172,7 @@ class WebRTCPhone extends Emitter {
8650
9172
  // @TODO: line is not used here
8651
9173
  async makeCall(number , line , cameraEnabled ,
8652
9174
  audioOnly = false, conference = false) {
8653
- logger$6.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9175
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8654
9176
  if (!number) {
8655
9177
  return Promise.resolve(null);
8656
9178
  }
@@ -8660,7 +9182,7 @@ class WebRTCPhone extends Emitter {
8660
9182
  }
8661
9183
  if (this.currentSipSession) {
8662
9184
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true).catch(e => {
8663
- logger$6.warn('Unable to hold current session when making another call', e);
9185
+ logger$7.warn('Unable to hold current session when making another call', e);
8664
9186
  });
8665
9187
  }
8666
9188
 
@@ -8670,7 +9192,7 @@ class WebRTCPhone extends Emitter {
8670
9192
  this._bindEvents(sipSession);
8671
9193
  } catch (error) {
8672
9194
  console.warn(error);
8673
- logger$6.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
9195
+ logger$7.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8674
9196
  return Promise.resolve(null);
8675
9197
  }
8676
9198
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
@@ -8698,7 +9220,7 @@ class WebRTCPhone extends Emitter {
8698
9220
  return;
8699
9221
  }
8700
9222
 
8701
- logger$6.info('WebRTC transfer', { sipId: sipSession.id, target });
9223
+ logger$7.info('WebRTC transfer', { sipId: sipSession.id, target });
8702
9224
 
8703
9225
  this.client.transfer(sipSession, target);
8704
9226
  }
@@ -8707,7 +9229,7 @@ class WebRTCPhone extends Emitter {
8707
9229
  const sipSession = this.client.getSipSession(source.sipCallId);
8708
9230
  const sipSessionTarget = this.client.getSipSession(destination.sipCallId);
8709
9231
 
8710
- logger$6.info('WebRTC indirect transfer', {
9232
+ logger$7.info('WebRTC indirect transfer', {
8711
9233
  sipId: sipSession ? sipSession.id : null,
8712
9234
  target: sipSessionTarget ? sipSessionTarget.id : null,
8713
9235
  });
@@ -8735,7 +9257,7 @@ class WebRTCPhone extends Emitter {
8735
9257
  return false;
8736
9258
  }
8737
9259
 
8738
- logger$6.info('WebRTC hangup', { sipId: sipSession.id });
9260
+ logger$7.info('WebRTC hangup', { sipId: sipSession.id });
8739
9261
 
8740
9262
  const sipSessionId = this.getSipSessionId(sipSession);
8741
9263
 
@@ -8780,7 +9302,7 @@ class WebRTCPhone extends Emitter {
8780
9302
  }
8781
9303
 
8782
9304
  async close() {
8783
- logger$6.info('WebRTC close');
9305
+ logger$7.info('WebRTC close');
8784
9306
 
8785
9307
  try {
8786
9308
  await Promise.race([
@@ -8788,7 +9310,7 @@ class WebRTCPhone extends Emitter {
8788
9310
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Unregister, timed out')), 3000)),
8789
9311
  ]);
8790
9312
  } catch (e) {
8791
- logger$6.error('WebRTC close, unregister error', e);
9313
+ logger$7.error('WebRTC close, unregister error', e);
8792
9314
  }
8793
9315
 
8794
9316
  this.client.close();
@@ -8806,12 +9328,12 @@ class WebRTCPhone extends Emitter {
8806
9328
  }
8807
9329
 
8808
9330
  enableRinging() {
8809
- logger$6.info('WebRTC enable ringing');
9331
+ logger$7.info('WebRTC enable ringing');
8810
9332
  this.ringingEnabled = true;
8811
9333
  }
8812
9334
 
8813
9335
  disableRinging() {
8814
- logger$6.info('WebRTC disable ringing');
9336
+ logger$7.info('WebRTC disable ringing');
8815
9337
  this.ringingEnabled = false;
8816
9338
  }
8817
9339
 
@@ -8851,7 +9373,7 @@ class WebRTCPhone extends Emitter {
8851
9373
 
8852
9374
  // Deprecated
8853
9375
  getLocalMediaStream(callSession ) {
8854
- logger$6.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
9376
+ logger$7.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
8855
9377
  return this.getLocalStream(callSession);
8856
9378
  }
8857
9379
 
@@ -8859,6 +9381,10 @@ class WebRTCPhone extends Emitter {
8859
9381
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
8860
9382
  }
8861
9383
 
9384
+ hasALocalVideoTrack(callSession ) {
9385
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
9386
+ }
9387
+
8862
9388
  getRemoteStream(callSession ) {
8863
9389
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
8864
9390
  }
@@ -8881,7 +9407,7 @@ class WebRTCPhone extends Emitter {
8881
9407
  this.client.on(this.client.INVITE, (sipSession , wantsToDoVideo ) => {
8882
9408
  const autoAnswer = sipSession.request.getHeader('Answer-Mode') === 'Auto';
8883
9409
  const withVideo = this.allowVideo ? wantsToDoVideo : false;
8884
- logger$6.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
9410
+ logger$7.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
8885
9411
 
8886
9412
  const callSession = this._createIncomingCallSession(sipSession, withVideo, null, autoAnswer);
8887
9413
  this.incomingSessions.push(callSession.getId());
@@ -8904,7 +9430,7 @@ class WebRTCPhone extends Emitter {
8904
9430
  });
8905
9431
 
8906
9432
  this.client.on(this.client.ON_REINVITE, (...args) => {
8907
- logger$6.info('WebRTC on reinvite', {
9433
+ logger$7.info('WebRTC on reinvite', {
8908
9434
  sessionId: args[0].id,
8909
9435
  inviteId: args[1].id,
8910
9436
  updatedCalleeName: args[2],
@@ -8924,7 +9450,7 @@ class WebRTCPhone extends Emitter {
8924
9450
  });
8925
9451
 
8926
9452
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
8927
- logger$6.info('WebRTC call accepted', { sipId: sipSession.id });
9453
+ logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
8928
9454
 
8929
9455
  this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
8930
9456
 
@@ -8935,17 +9461,17 @@ class WebRTCPhone extends Emitter {
8935
9461
  this.client.on('ended', () => {});
8936
9462
 
8937
9463
  this.client.on(this.client.ON_ERROR, e => {
8938
- logger$6.error('WebRTC error', e);
9464
+ logger$7.error('WebRTC error', e);
8939
9465
  this.eventEmitter.emit(ON_CALL_ERROR, e);
8940
9466
  });
8941
9467
 
8942
9468
  this.client.on(this.client.UNREGISTERED, () => {
8943
- logger$6.info('WebRTC unregistered');
9469
+ logger$7.info('WebRTC unregistered');
8944
9470
  this.eventEmitter.emit(ON_UNREGISTERED);
8945
9471
  });
8946
9472
 
8947
9473
  this.client.on(this.client.REGISTERED, () => {
8948
- logger$6.info('WebRTC registered', {
9474
+ logger$7.info('WebRTC registered', {
8949
9475
  shouldSendReinvite: this.shouldSendReinvite,
8950
9476
  state: this.currentSipSession ? this.currentSipSession.state : null,
8951
9477
  currentSipSession: !!this.currentSipSession,
@@ -8961,19 +9487,19 @@ class WebRTCPhone extends Emitter {
8961
9487
  try {
8962
9488
  this.sendReinvite(this.currentCallSession);
8963
9489
  } catch (e) {
8964
- logger$6.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9490
+ logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
8965
9491
  }
8966
9492
  }
8967
9493
  });
8968
9494
 
8969
9495
  this.client.on(this.client.CONNECTED, () => {
8970
- logger$6.info('WebRTC client connected');
9496
+ logger$7.info('WebRTC client connected');
8971
9497
 
8972
9498
  this.stopHeartbeat();
8973
9499
  });
8974
9500
 
8975
9501
  this.client.on(this.client.DISCONNECTED, () => {
8976
- logger$6.info('WebRTC client disconnected');
9502
+ logger$7.info('WebRTC client disconnected');
8977
9503
 
8978
9504
  this.eventEmitter.emit(ON_UNREGISTERED);
8979
9505
 
@@ -9205,7 +9731,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9205
9731
 
9206
9732
  //
9207
9733
 
9208
- const logger$5 = IssueReporter$1.loggerFor('simple-phone');
9734
+ const logger$6 = IssueReporter$1.loggerFor('simple-phone');
9209
9735
  const sipLogger = IssueReporter$1.loggerFor('sip.js');
9210
9736
  const protocolLogger = IssueReporter$1.loggerFor('sip');
9211
9737
 
@@ -9312,7 +9838,7 @@ class Phone extends Emitter {
9312
9838
  async disconnect() {
9313
9839
  if (this.phone) {
9314
9840
  if (this.phone.hasAnActiveCall()) {
9315
- logger$5.info('hangup call on disconnect');
9841
+ logger$6.info('hangup call on disconnect');
9316
9842
  // $FlowFixMe
9317
9843
  await this.phone.hangup();
9318
9844
  }
@@ -9335,13 +9861,13 @@ class Phone extends Emitter {
9335
9861
  }
9336
9862
 
9337
9863
  async hangup(callSession ) {
9338
- logger$5.info('hangup via simple phone', { callId: callSession.getId() });
9864
+ logger$6.info('hangup via simple phone', { callId: callSession.getId() });
9339
9865
 
9340
9866
  return this.phone && this.phone.hangup(callSession);
9341
9867
  }
9342
9868
 
9343
9869
  async accept(callSession , cameraEnabled ) {
9344
- logger$5.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9870
+ logger$6.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9345
9871
 
9346
9872
  return this.phone && this.phone.accept(callSession, cameraEnabled);
9347
9873
  }
@@ -9361,13 +9887,18 @@ class Phone extends Emitter {
9361
9887
  return adHocConference.start();
9362
9888
  }
9363
9889
 
9364
- mute(callSession ) {
9365
- this.muteViaAPI(callSession);
9890
+ mute(callSession , withApi = true) {
9891
+ if (withApi) {
9892
+ this.muteViaAPI(callSession);
9893
+ }
9894
+
9366
9895
  return this.phone && this.phone.mute(callSession);
9367
9896
  }
9368
9897
 
9369
- unmute(callSession ) {
9370
- this.unmuteViaAPI(callSession);
9898
+ unmute(callSession , withApi = true) {
9899
+ if (withApi) {
9900
+ this.unmuteViaAPI(callSession);
9901
+ }
9371
9902
 
9372
9903
  return this.phone && this.phone.unmute(callSession);
9373
9904
  }
@@ -9375,7 +9906,7 @@ class Phone extends Emitter {
9375
9906
  muteViaAPI(callSession ) {
9376
9907
  if (callSession && callSession.callId) {
9377
9908
  Wazo.getApiClient().calld.mute(callSession.callId).catch(e => {
9378
- logger$5.error('Mute via API, error', e);
9909
+ logger$6.error('Mute via API, error', e);
9379
9910
  });
9380
9911
  }
9381
9912
  }
@@ -9383,7 +9914,7 @@ class Phone extends Emitter {
9383
9914
  unmuteViaAPI(callSession ) {
9384
9915
  if (callSession && callSession.callId) {
9385
9916
  Wazo.getApiClient().calld.unmute(callSession.callId).catch(e => {
9386
- logger$5.error('Unmute via API, error', e);
9917
+ logger$6.error('Unmute via API, error', e);
9387
9918
  });
9388
9919
  }
9389
9920
  }
@@ -9473,9 +10004,13 @@ class Phone extends Emitter {
9473
10004
  return this.phone && this.phone.hasLocalVideo(callSession);
9474
10005
  }
9475
10006
 
10007
+ hasALocalVideoTrack(callSession ) {
10008
+ return this.phone && this.phone.hasALocalVideoTrack(callSession);
10009
+ }
10010
+
9476
10011
  // @Deprecated
9477
10012
  getLocalMediaStream(callSession ) {
9478
- logger$5.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
10013
+ logger$6.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9479
10014
 
9480
10015
  return this.phone && this.phone.getLocalStream(callSession);
9481
10016
  }
@@ -9494,20 +10029,20 @@ class Phone extends Emitter {
9494
10029
 
9495
10030
  // @Deprecated
9496
10031
  getRemoteStreamForCall(callSession ) {
9497
- logger$5.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
10032
+ logger$6.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9498
10033
  return this.getRemoteStream(callSession);
9499
10034
  }
9500
10035
 
9501
10036
  // Returns remote streams directly from the peerConnection
9502
10037
  // @Deprecated
9503
10038
  getRemoteStreamsForCall(callSession ) {
9504
- logger$5.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
10039
+ logger$6.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9505
10040
  return this.getLocalStream(callSession);
9506
10041
  }
9507
10042
 
9508
10043
  // @Deprecated
9509
10044
  getRemoteVideoStreamForCall(callSession ) {
9510
- logger$5.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
10045
+ logger$6.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9511
10046
 
9512
10047
  return this.getRemoteVideoStream(callSession);
9513
10048
  }
@@ -9637,6 +10172,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
9637
10172
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
9638
10173
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
9639
10174
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
10175
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
10176
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
9640
10177
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
9641
10178
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
9642
10179
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -9678,7 +10215,7 @@ const BLACKLIST_EVENTS = [
9678
10215
  ];
9679
10216
 
9680
10217
  const HEARTBEAT_ENGINE_VERSION = '20.09';
9681
- const logger$4 = IssueReporter$1.loggerFor('wazo-ws');
10218
+ const logger$5 = IssueReporter$1.loggerFor('wazo-ws');
9682
10219
  const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
9683
10220
 
9684
10221
  class WebSocketClient extends Emitter {
@@ -9727,19 +10264,19 @@ class WebSocketClient extends Emitter {
9727
10264
  }
9728
10265
 
9729
10266
  connect() {
9730
- logger$4.info('connect method started', { host: this.host, token: this.token });
10267
+ logger$5.info('connect method started', { host: this.host, token: this.token });
9731
10268
  this.socket = new ReconnectingWebSocket__default['default'](this._getUrl.bind(this), [], this.options);
9732
10269
  if (this.options.binaryType) {
9733
10270
  this.socket.binaryType = this.options.binaryType;
9734
10271
  }
9735
10272
 
9736
10273
  this.socket.onopen = () => {
9737
- logger$4.info('on Wazo WS open', { method: 'connect', host: this.host });
10274
+ logger$5.info('on Wazo WS open', { method: 'connect', host: this.host });
9738
10275
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_OPEN);
9739
10276
  };
9740
10277
 
9741
10278
  this.socket.onerror = event => {
9742
- logger$4.error('on Wazo WS error', event.target);
10279
+ logger$5.error('on Wazo WS error', event.target);
9743
10280
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_ERROR, event);
9744
10281
  };
9745
10282
 
@@ -9769,7 +10306,7 @@ class WebSocketClient extends Emitter {
9769
10306
 
9770
10307
  this.socket.onclose = event => {
9771
10308
  // Can't be converted to JSON (circular structure)
9772
- logger$4.info('on Wazo WS close', {
10309
+ logger$5.info('on Wazo WS close', {
9773
10310
  reason: event.reason,
9774
10311
  code: event.code,
9775
10312
  readyState: event.target.readyState,
@@ -9787,12 +10324,12 @@ class WebSocketClient extends Emitter {
9787
10324
  };
9788
10325
 
9789
10326
  this.socket.onerror = event => {
9790
- logger$4.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
10327
+ logger$5.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
9791
10328
  };
9792
10329
  }
9793
10330
 
9794
10331
  close(force = false) {
9795
- logger$4.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
10332
+ logger$5.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
9796
10333
 
9797
10334
  if (!this.socket) {
9798
10335
  return;
@@ -9810,7 +10347,7 @@ class WebSocketClient extends Emitter {
9810
10347
 
9811
10348
  updateToken(token ) {
9812
10349
  this.token = token;
9813
- logger$4.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
10350
+ logger$5.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
9814
10351
 
9815
10352
  if (this.socket) {
9816
10353
  // If still connected, send the token to the WS
@@ -9828,7 +10365,7 @@ class WebSocketClient extends Emitter {
9828
10365
  }
9829
10366
 
9830
10367
  startHeartbeat() {
9831
- logger$4.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
10368
+ logger$5.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
9832
10369
 
9833
10370
  if (!this.socket) {
9834
10371
  this.heartbeat.stop();
@@ -9842,7 +10379,7 @@ class WebSocketClient extends Emitter {
9842
10379
  }
9843
10380
 
9844
10381
  stopHeartbeat() {
9845
- logger$4.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
10382
+ logger$5.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
9846
10383
 
9847
10384
  this.heartbeat.stop();
9848
10385
  }
@@ -9872,7 +10409,7 @@ class WebSocketClient extends Emitter {
9872
10409
  }
9873
10410
 
9874
10411
  reconnect(reason ) {
9875
- logger$4.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
10412
+ logger$5.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
9876
10413
  if (!this.socket) {
9877
10414
  return;
9878
10415
  }
@@ -9928,7 +10465,7 @@ class WebSocketClient extends Emitter {
9928
10465
  this.close();
9929
10466
  }
9930
10467
  const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
9931
- logger$4.log('Wazo WS url computed to reconnect', { url });
10468
+ logger$5.log('Wazo WS url computed to reconnect', { url });
9932
10469
 
9933
10470
  return url;
9934
10471
  }
@@ -9936,12 +10473,12 @@ class WebSocketClient extends Emitter {
9936
10473
  _onHeartbeat(message ) {
9937
10474
  if (message.payload === 'pong') {
9938
10475
  this.heartbeat.onHeartbeat();
9939
- logger$4.log('on heartbeat received from Wazo WS');
10476
+ logger$5.log('on heartbeat received from Wazo WS');
9940
10477
  }
9941
10478
  }
9942
10479
 
9943
10480
  async _onHeartbeatTimeout() {
9944
- logger$4.log('heartbeat timed out', { host: this.host, token: this.token });
10481
+ logger$5.log('heartbeat timed out', { host: this.host, token: this.token });
9945
10482
 
9946
10483
  this.close();
9947
10484
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_CLOSE, new Error('Websocket ping failure.'));
@@ -9983,6 +10520,8 @@ WebSocketClient.eventLists = [
9983
10520
  CHATD_USER_ROOM_CREATED,
9984
10521
  CONFERENCE_USER_PARTICIPANT_JOINED,
9985
10522
  CONFERENCE_USER_PARTICIPANT_LEFT,
10523
+ MEETING_USER_PARTICIPANT_JOINED,
10524
+ MEETING_USER_PARTICIPANT_LEFT,
9986
10525
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9987
10526
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
9988
10527
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -10053,6 +10592,8 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10053
10592
  CONFERENCE_USER_PARTICIPANT_LEFT: CONFERENCE_USER_PARTICIPANT_LEFT,
10054
10593
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED: CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
10055
10594
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED: CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
10595
+ MEETING_USER_PARTICIPANT_JOINED: MEETING_USER_PARTICIPANT_JOINED,
10596
+ MEETING_USER_PARTICIPANT_LEFT: MEETING_USER_PARTICIPANT_LEFT,
10056
10597
  SWITCHBOARD_QUEUED_CALLS_UPDATED: SWITCHBOARD_QUEUED_CALLS_UPDATED,
10057
10598
  SWITCHBOARD_QUEUED_CALL_ANSWERED: SWITCHBOARD_QUEUED_CALL_ANSWERED,
10058
10599
  SWITCHBOARD_HELD_CALLS_UPDATED: SWITCHBOARD_HELD_CALLS_UPDATED,
@@ -10094,7 +10635,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10094
10635
  const { SOCKET_EVENTS, ...OTHER_EVENTS } = WebSocketClient$1;
10095
10636
  const ALL_EVENTS = [...Object.values(SOCKET_EVENTS), ...Object.values(OTHER_EVENTS)];
10096
10637
 
10097
- const logger$3 = IssueReporter$1.loggerFor('simple-ws-client');
10638
+ const logger$4 = IssueReporter$1.loggerFor('simple-ws-client');
10098
10639
 
10099
10640
  class Websocket extends Emitter {
10100
10641
 
@@ -10118,7 +10659,7 @@ class Websocket extends Emitter {
10118
10659
  }
10119
10660
 
10120
10661
  open(host , session ) {
10121
- logger$3.info('open simple WebSocket', { host, token: session.token });
10662
+ logger$4.info('open simple WebSocket', { host, token: session.token });
10122
10663
  this.ws = new WebSocketClient(
10123
10664
  {
10124
10665
  host,
@@ -10146,7 +10687,7 @@ class Websocket extends Emitter {
10146
10687
  }
10147
10688
 
10148
10689
  updateToken(token ) {
10149
- logger$3.info('update token via simple Websocket', { token, ws: !!this.ws });
10690
+ logger$4.info('update token via simple Websocket', { token, ws: !!this.ws });
10150
10691
 
10151
10692
  if (!this.ws) {
10152
10693
  return;
@@ -10174,6 +10715,145 @@ var Websocket$1 = global.wazoWebsocketInstance;
10174
10715
 
10175
10716
  //
10176
10717
 
10718
+ const logger$3 = IssueReporter$1.loggerFor('sdk-sip-room');
10719
+
10720
+ class SipRoom extends Room {
10721
+
10722
+ static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
10723
+ logger$3.info('connecting to sip room', { extension, audioOnly, room: !!room });
10724
+
10725
+ if (!room) {
10726
+ await Wazo.Phone.connect();
10727
+
10728
+ const withCamera = constraints && !!constraints.video;
10729
+
10730
+ const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
10731
+ // eslint-disable-next-line no-param-reassign
10732
+ room = new SipRoom(callSession, extension, null, null, extra);
10733
+ }
10734
+
10735
+ if (room && room.callSession && room.callSession.call) {
10736
+ room.setCallId(room.callSession.call.id);
10737
+ }
10738
+
10739
+ logger$3.info('connected to room', {
10740
+ extension: room.extension,
10741
+ });
10742
+
10743
+ return room;
10744
+ }
10745
+
10746
+ mute() {
10747
+ logger$3.info('mute sip room');
10748
+
10749
+ Wazo.Phone.mute(this.callSession, false);
10750
+
10751
+ this.sendMuteStatus();
10752
+ }
10753
+
10754
+ unmute() {
10755
+ logger$3.info('unmute sip room');
10756
+
10757
+ Wazo.Phone.unmute(this.callSession, false);
10758
+
10759
+ this.sendUnMuteStatus();
10760
+ }
10761
+
10762
+ getLocalGuestName() {
10763
+ return Wazo.Phone.phone.client.userAgent.options.displayName;
10764
+ }
10765
+
10766
+ // Overridden to not listen to websocket messages
10767
+ _transferEvents() {
10768
+ // Phone events
10769
+ Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
10770
+ Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
10771
+ Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
10772
+ Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
10773
+
10774
+ [this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
10775
+ Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
10776
+ }
10777
+
10778
+ _onMessage(message ) {
10779
+ // eslint-disable-next-line no-underscore-dangle
10780
+ const body = super._onMessage(message);
10781
+ if (!body) {
10782
+ return;
10783
+ }
10784
+
10785
+ const getChannel = () => body.channels[0];
10786
+
10787
+ switch (body.type) {
10788
+ case 'ConfbridgeWelcome':
10789
+ body.channels.forEach(channel => {
10790
+ this._onParticipantJoined(channel);
10791
+ });
10792
+
10793
+ break;
10794
+ case 'ConfbridgeJoin': {
10795
+ const channel = getChannel();
10796
+ this._onParticipantJoined(channel);
10797
+ break;
10798
+ }
10799
+ case 'ConfbridgeLeave': {
10800
+ const channel = getChannel();
10801
+ this._onParticipantLeft({
10802
+ data: {
10803
+ call_id: channel.id,
10804
+ },
10805
+ });
10806
+ break;
10807
+ }
10808
+ }
10809
+ }
10810
+
10811
+ async _onParticipantJoined(channel ) {
10812
+ const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
10813
+ const callId = channel.id;
10814
+ const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
10815
+ const name = channel.caller ? channel.caller.name : null;
10816
+ const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
10817
+ const participant = new ParticipantClass(this, {
10818
+ caller_id_name: name,
10819
+ call_id: callId,
10820
+ }, extra);
10821
+
10822
+ const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
10823
+ if (participantIdx !== -1 && name) {
10824
+ this.participants[participantIdx].name = name;
10825
+ return;
10826
+ }
10827
+
10828
+ if (isLocal) {
10829
+ // Should be updated by the Wazo WS but we don't have it for now
10830
+ if (this.callSession) {
10831
+ this.callSession.ringing = false;
10832
+ }
10833
+
10834
+ this._onLocalParticipantJoined(participant);
10835
+
10836
+ // Give some time for the stream to be updated
10837
+ setTimeout(() => {
10838
+ this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
10839
+ }, 1000);
10840
+ }
10841
+
10842
+ this.participants.push(participant);
10843
+
10844
+ this._isParticipantJoining(participant);
10845
+
10846
+ return participant;
10847
+ }
10848
+
10849
+ _getCurrentSipCallIs() {
10850
+ return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
10851
+ }
10852
+
10853
+ }
10854
+
10855
+ //
10856
+
10177
10857
  const logger$2 = IssueReporter$1.loggerFor('room');
10178
10858
 
10179
10859
  class Participant extends Emitter {
@@ -10208,6 +10888,7 @@ class Participant extends Emitter {
10208
10888
 
10209
10889
 
10210
10890
  /**
10891
+ * @param room Room The room where the participant is
10211
10892
  * @param rawParticipant string Participant sent via the Wazo WS
10212
10893
  * @param extra Object extra status of the participant
10213
10894
  */
@@ -10435,6 +11116,11 @@ class Participant extends Emitter {
10435
11116
  // Poor man's object comparison
10436
11117
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
10437
11118
  this.extra = { ...this.extra, ...status.extra };
11119
+
11120
+ if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
11121
+ this.extra.contact = new Contact(this.extra.contact);
11122
+ }
11123
+
10438
11124
  this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
10439
11125
  }
10440
11126
  }
@@ -10506,9 +11192,7 @@ class Stream {
10506
11192
  return false;
10507
11193
  }
10508
11194
 
10509
- // With canvas track (used to fake upgrade in conference), we don't have a width
10510
- return this.htmlStream.getTracks().find(track => track.kind === 'video'
10511
- && track.readyState !== 'ended' && 'width' in track.getSettings());
11195
+ return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
10512
11196
  }
10513
11197
 
10514
11198
  get id() {
@@ -11409,6 +12093,7 @@ const Wazo = {
11409
12093
  Phone: Phone$1,
11410
12094
  Websocket: Websocket$1,
11411
12095
  Room,
12096
+ SipRoom,
11412
12097
  RemoteParticipant,
11413
12098
  LocalParticipant,
11414
12099
  Stream,
@@ -11428,6 +12113,7 @@ const Wazo = {
11428
12113
  ServerError,
11429
12114
  Call,
11430
12115
  CallLog,
12116
+ CTIPhone,
11431
12117
  Recording,
11432
12118
  ChatMessage,
11433
12119
  ChatRoom,
@@ -11443,6 +12129,8 @@ const Wazo = {
11443
12129
  CallSession,
11444
12130
  IndirectTransfer,
11445
12131
  SwitchboardCall,
12132
+ WebRTCPhone,
12133
+ Meeting,
11446
12134
  },
11447
12135
 
11448
12136
  // Api
@@ -11471,7 +12159,7 @@ if (global) {
11471
12159
  global.Wazo = Wazo;
11472
12160
  }
11473
12161
 
11474
- /* global document */
12162
+ //
11475
12163
 
11476
12164
  const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
11477
12165
  const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
@@ -11483,6 +12171,7 @@ class Room extends Emitter {
11483
12171
 
11484
12172
 
11485
12173
 
12174
+
11486
12175
 
11487
12176
 
11488
12177
 
@@ -11504,6 +12193,8 @@ class Room extends Emitter {
11504
12193
 
11505
12194
 
11506
12195
 
12196
+
12197
+
11507
12198
 
11508
12199
 
11509
12200
 
@@ -11521,6 +12212,7 @@ class Room extends Emitter {
11521
12212
  * @param extension string
11522
12213
  * @param sourceId number
11523
12214
  * @param callId string
12215
+ * @param meetingUuid string
11524
12216
  * @param extra Object
11525
12217
  */
11526
12218
  constructor(
@@ -11528,15 +12220,17 @@ class Room extends Emitter {
11528
12220
  extension ,
11529
12221
  sourceId ,
11530
12222
  callId ,
12223
+ meetingUuid ,
11531
12224
  extra = {},
11532
12225
  ) {
11533
12226
  super();
11534
- logger.info('room initialized', { callId, extension, sourceId });
12227
+ logger.info('room initialized', { callId, extension, sourceId, meetingUuid });
11535
12228
 
11536
12229
  // Represents the room callSession
11537
12230
  this.callSession = callSession;
11538
12231
  this.extension = extension;
11539
12232
  this.sourceId = sourceId;
12233
+ this.meetingUuid = meetingUuid;
11540
12234
  this.callId = callId;
11541
12235
  this.participants = [];
11542
12236
  this.connected = false;
@@ -11556,6 +12250,8 @@ class Room extends Emitter {
11556
12250
  // Sugar syntax for `room.EVENT_NAME`
11557
12251
  this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
11558
12252
  this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
12253
+ this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
12254
+ this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
11559
12255
  this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
11560
12256
  this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
11561
12257
  this.ON_CHAT = Wazo.Phone.ON_CHAT;
@@ -11590,9 +12286,10 @@ class Room extends Emitter {
11590
12286
  * @param audioOnly boolean
11591
12287
  * @param extra Object
11592
12288
  * @param room ?Room
12289
+ * @param meeting ?Meeting
11593
12290
  * @returns {Promise<Room>}
11594
12291
  */
11595
- static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
12292
+ static async connect({ extension, constraints, audioOnly = false, extra, room, meeting } ) {
11596
12293
  logger.info('connecting to room', { extension, audioOnly, room: !!room });
11597
12294
 
11598
12295
  if (!room) {
@@ -11627,21 +12324,31 @@ class Room extends Emitter {
11627
12324
  room.setCallId(room.callSession.call.id);
11628
12325
  }
11629
12326
 
11630
- // Fetch conference source
11631
- const sources = await getApiClient().dird.fetchConferenceSource('default');
11632
- // Retrieve conference sources
11633
- const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
11634
- // Retrieve conference
11635
- const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
12327
+ if (!meeting) {
12328
+ // Fetch conference source
12329
+ const sources = await getApiClient().dird.fetchConferenceSource('default');
12330
+ // Retrieve conference sources
12331
+ const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
12332
+ // Retrieve conference
12333
+ const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
11636
12334
 
11637
- logger.info('connected to room', {
11638
- sourceId: conference ? conference.sourceId : null,
11639
- name: conference ? conference.name : null,
11640
- });
12335
+ logger.info('connected to room', {
12336
+ sourceId: conference ? conference.sourceId : null,
12337
+ name: conference ? conference.name : null,
12338
+ });
11641
12339
 
11642
- if (conference) {
11643
- room.setSourceId(conference.sourceId);
11644
- room.setName(conference.name);
12340
+ if (conference) {
12341
+ room.setSourceId(conference.sourceId);
12342
+ room.setName(conference.name);
12343
+ }
12344
+ } else if (meeting) {
12345
+ logger.info('Already connected to meeting', {
12346
+ uuid: meeting.uuid,
12347
+ name: meeting.name,
12348
+ });
12349
+
12350
+ room.setMeetingUuid(meeting.uuid);
12351
+ room.setName(meeting.name);
11645
12352
  }
11646
12353
 
11647
12354
  return room;
@@ -11669,10 +12376,8 @@ class Room extends Emitter {
11669
12376
  Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
11670
12377
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11671
12378
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11672
-
11673
- if (this.roomAudioElement && document.body) {
11674
- document.body.removeChild(this.roomAudioElement);
11675
- }
12379
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
12380
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11676
12381
  }
11677
12382
 
11678
12383
  setSourceId(sourceId ) {
@@ -11681,6 +12386,12 @@ class Room extends Emitter {
11681
12386
  this.sourceId = sourceId;
11682
12387
  }
11683
12388
 
12389
+ setMeetingUuid(meetingUuid ) {
12390
+ logger.info('set meeting uuid', { meetingUuid });
12391
+
12392
+ this.meetingUuid = meetingUuid;
12393
+ }
12394
+
11684
12395
  setCallId(callId ) {
11685
12396
  logger.info('set room call id', { callId });
11686
12397
 
@@ -11722,14 +12433,22 @@ class Room extends Emitter {
11722
12433
  return screensharingStream;
11723
12434
  }
11724
12435
 
11725
- stopScreenSharing(restoreLocalStream = true) {
12436
+ async stopScreenSharing(restoreLocalStream = true) {
11726
12437
  logger.info('stop room screen sharing');
11727
12438
 
11728
- Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
12439
+ const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
11729
12440
 
11730
12441
  if (this.localParticipant) {
11731
12442
  this.localParticipant.onStopScreensharing();
11732
12443
  }
12444
+
12445
+ if (!reinvited && this.localParticipant) {
12446
+ // When we had video and we made a screenshare we don't reinvite when stopping the screensahre
12447
+ // So not REINVITE even is fired, we have to restore the video stream manually
12448
+ const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
12449
+ // $FlowFixMe
12450
+ this._associateStreamTo(localVideoStream, this.localParticipant);
12451
+ }
11733
12452
  }
11734
12453
 
11735
12454
  turnCameraOff() {
@@ -11832,6 +12551,22 @@ class Room extends Emitter {
11832
12551
  return response;
11833
12552
  }
11834
12553
 
12554
+ hasALocalVideoTrack() {
12555
+ return Wazo.Phone.hasALocalVideoTrack(this.callSession);
12556
+ }
12557
+
12558
+ getLocalStream() {
12559
+ return Wazo.Phone.getLocalStream(this.callSession);
12560
+ }
12561
+
12562
+ getRemoteStream() {
12563
+ return Wazo.Phone.getRemoteStream(this.callSession);
12564
+ }
12565
+
12566
+ getRemoteVideoStream() {
12567
+ return Wazo.Phone.getRemoteVideoStream(this.callSession);
12568
+ }
12569
+
11835
12570
  _bindEvents() {
11836
12571
  if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
11837
12572
  return;
@@ -11853,27 +12588,10 @@ class Room extends Emitter {
11853
12588
  logger.info('on room audio stream');
11854
12589
 
11855
12590
  this.audioStream = stream;
11856
- if (document.createElement) {
11857
- // $FlowFixMe
11858
- let roomAudioElement = document.getElementById('audio-room');
11859
- if (!this.roomAudioElement) {
11860
- roomAudioElement = document.createElement('audio');
11861
- // $FlowFixMe
11862
- document.body.appendChild(roomAudioElement);
11863
- }
11864
- if (!roomAudioElement) {
11865
- return;
11866
- }
11867
- this.roomAudioElement = roomAudioElement;
12591
+ if (!this.roomAudioElement) {
12592
+ const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
12593
+ this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
11868
12594
  this.roomAudioElement.srcObject = stream;
11869
- this.roomAudioElement.autoplay = true;
11870
- this.roomAudioElement.id = 'audio-room';
11871
-
11872
- // $FlowFixMe
11873
- if (this.roomAudioElement.setSinkId) {
11874
- // $FlowFixMe
11875
- this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
11876
- }
11877
12595
  }
11878
12596
  });
11879
12597
 
@@ -11948,6 +12666,9 @@ class Room extends Emitter {
11948
12666
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11949
12667
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11950
12668
 
12669
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
12670
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
12671
+
11951
12672
  // Phone events
11952
12673
  Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
11953
12674
  Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
@@ -11958,15 +12679,15 @@ class Room extends Emitter {
11958
12679
  Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
11959
12680
  }
11960
12681
 
11961
- _onMessage(message ) {
12682
+ _onMessage(message ) {
11962
12683
  if (message.method !== 'MESSAGE') {
11963
- return;
12684
+ return null;
11964
12685
  }
11965
12686
  let body;
11966
12687
  try {
11967
12688
  body = JSON.parse(message.body);
11968
12689
  } catch (e) {
11969
- return;
12690
+ return null;
11970
12691
  }
11971
12692
 
11972
12693
  switch (body.type) {
@@ -11985,6 +12706,8 @@ class Room extends Emitter {
11985
12706
  }
11986
12707
 
11987
12708
  this.eventEmitter.emit(this.ON_MESSAGE, body);
12709
+
12710
+ return body;
11988
12711
  }
11989
12712
 
11990
12713
  _onChat(content ) {
@@ -12049,23 +12772,24 @@ class Room extends Emitter {
12049
12772
  const session = Wazo.Auth.getSession();
12050
12773
  let participants = [];
12051
12774
 
12052
- // @TODO: we could use a better function name here
12053
- const isJoining = part => {
12054
- this.__associateStreams(part);
12055
- // @VALIDATE: no need to publicize ourselves, no?
12056
- if (part instanceof RemoteParticipant) {
12057
- this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
12058
- }
12059
- };
12060
-
12061
12775
  // When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
12062
12776
  if (participant.user_uuid === session.uuid) {
12063
12777
  logger.info('room current user joined');
12064
12778
 
12065
12779
  // Retrieve participants via an API calls
12066
12780
  const conferenceId = this.sourceId || payload.data.conference_id;
12067
- const response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
12068
- logger.info('fetching conference participants', { conferenceId });
12781
+ let response;
12782
+ try {
12783
+ if (this.meetingUuid) {
12784
+ logger.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
12785
+ response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
12786
+ } else {
12787
+ logger.info('fetching conference participants', { conferenceId });
12788
+ response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
12789
+ }
12790
+ } catch (e) {
12791
+ logger.error('room participants fetching, error', e);
12792
+ }
12069
12793
  if (response) {
12070
12794
  logger.info('conference participants fetched', { nb: response.items.length });
12071
12795
  participants = response.items.map(item => {
@@ -12080,25 +12804,10 @@ class Room extends Emitter {
12080
12804
 
12081
12805
  const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
12082
12806
  if (!this.localParticipant && localParticipant) {
12083
- this.localParticipant = localParticipant;
12084
-
12085
- const localVideoStream = this._getLocalVideoStream();
12086
- if (localVideoStream) {
12087
- this._saveLocalVideoStream(localVideoStream);
12088
- }
12089
-
12090
- this.connected = true;
12091
-
12092
- // we're in the room, now let's request everyone's status
12093
- if (this.localParticipant) {
12094
- this.sendSignal({
12095
- type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
12096
- origin: this.localParticipant.getStatus(),
12097
- });
12098
- }
12807
+ this._onLocalParticipantJoined(localParticipant);
12099
12808
  }
12100
12809
 
12101
- participants.forEach(someParticipant => isJoining(someParticipant));
12810
+ participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
12102
12811
  this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
12103
12812
  }
12104
12813
 
@@ -12113,12 +12822,41 @@ class Room extends Emitter {
12113
12822
 
12114
12823
  if (remoteParticipant) {
12115
12824
  this.participants.push(remoteParticipant);
12116
- isJoining(remoteParticipant);
12825
+ this._isParticipantJoining(remoteParticipant);
12117
12826
  }
12118
12827
 
12119
12828
  return remoteParticipant;
12120
12829
  }
12121
12830
 
12831
+ _onLocalParticipantJoined(localParticipant ) {
12832
+ this.localParticipant = localParticipant;
12833
+
12834
+ const localVideoStream = this._getLocalVideoStream();
12835
+ if (localVideoStream) {
12836
+ this._saveLocalVideoStream(localVideoStream);
12837
+ }
12838
+
12839
+ this.connected = true;
12840
+
12841
+ localParticipant.broadcastStatus();
12842
+
12843
+ // we're in the room, now let's request everyone's status
12844
+ if (this.localParticipant) {
12845
+ this.sendSignal({
12846
+ type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
12847
+ origin: this.localParticipant.getStatus(),
12848
+ });
12849
+ }
12850
+ }
12851
+
12852
+ _isParticipantJoining(participant ) {
12853
+ this.__associateStreams(participant);
12854
+ // @VALIDATE: no need to publicize ourselves, no?
12855
+ if (participant instanceof RemoteParticipant) {
12856
+ this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
12857
+ }
12858
+ }
12859
+
12122
12860
  _saveLocalVideoStream(stream ) {
12123
12861
  const { localParticipant } = this;
12124
12862
 
@@ -12164,9 +12902,11 @@ class Room extends Emitter {
12164
12902
  _onParticipantTrackUpdate(oldParticipant , update ) {
12165
12903
  const newParticipant = oldParticipant;
12166
12904
 
12167
- const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
12905
+ const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
12168
12906
  const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
12169
- const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
12907
+ // Can't use `getReceivers` here because on FF we make the mapping based on the streamId
12908
+ const stream = pc.getRemoteStreams().find(someStream =>
12909
+ someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
12170
12910
 
12171
12911
  if (update === 'downgrade') {
12172
12912
  newParticipant.streams = [];
@@ -12196,15 +12936,41 @@ class Room extends Emitter {
12196
12936
  return;
12197
12937
  }
12198
12938
 
12199
- if (this._unassociatedVideoStreams[trackId]) {
12939
+ const streamId = this._getStreamIdFrTrackId(trackId);
12940
+ const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
12941
+ const stream = this._unassociatedVideoStreams[key];
12942
+
12943
+ if (stream) {
12200
12944
  // Try to associate stream
12201
- this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
12945
+ this._associateStreamTo(stream, participant);
12202
12946
 
12203
- delete this._unassociatedVideoStreams[trackId];
12947
+ delete this._unassociatedVideoStreams[key];
12204
12948
  delete this._unassociatedParticipants[participant.callId];
12205
12949
  }
12206
12950
  }
12207
12951
 
12952
+ _getUnassociatedMapIdFromTrackIdOrStreamId(trackId , streamId ) {
12953
+ // Find by trackId
12954
+ if (trackId in this._unassociatedVideoStreams) {
12955
+ return trackId;
12956
+ }
12957
+
12958
+ // Find by streamId
12959
+ if (streamId && streamId in this._unassociatedVideoStreams) {
12960
+ return streamId;
12961
+ }
12962
+
12963
+ // Find in all the streams by streamId (used on FF where we can't map by trackId)
12964
+ const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream ) => stream.id === streamId);
12965
+ return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
12966
+ }
12967
+
12968
+ _getStreamIdFrTrackId(trackId ) {
12969
+ const mapping = Object.values(this._callIdStreamIdMap).find((map ) => map.trackId === trackId);
12970
+
12971
+ return mapping ? mapping.streamId : null;
12972
+ }
12973
+
12208
12974
  _associateStreamTo(rawStream , participant ) {
12209
12975
  const stream = new Wazo.Stream(rawStream, participant);
12210
12976
  participant.streams.push(stream);