@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
@@ -340,7 +340,13 @@ class IssueReporter {
340
340
  }
341
341
 
342
342
  _isLevelAbove(level1 , level2 ) {
343
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
343
+ const index1 = LOG_LEVELS.indexOf(level1);
344
+ const index2 = LOG_LEVELS.indexOf(level2);
345
+ if (index1 === -1 || index2 === -1) {
346
+ return false;
347
+ }
348
+
349
+ return index1 > index2;
344
350
  }
345
351
 
346
352
  _makeCategory(category ) {
@@ -363,7 +369,7 @@ var IssueReporter$1 = new IssueReporter();
363
369
 
364
370
  const methods = ['head', 'get', 'post', 'put', 'delete'];
365
371
 
366
- const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
372
+ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
367
373
 
368
374
  // Use a function here to be able to mock it in tests
369
375
  const realFetch = () => {
@@ -502,7 +508,7 @@ class ApiRequester {
502
508
  };
503
509
 
504
510
  if (this.refreshTokenPromise) {
505
- logger$a.info('A token is already refreshing, waiting ...', { url });
511
+ logger$c.info('A token is already refreshing, waiting ...', { url });
506
512
  await this.refreshTokenPromise;
507
513
  }
508
514
 
@@ -522,7 +528,7 @@ class ApiRequester {
522
528
  return promise.then(async (err ) => {
523
529
  // Check if the token is still valid
524
530
  if (firstCall && this._checkTokenExpired(response, err)) {
525
- logger$a.warn('token expired', { error: err.reason });
531
+ logger$c.warn('token expired', { error: err.reason });
526
532
  // Replay the call after refreshing the token
527
533
  return this._replayWithNewToken(err, path, method, body, headers, parse);
528
534
  }
@@ -532,7 +538,7 @@ class ApiRequester {
532
538
  : exceptionClass.fromResponse(err, response.status);
533
539
 
534
540
  if (this.shouldLogErrors) {
535
- logger$a.error('API error', error);
541
+ logger$c.error('API error', error);
536
542
  }
537
543
 
538
544
  throw error;
@@ -542,7 +548,7 @@ class ApiRequester {
542
548
  return newParse(response, isJson);
543
549
  }).catch(error => {
544
550
  if (this.shouldLogErrors) {
545
- logger$a.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
551
+ logger$c.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
546
552
  }
547
553
 
548
554
  throw error;
@@ -570,13 +576,13 @@ class ApiRequester {
570
576
  ) {
571
577
  const isTokenNotFound = this._isTokenNotFound(err);
572
578
  let newPath = path;
573
- logger$a.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
579
+ logger$c.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
574
580
 
575
581
  this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
576
582
 
577
583
  return this.refreshTokenPromise.then(() => {
578
584
  this.refreshTokenPromise = null;
579
- logger$a.info('token refreshed', { isTokenNotFound });
585
+ logger$c.info('token refreshed', { isTokenNotFound });
580
586
  if (isTokenNotFound) {
581
587
  const pathParts = path.split('/');
582
588
  pathParts.pop();
@@ -2518,6 +2524,65 @@ class ExternalApp {
2518
2524
  }
2519
2525
  }
2520
2526
 
2527
+ //
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+
2538
+
2539
+ class Meeting {
2540
+
2541
+
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+
2549
+
2550
+ static parse(plain ) {
2551
+ return new Meeting({
2552
+ guestSipAuthorization: plain.guest_sip_authorization,
2553
+ hostname: plain.hostname,
2554
+ name: plain.name,
2555
+ ownerUuids: plain.owner_uuids,
2556
+ port: plain.port,
2557
+ uuid: plain.uuid,
2558
+ number: plain.number,
2559
+ });
2560
+ }
2561
+
2562
+ static newFrom(meeting ) {
2563
+ return newFrom(meeting, Meeting);
2564
+ }
2565
+
2566
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2567
+ this.guestSipAuthorization = guestSipAuthorization;
2568
+ this.hostname = hostname;
2569
+ this.name = name;
2570
+ this.ownerUuids = ownerUuids;
2571
+ this.port = port;
2572
+ this.uuid = uuid;
2573
+ this.number = number;
2574
+
2575
+ // Useful to compare instead of instanceof with minified code
2576
+ this.type = 'Meeting';
2577
+ }
2578
+
2579
+ getGuestSipCredentials() {
2580
+ // eslint-disable-next-line no-undef
2581
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2582
+ return { username, secret };
2583
+ }
2584
+ }
2585
+
2521
2586
  /* */
2522
2587
 
2523
2588
  var confdMethods = (client , baseUrl ) => ({
@@ -2582,6 +2647,18 @@ var confdMethods = (client , baseUrl ) => ({
2582
2647
  return null;
2583
2648
  }
2584
2649
  },
2650
+
2651
+ createMyMeeting: (name ) =>
2652
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2653
+
2654
+ deleteMyMeeting: (meetingUuid ) =>
2655
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2656
+
2657
+ getMeeting: (meetingUuid ) =>
2658
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2659
+
2660
+ guestGetMeeting: (meetingUuid ) =>
2661
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2585
2662
  });
2586
2663
 
2587
2664
  //
@@ -3339,7 +3416,7 @@ class CallSession {
3339
3416
  return newFrom(callSession, CallSession);
3340
3417
  }
3341
3418
 
3342
- static parseCall(session , call ) {
3419
+ static parseCall(call ) {
3343
3420
  return new CallSession({
3344
3421
  callId: call.id,
3345
3422
  sipCallId: call.sipCallId,
@@ -3524,7 +3601,11 @@ class CallLog {
3524
3601
  answered: plain.answered,
3525
3602
  callDirection: plain.call_direction,
3526
3603
  destination: {
3527
- extension: plain.requested_extension || plain.destination_extension,
3604
+ // @TEMP: Temporarily assuming empty numbers are meetings
3605
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3606
+ extension: plain.requested_extension
3607
+ || plain.destination_extension
3608
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3528
3609
  name: plain.requested_name || plain.destination_name || '',
3529
3610
  },
3530
3611
  source: {
@@ -3540,27 +3621,11 @@ class CallLog {
3540
3621
  }
3541
3622
 
3542
3623
  static parseNew(plain , session ) {
3543
- return new CallLog({
3544
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3545
- answered: plain.answered,
3546
- callDirection: plain.call_direction,
3547
- destination: {
3548
- extension: plain.requested_extension || plain.destination_extension,
3549
- name: plain.requested_name || plain.destination_name || '',
3550
- },
3551
- source: {
3552
- extension: plain.source_extension,
3553
- name: plain.source_name,
3554
- },
3555
- id: plain.id,
3556
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3557
- start: moment__default['default'](plain.start).toDate(),
3558
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3559
- recordings: Recording.parseMany(plain.recordings),
3560
- // @TODO: FIXME add verification declined vs missed call
3561
- newMissedCall: session
3562
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3563
- });
3624
+ const callLog = CallLog.parse(plain);
3625
+ // @TODO: FIXME add verification declined vs missed call
3626
+ callLog.newMissedCall = session
3627
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3628
+ return callLog;
3564
3629
  }
3565
3630
 
3566
3631
  static newFrom(profile ) {
@@ -3720,29 +3785,432 @@ class IndirectTransfer {
3720
3785
  });
3721
3786
  }
3722
3787
 
3723
- destinationIs(callSession ) {
3724
- return callSession.isId(this.destinationId);
3788
+ destinationIs(callSession ) {
3789
+ return callSession.isId(this.destinationId);
3790
+ }
3791
+
3792
+ sourceIs(callSession ) {
3793
+ return callSession.isId(this.sourceId);
3794
+ }
3795
+
3796
+ updateFrom(indirectTransfer ) {
3797
+ updateFrom(this, indirectTransfer);
3798
+ }
3799
+
3800
+ static newFrom(indirectTransfer ) {
3801
+ return newFrom(indirectTransfer, IndirectTransfer);
3802
+ }
3803
+ }
3804
+
3805
+ //
3806
+
3807
+ class CallApi {
3808
+ static async fetchCallLogs(offset , limit ) {
3809
+ return getApiClient().callLogd.listCallLogs(offset, limit);
3810
+ }
3811
+
3812
+ static async fetchDistinctCallLogs(offset , limit , distinct = 'peer_exten') {
3813
+ return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
3814
+ }
3815
+
3816
+ static async fetchActiveCalls() {
3817
+ return getApiClient().calld.listCalls();
3818
+ }
3819
+
3820
+ static async fetchCallLogsFromDate(from , number ) {
3821
+ return getApiClient().callLogd.listCallLogsFromDate(from, number);
3822
+ }
3823
+
3824
+ static async search(query , limit ) {
3825
+ return getApiClient().callLogd.search(query, limit);
3826
+ }
3827
+
3828
+ static async searchBy(field , value , limit ) {
3829
+ return getApiClient().callLogd.searchBy(field, value, limit);
3830
+ }
3831
+
3832
+ static async fetchSIP(session , line ) {
3833
+ const lineToUse = line || session.primaryLine();
3834
+ return getApiClient().confd.getUserLineSip(session.uuid, lineToUse ? lineToUse.id : null);
3835
+ }
3836
+
3837
+ static async cancelCall(callSession ) {
3838
+ return getApiClient().calld.cancelCall(callSession.callId);
3839
+ }
3840
+
3841
+ static async makeCall(callFromLine , extension , isMobile = false,
3842
+ callbackAllLines = false) {
3843
+ const lineId = callFromLine ? callFromLine.id : null;
3844
+
3845
+ const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
3846
+ return Call.parse(response);
3847
+ }
3848
+
3849
+ static async relocateCall(callId , line , contactIdentifier ) {
3850
+ return getApiClient().calld.relocateCall(callId, 'line', line, contactIdentifier);
3851
+ }
3852
+
3853
+ static async hold(callId ) {
3854
+ return getApiClient().calld.hold(callId);
3855
+ }
3856
+
3857
+ static async resume(callId ) {
3858
+ return getApiClient().calld.resume(callId);
3859
+ }
3860
+
3861
+ static async mute(callId ) {
3862
+ return getApiClient().calld.mute(callId);
3863
+ }
3864
+
3865
+ static async sendDTMF(callId , digits ) {
3866
+ return getApiClient().calld.sendDTMF(callId, digits);
3867
+ }
3868
+
3869
+ static async unmute(callId ) {
3870
+ return getApiClient().calld.unmute(callId);
3871
+ }
3872
+
3873
+ static async transferCall(callId , number , flow ) {
3874
+ return getApiClient().calld.transferCall(callId, number, flow);
3875
+ }
3876
+
3877
+ static async cancelCallTransfer(transferId ) {
3878
+ return getApiClient().calld.cancelCallTransfer(transferId);
3879
+ }
3880
+
3881
+ static async confirmCallTransfer(transferId ) {
3882
+ return getApiClient().calld.confirmCallTransfer(transferId);
3883
+ }
3884
+ }
3885
+
3886
+ //
3887
+
3888
+ const TRANSFER_FLOW_ATTENDED = 'attended';
3889
+ const TRANSFER_FLOW_BLIND = 'blind';
3890
+
3891
+ // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
3892
+
3893
+ const logger$b = IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
3894
+
3895
+ class CTIPhone extends Emitter {
3896
+
3897
+
3898
+
3899
+
3900
+
3901
+
3902
+
3903
+
3904
+ constructor(session , isMobile = false, callbackAllLines = false) {
3905
+ super();
3906
+ logger$b.info('CTI Phone created');
3907
+ this.session = session;
3908
+ this.isMobile = isMobile;
3909
+ this.callbackAllLines = callbackAllLines;
3910
+ }
3911
+
3912
+ getOptions() {
3913
+ // @FIXME: temporarily disabling this option
3914
+ // const hold = this.session.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD);
3915
+
3916
+ return {
3917
+ accept: false,
3918
+ decline: true,
3919
+ mute: true,
3920
+ hold: false,
3921
+ transfer: true,
3922
+ sendKey: true,
3923
+ addParticipant: false,
3924
+ record: true,
3925
+ merge: false,
3926
+ };
3927
+ }
3928
+
3929
+ hasAnActiveCall() {
3930
+ return !!this.currentCall;
3931
+ }
3932
+
3933
+ callCount() {
3934
+ return this.currentCall ? 1 : 0;
3935
+ }
3936
+
3937
+ isWebRTC() {
3938
+ return false;
3939
+ }
3940
+
3941
+ getUserAgent() {
3942
+ return 'cti-phone';
3943
+ }
3944
+
3945
+ startHeartbeat() {
3946
+ }
3947
+
3948
+ setOnHeartbeatTimeout() {
3949
+ }
3950
+
3951
+ setOnHeartbeatCallback() {
3952
+ }
3953
+
3954
+ stopHeartbeat() {
3955
+ }
3956
+
3957
+ bindClientEvents() {
3958
+ }
3959
+
3960
+ onConnect() {
3961
+ }
3962
+
3963
+ onDisconnect() {
3964
+ }
3965
+
3966
+ async makeCall(number , line ) {
3967
+ logger$b.info('make CTI call', { number });
3968
+
3969
+ if (!number) {
3970
+ return null;
3971
+ }
3972
+ try {
3973
+ this.currentCall = await CallApi.makeCall(line, number, this.isMobile, this.callbackAllLines);
3974
+ } catch (_) {
3975
+ // We have to deal with error like `User has no mobile phone number` error in the UI.
3976
+ }
3977
+ if (!this.currentCall) {
3978
+ return null;
3979
+ }
3980
+ const callSession = CallSession.parseCall(this.currentCall);
3981
+ this.eventEmitter.emit('onCallOutgoing', callSession);
3982
+
3983
+ return callSession;
3984
+ }
3985
+
3986
+ accept(callSession ) {
3987
+ if (!callSession) {
3988
+ return Promise.resolve(null);
3989
+ }
3990
+ logger$b.info('accept CTI call', { callId: callSession.getId(), number: callSession.number });
3991
+
3992
+ if (!this.currentCall) {
3993
+ this.currentCall = callSession.call;
3994
+ }
3995
+
3996
+ return Promise.resolve(callSession.getId());
3997
+ }
3998
+
3999
+ endCurrentCall(callSession ) {
4000
+ if (!callSession) {
4001
+ return;
4002
+ }
4003
+ logger$b.info('end current CTI call', { callId: callSession.getId(), number: callSession.number });
4004
+
4005
+ this.currentCall = undefined;
4006
+ this.eventEmitter.emit('onCallEnded', callSession);
4007
+ }
4008
+
4009
+ async hangup(callSession ) {
4010
+ if (!callSession) {
4011
+ return Promise.resolve(false);
4012
+ }
4013
+ logger$b.info('hangup CTI call', { callId: callSession.getId(), number: callSession.number });
4014
+
4015
+ try {
4016
+ await CallApi.cancelCall(callSession);
4017
+ if (this.currentCall && callSession.callId === this.currentCall.id) {
4018
+ this.endCurrentCall(callSession);
4019
+ }
4020
+
4021
+ this.eventEmitter.emit('onCallEnded', callSession);
4022
+ return true;
4023
+ } catch (e) {
4024
+ logger$b.error('hangup CTI call, error', e);
4025
+
4026
+ this.eventEmitter.emit('onCallFailed', callSession);
4027
+ return false;
4028
+ }
4029
+ }
4030
+
4031
+ ignore() {}
4032
+
4033
+ async reject(callSession ) {
4034
+ if (!callSession) {
4035
+ return;
4036
+ }
4037
+ logger$b.info('reject CTI call', { callId: callSession.getId(), number: callSession.number });
4038
+
4039
+ await CallApi.cancelCall(callSession);
4040
+ this.eventEmitter.emit('onCallEnded', callSession);
4041
+ }
4042
+
4043
+ async transfer(callSession , number ) {
4044
+ if (!callSession) {
4045
+ return;
4046
+ }
4047
+ logger$b.info('transfer CTI call', { callId: callSession.getId(), number: callSession.number, to: number });
4048
+
4049
+ await CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_BLIND);
4050
+ }
4051
+
4052
+ indirectTransfer() {}
4053
+
4054
+ async initiateCTIIndirectTransfer(callSession , number ) {
4055
+ if (!callSession) {
4056
+ return;
4057
+ }
4058
+ logger$b.info('indirect CTI transfer', { callId: callSession.getId(), number: callSession.number, to: number });
4059
+
4060
+ return CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_ATTENDED);
4061
+ }
4062
+
4063
+ async cancelCTIIndirectTransfer(transferId ) {
4064
+ logger$b.info('cancel CTI transfer', { transferId });
4065
+
4066
+ return CallApi.cancelCallTransfer(transferId);
4067
+ }
4068
+
4069
+ async confirmCTIIndirectTransfer(transferId ) {
4070
+ logger$b.info('confirm CTI transfer', { transferId });
4071
+
4072
+ return CallApi.confirmCallTransfer(transferId);
4073
+ }
4074
+
4075
+ sendKey(callSession , digits ) {
4076
+ if (!callSession) {
4077
+ return;
4078
+ }
4079
+ logger$b.info('send CTI key', { callId: callSession.getId(), number: callSession.number, digits });
4080
+
4081
+ return CallApi.sendDTMF(callSession.callId, digits);
4082
+ }
4083
+
4084
+ onConnectionMade() {
4085
+ logger$b.info('on CTI connection made');
4086
+
4087
+ this.eventEmitter.emit('onCallAccepted');
4088
+ }
4089
+
4090
+ async close() {
4091
+ logger$b.info('CTI close');
4092
+
4093
+ return Promise.resolve();
4094
+ }
4095
+
4096
+ async hold(callSession ) {
4097
+ if (!callSession) {
4098
+ return;
4099
+ }
4100
+ logger$b.info('CTI hold', { callId: callSession.getId(), number: callSession.number });
4101
+
4102
+ return CallApi.hold(callSession.callId);
4103
+ }
4104
+
4105
+ async resume(callSession ) {
4106
+ if (!callSession) {
4107
+ return;
4108
+ }
4109
+ logger$b.info('CTI resume', { callId: callSession.getId(), number: callSession.number });
4110
+
4111
+ return CallApi.resume(callSession.callId);
4112
+ }
4113
+
4114
+ async mute(callSession ) {
4115
+ if (!callSession) {
4116
+ return;
4117
+ }
4118
+ logger$b.info('CTI mute', { callId: callSession.getId(), number: callSession.number });
4119
+
4120
+ return CallApi.mute(callSession.callId);
4121
+ }
4122
+
4123
+ async unmute(callSession ) {
4124
+ if (!callSession) {
4125
+ return;
4126
+ }
4127
+ logger$b.info('CTI unmute', { callId: callSession.getId(), number: callSession.number });
4128
+
4129
+ return CallApi.unmute(callSession.callId);
4130
+ }
4131
+
4132
+ putOnSpeaker() {}
4133
+
4134
+ putOffSpeaker() {}
4135
+
4136
+ turnCameraOff() {}
4137
+
4138
+ turnCameraOn() {}
4139
+
4140
+ changeAudioInputDevice() {}
4141
+
4142
+ changeVideoInputDevice() {}
4143
+
4144
+ changeAudioDevice() {}
4145
+
4146
+ changeRingDevice() {}
4147
+
4148
+ changeAudioVolume() {}
4149
+
4150
+ changeRingVolume() {}
4151
+
4152
+ hasVideo() {
4153
+ return false;
4154
+ }
4155
+
4156
+ getLocalStreamForCall() {
4157
+ return null;
4158
+ }
4159
+
4160
+ getRemoteStreamForCall() {
4161
+ return null;
4162
+ }
4163
+
4164
+ getLocalVideoStream() {
4165
+ return null;
4166
+ }
4167
+
4168
+ setActiveSipSession() {}
4169
+
4170
+ isRegistered() {
4171
+ return true;
4172
+ }
4173
+
4174
+ hasIncomingCallSession() {
4175
+ return true;
4176
+ }
4177
+
4178
+ hasActiveRemoteVideoStream() {
4179
+ return false;
4180
+ }
4181
+
4182
+ getCurrentCallSession() {
4183
+ return this.currentCall ? CallSession.parseCall(this.currentCall) : null;
3725
4184
  }
3726
4185
 
3727
- sourceIs(callSession ) {
3728
- return callSession.isId(this.sourceId);
4186
+ enableRinging() {}
4187
+
4188
+ sendMessage() {}
4189
+
4190
+ disableRinging() {}
4191
+
4192
+ getLocalStream() {
4193
+ return null;
3729
4194
  }
3730
4195
 
3731
- updateFrom(indirectTransfer ) {
3732
- updateFrom(this, indirectTransfer);
4196
+ getRemoteStream() {
4197
+ return null;
3733
4198
  }
3734
4199
 
3735
- static newFrom(indirectTransfer ) {
3736
- return newFrom(indirectTransfer, IndirectTransfer);
4200
+ getRemoteVideoStream() {
4201
+ return null;
3737
4202
  }
3738
- }
3739
4203
 
3740
- //
3741
- const TRANSFER_FLOW_BLIND = 'blind';
4204
+ getRemoteAudioStream() {
4205
+ return null;
4206
+ }
3742
4207
 
3743
- // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
4208
+ hasLocalVideo() {
4209
+ return false;
4210
+ }
3744
4211
 
3745
- IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
4212
+ useLocalVideoElement() {}
4213
+ }
3746
4214
 
3747
4215
  /* */
3748
4216
 
@@ -4302,6 +4770,9 @@ var calldMethods = (client , baseUrl ) => ({
4302
4770
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4303
4771
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4304
4772
 
4773
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4774
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4775
+
4305
4776
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4306
4777
 
4307
4778
  mute: (callId ) =>
@@ -4655,7 +5126,7 @@ const AGENTD_VERSION = '1.0';
4655
5126
  const WEBHOOKD_VERSION = '1.0';
4656
5127
  const AMID_VERSION = '1.0';
4657
5128
 
4658
- const logger$9 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
5129
+ const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
4659
5130
 
4660
5131
  class ApiClient {
4661
5132
 
@@ -4707,12 +5178,12 @@ class ApiClient {
4707
5178
  }
4708
5179
 
4709
5180
  async forceRefreshToken() {
4710
- logger$9.info('forcing refresh token, calling callback');
5181
+ logger$a.info('forcing refresh token, calling callback');
4711
5182
  return this.refreshTokenCallback();
4712
5183
  }
4713
5184
 
4714
5185
  async refreshTokenCallback() {
4715
- logger$9.info('refresh token callback called', {
5186
+ logger$a.info('refresh token callback called', {
4716
5187
  refreshToken: this.refreshToken,
4717
5188
  refreshBackend: this.refreshBackend,
4718
5189
  refreshExpiration: this.refreshExpiration,
@@ -4730,7 +5201,7 @@ class ApiClient {
4730
5201
  this.isMobile,
4731
5202
  );
4732
5203
 
4733
- logger$9.info('token refreshed', { token: session.token });
5204
+ logger$a.info('token refreshed', { token: session.token });
4734
5205
 
4735
5206
  if (this.onRefreshToken) {
4736
5207
  this.onRefreshToken(session.token, session);
@@ -4871,7 +5342,7 @@ var getApiClient = (forServer ) => {
4871
5342
  class InvalidSubscription extends Error {}
4872
5343
  class InvalidAuthorization extends Error {}
4873
5344
 
4874
- const logger$8 = IssueReporter$1.loggerFor('simple-auth');
5345
+ const logger$9 = IssueReporter$1.loggerFor('simple-auth');
4875
5346
 
4876
5347
  class Auth {
4877
5348
 
@@ -4906,7 +5377,7 @@ class Auth {
4906
5377
  setApiClientId(this.clientId);
4907
5378
  setRefreshExpiration(this.expiration);
4908
5379
  setOnRefreshToken((token , session ) => {
4909
- logger$8.info('on refresh token done', { token });
5380
+ logger$9.info('on refresh token done', { token });
4910
5381
  setApiToken(token);
4911
5382
  Wazo.Websocket.updateToken(token);
4912
5383
 
@@ -5465,7 +5936,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5465
5936
  .then(() => {
5466
5937
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5467
5938
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5468
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5939
+ if (this.peerConnection.addTransceiver) {
5940
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5941
+ }
5469
5942
  }
5470
5943
  })
5471
5944
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5492,12 +5965,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5492
5965
  };
5493
5966
  })
5494
5967
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5495
- .then((sessionDescription) => {
5496
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5497
- this.localMediaStreamConstraints = options.constraints;
5498
-
5499
- return sessionDescription;
5500
- })
5501
5968
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5502
5969
  .catch((error) => {
5503
5970
  wazoLogger.error('error when creating media', error);
@@ -5692,6 +6159,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5692
6159
 
5693
6160
  // set the transceiver direction to the answer direction
5694
6161
  this._peerConnection.getTransceivers().forEach((transceiver) => {
6162
+ if (transceiver.stopped) {
6163
+ return;
6164
+ }
5695
6165
  if (transceiver.direction /* guarding, but should always be true */) {
5696
6166
  const { receiver } = transceiver;
5697
6167
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5736,10 +6206,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5736
6206
  if (kind !== 'audio' && kind !== 'video') {
5737
6207
  throw new Error(`Unknown new track kind ${kind}.`);
5738
6208
  }
5739
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
6209
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
6210
+ otherSender.track && otherSender.track.kind === kind);
5740
6211
 
5741
6212
  // Do not reuse sender video tracks in SFU
5742
6213
  if (sender && (!sfu || newTrack.kind === 'audio')) {
6214
+ if (sender.track) {
6215
+ // eslint-disable-next-line no-param-reassign
6216
+ newTrack.enabled = sender.track.enabled;
6217
+ }
5743
6218
  trackUpdates.push(
5744
6219
  new Promise((resolve) => {
5745
6220
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5773,7 +6248,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5773
6248
  // Review: could make streamless tracks a configurable option?
5774
6249
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5775
6250
  try {
5776
- pc.addTrack(newTrack, localStream);
6251
+ if (pc.addTrack) {
6252
+ pc.addTrack(newTrack, localStream);
6253
+ } else {
6254
+ pc.addStream(localStream);
6255
+ }
5777
6256
  } catch (error) {
5778
6257
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5779
6258
  throw error;
@@ -5909,7 +6388,7 @@ const DEFAULT_ICE_TIMEOUT = 3000;
5909
6388
  const SEND_STATS_DELAY = 5000;
5910
6389
 
5911
6390
  const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
5912
- const logger$7 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
6391
+ const logger$8 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
5913
6392
  const statsLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-stats') : console;
5914
6393
 
5915
6394
  // events
@@ -5955,6 +6434,7 @@ const MAX_REGISTER_TRIES = 10;
5955
6434
 
5956
6435
 
5957
6436
 
6437
+
5958
6438
 
5959
6439
 
5960
6440
 
@@ -5981,6 +6461,7 @@ class WebRTCClient extends Emitter {
5981
6461
 
5982
6462
 
5983
6463
 
6464
+
5984
6465
 
5985
6466
  // sugar
5986
6467
 
@@ -6019,6 +6500,8 @@ class WebRTCClient extends Emitter {
6019
6500
  super();
6020
6501
  this.uaConfigOverrides = uaConfigOverrides;
6021
6502
  this.config = config;
6503
+ this.skipRegister = config.skipRegister;
6504
+
6022
6505
  this._buildConfig(config, session).then((newConfig ) => {
6023
6506
  this.config = newConfig;
6024
6507
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -6074,13 +6557,13 @@ class WebRTCClient extends Emitter {
6074
6557
 
6075
6558
  createUserAgent(configOverrides ) {
6076
6559
  const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
6077
- logger$7.info('sdk webrtc, creating UA', { webRTCConfiguration });
6560
+ logger$8.info('sdk webrtc, creating UA', { webRTCConfiguration });
6078
6561
 
6079
6562
  webRTCConfiguration.delegate = {
6080
6563
  onConnect: this.onConnect.bind(this),
6081
6564
  onDisconnect: this.onDisconnect.bind(this),
6082
6565
  onInvite: (invitation ) => {
6083
- logger$7.info('sdk webrtc on invite', {
6566
+ logger$8.info('sdk webrtc on invite', {
6084
6567
  method: 'delegate.onInvite',
6085
6568
  id: invitation.id,
6086
6569
  remoteURI: invitation.remoteURI,
@@ -6123,7 +6606,7 @@ class WebRTCClient extends Emitter {
6123
6606
  }
6124
6607
 
6125
6608
  onConnect() {
6126
- logger$7.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6609
+ logger$8.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6127
6610
  this.eventEmitter.emit(CONNECTED);
6128
6611
  if (!this.isRegistered() && this.registerer && this.registerer.waiting) {
6129
6612
  this.registerer.waitingToggle(false);
@@ -6132,7 +6615,7 @@ class WebRTCClient extends Emitter {
6132
6615
  }
6133
6616
 
6134
6617
  async onDisconnect(error ) {
6135
- logger$7.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6618
+ logger$8.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6136
6619
  this.connectionPromise = null;
6137
6620
  // The UA will attempt to reconnect automatically when an error occurred
6138
6621
  this.eventEmitter.emit(DISCONNECTED, error);
@@ -6146,40 +6629,48 @@ class WebRTCClient extends Emitter {
6146
6629
  }
6147
6630
 
6148
6631
  register(tries = 0) {
6149
- logger$7.info('sdk webrtc registering...', {
6632
+ const logInfo = {
6150
6633
  userAgent: !!this.userAgent,
6151
6634
  registered: this.isRegistered(),
6152
6635
  connectionPromise: !!this.connectionPromise,
6153
6636
  registerer: !!this.registerer,
6154
6637
  waiting: this.registerer && this.registerer.waiting,
6155
6638
  tries,
6156
- });
6639
+ skipRegister: this.skipRegister,
6640
+ };
6641
+
6642
+ if (this.skipRegister) {
6643
+ logger$8.info('sdk webrtc skip register...', logInfo);
6644
+ return Promise.resolve();
6645
+ }
6646
+
6647
+ logger$8.info('sdk webrtc registering...', logInfo);
6157
6648
 
6158
6649
  if (!this.userAgent) {
6159
- logger$7.info('sdk webrtc recreating User Agent');
6650
+ logger$8.info('sdk webrtc recreating User Agent');
6160
6651
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6161
6652
  }
6162
6653
  if (!this.userAgent || this.isRegistered()) {
6163
- logger$7.info('sdk webrtc registering aborted, already registered or no UA can be created');
6654
+ logger$8.info('sdk webrtc registering aborted, already registered or no UA can be created');
6164
6655
  return Promise.resolve();
6165
6656
  }
6166
6657
 
6167
6658
  if (this.connectionPromise || (this.registerer && this.registerer.waiting)) {
6168
- logger$7.info('sdk webrtc registering aborted due to a registration in progress.');
6659
+ logger$8.info('sdk webrtc registering aborted due to a registration in progress.');
6169
6660
  return Promise.resolve();
6170
6661
  }
6171
6662
 
6172
6663
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6173
6664
 
6174
6665
  const onRegisterFailed = () => {
6175
- logger$7.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6666
+ logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6176
6667
  this.connectionPromise = null;
6177
6668
  if (this.registerer && this.registerer.waiting) {
6178
6669
  this.registerer.waitingToggle(false);
6179
6670
  }
6180
6671
 
6181
6672
  if (tries <= MAX_REGISTER_TRIES) {
6182
- logger$7.info('sdk webrtc registering, retrying...', { tries });
6673
+ logger$8.info('sdk webrtc registering, retrying...', { tries });
6183
6674
  setTimeout(() => this.register(tries + 1), 300);
6184
6675
  }
6185
6676
  };
@@ -6188,18 +6679,18 @@ class WebRTCClient extends Emitter {
6188
6679
  // Avoid race condition with the close method called just before register and setting userAgent to null
6189
6680
  // during the resolution of the primise.
6190
6681
  if (!this.userAgent) {
6191
- logger$7.info('sdk webrtc recreating User Agent after connection');
6682
+ logger$8.info('sdk webrtc recreating User Agent after connection');
6192
6683
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6193
6684
  }
6194
6685
 
6195
- logger$7.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6686
+ logger$8.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6196
6687
  this.registerer = new registerer.Registerer(this.userAgent, registerOptions);
6197
6688
  this.connectionPromise = null;
6198
6689
  this._monkeyPatchRegisterer(this.registerer);
6199
6690
 
6200
6691
  // Bind registerer events
6201
6692
  this.registerer.stateChange.addListener(newState => {
6202
- logger$7.info('sdk webrtc registering, state changed', { newState });
6693
+ logger$8.info('sdk webrtc registering, state changed', { newState });
6203
6694
 
6204
6695
  if (newState === registererState.RegistererState.Registered && this.registerer
6205
6696
  && this.registerer.state === registererState.RegistererState.Registered) {
@@ -6212,7 +6703,7 @@ class WebRTCClient extends Emitter {
6212
6703
  const options = {
6213
6704
  requestDelegate: {
6214
6705
  onReject: response => {
6215
- logger$7.error('sdk webrtc registering, rejected', { response });
6706
+ logger$8.error('sdk webrtc registering, rejected', { response });
6216
6707
 
6217
6708
  onRegisterFailed();
6218
6709
  },
@@ -6220,13 +6711,13 @@ class WebRTCClient extends Emitter {
6220
6711
  };
6221
6712
 
6222
6713
  return this.registerer.register(options).catch((e) => {
6223
- logger$7.error('sdk webrtc registering, error', e);
6714
+ logger$8.error('sdk webrtc registering, error', e);
6224
6715
 
6225
6716
  this.eventEmitter.emit(REGISTRATION_FAILED);
6226
6717
  return e;
6227
6718
  });
6228
6719
  }).catch(error => {
6229
- logger$7.error('sdk webrtc registering, transport error', error);
6720
+ logger$8.error('sdk webrtc registering, transport error', error);
6230
6721
  onRegisterFailed();
6231
6722
  });
6232
6723
  }
@@ -6255,21 +6746,21 @@ class WebRTCClient extends Emitter {
6255
6746
  }
6256
6747
 
6257
6748
  unregister() {
6258
- logger$7.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6749
+ logger$8.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6259
6750
  if (!this.registerer) {
6260
6751
  return Promise.resolve();
6261
6752
  }
6262
6753
 
6263
6754
  try {
6264
6755
  return this.registerer.unregister().then(() => {
6265
- logger$7.info('sdk webrtc unregistered');
6756
+ logger$8.info('sdk webrtc unregistered');
6266
6757
  this._cleanupRegister();
6267
6758
  }).catch(e => {
6268
- logger$7.error('sdk webrtc unregistering, promise error', e);
6759
+ logger$8.error('sdk webrtc unregistering, promise error', e);
6269
6760
  this._cleanupRegister();
6270
6761
  });
6271
6762
  } catch (e) {
6272
- logger$7.error('sdk webrtc unregistering, error', e);
6763
+ logger$8.error('sdk webrtc unregistering, error', e);
6273
6764
  // Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
6274
6765
  // error when the registerer is in a bad state
6275
6766
  this._cleanupRegister();
@@ -6277,7 +6768,7 @@ class WebRTCClient extends Emitter {
6277
6768
  }
6278
6769
 
6279
6770
  stop() {
6280
- logger$7.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6771
+ logger$8.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6281
6772
  if (!this.userAgent) {
6282
6773
  return Promise.resolve();
6283
6774
  }
@@ -6285,12 +6776,12 @@ class WebRTCClient extends Emitter {
6285
6776
  return this.userAgent.stop().then(() => {
6286
6777
  return this._cleanupRegister();
6287
6778
  }).catch(e => {
6288
- logger$7.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6779
+ logger$8.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6289
6780
  });
6290
6781
  }
6291
6782
 
6292
6783
  call(number , enableVideo , audioOnly = false, conference = false) {
6293
- logger$7.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6784
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6294
6785
  const inviterOptions = {
6295
6786
  sessionDescriptionHandlerOptionsReInvite: {
6296
6787
  conference,
@@ -6319,7 +6810,7 @@ class WebRTCClient extends Emitter {
6319
6810
  this._onAccepted(session, response.session, true);
6320
6811
  },
6321
6812
  onReject: (response ) => {
6322
- logger$7.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6813
+ logger$8.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6323
6814
  this._stopSendingStats(session);
6324
6815
 
6325
6816
  this.eventEmitter.emit(REJECTED, session, response);
@@ -6341,11 +6832,11 @@ class WebRTCClient extends Emitter {
6341
6832
  }
6342
6833
 
6343
6834
  answer(session , enableVideo ) {
6344
- logger$7.info('sdk webrtc answer call', { id: session.id, enableVideo });
6835
+ logger$8.info('sdk webrtc answer call', { id: session.id, enableVideo });
6345
6836
 
6346
6837
  if (!session || !session.accept) {
6347
6838
  const error = 'No session to answer, or not an invitation';
6348
- logger$7.warn(error);
6839
+ logger$8.warn(error);
6349
6840
  return Promise.reject(new Error(error));
6350
6841
  }
6351
6842
  const options = {
@@ -6355,15 +6846,15 @@ class WebRTCClient extends Emitter {
6355
6846
  return session.accept(options).then(() => {
6356
6847
  if (session.isCanceled) {
6357
6848
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
6358
- logger$7.error(message, { id: session.id });
6849
+ logger$8.error(message, { id: session.id });
6359
6850
  this.onCallEnded(session);
6360
6851
 
6361
6852
  throw new CanceledCallError(message);
6362
6853
  }
6363
- logger$7.info('sdk webrtc answer, accepted.');
6854
+ logger$8.info('sdk webrtc answer, accepted.');
6364
6855
  this._onAccepted(session);
6365
6856
  }).catch(e => {
6366
- logger$7.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6857
+ logger$8.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6367
6858
 
6368
6859
  throw e;
6369
6860
  });
@@ -6371,7 +6862,7 @@ class WebRTCClient extends Emitter {
6371
6862
 
6372
6863
  hangup(session ) {
6373
6864
  const { state, id } = session;
6374
- logger$7.info('sdk webrtc hangup call', { id, state });
6865
+ logger$8.info('sdk webrtc hangup call', { id, state });
6375
6866
 
6376
6867
  try {
6377
6868
  this._stopSendingStats(session);
@@ -6400,24 +6891,24 @@ class WebRTCClient extends Emitter {
6400
6891
 
6401
6892
  return bye();
6402
6893
  } catch (error) {
6403
- logger$7.warn('sdk webrtc hangup, error', error);
6894
+ logger$8.warn('sdk webrtc hangup, error', error);
6404
6895
  }
6405
6896
 
6406
6897
  return null;
6407
6898
  }
6408
6899
 
6409
6900
  reject(session ) {
6410
- logger$7.info('sdk webrtc reject call', { id: session.id });
6901
+ logger$8.info('sdk webrtc reject call', { id: session.id });
6411
6902
 
6412
6903
  try {
6413
6904
  return session.reject ? session.reject() : session.cancel();
6414
6905
  } catch (e) {
6415
- logger$7.warn('Error when rejecting call', e.message, e.stack);
6906
+ logger$8.warn('Error when rejecting call', e.message, e.stack);
6416
6907
  }
6417
6908
  }
6418
6909
 
6419
6910
  async close() {
6420
- logger$7.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6911
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6421
6912
  this._cleanupMedia();
6422
6913
  this.connectionPromise = null;
6423
6914
 
@@ -6448,7 +6939,7 @@ class WebRTCClient extends Emitter {
6448
6939
  // eg: "INVITE not rejectable in state Completed"
6449
6940
  }
6450
6941
  this.userAgent = null;
6451
- logger$7.info('sdk webrtc client closed');
6942
+ logger$8.info('sdk webrtc client closed');
6452
6943
  }
6453
6944
 
6454
6945
  getNumber(session ) {
@@ -6461,13 +6952,13 @@ class WebRTCClient extends Emitter {
6461
6952
  }
6462
6953
 
6463
6954
  mute(session ) {
6464
- logger$7.info('sdk webrtc mute', { id: session.id });
6955
+ logger$8.info('sdk webrtc mute', { id: session.id });
6465
6956
 
6466
6957
  this._toggleAudio(session, true);
6467
6958
  }
6468
6959
 
6469
6960
  unmute(session ) {
6470
- logger$7.info('sdk webrtc unmute', { id: session.id });
6961
+ logger$8.info('sdk webrtc unmute', { id: session.id });
6471
6962
 
6472
6963
  this._toggleAudio(session, false);
6473
6964
  }
@@ -6484,12 +6975,18 @@ class WebRTCClient extends Emitter {
6484
6975
  }
6485
6976
 
6486
6977
  if (pc.getSenders) {
6978
+ if (!pc.getSenders().length) {
6979
+ return false;
6980
+ }
6487
6981
  pc.getSenders().forEach(sender => {
6488
6982
  if (sender && sender.track && sender.track.kind === 'audio') {
6489
6983
  muted = muted && !sender.track.enabled;
6490
6984
  }
6491
6985
  });
6492
6986
  } else {
6987
+ if (!pc.getLocalStreams().length) {
6988
+ return false;
6989
+ }
6493
6990
  pc.getLocalStreams().forEach(stream => {
6494
6991
  stream.getAudioTracks().forEach(track => {
6495
6992
  muted = muted && !track.enabled;
@@ -6501,20 +6998,20 @@ class WebRTCClient extends Emitter {
6501
6998
  }
6502
6999
 
6503
7000
  toggleCameraOn(session ) {
6504
- logger$7.info('sdk webrtc toggle camera on', { id: session.id });
7001
+ logger$8.info('sdk webrtc toggle camera on', { id: session.id });
6505
7002
 
6506
7003
  this._toggleVideo(session, false);
6507
7004
  }
6508
7005
 
6509
7006
  toggleCameraOff(session ) {
6510
- logger$7.info('sdk webrtc toggle camera off', { id: session.id });
7007
+ logger$8.info('sdk webrtc toggle camera off', { id: session.id });
6511
7008
 
6512
7009
  this._toggleVideo(session, true);
6513
7010
  }
6514
7011
 
6515
7012
  hold(session , isConference = false) {
6516
7013
  const sessionId = this.getSipSessionId(session);
6517
- logger$7.info('sdk webrtc hold', {
7014
+ logger$8.info('sdk webrtc hold', {
6518
7015
  sessionId,
6519
7016
  keys: Object.keys(this.heldSessions),
6520
7017
  pendingReinvite: !!session.pendingReinvite,
@@ -6546,6 +7043,9 @@ class WebRTCClient extends Emitter {
6546
7043
  if (!this._isWeb()) {
6547
7044
  options.sessionDescriptionHandlerModifiers = [modifiers.holdModifier];
6548
7045
  }
7046
+ options.sessionDescriptionHandlerOptions = {
7047
+ constraints: options.constraints,
7048
+ };
6549
7049
 
6550
7050
  // Send re-INVITE
6551
7051
  return session.invite(options);
@@ -6554,7 +7054,7 @@ class WebRTCClient extends Emitter {
6554
7054
  unhold(session , isConference = false) {
6555
7055
  const sessionId = this.getSipSessionId(session);
6556
7056
 
6557
- logger$7.info('sdk webrtc unhold', {
7057
+ logger$8.info('sdk webrtc unhold', {
6558
7058
  sessionId,
6559
7059
  keys: Object.keys(this.heldSessions),
6560
7060
  pendingReinvite: !!session.pendingReinvite,
@@ -6585,6 +7085,9 @@ class WebRTCClient extends Emitter {
6585
7085
  // (eg: holdModifier)
6586
7086
  options.sessionDescriptionHandlerModifiers = [];
6587
7087
  }
7088
+ options.sessionDescriptionHandlerOptions = {
7089
+ constraints: options.constraints,
7090
+ };
6588
7091
 
6589
7092
  // Send re-INVITE
6590
7093
  return session.invite(options);
@@ -6642,7 +7145,7 @@ class WebRTCClient extends Emitter {
6642
7145
  return;
6643
7146
  }
6644
7147
 
6645
- logger$7.info('send WebRTC message', { sipId: sipSession.id, contentType });
7148
+ logger$8.info('send WebRTC message', { sipId: sipSession.id, contentType });
6646
7149
 
6647
7150
  try {
6648
7151
  sipSession.message({
@@ -6767,7 +7270,8 @@ class WebRTCClient extends Emitter {
6767
7270
  }
6768
7271
  const sdh = session.sessionDescriptionHandler;
6769
7272
  const pc = sdh.peerConnection;
6770
- const localStream = this.getLocalStream(this.getSipSessionId(session));
7273
+ const sessionId = this.getSipSessionId(session);
7274
+ const localStream = this.getLocalStream(sessionId);
6771
7275
 
6772
7276
  // Release old video stream
6773
7277
  if (localStream) {
@@ -6793,11 +7297,8 @@ class WebRTCClient extends Emitter {
6793
7297
 
6794
7298
  // let's update the local stream
6795
7299
  this.eventEmitter.emit('onVideoInputChange', stream);
6796
- try {
6797
- await sdh.setLocalMediaStream(stream);
6798
- } catch (_) {
6799
- // Nothing to do
6800
- }
7300
+ this.setLocalMediaStream(sessionId, stream);
7301
+
6801
7302
  return stream;
6802
7303
  });
6803
7304
  }
@@ -7009,7 +7510,7 @@ class WebRTCClient extends Emitter {
7009
7510
  }
7010
7511
 
7011
7512
  startHeartbeat() {
7012
- logger$7.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7513
+ logger$8.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7013
7514
  if (!this.userAgent) {
7014
7515
  this.heartbeat.stop();
7015
7516
  return;
@@ -7022,7 +7523,7 @@ class WebRTCClient extends Emitter {
7022
7523
  }
7023
7524
 
7024
7525
  stopHeartbeat() {
7025
- logger$7.info('sdk webrtc stop heartbeat');
7526
+ logger$8.info('sdk webrtc stop heartbeat');
7026
7527
  this.heartbeat.stop();
7027
7528
  }
7028
7529
 
@@ -7042,7 +7543,7 @@ class WebRTCClient extends Emitter {
7042
7543
  }
7043
7544
 
7044
7545
  attemptReconnection() {
7045
- logger$7.info('attempt reconnection', { userAgent: !!this.userAgent });
7546
+ logger$8.info('attempt reconnection', { userAgent: !!this.userAgent });
7046
7547
  if (!this.userAgent) {
7047
7548
  return;
7048
7549
  }
@@ -7099,9 +7600,11 @@ class WebRTCClient extends Emitter {
7099
7600
  remoteStream.removeTrack(track);
7100
7601
  });
7101
7602
 
7102
- pc.getReceivers().forEach(receiver => {
7103
- remoteStream.addTrack(receiver.track);
7104
- });
7603
+ if (pc.getReceivers) {
7604
+ pc.getReceivers().forEach(receiver => {
7605
+ remoteStream.addTrack(receiver.track);
7606
+ });
7607
+ }
7105
7608
  }
7106
7609
 
7107
7610
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -7136,6 +7639,25 @@ class WebRTCClient extends Emitter {
7136
7639
  return sessionId in this.conferences;
7137
7640
  }
7138
7641
 
7642
+ createAudioElementFor(sessionId ) {
7643
+ const audio = document.createElement('audio');
7644
+ audio.setAttribute('id', `audio-${sessionId}`);
7645
+
7646
+ if (audio.setSinkId && this.audioOutputDeviceId) {
7647
+ audio.setSinkId(this.audioOutputDeviceId);
7648
+ }
7649
+
7650
+ if (document.body) {
7651
+ document.body.appendChild(audio);
7652
+ }
7653
+ this.audioElements[sessionId] = audio;
7654
+
7655
+ audio.volume = this.audioOutputVolume;
7656
+ audio.autoplay = true;
7657
+
7658
+ return audio;
7659
+ }
7660
+
7139
7661
  _onTransportError() {
7140
7662
  this.eventEmitter.emit(TRANSPORT_ERROR);
7141
7663
  this.attemptReconnection();
@@ -7145,7 +7667,7 @@ class WebRTCClient extends Emitter {
7145
7667
  const body = message && typeof message === 'object' ? message.data : message;
7146
7668
  if (body && body.indexOf('200 OK') !== -1) {
7147
7669
  if (this.hasHeartbeat()) {
7148
- logger$7.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7670
+ logger$8.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7149
7671
 
7150
7672
  this.heartbeat.onHeartbeat();
7151
7673
  if (this.heartbeatCb) {
@@ -7156,7 +7678,7 @@ class WebRTCClient extends Emitter {
7156
7678
  }
7157
7679
 
7158
7680
  async _onHeartbeatTimeout() {
7159
- logger$7.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7681
+ logger$8.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7160
7682
 
7161
7683
  if (this.heartbeatTimeoutCb) {
7162
7684
  this.heartbeatTimeoutCb();
@@ -7168,7 +7690,7 @@ class WebRTCClient extends Emitter {
7168
7690
  try {
7169
7691
  await this.userAgent.transport.disconnect();
7170
7692
  } catch (e) {
7171
- logger$7.error('Transport disconnection after heartbeat timeout, error', e);
7693
+ logger$8.error('Transport disconnection after heartbeat timeout, error', e);
7172
7694
  }
7173
7695
  }
7174
7696
 
@@ -7201,31 +7723,31 @@ class WebRTCClient extends Emitter {
7201
7723
  }
7202
7724
 
7203
7725
  _connectIfNeeded() {
7204
- logger$7.info('connect if needed, checking', { connected: this.isConnected() });
7726
+ logger$8.info('connect if needed, checking', { connected: this.isConnected() });
7205
7727
  if (!this.userAgent) {
7206
- logger$7.info('need to recreate User Agent');
7728
+ logger$8.info('need to recreate User Agent');
7207
7729
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
7208
7730
  }
7209
7731
 
7210
7732
  if (this.isConnected()) {
7211
- logger$7.info('webrtc sdk, already connected');
7733
+ logger$8.info('webrtc sdk, already connected');
7212
7734
  return Promise.resolve();
7213
7735
  }
7214
7736
 
7215
7737
  if (this.isConnecting()) {
7216
- logger$7.info('webrtc sdk, already connecting...');
7738
+ logger$8.info('webrtc sdk, already connecting...');
7217
7739
 
7218
7740
  this.connectionPromise = this.userAgent.transport.connectPromise;
7219
7741
  return this.connectionPromise;
7220
7742
  }
7221
7743
 
7222
7744
  if (this.connectionPromise) {
7223
- logger$7.info('webrtc sdk, connection promise connecting...');
7745
+ logger$8.info('webrtc sdk, connection promise connecting...');
7224
7746
  // $FlowFixMe
7225
7747
  return this.connectionPromise;
7226
7748
  }
7227
7749
 
7228
- logger$7.info('WebRTC UA needs to connect');
7750
+ logger$8.info('WebRTC UA needs to connect');
7229
7751
 
7230
7752
  // Force UA to reconnect
7231
7753
  if (this.userAgent && this.userAgent.state !== userAgentState.UserAgentState.Stopped) {
@@ -7350,7 +7872,7 @@ class WebRTCClient extends Emitter {
7350
7872
 
7351
7873
  sdh.peerConnectionDelegate = {
7352
7874
  onicecandidateerror: (error ) => {
7353
- logger$7.error('on icecandidate error', {
7875
+ logger$8.error('on icecandidate error', {
7354
7876
  address: error.address,
7355
7877
  port: error.port,
7356
7878
  errorCode: error.errorCode,
@@ -7365,7 +7887,7 @@ class WebRTCClient extends Emitter {
7365
7887
  let hadRemoteVideo = false;
7366
7888
 
7367
7889
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7368
- // Becase when `onInvite` is called we already got the video track
7890
+ // Because when `onInvite` is called we already got the video track
7369
7891
  session.onInviteRequest = (request) => {
7370
7892
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7371
7893
 
@@ -7379,7 +7901,7 @@ class WebRTCClient extends Emitter {
7379
7901
  updatedNumber = session.assertedIdentity.uri.normal.user;
7380
7902
  updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
7381
7903
  }
7382
- logger$7.info('re-invite received', { updatedCalleeName, updatedNumber });
7904
+ logger$8.info('re-invite received', { updatedCalleeName, updatedNumber });
7383
7905
 
7384
7906
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
7385
7907
 
@@ -7400,7 +7922,7 @@ class WebRTCClient extends Emitter {
7400
7922
  }
7401
7923
 
7402
7924
  _onAccepted(session , sessionDialog , withEvent = true) {
7403
- logger$7.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7925
+ logger$8.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7404
7926
 
7405
7927
  this.storeSipSession(session);
7406
7928
 
@@ -7440,20 +7962,10 @@ class WebRTCClient extends Emitter {
7440
7962
  const isConference = this.isConference(sessionId);
7441
7963
 
7442
7964
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7443
- const audio = document.createElement('audio');
7444
- audio.setAttribute('id', `audio-${sessionId}`);
7445
-
7446
- if (audio.setSinkId && this.audioOutputDeviceId) {
7447
- audio.setSinkId(this.audioOutputDeviceId);
7448
- }
7449
-
7450
- if (document.body) {
7451
- document.body.appendChild(audio);
7452
- }
7453
- this.audioElements[sessionId] = audio;
7965
+ this.createAudioElementFor(sessionId);
7454
7966
  }
7455
7967
 
7456
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7968
+ const audioElement = this.audioElements[sessionId];
7457
7969
  const stream = newStream || this.getRemoteStream(sessionId);
7458
7970
 
7459
7971
  if (!this._isWeb() || !stream) {
@@ -7600,10 +8112,10 @@ class WebRTCClient extends Emitter {
7600
8112
 
7601
8113
  _stopSendingStats(session ) {
7602
8114
  const sessionId = this.getSipSessionId(session);
7603
- logger$7.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
8115
+ logger$8.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7604
8116
 
7605
8117
  if (sessionId in this.statsIntervals) {
7606
- logger$7.trace('Stop sending stats for call', { sessionId });
8118
+ logger$8.trace('Stop sending stats for call', { sessionId });
7607
8119
  this.statsIntervals[sessionId]();
7608
8120
  delete this.statsIntervals[sessionId];
7609
8121
  }
@@ -7619,7 +8131,7 @@ class WebRTCClient extends Emitter {
7619
8131
  try {
7620
8132
  await this.userAgent.transport.disconnect();
7621
8133
  } catch (e) {
7622
- logger$7.error('WebRTC transport disconnect, error', e);
8134
+ logger$8.error('WebRTC transport disconnect, error', e);
7623
8135
  }
7624
8136
  }
7625
8137
  }
@@ -7706,7 +8218,7 @@ const events = [
7706
8218
  ON_SIGNAL,
7707
8219
  ];
7708
8220
 
7709
- const logger$6 = IssueReporter$1.loggerFor('webrtc-phone');
8221
+ const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
7710
8222
 
7711
8223
  class WebRTCPhone extends Emitter {
7712
8224
 
@@ -7777,7 +8289,7 @@ class WebRTCPhone extends Emitter {
7777
8289
  }).catch(error => {
7778
8290
  // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
7779
8291
  console.error('register error', error, error.message, error.stack);
7780
- logger$6.error('WebRTC register error', { message: error.message, stack: error.stack });
8292
+ logger$7.error('WebRTC register error', { message: error.message, stack: error.stack });
7781
8293
  });
7782
8294
  }
7783
8295
 
@@ -7792,7 +8304,7 @@ class WebRTCPhone extends Emitter {
7792
8304
  if (!this.client) {
7793
8305
  return;
7794
8306
  }
7795
- logger$6.info('WebRTC phone stop');
8307
+ logger$7.info('WebRTC phone stop');
7796
8308
  this.client.stop();
7797
8309
  }
7798
8310
 
@@ -7807,14 +8319,14 @@ class WebRTCPhone extends Emitter {
7807
8319
  async sendReinvite(callSession , constraints = null, conference = false,
7808
8320
  audioOnly = false) {
7809
8321
  const sipSession = this.findSipSession(callSession);
7810
- logger$6.info('WebRTC phone - send reinvite', {
8322
+ logger$7.info('WebRTC phone - send reinvite', {
7811
8323
  sessionId: sipSession ? sipSession.id : null,
7812
8324
  constraints,
7813
8325
  audioOnly,
7814
8326
  });
7815
8327
 
7816
8328
  if (!sipSession) {
7817
- return null;
8329
+ return false;
7818
8330
  }
7819
8331
 
7820
8332
  // $FlowFixMe
@@ -7824,19 +8336,17 @@ class WebRTCPhone extends Emitter {
7824
8336
  // Downgrade
7825
8337
  if (constraints && !isUpgrade) {
7826
8338
  // No reinvite needed
7827
- return this._downgradeToAudio(callSession);
8339
+ this._downgradeToAudio(callSession);
8340
+ return false;
7828
8341
  }
7829
8342
 
7830
8343
  if (isUpgrade) {
7831
8344
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
7832
8345
  if (!shouldReinvite) {
7833
- return;
8346
+ return false;
7834
8347
  }
7835
8348
  }
7836
8349
 
7837
- // Force reinvite in SDH
7838
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
7839
-
7840
8350
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
7841
8351
  }
7842
8352
 
@@ -7845,7 +8355,7 @@ class WebRTCPhone extends Emitter {
7845
8355
  }
7846
8356
 
7847
8357
  startHeartbeat() {
7848
- logger$6.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
8358
+ logger$7.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
7849
8359
  if (!this.client || this.client.hasHeartbeat()) {
7850
8360
  return;
7851
8361
  }
@@ -7854,7 +8364,7 @@ class WebRTCPhone extends Emitter {
7854
8364
  }
7855
8365
 
7856
8366
  stopHeartbeat() {
7857
- logger$6.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
8367
+ logger$7.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
7858
8368
  if (!this.client) {
7859
8369
  return;
7860
8370
  }
@@ -7871,7 +8381,7 @@ class WebRTCPhone extends Emitter {
7871
8381
  }
7872
8382
 
7873
8383
  reconnect() {
7874
- logger$6.info('WebRTC phone - reconnect', { client: !!this.client });
8384
+ logger$7.info('WebRTC phone - reconnect', { client: !!this.client });
7875
8385
  if (!this.client) {
7876
8386
  return;
7877
8387
  }
@@ -7909,7 +8419,7 @@ class WebRTCPhone extends Emitter {
7909
8419
  _downgradeToAudio(callSession ) {
7910
8420
  const sipSession = this.findSipSession(callSession);
7911
8421
  if (!sipSession) {
7912
- return;
8422
+ return false;
7913
8423
  }
7914
8424
 
7915
8425
  // Release local video stream when downgrading to audio
@@ -8022,7 +8532,7 @@ class WebRTCPhone extends Emitter {
8022
8532
  // Monkey patch to know when canceled with the CANCEL message
8023
8533
  const onCancel = sipSession._onCancel.bind(sipSession);
8024
8534
  sipSession._onCancel = (message ) => {
8025
- logger$6.trace('on sip session canceled', { callId: message.callId });
8535
+ logger$7.trace('on sip session canceled', { callId: message.callId });
8026
8536
 
8027
8537
  onCancel(message);
8028
8538
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
@@ -8047,13 +8557,13 @@ class WebRTCPhone extends Emitter {
8047
8557
  this.audioOutputVolume,
8048
8558
  );
8049
8559
  case sessionState.SessionState.Terminating:
8050
- logger$6.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8560
+ logger$7.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8051
8561
 
8052
8562
  this.eventEmitter.emit(ON_CALL_ENDING, this._createCallSession(sipSession));
8053
8563
 
8054
8564
  break;
8055
8565
  case sessionState.SessionState.Terminated:
8056
- logger$6.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8566
+ logger$7.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8057
8567
 
8058
8568
  this._onCallTerminated(sipSession);
8059
8569
 
@@ -8089,7 +8599,7 @@ class WebRTCPhone extends Emitter {
8089
8599
  }
8090
8600
 
8091
8601
  async startScreenSharing(constraints , callSession ) {
8092
- logger$6.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8602
+ logger$7.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8093
8603
 
8094
8604
  const screenShareStream = await this._getStreamFromConstraints(constraints);
8095
8605
  if (!screenShareStream) {
@@ -8111,6 +8621,10 @@ class WebRTCPhone extends Emitter {
8111
8621
  localStream.removeTrack(videoTrack);
8112
8622
  }
8113
8623
 
8624
+ if (localStream) {
8625
+ localStream.addTrack(screenTrack);
8626
+ }
8627
+
8114
8628
  if (sender) {
8115
8629
  sender.replaceTrack(screenTrack);
8116
8630
  }
@@ -8125,7 +8639,8 @@ class WebRTCPhone extends Emitter {
8125
8639
  return;
8126
8640
  }
8127
8641
 
8128
- logger$6.info('WebRTC phone - stop screen sharing');
8642
+ logger$7.info('WebRTC phone - stop screen sharing');
8643
+ let reinvited = false;
8129
8644
 
8130
8645
  try {
8131
8646
  if (this.currentScreenShare.stream) {
@@ -8140,7 +8655,8 @@ class WebRTCPhone extends Emitter {
8140
8655
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
8141
8656
  // We have to downgrade to audio.
8142
8657
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
8143
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
8658
+ const constraints = { audio: false, video: screenshareStopped };
8659
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
8144
8660
  }
8145
8661
  } catch (e) {
8146
8662
  console.warn(e);
@@ -8154,6 +8670,8 @@ class WebRTCPhone extends Emitter {
8154
8670
  );
8155
8671
 
8156
8672
  this.currentScreenShare = null;
8673
+
8674
+ return reinvited;
8157
8675
  }
8158
8676
 
8159
8677
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -8191,7 +8709,7 @@ class WebRTCPhone extends Emitter {
8191
8709
  }
8192
8710
 
8193
8711
  _onCallAccepted(sipSession , cameraEnabled ) {
8194
- logger$6.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8712
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8195
8713
 
8196
8714
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
8197
8715
  this.currentSipSession = sipSession;
@@ -8209,11 +8727,15 @@ class WebRTCPhone extends Emitter {
8209
8727
  }
8210
8728
 
8211
8729
  changeAudioDevice(id ) {
8212
- logger$6.info('WebRTC phone - change audio device', { deviceId: id });
8730
+ logger$7.info('WebRTC phone - change audio device', { deviceId: id });
8213
8731
  this.audioOutputDeviceId = id;
8214
8732
  this.client.changeAudioOutputDevice(id);
8215
8733
  }
8216
8734
 
8735
+ createAudioElementFor(sessionId ) {
8736
+ return this.client.createAudioElementFor(sessionId);
8737
+ }
8738
+
8217
8739
  changeRingDevice(id ) {
8218
8740
  this.audioRingDeviceId = id;
8219
8741
  }
@@ -8230,25 +8752,25 @@ class WebRTCPhone extends Emitter {
8230
8752
  }
8231
8753
 
8232
8754
  changeAudioInputDevice(id ) {
8233
- logger$6.info('WebRTC phone - changeAudio input device', { deviceId: id });
8755
+ logger$7.info('WebRTC phone - changeAudio input device', { deviceId: id });
8234
8756
 
8235
8757
  return this.client.changeAudioInputDevice(id, this.currentSipSession);
8236
8758
  }
8237
8759
 
8238
8760
  changeVideoInputDevice(id ) {
8239
- logger$6.info('WebRTC phone - change video input device', { deviceId: id });
8761
+ logger$7.info('WebRTC phone - change video input device', { deviceId: id });
8240
8762
 
8241
8763
  return this.client.changeVideoInputDevice(id, this.currentSipSession);
8242
8764
  }
8243
8765
 
8244
8766
  changeSessionVideoInputDevice(id ) {
8245
- logger$6.info('WebRTC phone - change session video input device', { deviceId: id });
8767
+ logger$7.info('WebRTC phone - change session video input device', { deviceId: id });
8246
8768
 
8247
8769
  return this.client.changeSessionVideoInputDevice(id, this.currentSipSession);
8248
8770
  }
8249
8771
 
8250
8772
  _onCallTerminated(sipSession ) {
8251
- logger$6.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8773
+ logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8252
8774
 
8253
8775
  const callSession = this._createCallSession(sipSession);
8254
8776
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
@@ -8282,7 +8804,7 @@ class WebRTCPhone extends Emitter {
8282
8804
  const hasIncomingCallSession = this.hasIncomingCallSession();
8283
8805
 
8284
8806
  // Re-trigger incoming call event for remaining incoming calls
8285
- logger$6.info('WebRTC phone - check to re-trigger incoming call', {
8807
+ logger$7.info('WebRTC phone - check to re-trigger incoming call', {
8286
8808
  sipId: sipSession.id,
8287
8809
  shouldRetrigger,
8288
8810
  hasIncomingCallSession,
@@ -8371,37 +8893,37 @@ class WebRTCPhone extends Emitter {
8371
8893
 
8372
8894
  // Deprecated
8373
8895
  getLocalStreamForCall(callSession ) {
8374
- logger$6.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8896
+ logger$7.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8375
8897
 
8376
8898
  return this.getLocalStream(callSession);
8377
8899
  }
8378
8900
 
8379
8901
  // Deprecated
8380
8902
  getRemoteStreamForCall(callSession ) {
8381
- logger$6.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8903
+ logger$7.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8382
8904
 
8383
8905
  return this.getRemoteVideoStream(callSession);
8384
8906
  }
8385
8907
 
8386
8908
  getRemoteStreamsForCall(callSession ) {
8387
- logger$6.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8909
+ logger$7.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8388
8910
 
8389
8911
  return this.getRemoteStream(callSession);
8390
8912
  }
8391
8913
 
8392
8914
  accept(callSession , cameraEnabled ) {
8393
- logger$6.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8915
+ logger$7.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8394
8916
  if (this.currentSipSession) {
8395
8917
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
8396
8918
  }
8397
8919
 
8398
8920
  if (!callSession) {
8399
- logger$6.warn('no CallSession to accept.');
8921
+ logger$7.warn('no CallSession to accept.');
8400
8922
  return Promise.resolve(null);
8401
8923
  }
8402
8924
 
8403
8925
  if (callSession.getId() in this.acceptedSessions) {
8404
- logger$6.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8926
+ logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8405
8927
  return Promise.resolve(callSession.sipCallId);
8406
8928
  }
8407
8929
 
@@ -8413,24 +8935,24 @@ class WebRTCPhone extends Emitter {
8413
8935
  const sipSession = this.client.getSipSession(callSession.getId());
8414
8936
  if (sipSession) {
8415
8937
  if (sipSession.state === sessionState.SessionState.Terminated || sipSession.state === sessionState.SessionState.Terminating) {
8416
- logger$6.warn('Trying to answer a terminated sipSession.');
8938
+ logger$7.warn('Trying to answer a terminated sipSession.');
8417
8939
 
8418
8940
  return Promise.resolve(null);
8419
8941
  }
8420
8942
 
8421
- logger$6.info('accept call, session found', { sipId: sipSession.id });
8943
+ logger$7.info('accept call, session found', { sipId: sipSession.id });
8422
8944
 
8423
8945
  // $FlowFixMe
8424
8946
  return this.client.answer(sipSession, this.allowVideo ? cameraEnabled : false).then(() => {
8425
8947
  return callSession.sipCallId;
8426
8948
  }).catch(e => {
8427
- logger$6.error(e);
8949
+ logger$7.error(e);
8428
8950
  this.endCurrentCall(callSession);
8429
8951
  throw e;
8430
8952
  });
8431
8953
  }
8432
8954
 
8433
- logger$6.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8955
+ logger$7.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8434
8956
 
8435
8957
  return Promise.resolve(null);
8436
8958
  }
@@ -8440,7 +8962,7 @@ class WebRTCPhone extends Emitter {
8440
8962
  }
8441
8963
 
8442
8964
  async reject(callSession ) {
8443
- logger$6.info('reject WebRTC called', { id: callSession.getId() });
8965
+ logger$7.info('reject WebRTC called', { id: callSession.getId() });
8444
8966
 
8445
8967
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call rejected locally');
8446
8968
  if (!callSession || callSession.getId() in this.rejectedSessions) {
@@ -8452,14 +8974,14 @@ class WebRTCPhone extends Emitter {
8452
8974
 
8453
8975
  const sipSession = this.findSipSession(callSession);
8454
8976
  if (sipSession) {
8455
- logger$6.info('WebRTC rejecting', { sipId: sipSession.id });
8977
+ logger$7.info('WebRTC rejecting', { sipId: sipSession.id });
8456
8978
 
8457
8979
  this.client.hangup(sipSession);
8458
8980
  }
8459
8981
  }
8460
8982
 
8461
8983
  async ignore(callSession ) {
8462
- logger$6.info('WebRTC ignore', { id: callSession.getId() });
8984
+ logger$7.info('WebRTC ignore', { id: callSession.getId() });
8463
8985
 
8464
8986
  // kill the ring
8465
8987
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'ignoring call');
@@ -8468,7 +8990,7 @@ class WebRTCPhone extends Emitter {
8468
8990
  }
8469
8991
 
8470
8992
  hold(callSession , withEvent = true, isConference = false) {
8471
- logger$6.info('WebRTC hold', { id: callSession.getId() });
8993
+ logger$7.info('WebRTC hold', { id: callSession.getId() });
8472
8994
 
8473
8995
  const sipSession = this.findSipSession(callSession);
8474
8996
 
@@ -8479,7 +9001,7 @@ class WebRTCPhone extends Emitter {
8479
9001
 
8480
9002
  // @Deprecated
8481
9003
  unhold(callSession , withEvent = true, isConference = false) {
8482
- logger$6.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
9004
+ logger$7.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8483
9005
 
8484
9006
  console.warn('Please note that `phone.unhold()` is being deprecated; `phone.resume()` is the preferred method');
8485
9007
 
@@ -8494,7 +9016,7 @@ class WebRTCPhone extends Emitter {
8494
9016
  const sipSession = this.findSipSession(callSession);
8495
9017
 
8496
9018
  if (sipSession) {
8497
- logger$6.info('WebRTC atxfer', { sipId: sipSession.id });
9019
+ logger$7.info('WebRTC atxfer', { sipId: sipSession.id });
8498
9020
 
8499
9021
  return this.client.atxfer(sipSession);
8500
9022
  }
@@ -8509,7 +9031,7 @@ class WebRTCPhone extends Emitter {
8509
9031
  if (!sipSession) {
8510
9032
  return new Promise((resolve, reject) => reject(new Error('No session to hold')));
8511
9033
  }
8512
- logger$6.info('WebRTC hold sip session', { sipId: sipSession.id });
9034
+ logger$7.info('WebRTC hold sip session', { sipId: sipSession.id });
8513
9035
 
8514
9036
  const promise = this.client.hold(sipSession, isConference);
8515
9037
  if (withEvent) {
@@ -8528,7 +9050,7 @@ class WebRTCPhone extends Emitter {
8528
9050
  if (!sipSession) {
8529
9051
  return new Promise((resolve, reject) => reject(new Error('No session to unhold')));
8530
9052
  }
8531
- logger$6.info('WebRTC unhold', { sipId: sipSession.id });
9053
+ logger$7.info('WebRTC unhold', { sipId: sipSession.id });
8532
9054
 
8533
9055
  const promise = this.client.unhold(sipSession, isConference);
8534
9056
  if (withEvent) {
@@ -8539,18 +9061,18 @@ class WebRTCPhone extends Emitter {
8539
9061
  }
8540
9062
 
8541
9063
  resume(callSession , isConference = false) {
8542
- logger$6.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
9064
+ logger$7.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8543
9065
 
8544
9066
  const sipSession = this.findSipSession(callSession);
8545
9067
  if (!sipSession) {
8546
9068
  return new Promise((resolve, reject) => reject(new Error('No session to resume')));
8547
9069
  }
8548
9070
 
8549
- logger$6.info('WebRTC resuming', { sipId: sipSession.id });
9071
+ logger$7.info('WebRTC resuming', { sipId: sipSession.id });
8550
9072
 
8551
9073
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
8552
9074
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
8553
- logger$6.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9075
+ logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8554
9076
  this.holdSipSession(this.currentSipSession, callSession);
8555
9077
  }
8556
9078
 
@@ -8565,14 +9087,14 @@ class WebRTCPhone extends Emitter {
8565
9087
  }
8566
9088
 
8567
9089
  mute(callSession , withEvent = true) {
8568
- logger$6.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
9090
+ logger$7.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8569
9091
 
8570
9092
  const sipSession = this.findSipSession(callSession);
8571
9093
  if (!sipSession) {
8572
9094
  return;
8573
9095
  }
8574
9096
 
8575
- logger$6.info('WebRTC muting', { sipId: sipSession.id });
9097
+ logger$7.info('WebRTC muting', { sipId: sipSession.id });
8576
9098
  this.client.mute(sipSession);
8577
9099
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: true });
8578
9100
 
@@ -8586,14 +9108,14 @@ class WebRTCPhone extends Emitter {
8586
9108
  }
8587
9109
 
8588
9110
  unmute(callSession , withEvent = true) {
8589
- logger$6.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
9111
+ logger$7.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8590
9112
 
8591
9113
  const sipSession = this.findSipSession(callSession);
8592
9114
  if (!sipSession) {
8593
9115
  return;
8594
9116
  }
8595
9117
 
8596
- logger$6.info('WebRTC unmuting', { sipId: sipSession.id });
9118
+ logger$7.info('WebRTC unmuting', { sipId: sipSession.id });
8597
9119
  this.client.unmute(sipSession);
8598
9120
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: false });
8599
9121
 
@@ -8620,7 +9142,7 @@ class WebRTCPhone extends Emitter {
8620
9142
  if (!sipSession) {
8621
9143
  return;
8622
9144
  }
8623
- logger$6.info('WebRTC turn camera on', { sipId: sipSession.id });
9145
+ logger$7.info('WebRTC turn camera on', { sipId: sipSession.id });
8624
9146
 
8625
9147
  this.client.toggleCameraOn(sipSession);
8626
9148
 
@@ -8632,7 +9154,7 @@ class WebRTCPhone extends Emitter {
8632
9154
  if (!sipSession) {
8633
9155
  return;
8634
9156
  }
8635
- logger$6.info('WebRTC turn camera off', { sipId: sipSession.id });
9157
+ logger$7.info('WebRTC turn camera off', { sipId: sipSession.id });
8636
9158
 
8637
9159
  this.client.toggleCameraOff(sipSession);
8638
9160
  this.eventEmitter.emit(ON_CAMERA_DISABLED, this._createCameraDisabledCallSession(sipSession, callSession));
@@ -8644,7 +9166,7 @@ class WebRTCPhone extends Emitter {
8644
9166
  return;
8645
9167
  }
8646
9168
 
8647
- logger$6.info('WebRTC send key', { sipId: sipSession.id, tone });
9169
+ logger$7.info('WebRTC send key', { sipId: sipSession.id, tone });
8648
9170
  this.client.sendDTMF(sipSession, tone);
8649
9171
  }
8650
9172
 
@@ -8652,7 +9174,7 @@ class WebRTCPhone extends Emitter {
8652
9174
  // @TODO: line is not used here
8653
9175
  async makeCall(number , line , cameraEnabled ,
8654
9176
  audioOnly = false, conference = false) {
8655
- logger$6.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9177
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8656
9178
  if (!number) {
8657
9179
  return Promise.resolve(null);
8658
9180
  }
@@ -8662,7 +9184,7 @@ class WebRTCPhone extends Emitter {
8662
9184
  }
8663
9185
  if (this.currentSipSession) {
8664
9186
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true).catch(e => {
8665
- logger$6.warn('Unable to hold current session when making another call', e);
9187
+ logger$7.warn('Unable to hold current session when making another call', e);
8666
9188
  });
8667
9189
  }
8668
9190
 
@@ -8672,7 +9194,7 @@ class WebRTCPhone extends Emitter {
8672
9194
  this._bindEvents(sipSession);
8673
9195
  } catch (error) {
8674
9196
  console.warn(error);
8675
- logger$6.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
9197
+ logger$7.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8676
9198
  return Promise.resolve(null);
8677
9199
  }
8678
9200
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
@@ -8700,7 +9222,7 @@ class WebRTCPhone extends Emitter {
8700
9222
  return;
8701
9223
  }
8702
9224
 
8703
- logger$6.info('WebRTC transfer', { sipId: sipSession.id, target });
9225
+ logger$7.info('WebRTC transfer', { sipId: sipSession.id, target });
8704
9226
 
8705
9227
  this.client.transfer(sipSession, target);
8706
9228
  }
@@ -8709,7 +9231,7 @@ class WebRTCPhone extends Emitter {
8709
9231
  const sipSession = this.client.getSipSession(source.sipCallId);
8710
9232
  const sipSessionTarget = this.client.getSipSession(destination.sipCallId);
8711
9233
 
8712
- logger$6.info('WebRTC indirect transfer', {
9234
+ logger$7.info('WebRTC indirect transfer', {
8713
9235
  sipId: sipSession ? sipSession.id : null,
8714
9236
  target: sipSessionTarget ? sipSessionTarget.id : null,
8715
9237
  });
@@ -8737,7 +9259,7 @@ class WebRTCPhone extends Emitter {
8737
9259
  return false;
8738
9260
  }
8739
9261
 
8740
- logger$6.info('WebRTC hangup', { sipId: sipSession.id });
9262
+ logger$7.info('WebRTC hangup', { sipId: sipSession.id });
8741
9263
 
8742
9264
  const sipSessionId = this.getSipSessionId(sipSession);
8743
9265
 
@@ -8782,7 +9304,7 @@ class WebRTCPhone extends Emitter {
8782
9304
  }
8783
9305
 
8784
9306
  async close() {
8785
- logger$6.info('WebRTC close');
9307
+ logger$7.info('WebRTC close');
8786
9308
 
8787
9309
  try {
8788
9310
  await Promise.race([
@@ -8790,7 +9312,7 @@ class WebRTCPhone extends Emitter {
8790
9312
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Unregister, timed out')), 3000)),
8791
9313
  ]);
8792
9314
  } catch (e) {
8793
- logger$6.error('WebRTC close, unregister error', e);
9315
+ logger$7.error('WebRTC close, unregister error', e);
8794
9316
  }
8795
9317
 
8796
9318
  this.client.close();
@@ -8808,12 +9330,12 @@ class WebRTCPhone extends Emitter {
8808
9330
  }
8809
9331
 
8810
9332
  enableRinging() {
8811
- logger$6.info('WebRTC enable ringing');
9333
+ logger$7.info('WebRTC enable ringing');
8812
9334
  this.ringingEnabled = true;
8813
9335
  }
8814
9336
 
8815
9337
  disableRinging() {
8816
- logger$6.info('WebRTC disable ringing');
9338
+ logger$7.info('WebRTC disable ringing');
8817
9339
  this.ringingEnabled = false;
8818
9340
  }
8819
9341
 
@@ -8853,7 +9375,7 @@ class WebRTCPhone extends Emitter {
8853
9375
 
8854
9376
  // Deprecated
8855
9377
  getLocalMediaStream(callSession ) {
8856
- logger$6.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
9378
+ logger$7.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
8857
9379
  return this.getLocalStream(callSession);
8858
9380
  }
8859
9381
 
@@ -8861,6 +9383,10 @@ class WebRTCPhone extends Emitter {
8861
9383
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
8862
9384
  }
8863
9385
 
9386
+ hasALocalVideoTrack(callSession ) {
9387
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
9388
+ }
9389
+
8864
9390
  getRemoteStream(callSession ) {
8865
9391
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
8866
9392
  }
@@ -8883,7 +9409,7 @@ class WebRTCPhone extends Emitter {
8883
9409
  this.client.on(this.client.INVITE, (sipSession , wantsToDoVideo ) => {
8884
9410
  const autoAnswer = sipSession.request.getHeader('Answer-Mode') === 'Auto';
8885
9411
  const withVideo = this.allowVideo ? wantsToDoVideo : false;
8886
- logger$6.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
9412
+ logger$7.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
8887
9413
 
8888
9414
  const callSession = this._createIncomingCallSession(sipSession, withVideo, null, autoAnswer);
8889
9415
  this.incomingSessions.push(callSession.getId());
@@ -8906,7 +9432,7 @@ class WebRTCPhone extends Emitter {
8906
9432
  });
8907
9433
 
8908
9434
  this.client.on(this.client.ON_REINVITE, (...args) => {
8909
- logger$6.info('WebRTC on reinvite', {
9435
+ logger$7.info('WebRTC on reinvite', {
8910
9436
  sessionId: args[0].id,
8911
9437
  inviteId: args[1].id,
8912
9438
  updatedCalleeName: args[2],
@@ -8926,7 +9452,7 @@ class WebRTCPhone extends Emitter {
8926
9452
  });
8927
9453
 
8928
9454
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
8929
- logger$6.info('WebRTC call accepted', { sipId: sipSession.id });
9455
+ logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
8930
9456
 
8931
9457
  this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
8932
9458
 
@@ -8937,17 +9463,17 @@ class WebRTCPhone extends Emitter {
8937
9463
  this.client.on('ended', () => {});
8938
9464
 
8939
9465
  this.client.on(this.client.ON_ERROR, e => {
8940
- logger$6.error('WebRTC error', e);
9466
+ logger$7.error('WebRTC error', e);
8941
9467
  this.eventEmitter.emit(ON_CALL_ERROR, e);
8942
9468
  });
8943
9469
 
8944
9470
  this.client.on(this.client.UNREGISTERED, () => {
8945
- logger$6.info('WebRTC unregistered');
9471
+ logger$7.info('WebRTC unregistered');
8946
9472
  this.eventEmitter.emit(ON_UNREGISTERED);
8947
9473
  });
8948
9474
 
8949
9475
  this.client.on(this.client.REGISTERED, () => {
8950
- logger$6.info('WebRTC registered', {
9476
+ logger$7.info('WebRTC registered', {
8951
9477
  shouldSendReinvite: this.shouldSendReinvite,
8952
9478
  state: this.currentSipSession ? this.currentSipSession.state : null,
8953
9479
  currentSipSession: !!this.currentSipSession,
@@ -8963,19 +9489,19 @@ class WebRTCPhone extends Emitter {
8963
9489
  try {
8964
9490
  this.sendReinvite(this.currentCallSession);
8965
9491
  } catch (e) {
8966
- logger$6.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9492
+ logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
8967
9493
  }
8968
9494
  }
8969
9495
  });
8970
9496
 
8971
9497
  this.client.on(this.client.CONNECTED, () => {
8972
- logger$6.info('WebRTC client connected');
9498
+ logger$7.info('WebRTC client connected');
8973
9499
 
8974
9500
  this.stopHeartbeat();
8975
9501
  });
8976
9502
 
8977
9503
  this.client.on(this.client.DISCONNECTED, () => {
8978
- logger$6.info('WebRTC client disconnected');
9504
+ logger$7.info('WebRTC client disconnected');
8979
9505
 
8980
9506
  this.eventEmitter.emit(ON_UNREGISTERED);
8981
9507
 
@@ -9207,7 +9733,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9207
9733
 
9208
9734
  //
9209
9735
 
9210
- const logger$5 = IssueReporter$1.loggerFor('simple-phone');
9736
+ const logger$6 = IssueReporter$1.loggerFor('simple-phone');
9211
9737
  const sipLogger = IssueReporter$1.loggerFor('sip.js');
9212
9738
  const protocolLogger = IssueReporter$1.loggerFor('sip');
9213
9739
 
@@ -9314,7 +9840,7 @@ class Phone extends Emitter {
9314
9840
  async disconnect() {
9315
9841
  if (this.phone) {
9316
9842
  if (this.phone.hasAnActiveCall()) {
9317
- logger$5.info('hangup call on disconnect');
9843
+ logger$6.info('hangup call on disconnect');
9318
9844
  // $FlowFixMe
9319
9845
  await this.phone.hangup();
9320
9846
  }
@@ -9337,13 +9863,13 @@ class Phone extends Emitter {
9337
9863
  }
9338
9864
 
9339
9865
  async hangup(callSession ) {
9340
- logger$5.info('hangup via simple phone', { callId: callSession.getId() });
9866
+ logger$6.info('hangup via simple phone', { callId: callSession.getId() });
9341
9867
 
9342
9868
  return this.phone && this.phone.hangup(callSession);
9343
9869
  }
9344
9870
 
9345
9871
  async accept(callSession , cameraEnabled ) {
9346
- logger$5.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9872
+ logger$6.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9347
9873
 
9348
9874
  return this.phone && this.phone.accept(callSession, cameraEnabled);
9349
9875
  }
@@ -9363,13 +9889,18 @@ class Phone extends Emitter {
9363
9889
  return adHocConference.start();
9364
9890
  }
9365
9891
 
9366
- mute(callSession ) {
9367
- this.muteViaAPI(callSession);
9892
+ mute(callSession , withApi = true) {
9893
+ if (withApi) {
9894
+ this.muteViaAPI(callSession);
9895
+ }
9896
+
9368
9897
  return this.phone && this.phone.mute(callSession);
9369
9898
  }
9370
9899
 
9371
- unmute(callSession ) {
9372
- this.unmuteViaAPI(callSession);
9900
+ unmute(callSession , withApi = true) {
9901
+ if (withApi) {
9902
+ this.unmuteViaAPI(callSession);
9903
+ }
9373
9904
 
9374
9905
  return this.phone && this.phone.unmute(callSession);
9375
9906
  }
@@ -9377,7 +9908,7 @@ class Phone extends Emitter {
9377
9908
  muteViaAPI(callSession ) {
9378
9909
  if (callSession && callSession.callId) {
9379
9910
  Wazo.getApiClient().calld.mute(callSession.callId).catch(e => {
9380
- logger$5.error('Mute via API, error', e);
9911
+ logger$6.error('Mute via API, error', e);
9381
9912
  });
9382
9913
  }
9383
9914
  }
@@ -9385,7 +9916,7 @@ class Phone extends Emitter {
9385
9916
  unmuteViaAPI(callSession ) {
9386
9917
  if (callSession && callSession.callId) {
9387
9918
  Wazo.getApiClient().calld.unmute(callSession.callId).catch(e => {
9388
- logger$5.error('Unmute via API, error', e);
9919
+ logger$6.error('Unmute via API, error', e);
9389
9920
  });
9390
9921
  }
9391
9922
  }
@@ -9475,9 +10006,13 @@ class Phone extends Emitter {
9475
10006
  return this.phone && this.phone.hasLocalVideo(callSession);
9476
10007
  }
9477
10008
 
10009
+ hasALocalVideoTrack(callSession ) {
10010
+ return this.phone && this.phone.hasALocalVideoTrack(callSession);
10011
+ }
10012
+
9478
10013
  // @Deprecated
9479
10014
  getLocalMediaStream(callSession ) {
9480
- logger$5.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
10015
+ logger$6.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9481
10016
 
9482
10017
  return this.phone && this.phone.getLocalStream(callSession);
9483
10018
  }
@@ -9496,20 +10031,20 @@ class Phone extends Emitter {
9496
10031
 
9497
10032
  // @Deprecated
9498
10033
  getRemoteStreamForCall(callSession ) {
9499
- logger$5.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
10034
+ logger$6.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9500
10035
  return this.getRemoteStream(callSession);
9501
10036
  }
9502
10037
 
9503
10038
  // Returns remote streams directly from the peerConnection
9504
10039
  // @Deprecated
9505
10040
  getRemoteStreamsForCall(callSession ) {
9506
- logger$5.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
10041
+ logger$6.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9507
10042
  return this.getLocalStream(callSession);
9508
10043
  }
9509
10044
 
9510
10045
  // @Deprecated
9511
10046
  getRemoteVideoStreamForCall(callSession ) {
9512
- logger$5.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
10047
+ logger$6.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9513
10048
 
9514
10049
  return this.getRemoteVideoStream(callSession);
9515
10050
  }
@@ -9639,6 +10174,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
9639
10174
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
9640
10175
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
9641
10176
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
10177
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
10178
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
9642
10179
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
9643
10180
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
9644
10181
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -9680,7 +10217,7 @@ const BLACKLIST_EVENTS = [
9680
10217
  ];
9681
10218
 
9682
10219
  const HEARTBEAT_ENGINE_VERSION = '20.09';
9683
- const logger$4 = IssueReporter$1.loggerFor('wazo-ws');
10220
+ const logger$5 = IssueReporter$1.loggerFor('wazo-ws');
9684
10221
  const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
9685
10222
 
9686
10223
  class WebSocketClient extends Emitter {
@@ -9729,19 +10266,19 @@ class WebSocketClient extends Emitter {
9729
10266
  }
9730
10267
 
9731
10268
  connect() {
9732
- logger$4.info('connect method started', { host: this.host, token: this.token });
10269
+ logger$5.info('connect method started', { host: this.host, token: this.token });
9733
10270
  this.socket = new ReconnectingWebSocket__default['default'](this._getUrl.bind(this), [], this.options);
9734
10271
  if (this.options.binaryType) {
9735
10272
  this.socket.binaryType = this.options.binaryType;
9736
10273
  }
9737
10274
 
9738
10275
  this.socket.onopen = () => {
9739
- logger$4.info('on Wazo WS open', { method: 'connect', host: this.host });
10276
+ logger$5.info('on Wazo WS open', { method: 'connect', host: this.host });
9740
10277
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_OPEN);
9741
10278
  };
9742
10279
 
9743
10280
  this.socket.onerror = event => {
9744
- logger$4.error('on Wazo WS error', event.target);
10281
+ logger$5.error('on Wazo WS error', event.target);
9745
10282
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_ERROR, event);
9746
10283
  };
9747
10284
 
@@ -9771,7 +10308,7 @@ class WebSocketClient extends Emitter {
9771
10308
 
9772
10309
  this.socket.onclose = event => {
9773
10310
  // Can't be converted to JSON (circular structure)
9774
- logger$4.info('on Wazo WS close', {
10311
+ logger$5.info('on Wazo WS close', {
9775
10312
  reason: event.reason,
9776
10313
  code: event.code,
9777
10314
  readyState: event.target.readyState,
@@ -9789,12 +10326,12 @@ class WebSocketClient extends Emitter {
9789
10326
  };
9790
10327
 
9791
10328
  this.socket.onerror = event => {
9792
- logger$4.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
10329
+ logger$5.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
9793
10330
  };
9794
10331
  }
9795
10332
 
9796
10333
  close(force = false) {
9797
- logger$4.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
10334
+ logger$5.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
9798
10335
 
9799
10336
  if (!this.socket) {
9800
10337
  return;
@@ -9812,7 +10349,7 @@ class WebSocketClient extends Emitter {
9812
10349
 
9813
10350
  updateToken(token ) {
9814
10351
  this.token = token;
9815
- logger$4.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
10352
+ logger$5.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
9816
10353
 
9817
10354
  if (this.socket) {
9818
10355
  // If still connected, send the token to the WS
@@ -9830,7 +10367,7 @@ class WebSocketClient extends Emitter {
9830
10367
  }
9831
10368
 
9832
10369
  startHeartbeat() {
9833
- logger$4.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
10370
+ logger$5.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
9834
10371
 
9835
10372
  if (!this.socket) {
9836
10373
  this.heartbeat.stop();
@@ -9844,7 +10381,7 @@ class WebSocketClient extends Emitter {
9844
10381
  }
9845
10382
 
9846
10383
  stopHeartbeat() {
9847
- logger$4.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
10384
+ logger$5.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
9848
10385
 
9849
10386
  this.heartbeat.stop();
9850
10387
  }
@@ -9874,7 +10411,7 @@ class WebSocketClient extends Emitter {
9874
10411
  }
9875
10412
 
9876
10413
  reconnect(reason ) {
9877
- logger$4.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
10414
+ logger$5.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
9878
10415
  if (!this.socket) {
9879
10416
  return;
9880
10417
  }
@@ -9930,7 +10467,7 @@ class WebSocketClient extends Emitter {
9930
10467
  this.close();
9931
10468
  }
9932
10469
  const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
9933
- logger$4.log('Wazo WS url computed to reconnect', { url });
10470
+ logger$5.log('Wazo WS url computed to reconnect', { url });
9934
10471
 
9935
10472
  return url;
9936
10473
  }
@@ -9938,12 +10475,12 @@ class WebSocketClient extends Emitter {
9938
10475
  _onHeartbeat(message ) {
9939
10476
  if (message.payload === 'pong') {
9940
10477
  this.heartbeat.onHeartbeat();
9941
- logger$4.log('on heartbeat received from Wazo WS');
10478
+ logger$5.log('on heartbeat received from Wazo WS');
9942
10479
  }
9943
10480
  }
9944
10481
 
9945
10482
  async _onHeartbeatTimeout() {
9946
- logger$4.log('heartbeat timed out', { host: this.host, token: this.token });
10483
+ logger$5.log('heartbeat timed out', { host: this.host, token: this.token });
9947
10484
 
9948
10485
  this.close();
9949
10486
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_CLOSE, new Error('Websocket ping failure.'));
@@ -9985,6 +10522,8 @@ WebSocketClient.eventLists = [
9985
10522
  CHATD_USER_ROOM_CREATED,
9986
10523
  CONFERENCE_USER_PARTICIPANT_JOINED,
9987
10524
  CONFERENCE_USER_PARTICIPANT_LEFT,
10525
+ MEETING_USER_PARTICIPANT_JOINED,
10526
+ MEETING_USER_PARTICIPANT_LEFT,
9988
10527
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9989
10528
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
9990
10529
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -10055,6 +10594,8 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10055
10594
  CONFERENCE_USER_PARTICIPANT_LEFT: CONFERENCE_USER_PARTICIPANT_LEFT,
10056
10595
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED: CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
10057
10596
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED: CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
10597
+ MEETING_USER_PARTICIPANT_JOINED: MEETING_USER_PARTICIPANT_JOINED,
10598
+ MEETING_USER_PARTICIPANT_LEFT: MEETING_USER_PARTICIPANT_LEFT,
10058
10599
  SWITCHBOARD_QUEUED_CALLS_UPDATED: SWITCHBOARD_QUEUED_CALLS_UPDATED,
10059
10600
  SWITCHBOARD_QUEUED_CALL_ANSWERED: SWITCHBOARD_QUEUED_CALL_ANSWERED,
10060
10601
  SWITCHBOARD_HELD_CALLS_UPDATED: SWITCHBOARD_HELD_CALLS_UPDATED,
@@ -10096,7 +10637,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10096
10637
  const { SOCKET_EVENTS, ...OTHER_EVENTS } = WebSocketClient$1;
10097
10638
  const ALL_EVENTS = [...Object.values(SOCKET_EVENTS), ...Object.values(OTHER_EVENTS)];
10098
10639
 
10099
- const logger$3 = IssueReporter$1.loggerFor('simple-ws-client');
10640
+ const logger$4 = IssueReporter$1.loggerFor('simple-ws-client');
10100
10641
 
10101
10642
  class Websocket extends Emitter {
10102
10643
 
@@ -10120,7 +10661,7 @@ class Websocket extends Emitter {
10120
10661
  }
10121
10662
 
10122
10663
  open(host , session ) {
10123
- logger$3.info('open simple WebSocket', { host, token: session.token });
10664
+ logger$4.info('open simple WebSocket', { host, token: session.token });
10124
10665
  this.ws = new WebSocketClient(
10125
10666
  {
10126
10667
  host,
@@ -10148,7 +10689,7 @@ class Websocket extends Emitter {
10148
10689
  }
10149
10690
 
10150
10691
  updateToken(token ) {
10151
- logger$3.info('update token via simple Websocket', { token, ws: !!this.ws });
10692
+ logger$4.info('update token via simple Websocket', { token, ws: !!this.ws });
10152
10693
 
10153
10694
  if (!this.ws) {
10154
10695
  return;
@@ -10176,6 +10717,145 @@ var Websocket$1 = global.wazoWebsocketInstance;
10176
10717
 
10177
10718
  //
10178
10719
 
10720
+ const logger$3 = IssueReporter$1.loggerFor('sdk-sip-room');
10721
+
10722
+ class SipRoom extends Room {
10723
+
10724
+ static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
10725
+ logger$3.info('connecting to sip room', { extension, audioOnly, room: !!room });
10726
+
10727
+ if (!room) {
10728
+ await Wazo.Phone.connect();
10729
+
10730
+ const withCamera = constraints && !!constraints.video;
10731
+
10732
+ const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
10733
+ // eslint-disable-next-line no-param-reassign
10734
+ room = new SipRoom(callSession, extension, null, null, extra);
10735
+ }
10736
+
10737
+ if (room && room.callSession && room.callSession.call) {
10738
+ room.setCallId(room.callSession.call.id);
10739
+ }
10740
+
10741
+ logger$3.info('connected to room', {
10742
+ extension: room.extension,
10743
+ });
10744
+
10745
+ return room;
10746
+ }
10747
+
10748
+ mute() {
10749
+ logger$3.info('mute sip room');
10750
+
10751
+ Wazo.Phone.mute(this.callSession, false);
10752
+
10753
+ this.sendMuteStatus();
10754
+ }
10755
+
10756
+ unmute() {
10757
+ logger$3.info('unmute sip room');
10758
+
10759
+ Wazo.Phone.unmute(this.callSession, false);
10760
+
10761
+ this.sendUnMuteStatus();
10762
+ }
10763
+
10764
+ getLocalGuestName() {
10765
+ return Wazo.Phone.phone.client.userAgent.options.displayName;
10766
+ }
10767
+
10768
+ // Overridden to not listen to websocket messages
10769
+ _transferEvents() {
10770
+ // Phone events
10771
+ Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
10772
+ Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
10773
+ Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
10774
+ Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
10775
+
10776
+ [this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
10777
+ Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
10778
+ }
10779
+
10780
+ _onMessage(message ) {
10781
+ // eslint-disable-next-line no-underscore-dangle
10782
+ const body = super._onMessage(message);
10783
+ if (!body) {
10784
+ return;
10785
+ }
10786
+
10787
+ const getChannel = () => body.channels[0];
10788
+
10789
+ switch (body.type) {
10790
+ case 'ConfbridgeWelcome':
10791
+ body.channels.forEach(channel => {
10792
+ this._onParticipantJoined(channel);
10793
+ });
10794
+
10795
+ break;
10796
+ case 'ConfbridgeJoin': {
10797
+ const channel = getChannel();
10798
+ this._onParticipantJoined(channel);
10799
+ break;
10800
+ }
10801
+ case 'ConfbridgeLeave': {
10802
+ const channel = getChannel();
10803
+ this._onParticipantLeft({
10804
+ data: {
10805
+ call_id: channel.id,
10806
+ },
10807
+ });
10808
+ break;
10809
+ }
10810
+ }
10811
+ }
10812
+
10813
+ async _onParticipantJoined(channel ) {
10814
+ const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
10815
+ const callId = channel.id;
10816
+ const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
10817
+ const name = channel.caller ? channel.caller.name : null;
10818
+ const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
10819
+ const participant = new ParticipantClass(this, {
10820
+ caller_id_name: name,
10821
+ call_id: callId,
10822
+ }, extra);
10823
+
10824
+ const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
10825
+ if (participantIdx !== -1 && name) {
10826
+ this.participants[participantIdx].name = name;
10827
+ return;
10828
+ }
10829
+
10830
+ if (isLocal) {
10831
+ // Should be updated by the Wazo WS but we don't have it for now
10832
+ if (this.callSession) {
10833
+ this.callSession.ringing = false;
10834
+ }
10835
+
10836
+ this._onLocalParticipantJoined(participant);
10837
+
10838
+ // Give some time for the stream to be updated
10839
+ setTimeout(() => {
10840
+ this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
10841
+ }, 1000);
10842
+ }
10843
+
10844
+ this.participants.push(participant);
10845
+
10846
+ this._isParticipantJoining(participant);
10847
+
10848
+ return participant;
10849
+ }
10850
+
10851
+ _getCurrentSipCallIs() {
10852
+ return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
10853
+ }
10854
+
10855
+ }
10856
+
10857
+ //
10858
+
10179
10859
  const logger$2 = IssueReporter$1.loggerFor('room');
10180
10860
 
10181
10861
  class Participant extends Emitter {
@@ -10210,6 +10890,7 @@ class Participant extends Emitter {
10210
10890
 
10211
10891
 
10212
10892
  /**
10893
+ * @param room Room The room where the participant is
10213
10894
  * @param rawParticipant string Participant sent via the Wazo WS
10214
10895
  * @param extra Object extra status of the participant
10215
10896
  */
@@ -10437,6 +11118,11 @@ class Participant extends Emitter {
10437
11118
  // Poor man's object comparison
10438
11119
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
10439
11120
  this.extra = { ...this.extra, ...status.extra };
11121
+
11122
+ if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
11123
+ this.extra.contact = new Contact(this.extra.contact);
11124
+ }
11125
+
10440
11126
  this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
10441
11127
  }
10442
11128
  }
@@ -10519,9 +11205,7 @@ class Stream {
10519
11205
  return false;
10520
11206
  }
10521
11207
 
10522
- // With canvas track (used to fake upgrade in conference), we don't have a width
10523
- return this.htmlStream.getTracks().find(track => track.kind === 'video'
10524
- && track.readyState !== 'ended' && 'width' in track.getSettings());
11208
+ return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
10525
11209
  }
10526
11210
 
10527
11211
  get id() {
@@ -11422,6 +12106,7 @@ const Wazo = {
11422
12106
  Phone: Phone$1,
11423
12107
  Websocket: Websocket$1,
11424
12108
  Room,
12109
+ SipRoom,
11425
12110
  RemoteParticipant,
11426
12111
  LocalParticipant,
11427
12112
  Stream,
@@ -11441,6 +12126,7 @@ const Wazo = {
11441
12126
  ServerError,
11442
12127
  Call,
11443
12128
  CallLog,
12129
+ CTIPhone,
11444
12130
  Recording,
11445
12131
  ChatMessage,
11446
12132
  ChatRoom,
@@ -11456,6 +12142,8 @@ const Wazo = {
11456
12142
  CallSession,
11457
12143
  IndirectTransfer,
11458
12144
  SwitchboardCall,
12145
+ WebRTCPhone,
12146
+ Meeting,
11459
12147
  },
11460
12148
 
11461
12149
  // Api
@@ -11484,7 +12172,7 @@ if (global) {
11484
12172
  global.Wazo = Wazo;
11485
12173
  }
11486
12174
 
11487
- /* global document */
12175
+ //
11488
12176
 
11489
12177
  const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
11490
12178
  const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
@@ -11496,6 +12184,7 @@ class Room extends Emitter {
11496
12184
 
11497
12185
 
11498
12186
 
12187
+
11499
12188
 
11500
12189
 
11501
12190
 
@@ -11517,6 +12206,8 @@ class Room extends Emitter {
11517
12206
 
11518
12207
 
11519
12208
 
12209
+
12210
+
11520
12211
 
11521
12212
 
11522
12213
 
@@ -11534,6 +12225,7 @@ class Room extends Emitter {
11534
12225
  * @param extension string
11535
12226
  * @param sourceId number
11536
12227
  * @param callId string
12228
+ * @param meetingUuid string
11537
12229
  * @param extra Object
11538
12230
  */
11539
12231
  constructor(
@@ -11541,15 +12233,17 @@ class Room extends Emitter {
11541
12233
  extension ,
11542
12234
  sourceId ,
11543
12235
  callId ,
12236
+ meetingUuid ,
11544
12237
  extra = {},
11545
12238
  ) {
11546
12239
  super();
11547
- logger.info('room initialized', { callId, extension, sourceId });
12240
+ logger.info('room initialized', { callId, extension, sourceId, meetingUuid });
11548
12241
 
11549
12242
  // Represents the room callSession
11550
12243
  this.callSession = callSession;
11551
12244
  this.extension = extension;
11552
12245
  this.sourceId = sourceId;
12246
+ this.meetingUuid = meetingUuid;
11553
12247
  this.callId = callId;
11554
12248
  this.participants = [];
11555
12249
  this.connected = false;
@@ -11569,6 +12263,8 @@ class Room extends Emitter {
11569
12263
  // Sugar syntax for `room.EVENT_NAME`
11570
12264
  this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
11571
12265
  this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
12266
+ this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
12267
+ this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
11572
12268
  this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
11573
12269
  this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
11574
12270
  this.ON_CHAT = Wazo.Phone.ON_CHAT;
@@ -11603,9 +12299,10 @@ class Room extends Emitter {
11603
12299
  * @param audioOnly boolean
11604
12300
  * @param extra Object
11605
12301
  * @param room ?Room
12302
+ * @param meeting ?Meeting
11606
12303
  * @returns {Promise<Room>}
11607
12304
  */
11608
- static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
12305
+ static async connect({ extension, constraints, audioOnly = false, extra, room, meeting } ) {
11609
12306
  logger.info('connecting to room', { extension, audioOnly, room: !!room });
11610
12307
 
11611
12308
  if (!room) {
@@ -11640,21 +12337,31 @@ class Room extends Emitter {
11640
12337
  room.setCallId(room.callSession.call.id);
11641
12338
  }
11642
12339
 
11643
- // Fetch conference source
11644
- const sources = await getApiClient().dird.fetchConferenceSource('default');
11645
- // Retrieve conference sources
11646
- const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
11647
- // Retrieve conference
11648
- const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
12340
+ if (!meeting) {
12341
+ // Fetch conference source
12342
+ const sources = await getApiClient().dird.fetchConferenceSource('default');
12343
+ // Retrieve conference sources
12344
+ const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
12345
+ // Retrieve conference
12346
+ const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
11649
12347
 
11650
- logger.info('connected to room', {
11651
- sourceId: conference ? conference.sourceId : null,
11652
- name: conference ? conference.name : null,
11653
- });
12348
+ logger.info('connected to room', {
12349
+ sourceId: conference ? conference.sourceId : null,
12350
+ name: conference ? conference.name : null,
12351
+ });
11654
12352
 
11655
- if (conference) {
11656
- room.setSourceId(conference.sourceId);
11657
- room.setName(conference.name);
12353
+ if (conference) {
12354
+ room.setSourceId(conference.sourceId);
12355
+ room.setName(conference.name);
12356
+ }
12357
+ } else if (meeting) {
12358
+ logger.info('Already connected to meeting', {
12359
+ uuid: meeting.uuid,
12360
+ name: meeting.name,
12361
+ });
12362
+
12363
+ room.setMeetingUuid(meeting.uuid);
12364
+ room.setName(meeting.name);
11658
12365
  }
11659
12366
 
11660
12367
  return room;
@@ -11682,10 +12389,8 @@ class Room extends Emitter {
11682
12389
  Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
11683
12390
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11684
12391
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11685
-
11686
- if (this.roomAudioElement && document.body) {
11687
- document.body.removeChild(this.roomAudioElement);
11688
- }
12392
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
12393
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11689
12394
  }
11690
12395
 
11691
12396
  setSourceId(sourceId ) {
@@ -11694,6 +12399,12 @@ class Room extends Emitter {
11694
12399
  this.sourceId = sourceId;
11695
12400
  }
11696
12401
 
12402
+ setMeetingUuid(meetingUuid ) {
12403
+ logger.info('set meeting uuid', { meetingUuid });
12404
+
12405
+ this.meetingUuid = meetingUuid;
12406
+ }
12407
+
11697
12408
  setCallId(callId ) {
11698
12409
  logger.info('set room call id', { callId });
11699
12410
 
@@ -11735,14 +12446,22 @@ class Room extends Emitter {
11735
12446
  return screensharingStream;
11736
12447
  }
11737
12448
 
11738
- stopScreenSharing(restoreLocalStream = true) {
12449
+ async stopScreenSharing(restoreLocalStream = true) {
11739
12450
  logger.info('stop room screen sharing');
11740
12451
 
11741
- Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
12452
+ const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
11742
12453
 
11743
12454
  if (this.localParticipant) {
11744
12455
  this.localParticipant.onStopScreensharing();
11745
12456
  }
12457
+
12458
+ if (!reinvited && this.localParticipant) {
12459
+ // When we had video and we made a screenshare we don't reinvite when stopping the screensahre
12460
+ // So not REINVITE even is fired, we have to restore the video stream manually
12461
+ const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
12462
+ // $FlowFixMe
12463
+ this._associateStreamTo(localVideoStream, this.localParticipant);
12464
+ }
11746
12465
  }
11747
12466
 
11748
12467
  turnCameraOff() {
@@ -11845,6 +12564,22 @@ class Room extends Emitter {
11845
12564
  return response;
11846
12565
  }
11847
12566
 
12567
+ hasALocalVideoTrack() {
12568
+ return Wazo.Phone.hasALocalVideoTrack(this.callSession);
12569
+ }
12570
+
12571
+ getLocalStream() {
12572
+ return Wazo.Phone.getLocalStream(this.callSession);
12573
+ }
12574
+
12575
+ getRemoteStream() {
12576
+ return Wazo.Phone.getRemoteStream(this.callSession);
12577
+ }
12578
+
12579
+ getRemoteVideoStream() {
12580
+ return Wazo.Phone.getRemoteVideoStream(this.callSession);
12581
+ }
12582
+
11848
12583
  _bindEvents() {
11849
12584
  if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
11850
12585
  return;
@@ -11866,27 +12601,10 @@ class Room extends Emitter {
11866
12601
  logger.info('on room audio stream');
11867
12602
 
11868
12603
  this.audioStream = stream;
11869
- if (document.createElement) {
11870
- // $FlowFixMe
11871
- let roomAudioElement = document.getElementById('audio-room');
11872
- if (!this.roomAudioElement) {
11873
- roomAudioElement = document.createElement('audio');
11874
- // $FlowFixMe
11875
- document.body.appendChild(roomAudioElement);
11876
- }
11877
- if (!roomAudioElement) {
11878
- return;
11879
- }
11880
- this.roomAudioElement = roomAudioElement;
12604
+ if (!this.roomAudioElement) {
12605
+ const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
12606
+ this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
11881
12607
  this.roomAudioElement.srcObject = stream;
11882
- this.roomAudioElement.autoplay = true;
11883
- this.roomAudioElement.id = 'audio-room';
11884
-
11885
- // $FlowFixMe
11886
- if (this.roomAudioElement.setSinkId) {
11887
- // $FlowFixMe
11888
- this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
11889
- }
11890
12608
  }
11891
12609
  });
11892
12610
 
@@ -11961,6 +12679,9 @@ class Room extends Emitter {
11961
12679
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11962
12680
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11963
12681
 
12682
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
12683
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
12684
+
11964
12685
  // Phone events
11965
12686
  Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
11966
12687
  Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
@@ -11971,15 +12692,15 @@ class Room extends Emitter {
11971
12692
  Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
11972
12693
  }
11973
12694
 
11974
- _onMessage(message ) {
12695
+ _onMessage(message ) {
11975
12696
  if (message.method !== 'MESSAGE') {
11976
- return;
12697
+ return null;
11977
12698
  }
11978
12699
  let body;
11979
12700
  try {
11980
12701
  body = JSON.parse(message.body);
11981
12702
  } catch (e) {
11982
- return;
12703
+ return null;
11983
12704
  }
11984
12705
 
11985
12706
  switch (body.type) {
@@ -11998,6 +12719,8 @@ class Room extends Emitter {
11998
12719
  }
11999
12720
 
12000
12721
  this.eventEmitter.emit(this.ON_MESSAGE, body);
12722
+
12723
+ return body;
12001
12724
  }
12002
12725
 
12003
12726
  _onChat(content ) {
@@ -12062,23 +12785,24 @@ class Room extends Emitter {
12062
12785
  const session = Wazo.Auth.getSession();
12063
12786
  let participants = [];
12064
12787
 
12065
- // @TODO: we could use a better function name here
12066
- const isJoining = part => {
12067
- this.__associateStreams(part);
12068
- // @VALIDATE: no need to publicize ourselves, no?
12069
- if (part instanceof RemoteParticipant) {
12070
- this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
12071
- }
12072
- };
12073
-
12074
12788
  // When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
12075
12789
  if (participant.user_uuid === session.uuid) {
12076
12790
  logger.info('room current user joined');
12077
12791
 
12078
12792
  // Retrieve participants via an API calls
12079
12793
  const conferenceId = this.sourceId || payload.data.conference_id;
12080
- const response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
12081
- logger.info('fetching conference participants', { conferenceId });
12794
+ let response;
12795
+ try {
12796
+ if (this.meetingUuid) {
12797
+ logger.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
12798
+ response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
12799
+ } else {
12800
+ logger.info('fetching conference participants', { conferenceId });
12801
+ response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
12802
+ }
12803
+ } catch (e) {
12804
+ logger.error('room participants fetching, error', e);
12805
+ }
12082
12806
  if (response) {
12083
12807
  logger.info('conference participants fetched', { nb: response.items.length });
12084
12808
  participants = response.items.map(item => {
@@ -12093,25 +12817,10 @@ class Room extends Emitter {
12093
12817
 
12094
12818
  const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
12095
12819
  if (!this.localParticipant && localParticipant) {
12096
- this.localParticipant = localParticipant;
12097
-
12098
- const localVideoStream = this._getLocalVideoStream();
12099
- if (localVideoStream) {
12100
- this._saveLocalVideoStream(localVideoStream);
12101
- }
12102
-
12103
- this.connected = true;
12104
-
12105
- // we're in the room, now let's request everyone's status
12106
- if (this.localParticipant) {
12107
- this.sendSignal({
12108
- type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
12109
- origin: this.localParticipant.getStatus(),
12110
- });
12111
- }
12820
+ this._onLocalParticipantJoined(localParticipant);
12112
12821
  }
12113
12822
 
12114
- participants.forEach(someParticipant => isJoining(someParticipant));
12823
+ participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
12115
12824
  this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
12116
12825
  }
12117
12826
 
@@ -12126,12 +12835,41 @@ class Room extends Emitter {
12126
12835
 
12127
12836
  if (remoteParticipant) {
12128
12837
  this.participants.push(remoteParticipant);
12129
- isJoining(remoteParticipant);
12838
+ this._isParticipantJoining(remoteParticipant);
12130
12839
  }
12131
12840
 
12132
12841
  return remoteParticipant;
12133
12842
  }
12134
12843
 
12844
+ _onLocalParticipantJoined(localParticipant ) {
12845
+ this.localParticipant = localParticipant;
12846
+
12847
+ const localVideoStream = this._getLocalVideoStream();
12848
+ if (localVideoStream) {
12849
+ this._saveLocalVideoStream(localVideoStream);
12850
+ }
12851
+
12852
+ this.connected = true;
12853
+
12854
+ localParticipant.broadcastStatus();
12855
+
12856
+ // we're in the room, now let's request everyone's status
12857
+ if (this.localParticipant) {
12858
+ this.sendSignal({
12859
+ type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
12860
+ origin: this.localParticipant.getStatus(),
12861
+ });
12862
+ }
12863
+ }
12864
+
12865
+ _isParticipantJoining(participant ) {
12866
+ this.__associateStreams(participant);
12867
+ // @VALIDATE: no need to publicize ourselves, no?
12868
+ if (participant instanceof RemoteParticipant) {
12869
+ this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
12870
+ }
12871
+ }
12872
+
12135
12873
  _saveLocalVideoStream(stream ) {
12136
12874
  const { localParticipant } = this;
12137
12875
 
@@ -12177,9 +12915,11 @@ class Room extends Emitter {
12177
12915
  _onParticipantTrackUpdate(oldParticipant , update ) {
12178
12916
  const newParticipant = oldParticipant;
12179
12917
 
12180
- const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
12918
+ const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
12181
12919
  const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
12182
- const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
12920
+ // Can't use `getReceivers` here because on FF we make the mapping based on the streamId
12921
+ const stream = pc.getRemoteStreams().find(someStream =>
12922
+ someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
12183
12923
 
12184
12924
  if (update === 'downgrade') {
12185
12925
  newParticipant.streams = [];
@@ -12209,15 +12949,41 @@ class Room extends Emitter {
12209
12949
  return;
12210
12950
  }
12211
12951
 
12212
- if (this._unassociatedVideoStreams[trackId]) {
12952
+ const streamId = this._getStreamIdFrTrackId(trackId);
12953
+ const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
12954
+ const stream = this._unassociatedVideoStreams[key];
12955
+
12956
+ if (stream) {
12213
12957
  // Try to associate stream
12214
- this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
12958
+ this._associateStreamTo(stream, participant);
12215
12959
 
12216
- delete this._unassociatedVideoStreams[trackId];
12960
+ delete this._unassociatedVideoStreams[key];
12217
12961
  delete this._unassociatedParticipants[participant.callId];
12218
12962
  }
12219
12963
  }
12220
12964
 
12965
+ _getUnassociatedMapIdFromTrackIdOrStreamId(trackId , streamId ) {
12966
+ // Find by trackId
12967
+ if (trackId in this._unassociatedVideoStreams) {
12968
+ return trackId;
12969
+ }
12970
+
12971
+ // Find by streamId
12972
+ if (streamId && streamId in this._unassociatedVideoStreams) {
12973
+ return streamId;
12974
+ }
12975
+
12976
+ // Find in all the streams by streamId (used on FF where we can't map by trackId)
12977
+ const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream ) => stream.id === streamId);
12978
+ return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
12979
+ }
12980
+
12981
+ _getStreamIdFrTrackId(trackId ) {
12982
+ const mapping = Object.values(this._callIdStreamIdMap).find((map ) => map.trackId === trackId);
12983
+
12984
+ return mapping ? mapping.streamId : null;
12985
+ }
12986
+
12221
12987
  _associateStreamTo(rawStream , participant ) {
12222
12988
  const stream = new Wazo.Stream(rawStream, participant);
12223
12989
  participant.streams.push(stream);