@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
@@ -128,7 +128,7 @@ const isMobile = () => typeof navigator !== 'undefined' && navigator.product ===
128
128
 
129
129
  const methods = ['head', 'get', 'post', 'put', 'delete'];
130
130
 
131
- const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
131
+ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
132
132
 
133
133
  // Use a function here to be able to mock it in tests
134
134
  const realFetch = () => {
@@ -267,7 +267,7 @@ class ApiRequester {
267
267
  };
268
268
 
269
269
  if (this.refreshTokenPromise) {
270
- logger$a.info('A token is already refreshing, waiting ...', { url });
270
+ logger$c.info('A token is already refreshing, waiting ...', { url });
271
271
  await this.refreshTokenPromise;
272
272
  }
273
273
 
@@ -287,7 +287,7 @@ class ApiRequester {
287
287
  return promise.then(async (err ) => {
288
288
  // Check if the token is still valid
289
289
  if (firstCall && this._checkTokenExpired(response, err)) {
290
- logger$a.warn('token expired', { error: err.reason });
290
+ logger$c.warn('token expired', { error: err.reason });
291
291
  // Replay the call after refreshing the token
292
292
  return this._replayWithNewToken(err, path, method, body, headers, parse);
293
293
  }
@@ -297,7 +297,7 @@ class ApiRequester {
297
297
  : exceptionClass.fromResponse(err, response.status);
298
298
 
299
299
  if (this.shouldLogErrors) {
300
- logger$a.error('API error', error);
300
+ logger$c.error('API error', error);
301
301
  }
302
302
 
303
303
  throw error;
@@ -307,7 +307,7 @@ class ApiRequester {
307
307
  return newParse(response, isJson);
308
308
  }).catch(error => {
309
309
  if (this.shouldLogErrors) {
310
- logger$a.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
310
+ logger$c.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
311
311
  }
312
312
 
313
313
  throw error;
@@ -335,13 +335,13 @@ class ApiRequester {
335
335
  ) {
336
336
  const isTokenNotFound = this._isTokenNotFound(err);
337
337
  let newPath = path;
338
- logger$a.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
338
+ logger$c.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
339
339
 
340
340
  this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
341
341
 
342
342
  return this.refreshTokenPromise.then(() => {
343
343
  this.refreshTokenPromise = null;
344
- logger$a.info('token refreshed', { isTokenNotFound });
344
+ logger$c.info('token refreshed', { isTokenNotFound });
345
345
  if (isTokenNotFound) {
346
346
  const pathParts = path.split('/');
347
347
  pathParts.pop();
@@ -619,7 +619,13 @@ class IssueReporter {
619
619
  }
620
620
 
621
621
  _isLevelAbove(level1 , level2 ) {
622
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
622
+ const index1 = LOG_LEVELS.indexOf(level1);
623
+ const index2 = LOG_LEVELS.indexOf(level2);
624
+ if (index1 === -1 || index2 === -1) {
625
+ return false;
626
+ }
627
+
628
+ return index1 > index2;
623
629
  }
624
630
 
625
631
  _makeCategory(category ) {
@@ -2532,6 +2538,65 @@ class ExternalApp {
2532
2538
  }
2533
2539
  }
2534
2540
 
2541
+ //
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+
2549
+
2550
+
2551
+
2552
+
2553
+ class Meeting {
2554
+
2555
+
2556
+
2557
+
2558
+
2559
+
2560
+
2561
+
2562
+
2563
+
2564
+ static parse(plain ) {
2565
+ return new Meeting({
2566
+ guestSipAuthorization: plain.guest_sip_authorization,
2567
+ hostname: plain.hostname,
2568
+ name: plain.name,
2569
+ ownerUuids: plain.owner_uuids,
2570
+ port: plain.port,
2571
+ uuid: plain.uuid,
2572
+ number: plain.number,
2573
+ });
2574
+ }
2575
+
2576
+ static newFrom(meeting ) {
2577
+ return newFrom(meeting, Meeting);
2578
+ }
2579
+
2580
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2581
+ this.guestSipAuthorization = guestSipAuthorization;
2582
+ this.hostname = hostname;
2583
+ this.name = name;
2584
+ this.ownerUuids = ownerUuids;
2585
+ this.port = port;
2586
+ this.uuid = uuid;
2587
+ this.number = number;
2588
+
2589
+ // Useful to compare instead of instanceof with minified code
2590
+ this.type = 'Meeting';
2591
+ }
2592
+
2593
+ getGuestSipCredentials() {
2594
+ // eslint-disable-next-line no-undef
2595
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2596
+ return { username, secret };
2597
+ }
2598
+ }
2599
+
2535
2600
  /* */
2536
2601
 
2537
2602
  var confdMethods = (client , baseUrl ) => ({
@@ -2596,6 +2661,18 @@ var confdMethods = (client , baseUrl ) => ({
2596
2661
  return null;
2597
2662
  }
2598
2663
  },
2664
+
2665
+ createMyMeeting: (name ) =>
2666
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2667
+
2668
+ deleteMyMeeting: (meetingUuid ) =>
2669
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2670
+
2671
+ getMeeting: (meetingUuid ) =>
2672
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2673
+
2674
+ guestGetMeeting: (meetingUuid ) =>
2675
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2599
2676
  });
2600
2677
 
2601
2678
  //
@@ -3353,7 +3430,7 @@ class CallSession {
3353
3430
  return newFrom(callSession, CallSession);
3354
3431
  }
3355
3432
 
3356
- static parseCall(session , call ) {
3433
+ static parseCall(call ) {
3357
3434
  return new CallSession({
3358
3435
  callId: call.id,
3359
3436
  sipCallId: call.sipCallId,
@@ -3512,7 +3589,11 @@ class CallLog {
3512
3589
  answered: plain.answered,
3513
3590
  callDirection: plain.call_direction,
3514
3591
  destination: {
3515
- extension: plain.requested_extension || plain.destination_extension,
3592
+ // @TEMP: Temporarily assuming empty numbers are meetings
3593
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3594
+ extension: plain.requested_extension
3595
+ || plain.destination_extension
3596
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3516
3597
  name: plain.requested_name || plain.destination_name || '',
3517
3598
  },
3518
3599
  source: {
@@ -3528,27 +3609,11 @@ class CallLog {
3528
3609
  }
3529
3610
 
3530
3611
  static parseNew(plain , session ) {
3531
- return new CallLog({
3532
- answer: plain.answer ? moment(plain.answer).toDate() : null,
3533
- answered: plain.answered,
3534
- callDirection: plain.call_direction,
3535
- destination: {
3536
- extension: plain.requested_extension || plain.destination_extension,
3537
- name: plain.requested_name || plain.destination_name || '',
3538
- },
3539
- source: {
3540
- extension: plain.source_extension,
3541
- name: plain.source_name,
3542
- },
3543
- id: plain.id,
3544
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3545
- start: moment(plain.start).toDate(),
3546
- end: plain.end ? moment(plain.end).toDate() : null,
3547
- recordings: Recording.parseMany(plain.recordings),
3548
- // @TODO: FIXME add verification declined vs missed call
3549
- newMissedCall: session
3550
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3551
- });
3612
+ const callLog = CallLog.parse(plain);
3613
+ // @TODO: FIXME add verification declined vs missed call
3614
+ callLog.newMissedCall = session
3615
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3616
+ return callLog;
3552
3617
  }
3553
3618
 
3554
3619
  static newFrom(profile ) {
@@ -3708,29 +3773,432 @@ class IndirectTransfer {
3708
3773
  });
3709
3774
  }
3710
3775
 
3711
- destinationIs(callSession ) {
3712
- return callSession.isId(this.destinationId);
3776
+ destinationIs(callSession ) {
3777
+ return callSession.isId(this.destinationId);
3778
+ }
3779
+
3780
+ sourceIs(callSession ) {
3781
+ return callSession.isId(this.sourceId);
3782
+ }
3783
+
3784
+ updateFrom(indirectTransfer ) {
3785
+ updateFrom(this, indirectTransfer);
3786
+ }
3787
+
3788
+ static newFrom(indirectTransfer ) {
3789
+ return newFrom(indirectTransfer, IndirectTransfer);
3790
+ }
3791
+ }
3792
+
3793
+ //
3794
+
3795
+ class CallApi {
3796
+ static async fetchCallLogs(offset , limit ) {
3797
+ return getApiClient().callLogd.listCallLogs(offset, limit);
3798
+ }
3799
+
3800
+ static async fetchDistinctCallLogs(offset , limit , distinct = 'peer_exten') {
3801
+ return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
3802
+ }
3803
+
3804
+ static async fetchActiveCalls() {
3805
+ return getApiClient().calld.listCalls();
3806
+ }
3807
+
3808
+ static async fetchCallLogsFromDate(from , number ) {
3809
+ return getApiClient().callLogd.listCallLogsFromDate(from, number);
3810
+ }
3811
+
3812
+ static async search(query , limit ) {
3813
+ return getApiClient().callLogd.search(query, limit);
3814
+ }
3815
+
3816
+ static async searchBy(field , value , limit ) {
3817
+ return getApiClient().callLogd.searchBy(field, value, limit);
3818
+ }
3819
+
3820
+ static async fetchSIP(session , line ) {
3821
+ const lineToUse = line || session.primaryLine();
3822
+ return getApiClient().confd.getUserLineSip(session.uuid, lineToUse ? lineToUse.id : null);
3823
+ }
3824
+
3825
+ static async cancelCall(callSession ) {
3826
+ return getApiClient().calld.cancelCall(callSession.callId);
3827
+ }
3828
+
3829
+ static async makeCall(callFromLine , extension , isMobile = false,
3830
+ callbackAllLines = false) {
3831
+ const lineId = callFromLine ? callFromLine.id : null;
3832
+
3833
+ const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
3834
+ return Call.parse(response);
3835
+ }
3836
+
3837
+ static async relocateCall(callId , line , contactIdentifier ) {
3838
+ return getApiClient().calld.relocateCall(callId, 'line', line, contactIdentifier);
3839
+ }
3840
+
3841
+ static async hold(callId ) {
3842
+ return getApiClient().calld.hold(callId);
3843
+ }
3844
+
3845
+ static async resume(callId ) {
3846
+ return getApiClient().calld.resume(callId);
3847
+ }
3848
+
3849
+ static async mute(callId ) {
3850
+ return getApiClient().calld.mute(callId);
3851
+ }
3852
+
3853
+ static async sendDTMF(callId , digits ) {
3854
+ return getApiClient().calld.sendDTMF(callId, digits);
3855
+ }
3856
+
3857
+ static async unmute(callId ) {
3858
+ return getApiClient().calld.unmute(callId);
3859
+ }
3860
+
3861
+ static async transferCall(callId , number , flow ) {
3862
+ return getApiClient().calld.transferCall(callId, number, flow);
3863
+ }
3864
+
3865
+ static async cancelCallTransfer(transferId ) {
3866
+ return getApiClient().calld.cancelCallTransfer(transferId);
3867
+ }
3868
+
3869
+ static async confirmCallTransfer(transferId ) {
3870
+ return getApiClient().calld.confirmCallTransfer(transferId);
3871
+ }
3872
+ }
3873
+
3874
+ //
3875
+
3876
+ const TRANSFER_FLOW_ATTENDED = 'attended';
3877
+ const TRANSFER_FLOW_BLIND = 'blind';
3878
+
3879
+ // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
3880
+
3881
+ const logger$b = IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
3882
+
3883
+ class CTIPhone extends Emitter {
3884
+
3885
+
3886
+
3887
+
3888
+
3889
+
3890
+
3891
+
3892
+ constructor(session , isMobile = false, callbackAllLines = false) {
3893
+ super();
3894
+ logger$b.info('CTI Phone created');
3895
+ this.session = session;
3896
+ this.isMobile = isMobile;
3897
+ this.callbackAllLines = callbackAllLines;
3898
+ }
3899
+
3900
+ getOptions() {
3901
+ // @FIXME: temporarily disabling this option
3902
+ // const hold = this.session.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD);
3903
+
3904
+ return {
3905
+ accept: false,
3906
+ decline: true,
3907
+ mute: true,
3908
+ hold: false,
3909
+ transfer: true,
3910
+ sendKey: true,
3911
+ addParticipant: false,
3912
+ record: true,
3913
+ merge: false,
3914
+ };
3915
+ }
3916
+
3917
+ hasAnActiveCall() {
3918
+ return !!this.currentCall;
3919
+ }
3920
+
3921
+ callCount() {
3922
+ return this.currentCall ? 1 : 0;
3923
+ }
3924
+
3925
+ isWebRTC() {
3926
+ return false;
3927
+ }
3928
+
3929
+ getUserAgent() {
3930
+ return 'cti-phone';
3931
+ }
3932
+
3933
+ startHeartbeat() {
3934
+ }
3935
+
3936
+ setOnHeartbeatTimeout() {
3937
+ }
3938
+
3939
+ setOnHeartbeatCallback() {
3940
+ }
3941
+
3942
+ stopHeartbeat() {
3943
+ }
3944
+
3945
+ bindClientEvents() {
3946
+ }
3947
+
3948
+ onConnect() {
3949
+ }
3950
+
3951
+ onDisconnect() {
3952
+ }
3953
+
3954
+ async makeCall(number , line ) {
3955
+ logger$b.info('make CTI call', { number });
3956
+
3957
+ if (!number) {
3958
+ return null;
3959
+ }
3960
+ try {
3961
+ this.currentCall = await CallApi.makeCall(line, number, this.isMobile, this.callbackAllLines);
3962
+ } catch (_) {
3963
+ // We have to deal with error like `User has no mobile phone number` error in the UI.
3964
+ }
3965
+ if (!this.currentCall) {
3966
+ return null;
3967
+ }
3968
+ const callSession = CallSession.parseCall(this.currentCall);
3969
+ this.eventEmitter.emit('onCallOutgoing', callSession);
3970
+
3971
+ return callSession;
3972
+ }
3973
+
3974
+ accept(callSession ) {
3975
+ if (!callSession) {
3976
+ return Promise.resolve(null);
3977
+ }
3978
+ logger$b.info('accept CTI call', { callId: callSession.getId(), number: callSession.number });
3979
+
3980
+ if (!this.currentCall) {
3981
+ this.currentCall = callSession.call;
3982
+ }
3983
+
3984
+ return Promise.resolve(callSession.getId());
3985
+ }
3986
+
3987
+ endCurrentCall(callSession ) {
3988
+ if (!callSession) {
3989
+ return;
3990
+ }
3991
+ logger$b.info('end current CTI call', { callId: callSession.getId(), number: callSession.number });
3992
+
3993
+ this.currentCall = undefined;
3994
+ this.eventEmitter.emit('onCallEnded', callSession);
3995
+ }
3996
+
3997
+ async hangup(callSession ) {
3998
+ if (!callSession) {
3999
+ return Promise.resolve(false);
4000
+ }
4001
+ logger$b.info('hangup CTI call', { callId: callSession.getId(), number: callSession.number });
4002
+
4003
+ try {
4004
+ await CallApi.cancelCall(callSession);
4005
+ if (this.currentCall && callSession.callId === this.currentCall.id) {
4006
+ this.endCurrentCall(callSession);
4007
+ }
4008
+
4009
+ this.eventEmitter.emit('onCallEnded', callSession);
4010
+ return true;
4011
+ } catch (e) {
4012
+ logger$b.error('hangup CTI call, error', e);
4013
+
4014
+ this.eventEmitter.emit('onCallFailed', callSession);
4015
+ return false;
4016
+ }
4017
+ }
4018
+
4019
+ ignore() {}
4020
+
4021
+ async reject(callSession ) {
4022
+ if (!callSession) {
4023
+ return;
4024
+ }
4025
+ logger$b.info('reject CTI call', { callId: callSession.getId(), number: callSession.number });
4026
+
4027
+ await CallApi.cancelCall(callSession);
4028
+ this.eventEmitter.emit('onCallEnded', callSession);
4029
+ }
4030
+
4031
+ async transfer(callSession , number ) {
4032
+ if (!callSession) {
4033
+ return;
4034
+ }
4035
+ logger$b.info('transfer CTI call', { callId: callSession.getId(), number: callSession.number, to: number });
4036
+
4037
+ await CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_BLIND);
4038
+ }
4039
+
4040
+ indirectTransfer() {}
4041
+
4042
+ async initiateCTIIndirectTransfer(callSession , number ) {
4043
+ if (!callSession) {
4044
+ return;
4045
+ }
4046
+ logger$b.info('indirect CTI transfer', { callId: callSession.getId(), number: callSession.number, to: number });
4047
+
4048
+ return CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_ATTENDED);
4049
+ }
4050
+
4051
+ async cancelCTIIndirectTransfer(transferId ) {
4052
+ logger$b.info('cancel CTI transfer', { transferId });
4053
+
4054
+ return CallApi.cancelCallTransfer(transferId);
4055
+ }
4056
+
4057
+ async confirmCTIIndirectTransfer(transferId ) {
4058
+ logger$b.info('confirm CTI transfer', { transferId });
4059
+
4060
+ return CallApi.confirmCallTransfer(transferId);
4061
+ }
4062
+
4063
+ sendKey(callSession , digits ) {
4064
+ if (!callSession) {
4065
+ return;
4066
+ }
4067
+ logger$b.info('send CTI key', { callId: callSession.getId(), number: callSession.number, digits });
4068
+
4069
+ return CallApi.sendDTMF(callSession.callId, digits);
4070
+ }
4071
+
4072
+ onConnectionMade() {
4073
+ logger$b.info('on CTI connection made');
4074
+
4075
+ this.eventEmitter.emit('onCallAccepted');
4076
+ }
4077
+
4078
+ async close() {
4079
+ logger$b.info('CTI close');
4080
+
4081
+ return Promise.resolve();
4082
+ }
4083
+
4084
+ async hold(callSession ) {
4085
+ if (!callSession) {
4086
+ return;
4087
+ }
4088
+ logger$b.info('CTI hold', { callId: callSession.getId(), number: callSession.number });
4089
+
4090
+ return CallApi.hold(callSession.callId);
4091
+ }
4092
+
4093
+ async resume(callSession ) {
4094
+ if (!callSession) {
4095
+ return;
4096
+ }
4097
+ logger$b.info('CTI resume', { callId: callSession.getId(), number: callSession.number });
4098
+
4099
+ return CallApi.resume(callSession.callId);
4100
+ }
4101
+
4102
+ async mute(callSession ) {
4103
+ if (!callSession) {
4104
+ return;
4105
+ }
4106
+ logger$b.info('CTI mute', { callId: callSession.getId(), number: callSession.number });
4107
+
4108
+ return CallApi.mute(callSession.callId);
4109
+ }
4110
+
4111
+ async unmute(callSession ) {
4112
+ if (!callSession) {
4113
+ return;
4114
+ }
4115
+ logger$b.info('CTI unmute', { callId: callSession.getId(), number: callSession.number });
4116
+
4117
+ return CallApi.unmute(callSession.callId);
4118
+ }
4119
+
4120
+ putOnSpeaker() {}
4121
+
4122
+ putOffSpeaker() {}
4123
+
4124
+ turnCameraOff() {}
4125
+
4126
+ turnCameraOn() {}
4127
+
4128
+ changeAudioInputDevice() {}
4129
+
4130
+ changeVideoInputDevice() {}
4131
+
4132
+ changeAudioDevice() {}
4133
+
4134
+ changeRingDevice() {}
4135
+
4136
+ changeAudioVolume() {}
4137
+
4138
+ changeRingVolume() {}
4139
+
4140
+ hasVideo() {
4141
+ return false;
4142
+ }
4143
+
4144
+ getLocalStreamForCall() {
4145
+ return null;
4146
+ }
4147
+
4148
+ getRemoteStreamForCall() {
4149
+ return null;
4150
+ }
4151
+
4152
+ getLocalVideoStream() {
4153
+ return null;
4154
+ }
4155
+
4156
+ setActiveSipSession() {}
4157
+
4158
+ isRegistered() {
4159
+ return true;
4160
+ }
4161
+
4162
+ hasIncomingCallSession() {
4163
+ return true;
4164
+ }
4165
+
4166
+ hasActiveRemoteVideoStream() {
4167
+ return false;
4168
+ }
4169
+
4170
+ getCurrentCallSession() {
4171
+ return this.currentCall ? CallSession.parseCall(this.currentCall) : null;
3713
4172
  }
3714
4173
 
3715
- sourceIs(callSession ) {
3716
- return callSession.isId(this.sourceId);
4174
+ enableRinging() {}
4175
+
4176
+ sendMessage() {}
4177
+
4178
+ disableRinging() {}
4179
+
4180
+ getLocalStream() {
4181
+ return null;
3717
4182
  }
3718
4183
 
3719
- updateFrom(indirectTransfer ) {
3720
- updateFrom(this, indirectTransfer);
4184
+ getRemoteStream() {
4185
+ return null;
3721
4186
  }
3722
4187
 
3723
- static newFrom(indirectTransfer ) {
3724
- return newFrom(indirectTransfer, IndirectTransfer);
4188
+ getRemoteVideoStream() {
4189
+ return null;
3725
4190
  }
3726
- }
3727
4191
 
3728
- //
3729
- const TRANSFER_FLOW_BLIND = 'blind';
4192
+ getRemoteAudioStream() {
4193
+ return null;
4194
+ }
3730
4195
 
3731
- // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
4196
+ hasLocalVideo() {
4197
+ return false;
4198
+ }
3732
4199
 
3733
- IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
4200
+ useLocalVideoElement() {}
4201
+ }
3734
4202
 
3735
4203
  /* */
3736
4204
 
@@ -4290,6 +4758,9 @@ var calldMethods = (client , baseUrl ) => ({
4290
4758
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4291
4759
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4292
4760
 
4761
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4762
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4763
+
4293
4764
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4294
4765
 
4295
4766
  mute: (callId ) =>
@@ -4643,7 +5114,7 @@ const AGENTD_VERSION = '1.0';
4643
5114
  const WEBHOOKD_VERSION = '1.0';
4644
5115
  const AMID_VERSION = '1.0';
4645
5116
 
4646
- const logger$9 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
5117
+ const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
4647
5118
 
4648
5119
  class ApiClient {
4649
5120
 
@@ -4695,12 +5166,12 @@ class ApiClient {
4695
5166
  }
4696
5167
 
4697
5168
  async forceRefreshToken() {
4698
- logger$9.info('forcing refresh token, calling callback');
5169
+ logger$a.info('forcing refresh token, calling callback');
4699
5170
  return this.refreshTokenCallback();
4700
5171
  }
4701
5172
 
4702
5173
  async refreshTokenCallback() {
4703
- logger$9.info('refresh token callback called', {
5174
+ logger$a.info('refresh token callback called', {
4704
5175
  refreshToken: this.refreshToken,
4705
5176
  refreshBackend: this.refreshBackend,
4706
5177
  refreshExpiration: this.refreshExpiration,
@@ -4718,7 +5189,7 @@ class ApiClient {
4718
5189
  this.isMobile,
4719
5190
  );
4720
5191
 
4721
- logger$9.info('token refreshed', { token: session.token });
5192
+ logger$a.info('token refreshed', { token: session.token });
4722
5193
 
4723
5194
  if (this.onRefreshToken) {
4724
5195
  this.onRefreshToken(session.token, session);
@@ -4859,7 +5330,7 @@ var getApiClient = (forServer ) => {
4859
5330
  class InvalidSubscription extends Error {}
4860
5331
  class InvalidAuthorization extends Error {}
4861
5332
 
4862
- const logger$8 = IssueReporter$1.loggerFor('simple-auth');
5333
+ const logger$9 = IssueReporter$1.loggerFor('simple-auth');
4863
5334
 
4864
5335
  class Auth {
4865
5336
 
@@ -4894,7 +5365,7 @@ class Auth {
4894
5365
  setApiClientId(this.clientId);
4895
5366
  setRefreshExpiration(this.expiration);
4896
5367
  setOnRefreshToken((token , session ) => {
4897
- logger$8.info('on refresh token done', { token });
5368
+ logger$9.info('on refresh token done', { token });
4898
5369
  setApiToken(token);
4899
5370
  Wazo.Websocket.updateToken(token);
4900
5371
 
@@ -5453,7 +5924,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5453
5924
  .then(() => {
5454
5925
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5455
5926
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5456
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5927
+ if (this.peerConnection.addTransceiver) {
5928
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5929
+ }
5457
5930
  }
5458
5931
  })
5459
5932
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5480,12 +5953,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5480
5953
  };
5481
5954
  })
5482
5955
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5483
- .then((sessionDescription) => {
5484
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5485
- this.localMediaStreamConstraints = options.constraints;
5486
-
5487
- return sessionDescription;
5488
- })
5489
5956
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5490
5957
  .catch((error) => {
5491
5958
  wazoLogger.error('error when creating media', error);
@@ -5680,6 +6147,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5680
6147
 
5681
6148
  // set the transceiver direction to the answer direction
5682
6149
  this._peerConnection.getTransceivers().forEach((transceiver) => {
6150
+ if (transceiver.stopped) {
6151
+ return;
6152
+ }
5683
6153
  if (transceiver.direction /* guarding, but should always be true */) {
5684
6154
  const { receiver } = transceiver;
5685
6155
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5724,10 +6194,15 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5724
6194
  if (kind !== 'audio' && kind !== 'video') {
5725
6195
  throw new Error(`Unknown new track kind ${kind}.`);
5726
6196
  }
5727
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
6197
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
6198
+ otherSender.track && otherSender.track.kind === kind);
5728
6199
 
5729
6200
  // Do not reuse sender video tracks in SFU
5730
6201
  if (sender && (!sfu || newTrack.kind === 'audio')) {
6202
+ if (sender.track) {
6203
+ // eslint-disable-next-line no-param-reassign
6204
+ newTrack.enabled = sender.track.enabled;
6205
+ }
5731
6206
  trackUpdates.push(
5732
6207
  new Promise((resolve) => {
5733
6208
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5761,7 +6236,11 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5761
6236
  // Review: could make streamless tracks a configurable option?
5762
6237
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5763
6238
  try {
5764
- pc.addTrack(newTrack, localStream);
6239
+ if (pc.addTrack) {
6240
+ pc.addTrack(newTrack, localStream);
6241
+ } else {
6242
+ pc.addStream(localStream);
6243
+ }
5765
6244
  } catch (error) {
5766
6245
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5767
6246
  throw error;
@@ -5897,7 +6376,7 @@ const DEFAULT_ICE_TIMEOUT = 3000;
5897
6376
  const SEND_STATS_DELAY = 5000;
5898
6377
 
5899
6378
  const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
5900
- const logger$7 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
6379
+ const logger$8 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
5901
6380
  const statsLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-stats') : console;
5902
6381
 
5903
6382
  // events
@@ -5943,6 +6422,7 @@ const MAX_REGISTER_TRIES = 10;
5943
6422
 
5944
6423
 
5945
6424
 
6425
+
5946
6426
 
5947
6427
 
5948
6428
 
@@ -5969,6 +6449,7 @@ class WebRTCClient extends Emitter {
5969
6449
 
5970
6450
 
5971
6451
 
6452
+
5972
6453
 
5973
6454
  // sugar
5974
6455
 
@@ -6007,6 +6488,8 @@ class WebRTCClient extends Emitter {
6007
6488
  super();
6008
6489
  this.uaConfigOverrides = uaConfigOverrides;
6009
6490
  this.config = config;
6491
+ this.skipRegister = config.skipRegister;
6492
+
6010
6493
  this._buildConfig(config, session).then((newConfig ) => {
6011
6494
  this.config = newConfig;
6012
6495
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -6062,13 +6545,13 @@ class WebRTCClient extends Emitter {
6062
6545
 
6063
6546
  createUserAgent(configOverrides ) {
6064
6547
  const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
6065
- logger$7.info('sdk webrtc, creating UA', { webRTCConfiguration });
6548
+ logger$8.info('sdk webrtc, creating UA', { webRTCConfiguration });
6066
6549
 
6067
6550
  webRTCConfiguration.delegate = {
6068
6551
  onConnect: this.onConnect.bind(this),
6069
6552
  onDisconnect: this.onDisconnect.bind(this),
6070
6553
  onInvite: (invitation ) => {
6071
- logger$7.info('sdk webrtc on invite', {
6554
+ logger$8.info('sdk webrtc on invite', {
6072
6555
  method: 'delegate.onInvite',
6073
6556
  id: invitation.id,
6074
6557
  remoteURI: invitation.remoteURI,
@@ -6111,7 +6594,7 @@ class WebRTCClient extends Emitter {
6111
6594
  }
6112
6595
 
6113
6596
  onConnect() {
6114
- logger$7.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6597
+ logger$8.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6115
6598
  this.eventEmitter.emit(CONNECTED);
6116
6599
  if (!this.isRegistered() && this.registerer && this.registerer.waiting) {
6117
6600
  this.registerer.waitingToggle(false);
@@ -6120,7 +6603,7 @@ class WebRTCClient extends Emitter {
6120
6603
  }
6121
6604
 
6122
6605
  async onDisconnect(error ) {
6123
- logger$7.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6606
+ logger$8.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6124
6607
  this.connectionPromise = null;
6125
6608
  // The UA will attempt to reconnect automatically when an error occurred
6126
6609
  this.eventEmitter.emit(DISCONNECTED, error);
@@ -6134,40 +6617,48 @@ class WebRTCClient extends Emitter {
6134
6617
  }
6135
6618
 
6136
6619
  register(tries = 0) {
6137
- logger$7.info('sdk webrtc registering...', {
6620
+ const logInfo = {
6138
6621
  userAgent: !!this.userAgent,
6139
6622
  registered: this.isRegistered(),
6140
6623
  connectionPromise: !!this.connectionPromise,
6141
6624
  registerer: !!this.registerer,
6142
6625
  waiting: this.registerer && this.registerer.waiting,
6143
6626
  tries,
6144
- });
6627
+ skipRegister: this.skipRegister,
6628
+ };
6629
+
6630
+ if (this.skipRegister) {
6631
+ logger$8.info('sdk webrtc skip register...', logInfo);
6632
+ return Promise.resolve();
6633
+ }
6634
+
6635
+ logger$8.info('sdk webrtc registering...', logInfo);
6145
6636
 
6146
6637
  if (!this.userAgent) {
6147
- logger$7.info('sdk webrtc recreating User Agent');
6638
+ logger$8.info('sdk webrtc recreating User Agent');
6148
6639
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6149
6640
  }
6150
6641
  if (!this.userAgent || this.isRegistered()) {
6151
- logger$7.info('sdk webrtc registering aborted, already registered or no UA can be created');
6642
+ logger$8.info('sdk webrtc registering aborted, already registered or no UA can be created');
6152
6643
  return Promise.resolve();
6153
6644
  }
6154
6645
 
6155
6646
  if (this.connectionPromise || (this.registerer && this.registerer.waiting)) {
6156
- logger$7.info('sdk webrtc registering aborted due to a registration in progress.');
6647
+ logger$8.info('sdk webrtc registering aborted due to a registration in progress.');
6157
6648
  return Promise.resolve();
6158
6649
  }
6159
6650
 
6160
6651
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6161
6652
 
6162
6653
  const onRegisterFailed = () => {
6163
- logger$7.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6654
+ logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6164
6655
  this.connectionPromise = null;
6165
6656
  if (this.registerer && this.registerer.waiting) {
6166
6657
  this.registerer.waitingToggle(false);
6167
6658
  }
6168
6659
 
6169
6660
  if (tries <= MAX_REGISTER_TRIES) {
6170
- logger$7.info('sdk webrtc registering, retrying...', { tries });
6661
+ logger$8.info('sdk webrtc registering, retrying...', { tries });
6171
6662
  setTimeout(() => this.register(tries + 1), 300);
6172
6663
  }
6173
6664
  };
@@ -6176,18 +6667,18 @@ class WebRTCClient extends Emitter {
6176
6667
  // Avoid race condition with the close method called just before register and setting userAgent to null
6177
6668
  // during the resolution of the primise.
6178
6669
  if (!this.userAgent) {
6179
- logger$7.info('sdk webrtc recreating User Agent after connection');
6670
+ logger$8.info('sdk webrtc recreating User Agent after connection');
6180
6671
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6181
6672
  }
6182
6673
 
6183
- logger$7.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6674
+ logger$8.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6184
6675
  this.registerer = new Registerer(this.userAgent, registerOptions);
6185
6676
  this.connectionPromise = null;
6186
6677
  this._monkeyPatchRegisterer(this.registerer);
6187
6678
 
6188
6679
  // Bind registerer events
6189
6680
  this.registerer.stateChange.addListener(newState => {
6190
- logger$7.info('sdk webrtc registering, state changed', { newState });
6681
+ logger$8.info('sdk webrtc registering, state changed', { newState });
6191
6682
 
6192
6683
  if (newState === RegistererState.Registered && this.registerer
6193
6684
  && this.registerer.state === RegistererState.Registered) {
@@ -6200,7 +6691,7 @@ class WebRTCClient extends Emitter {
6200
6691
  const options = {
6201
6692
  requestDelegate: {
6202
6693
  onReject: response => {
6203
- logger$7.error('sdk webrtc registering, rejected', { response });
6694
+ logger$8.error('sdk webrtc registering, rejected', { response });
6204
6695
 
6205
6696
  onRegisterFailed();
6206
6697
  },
@@ -6208,13 +6699,13 @@ class WebRTCClient extends Emitter {
6208
6699
  };
6209
6700
 
6210
6701
  return this.registerer.register(options).catch((e) => {
6211
- logger$7.error('sdk webrtc registering, error', e);
6702
+ logger$8.error('sdk webrtc registering, error', e);
6212
6703
 
6213
6704
  this.eventEmitter.emit(REGISTRATION_FAILED);
6214
6705
  return e;
6215
6706
  });
6216
6707
  }).catch(error => {
6217
- logger$7.error('sdk webrtc registering, transport error', error);
6708
+ logger$8.error('sdk webrtc registering, transport error', error);
6218
6709
  onRegisterFailed();
6219
6710
  });
6220
6711
  }
@@ -6243,21 +6734,21 @@ class WebRTCClient extends Emitter {
6243
6734
  }
6244
6735
 
6245
6736
  unregister() {
6246
- logger$7.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6737
+ logger$8.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6247
6738
  if (!this.registerer) {
6248
6739
  return Promise.resolve();
6249
6740
  }
6250
6741
 
6251
6742
  try {
6252
6743
  return this.registerer.unregister().then(() => {
6253
- logger$7.info('sdk webrtc unregistered');
6744
+ logger$8.info('sdk webrtc unregistered');
6254
6745
  this._cleanupRegister();
6255
6746
  }).catch(e => {
6256
- logger$7.error('sdk webrtc unregistering, promise error', e);
6747
+ logger$8.error('sdk webrtc unregistering, promise error', e);
6257
6748
  this._cleanupRegister();
6258
6749
  });
6259
6750
  } catch (e) {
6260
- logger$7.error('sdk webrtc unregistering, error', e);
6751
+ logger$8.error('sdk webrtc unregistering, error', e);
6261
6752
  // Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
6262
6753
  // error when the registerer is in a bad state
6263
6754
  this._cleanupRegister();
@@ -6265,7 +6756,7 @@ class WebRTCClient extends Emitter {
6265
6756
  }
6266
6757
 
6267
6758
  stop() {
6268
- logger$7.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6759
+ logger$8.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6269
6760
  if (!this.userAgent) {
6270
6761
  return Promise.resolve();
6271
6762
  }
@@ -6273,12 +6764,12 @@ class WebRTCClient extends Emitter {
6273
6764
  return this.userAgent.stop().then(() => {
6274
6765
  return this._cleanupRegister();
6275
6766
  }).catch(e => {
6276
- logger$7.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6767
+ logger$8.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6277
6768
  });
6278
6769
  }
6279
6770
 
6280
6771
  call(number , enableVideo , audioOnly = false, conference = false) {
6281
- logger$7.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6772
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6282
6773
  const inviterOptions = {
6283
6774
  sessionDescriptionHandlerOptionsReInvite: {
6284
6775
  conference,
@@ -6307,7 +6798,7 @@ class WebRTCClient extends Emitter {
6307
6798
  this._onAccepted(session, response.session, true);
6308
6799
  },
6309
6800
  onReject: (response ) => {
6310
- logger$7.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6801
+ logger$8.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6311
6802
  this._stopSendingStats(session);
6312
6803
 
6313
6804
  this.eventEmitter.emit(REJECTED, session, response);
@@ -6329,11 +6820,11 @@ class WebRTCClient extends Emitter {
6329
6820
  }
6330
6821
 
6331
6822
  answer(session , enableVideo ) {
6332
- logger$7.info('sdk webrtc answer call', { id: session.id, enableVideo });
6823
+ logger$8.info('sdk webrtc answer call', { id: session.id, enableVideo });
6333
6824
 
6334
6825
  if (!session || !session.accept) {
6335
6826
  const error = 'No session to answer, or not an invitation';
6336
- logger$7.warn(error);
6827
+ logger$8.warn(error);
6337
6828
  return Promise.reject(new Error(error));
6338
6829
  }
6339
6830
  const options = {
@@ -6343,15 +6834,15 @@ class WebRTCClient extends Emitter {
6343
6834
  return session.accept(options).then(() => {
6344
6835
  if (session.isCanceled) {
6345
6836
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
6346
- logger$7.error(message, { id: session.id });
6837
+ logger$8.error(message, { id: session.id });
6347
6838
  this.onCallEnded(session);
6348
6839
 
6349
6840
  throw new CanceledCallError(message);
6350
6841
  }
6351
- logger$7.info('sdk webrtc answer, accepted.');
6842
+ logger$8.info('sdk webrtc answer, accepted.');
6352
6843
  this._onAccepted(session);
6353
6844
  }).catch(e => {
6354
- logger$7.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6845
+ logger$8.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6355
6846
 
6356
6847
  throw e;
6357
6848
  });
@@ -6359,7 +6850,7 @@ class WebRTCClient extends Emitter {
6359
6850
 
6360
6851
  hangup(session ) {
6361
6852
  const { state, id } = session;
6362
- logger$7.info('sdk webrtc hangup call', { id, state });
6853
+ logger$8.info('sdk webrtc hangup call', { id, state });
6363
6854
 
6364
6855
  try {
6365
6856
  this._stopSendingStats(session);
@@ -6388,24 +6879,24 @@ class WebRTCClient extends Emitter {
6388
6879
 
6389
6880
  return bye();
6390
6881
  } catch (error) {
6391
- logger$7.warn('sdk webrtc hangup, error', error);
6882
+ logger$8.warn('sdk webrtc hangup, error', error);
6392
6883
  }
6393
6884
 
6394
6885
  return null;
6395
6886
  }
6396
6887
 
6397
6888
  reject(session ) {
6398
- logger$7.info('sdk webrtc reject call', { id: session.id });
6889
+ logger$8.info('sdk webrtc reject call', { id: session.id });
6399
6890
 
6400
6891
  try {
6401
6892
  return session.reject ? session.reject() : session.cancel();
6402
6893
  } catch (e) {
6403
- logger$7.warn('Error when rejecting call', e.message, e.stack);
6894
+ logger$8.warn('Error when rejecting call', e.message, e.stack);
6404
6895
  }
6405
6896
  }
6406
6897
 
6407
6898
  async close() {
6408
- logger$7.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6899
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6409
6900
  this._cleanupMedia();
6410
6901
  this.connectionPromise = null;
6411
6902
 
@@ -6436,7 +6927,7 @@ class WebRTCClient extends Emitter {
6436
6927
  // eg: "INVITE not rejectable in state Completed"
6437
6928
  }
6438
6929
  this.userAgent = null;
6439
- logger$7.info('sdk webrtc client closed');
6930
+ logger$8.info('sdk webrtc client closed');
6440
6931
  }
6441
6932
 
6442
6933
  getNumber(session ) {
@@ -6449,13 +6940,13 @@ class WebRTCClient extends Emitter {
6449
6940
  }
6450
6941
 
6451
6942
  mute(session ) {
6452
- logger$7.info('sdk webrtc mute', { id: session.id });
6943
+ logger$8.info('sdk webrtc mute', { id: session.id });
6453
6944
 
6454
6945
  this._toggleAudio(session, true);
6455
6946
  }
6456
6947
 
6457
6948
  unmute(session ) {
6458
- logger$7.info('sdk webrtc unmute', { id: session.id });
6949
+ logger$8.info('sdk webrtc unmute', { id: session.id });
6459
6950
 
6460
6951
  this._toggleAudio(session, false);
6461
6952
  }
@@ -6472,12 +6963,18 @@ class WebRTCClient extends Emitter {
6472
6963
  }
6473
6964
 
6474
6965
  if (pc.getSenders) {
6966
+ if (!pc.getSenders().length) {
6967
+ return false;
6968
+ }
6475
6969
  pc.getSenders().forEach(sender => {
6476
6970
  if (sender && sender.track && sender.track.kind === 'audio') {
6477
6971
  muted = muted && !sender.track.enabled;
6478
6972
  }
6479
6973
  });
6480
6974
  } else {
6975
+ if (!pc.getLocalStreams().length) {
6976
+ return false;
6977
+ }
6481
6978
  pc.getLocalStreams().forEach(stream => {
6482
6979
  stream.getAudioTracks().forEach(track => {
6483
6980
  muted = muted && !track.enabled;
@@ -6489,20 +6986,20 @@ class WebRTCClient extends Emitter {
6489
6986
  }
6490
6987
 
6491
6988
  toggleCameraOn(session ) {
6492
- logger$7.info('sdk webrtc toggle camera on', { id: session.id });
6989
+ logger$8.info('sdk webrtc toggle camera on', { id: session.id });
6493
6990
 
6494
6991
  this._toggleVideo(session, false);
6495
6992
  }
6496
6993
 
6497
6994
  toggleCameraOff(session ) {
6498
- logger$7.info('sdk webrtc toggle camera off', { id: session.id });
6995
+ logger$8.info('sdk webrtc toggle camera off', { id: session.id });
6499
6996
 
6500
6997
  this._toggleVideo(session, true);
6501
6998
  }
6502
6999
 
6503
7000
  hold(session , isConference = false) {
6504
7001
  const sessionId = this.getSipSessionId(session);
6505
- logger$7.info('sdk webrtc hold', {
7002
+ logger$8.info('sdk webrtc hold', {
6506
7003
  sessionId,
6507
7004
  keys: Object.keys(this.heldSessions),
6508
7005
  pendingReinvite: !!session.pendingReinvite,
@@ -6534,6 +7031,9 @@ class WebRTCClient extends Emitter {
6534
7031
  if (!this._isWeb()) {
6535
7032
  options.sessionDescriptionHandlerModifiers = [holdModifier];
6536
7033
  }
7034
+ options.sessionDescriptionHandlerOptions = {
7035
+ constraints: options.constraints,
7036
+ };
6537
7037
 
6538
7038
  // Send re-INVITE
6539
7039
  return session.invite(options);
@@ -6542,7 +7042,7 @@ class WebRTCClient extends Emitter {
6542
7042
  unhold(session , isConference = false) {
6543
7043
  const sessionId = this.getSipSessionId(session);
6544
7044
 
6545
- logger$7.info('sdk webrtc unhold', {
7045
+ logger$8.info('sdk webrtc unhold', {
6546
7046
  sessionId,
6547
7047
  keys: Object.keys(this.heldSessions),
6548
7048
  pendingReinvite: !!session.pendingReinvite,
@@ -6573,6 +7073,9 @@ class WebRTCClient extends Emitter {
6573
7073
  // (eg: holdModifier)
6574
7074
  options.sessionDescriptionHandlerModifiers = [];
6575
7075
  }
7076
+ options.sessionDescriptionHandlerOptions = {
7077
+ constraints: options.constraints,
7078
+ };
6576
7079
 
6577
7080
  // Send re-INVITE
6578
7081
  return session.invite(options);
@@ -6630,7 +7133,7 @@ class WebRTCClient extends Emitter {
6630
7133
  return;
6631
7134
  }
6632
7135
 
6633
- logger$7.info('send WebRTC message', { sipId: sipSession.id, contentType });
7136
+ logger$8.info('send WebRTC message', { sipId: sipSession.id, contentType });
6634
7137
 
6635
7138
  try {
6636
7139
  sipSession.message({
@@ -6755,7 +7258,8 @@ class WebRTCClient extends Emitter {
6755
7258
  }
6756
7259
  const sdh = session.sessionDescriptionHandler;
6757
7260
  const pc = sdh.peerConnection;
6758
- const localStream = this.getLocalStream(this.getSipSessionId(session));
7261
+ const sessionId = this.getSipSessionId(session);
7262
+ const localStream = this.getLocalStream(sessionId);
6759
7263
 
6760
7264
  // Release old video stream
6761
7265
  if (localStream) {
@@ -6781,11 +7285,8 @@ class WebRTCClient extends Emitter {
6781
7285
 
6782
7286
  // let's update the local stream
6783
7287
  this.eventEmitter.emit('onVideoInputChange', stream);
6784
- try {
6785
- await sdh.setLocalMediaStream(stream);
6786
- } catch (_) {
6787
- // Nothing to do
6788
- }
7288
+ this.setLocalMediaStream(sessionId, stream);
7289
+
6789
7290
  return stream;
6790
7291
  });
6791
7292
  }
@@ -6997,7 +7498,7 @@ class WebRTCClient extends Emitter {
6997
7498
  }
6998
7499
 
6999
7500
  startHeartbeat() {
7000
- logger$7.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7501
+ logger$8.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7001
7502
  if (!this.userAgent) {
7002
7503
  this.heartbeat.stop();
7003
7504
  return;
@@ -7010,7 +7511,7 @@ class WebRTCClient extends Emitter {
7010
7511
  }
7011
7512
 
7012
7513
  stopHeartbeat() {
7013
- logger$7.info('sdk webrtc stop heartbeat');
7514
+ logger$8.info('sdk webrtc stop heartbeat');
7014
7515
  this.heartbeat.stop();
7015
7516
  }
7016
7517
 
@@ -7030,7 +7531,7 @@ class WebRTCClient extends Emitter {
7030
7531
  }
7031
7532
 
7032
7533
  attemptReconnection() {
7033
- logger$7.info('attempt reconnection', { userAgent: !!this.userAgent });
7534
+ logger$8.info('attempt reconnection', { userAgent: !!this.userAgent });
7034
7535
  if (!this.userAgent) {
7035
7536
  return;
7036
7537
  }
@@ -7087,9 +7588,11 @@ class WebRTCClient extends Emitter {
7087
7588
  remoteStream.removeTrack(track);
7088
7589
  });
7089
7590
 
7090
- pc.getReceivers().forEach(receiver => {
7091
- remoteStream.addTrack(receiver.track);
7092
- });
7591
+ if (pc.getReceivers) {
7592
+ pc.getReceivers().forEach(receiver => {
7593
+ remoteStream.addTrack(receiver.track);
7594
+ });
7595
+ }
7093
7596
  }
7094
7597
 
7095
7598
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -7124,6 +7627,25 @@ class WebRTCClient extends Emitter {
7124
7627
  return sessionId in this.conferences;
7125
7628
  }
7126
7629
 
7630
+ createAudioElementFor(sessionId ) {
7631
+ const audio = document.createElement('audio');
7632
+ audio.setAttribute('id', `audio-${sessionId}`);
7633
+
7634
+ if (audio.setSinkId && this.audioOutputDeviceId) {
7635
+ audio.setSinkId(this.audioOutputDeviceId);
7636
+ }
7637
+
7638
+ if (document.body) {
7639
+ document.body.appendChild(audio);
7640
+ }
7641
+ this.audioElements[sessionId] = audio;
7642
+
7643
+ audio.volume = this.audioOutputVolume;
7644
+ audio.autoplay = true;
7645
+
7646
+ return audio;
7647
+ }
7648
+
7127
7649
  _onTransportError() {
7128
7650
  this.eventEmitter.emit(TRANSPORT_ERROR);
7129
7651
  this.attemptReconnection();
@@ -7133,7 +7655,7 @@ class WebRTCClient extends Emitter {
7133
7655
  const body = message && typeof message === 'object' ? message.data : message;
7134
7656
  if (body && body.indexOf('200 OK') !== -1) {
7135
7657
  if (this.hasHeartbeat()) {
7136
- logger$7.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7658
+ logger$8.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7137
7659
 
7138
7660
  this.heartbeat.onHeartbeat();
7139
7661
  if (this.heartbeatCb) {
@@ -7144,7 +7666,7 @@ class WebRTCClient extends Emitter {
7144
7666
  }
7145
7667
 
7146
7668
  async _onHeartbeatTimeout() {
7147
- logger$7.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7669
+ logger$8.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7148
7670
 
7149
7671
  if (this.heartbeatTimeoutCb) {
7150
7672
  this.heartbeatTimeoutCb();
@@ -7156,7 +7678,7 @@ class WebRTCClient extends Emitter {
7156
7678
  try {
7157
7679
  await this.userAgent.transport.disconnect();
7158
7680
  } catch (e) {
7159
- logger$7.error('Transport disconnection after heartbeat timeout, error', e);
7681
+ logger$8.error('Transport disconnection after heartbeat timeout, error', e);
7160
7682
  }
7161
7683
  }
7162
7684
 
@@ -7189,31 +7711,31 @@ class WebRTCClient extends Emitter {
7189
7711
  }
7190
7712
 
7191
7713
  _connectIfNeeded() {
7192
- logger$7.info('connect if needed, checking', { connected: this.isConnected() });
7714
+ logger$8.info('connect if needed, checking', { connected: this.isConnected() });
7193
7715
  if (!this.userAgent) {
7194
- logger$7.info('need to recreate User Agent');
7716
+ logger$8.info('need to recreate User Agent');
7195
7717
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
7196
7718
  }
7197
7719
 
7198
7720
  if (this.isConnected()) {
7199
- logger$7.info('webrtc sdk, already connected');
7721
+ logger$8.info('webrtc sdk, already connected');
7200
7722
  return Promise.resolve();
7201
7723
  }
7202
7724
 
7203
7725
  if (this.isConnecting()) {
7204
- logger$7.info('webrtc sdk, already connecting...');
7726
+ logger$8.info('webrtc sdk, already connecting...');
7205
7727
 
7206
7728
  this.connectionPromise = this.userAgent.transport.connectPromise;
7207
7729
  return this.connectionPromise;
7208
7730
  }
7209
7731
 
7210
7732
  if (this.connectionPromise) {
7211
- logger$7.info('webrtc sdk, connection promise connecting...');
7733
+ logger$8.info('webrtc sdk, connection promise connecting...');
7212
7734
  // $FlowFixMe
7213
7735
  return this.connectionPromise;
7214
7736
  }
7215
7737
 
7216
- logger$7.info('WebRTC UA needs to connect');
7738
+ logger$8.info('WebRTC UA needs to connect');
7217
7739
 
7218
7740
  // Force UA to reconnect
7219
7741
  if (this.userAgent && this.userAgent.state !== UserAgentState.Stopped) {
@@ -7338,7 +7860,7 @@ class WebRTCClient extends Emitter {
7338
7860
 
7339
7861
  sdh.peerConnectionDelegate = {
7340
7862
  onicecandidateerror: (error ) => {
7341
- logger$7.error('on icecandidate error', {
7863
+ logger$8.error('on icecandidate error', {
7342
7864
  address: error.address,
7343
7865
  port: error.port,
7344
7866
  errorCode: error.errorCode,
@@ -7353,7 +7875,7 @@ class WebRTCClient extends Emitter {
7353
7875
  let hadRemoteVideo = false;
7354
7876
 
7355
7877
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7356
- // Becase when `onInvite` is called we already got the video track
7878
+ // Because when `onInvite` is called we already got the video track
7357
7879
  session.onInviteRequest = (request) => {
7358
7880
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7359
7881
 
@@ -7367,7 +7889,7 @@ class WebRTCClient extends Emitter {
7367
7889
  updatedNumber = session.assertedIdentity.uri.normal.user;
7368
7890
  updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
7369
7891
  }
7370
- logger$7.info('re-invite received', { updatedCalleeName, updatedNumber });
7892
+ logger$8.info('re-invite received', { updatedCalleeName, updatedNumber });
7371
7893
 
7372
7894
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
7373
7895
 
@@ -7388,7 +7910,7 @@ class WebRTCClient extends Emitter {
7388
7910
  }
7389
7911
 
7390
7912
  _onAccepted(session , sessionDialog , withEvent = true) {
7391
- logger$7.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7913
+ logger$8.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7392
7914
 
7393
7915
  this.storeSipSession(session);
7394
7916
 
@@ -7428,20 +7950,10 @@ class WebRTCClient extends Emitter {
7428
7950
  const isConference = this.isConference(sessionId);
7429
7951
 
7430
7952
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7431
- const audio = document.createElement('audio');
7432
- audio.setAttribute('id', `audio-${sessionId}`);
7433
-
7434
- if (audio.setSinkId && this.audioOutputDeviceId) {
7435
- audio.setSinkId(this.audioOutputDeviceId);
7436
- }
7437
-
7438
- if (document.body) {
7439
- document.body.appendChild(audio);
7440
- }
7441
- this.audioElements[sessionId] = audio;
7953
+ this.createAudioElementFor(sessionId);
7442
7954
  }
7443
7955
 
7444
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7956
+ const audioElement = this.audioElements[sessionId];
7445
7957
  const stream = newStream || this.getRemoteStream(sessionId);
7446
7958
 
7447
7959
  if (!this._isWeb() || !stream) {
@@ -7588,10 +8100,10 @@ class WebRTCClient extends Emitter {
7588
8100
 
7589
8101
  _stopSendingStats(session ) {
7590
8102
  const sessionId = this.getSipSessionId(session);
7591
- logger$7.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
8103
+ logger$8.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7592
8104
 
7593
8105
  if (sessionId in this.statsIntervals) {
7594
- logger$7.trace('Stop sending stats for call', { sessionId });
8106
+ logger$8.trace('Stop sending stats for call', { sessionId });
7595
8107
  this.statsIntervals[sessionId]();
7596
8108
  delete this.statsIntervals[sessionId];
7597
8109
  }
@@ -7607,7 +8119,7 @@ class WebRTCClient extends Emitter {
7607
8119
  try {
7608
8120
  await this.userAgent.transport.disconnect();
7609
8121
  } catch (e) {
7610
- logger$7.error('WebRTC transport disconnect, error', e);
8122
+ logger$8.error('WebRTC transport disconnect, error', e);
7611
8123
  }
7612
8124
  }
7613
8125
  }
@@ -7694,7 +8206,7 @@ const events = [
7694
8206
  ON_SIGNAL,
7695
8207
  ];
7696
8208
 
7697
- const logger$6 = IssueReporter$1.loggerFor('webrtc-phone');
8209
+ const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
7698
8210
 
7699
8211
  class WebRTCPhone extends Emitter {
7700
8212
 
@@ -7765,7 +8277,7 @@ class WebRTCPhone extends Emitter {
7765
8277
  }).catch(error => {
7766
8278
  // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
7767
8279
  console.error('register error', error, error.message, error.stack);
7768
- logger$6.error('WebRTC register error', { message: error.message, stack: error.stack });
8280
+ logger$7.error('WebRTC register error', { message: error.message, stack: error.stack });
7769
8281
  });
7770
8282
  }
7771
8283
 
@@ -7780,7 +8292,7 @@ class WebRTCPhone extends Emitter {
7780
8292
  if (!this.client) {
7781
8293
  return;
7782
8294
  }
7783
- logger$6.info('WebRTC phone stop');
8295
+ logger$7.info('WebRTC phone stop');
7784
8296
  this.client.stop();
7785
8297
  }
7786
8298
 
@@ -7795,14 +8307,14 @@ class WebRTCPhone extends Emitter {
7795
8307
  async sendReinvite(callSession , constraints = null, conference = false,
7796
8308
  audioOnly = false) {
7797
8309
  const sipSession = this.findSipSession(callSession);
7798
- logger$6.info('WebRTC phone - send reinvite', {
8310
+ logger$7.info('WebRTC phone - send reinvite', {
7799
8311
  sessionId: sipSession ? sipSession.id : null,
7800
8312
  constraints,
7801
8313
  audioOnly,
7802
8314
  });
7803
8315
 
7804
8316
  if (!sipSession) {
7805
- return null;
8317
+ return false;
7806
8318
  }
7807
8319
 
7808
8320
  // $FlowFixMe
@@ -7812,19 +8324,17 @@ class WebRTCPhone extends Emitter {
7812
8324
  // Downgrade
7813
8325
  if (constraints && !isUpgrade) {
7814
8326
  // No reinvite needed
7815
- return this._downgradeToAudio(callSession);
8327
+ this._downgradeToAudio(callSession);
8328
+ return false;
7816
8329
  }
7817
8330
 
7818
8331
  if (isUpgrade) {
7819
8332
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
7820
8333
  if (!shouldReinvite) {
7821
- return;
8334
+ return false;
7822
8335
  }
7823
8336
  }
7824
8337
 
7825
- // Force reinvite in SDH
7826
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
7827
-
7828
8338
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
7829
8339
  }
7830
8340
 
@@ -7833,7 +8343,7 @@ class WebRTCPhone extends Emitter {
7833
8343
  }
7834
8344
 
7835
8345
  startHeartbeat() {
7836
- logger$6.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
8346
+ logger$7.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
7837
8347
  if (!this.client || this.client.hasHeartbeat()) {
7838
8348
  return;
7839
8349
  }
@@ -7842,7 +8352,7 @@ class WebRTCPhone extends Emitter {
7842
8352
  }
7843
8353
 
7844
8354
  stopHeartbeat() {
7845
- logger$6.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
8355
+ logger$7.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
7846
8356
  if (!this.client) {
7847
8357
  return;
7848
8358
  }
@@ -7859,7 +8369,7 @@ class WebRTCPhone extends Emitter {
7859
8369
  }
7860
8370
 
7861
8371
  reconnect() {
7862
- logger$6.info('WebRTC phone - reconnect', { client: !!this.client });
8372
+ logger$7.info('WebRTC phone - reconnect', { client: !!this.client });
7863
8373
  if (!this.client) {
7864
8374
  return;
7865
8375
  }
@@ -7897,7 +8407,7 @@ class WebRTCPhone extends Emitter {
7897
8407
  _downgradeToAudio(callSession ) {
7898
8408
  const sipSession = this.findSipSession(callSession);
7899
8409
  if (!sipSession) {
7900
- return;
8410
+ return false;
7901
8411
  }
7902
8412
 
7903
8413
  // Release local video stream when downgrading to audio
@@ -8010,7 +8520,7 @@ class WebRTCPhone extends Emitter {
8010
8520
  // Monkey patch to know when canceled with the CANCEL message
8011
8521
  const onCancel = sipSession._onCancel.bind(sipSession);
8012
8522
  sipSession._onCancel = (message ) => {
8013
- logger$6.trace('on sip session canceled', { callId: message.callId });
8523
+ logger$7.trace('on sip session canceled', { callId: message.callId });
8014
8524
 
8015
8525
  onCancel(message);
8016
8526
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
@@ -8035,13 +8545,13 @@ class WebRTCPhone extends Emitter {
8035
8545
  this.audioOutputVolume,
8036
8546
  );
8037
8547
  case SessionState.Terminating:
8038
- logger$6.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8548
+ logger$7.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8039
8549
 
8040
8550
  this.eventEmitter.emit(ON_CALL_ENDING, this._createCallSession(sipSession));
8041
8551
 
8042
8552
  break;
8043
8553
  case SessionState.Terminated:
8044
- logger$6.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8554
+ logger$7.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8045
8555
 
8046
8556
  this._onCallTerminated(sipSession);
8047
8557
 
@@ -8077,7 +8587,7 @@ class WebRTCPhone extends Emitter {
8077
8587
  }
8078
8588
 
8079
8589
  async startScreenSharing(constraints , callSession ) {
8080
- logger$6.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8590
+ logger$7.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8081
8591
 
8082
8592
  const screenShareStream = await this._getStreamFromConstraints(constraints);
8083
8593
  if (!screenShareStream) {
@@ -8099,6 +8609,10 @@ class WebRTCPhone extends Emitter {
8099
8609
  localStream.removeTrack(videoTrack);
8100
8610
  }
8101
8611
 
8612
+ if (localStream) {
8613
+ localStream.addTrack(screenTrack);
8614
+ }
8615
+
8102
8616
  if (sender) {
8103
8617
  sender.replaceTrack(screenTrack);
8104
8618
  }
@@ -8113,7 +8627,8 @@ class WebRTCPhone extends Emitter {
8113
8627
  return;
8114
8628
  }
8115
8629
 
8116
- logger$6.info('WebRTC phone - stop screen sharing');
8630
+ logger$7.info('WebRTC phone - stop screen sharing');
8631
+ let reinvited = false;
8117
8632
 
8118
8633
  try {
8119
8634
  if (this.currentScreenShare.stream) {
@@ -8128,7 +8643,8 @@ class WebRTCPhone extends Emitter {
8128
8643
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
8129
8644
  // We have to downgrade to audio.
8130
8645
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
8131
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
8646
+ const constraints = { audio: false, video: screenshareStopped };
8647
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
8132
8648
  }
8133
8649
  } catch (e) {
8134
8650
  console.warn(e);
@@ -8142,6 +8658,8 @@ class WebRTCPhone extends Emitter {
8142
8658
  );
8143
8659
 
8144
8660
  this.currentScreenShare = null;
8661
+
8662
+ return reinvited;
8145
8663
  }
8146
8664
 
8147
8665
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -8179,7 +8697,7 @@ class WebRTCPhone extends Emitter {
8179
8697
  }
8180
8698
 
8181
8699
  _onCallAccepted(sipSession , cameraEnabled ) {
8182
- logger$6.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8700
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8183
8701
 
8184
8702
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
8185
8703
  this.currentSipSession = sipSession;
@@ -8197,11 +8715,15 @@ class WebRTCPhone extends Emitter {
8197
8715
  }
8198
8716
 
8199
8717
  changeAudioDevice(id ) {
8200
- logger$6.info('WebRTC phone - change audio device', { deviceId: id });
8718
+ logger$7.info('WebRTC phone - change audio device', { deviceId: id });
8201
8719
  this.audioOutputDeviceId = id;
8202
8720
  this.client.changeAudioOutputDevice(id);
8203
8721
  }
8204
8722
 
8723
+ createAudioElementFor(sessionId ) {
8724
+ return this.client.createAudioElementFor(sessionId);
8725
+ }
8726
+
8205
8727
  changeRingDevice(id ) {
8206
8728
  this.audioRingDeviceId = id;
8207
8729
  }
@@ -8218,25 +8740,25 @@ class WebRTCPhone extends Emitter {
8218
8740
  }
8219
8741
 
8220
8742
  changeAudioInputDevice(id ) {
8221
- logger$6.info('WebRTC phone - changeAudio input device', { deviceId: id });
8743
+ logger$7.info('WebRTC phone - changeAudio input device', { deviceId: id });
8222
8744
 
8223
8745
  return this.client.changeAudioInputDevice(id, this.currentSipSession);
8224
8746
  }
8225
8747
 
8226
8748
  changeVideoInputDevice(id ) {
8227
- logger$6.info('WebRTC phone - change video input device', { deviceId: id });
8749
+ logger$7.info('WebRTC phone - change video input device', { deviceId: id });
8228
8750
 
8229
8751
  return this.client.changeVideoInputDevice(id, this.currentSipSession);
8230
8752
  }
8231
8753
 
8232
8754
  changeSessionVideoInputDevice(id ) {
8233
- logger$6.info('WebRTC phone - change session video input device', { deviceId: id });
8755
+ logger$7.info('WebRTC phone - change session video input device', { deviceId: id });
8234
8756
 
8235
8757
  return this.client.changeSessionVideoInputDevice(id, this.currentSipSession);
8236
8758
  }
8237
8759
 
8238
8760
  _onCallTerminated(sipSession ) {
8239
- logger$6.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8761
+ logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8240
8762
 
8241
8763
  const callSession = this._createCallSession(sipSession);
8242
8764
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
@@ -8270,7 +8792,7 @@ class WebRTCPhone extends Emitter {
8270
8792
  const hasIncomingCallSession = this.hasIncomingCallSession();
8271
8793
 
8272
8794
  // Re-trigger incoming call event for remaining incoming calls
8273
- logger$6.info('WebRTC phone - check to re-trigger incoming call', {
8795
+ logger$7.info('WebRTC phone - check to re-trigger incoming call', {
8274
8796
  sipId: sipSession.id,
8275
8797
  shouldRetrigger,
8276
8798
  hasIncomingCallSession,
@@ -8359,37 +8881,37 @@ class WebRTCPhone extends Emitter {
8359
8881
 
8360
8882
  // Deprecated
8361
8883
  getLocalStreamForCall(callSession ) {
8362
- logger$6.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8884
+ logger$7.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8363
8885
 
8364
8886
  return this.getLocalStream(callSession);
8365
8887
  }
8366
8888
 
8367
8889
  // Deprecated
8368
8890
  getRemoteStreamForCall(callSession ) {
8369
- logger$6.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8891
+ logger$7.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8370
8892
 
8371
8893
  return this.getRemoteVideoStream(callSession);
8372
8894
  }
8373
8895
 
8374
8896
  getRemoteStreamsForCall(callSession ) {
8375
- logger$6.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8897
+ logger$7.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8376
8898
 
8377
8899
  return this.getRemoteStream(callSession);
8378
8900
  }
8379
8901
 
8380
8902
  accept(callSession , cameraEnabled ) {
8381
- logger$6.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8903
+ logger$7.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8382
8904
  if (this.currentSipSession) {
8383
8905
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
8384
8906
  }
8385
8907
 
8386
8908
  if (!callSession) {
8387
- logger$6.warn('no CallSession to accept.');
8909
+ logger$7.warn('no CallSession to accept.');
8388
8910
  return Promise.resolve(null);
8389
8911
  }
8390
8912
 
8391
8913
  if (callSession.getId() in this.acceptedSessions) {
8392
- logger$6.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8914
+ logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8393
8915
  return Promise.resolve(callSession.sipCallId);
8394
8916
  }
8395
8917
 
@@ -8401,24 +8923,24 @@ class WebRTCPhone extends Emitter {
8401
8923
  const sipSession = this.client.getSipSession(callSession.getId());
8402
8924
  if (sipSession) {
8403
8925
  if (sipSession.state === SessionState.Terminated || sipSession.state === SessionState.Terminating) {
8404
- logger$6.warn('Trying to answer a terminated sipSession.');
8926
+ logger$7.warn('Trying to answer a terminated sipSession.');
8405
8927
 
8406
8928
  return Promise.resolve(null);
8407
8929
  }
8408
8930
 
8409
- logger$6.info('accept call, session found', { sipId: sipSession.id });
8931
+ logger$7.info('accept call, session found', { sipId: sipSession.id });
8410
8932
 
8411
8933
  // $FlowFixMe
8412
8934
  return this.client.answer(sipSession, this.allowVideo ? cameraEnabled : false).then(() => {
8413
8935
  return callSession.sipCallId;
8414
8936
  }).catch(e => {
8415
- logger$6.error(e);
8937
+ logger$7.error(e);
8416
8938
  this.endCurrentCall(callSession);
8417
8939
  throw e;
8418
8940
  });
8419
8941
  }
8420
8942
 
8421
- logger$6.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8943
+ logger$7.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8422
8944
 
8423
8945
  return Promise.resolve(null);
8424
8946
  }
@@ -8428,7 +8950,7 @@ class WebRTCPhone extends Emitter {
8428
8950
  }
8429
8951
 
8430
8952
  async reject(callSession ) {
8431
- logger$6.info('reject WebRTC called', { id: callSession.getId() });
8953
+ logger$7.info('reject WebRTC called', { id: callSession.getId() });
8432
8954
 
8433
8955
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call rejected locally');
8434
8956
  if (!callSession || callSession.getId() in this.rejectedSessions) {
@@ -8440,14 +8962,14 @@ class WebRTCPhone extends Emitter {
8440
8962
 
8441
8963
  const sipSession = this.findSipSession(callSession);
8442
8964
  if (sipSession) {
8443
- logger$6.info('WebRTC rejecting', { sipId: sipSession.id });
8965
+ logger$7.info('WebRTC rejecting', { sipId: sipSession.id });
8444
8966
 
8445
8967
  this.client.hangup(sipSession);
8446
8968
  }
8447
8969
  }
8448
8970
 
8449
8971
  async ignore(callSession ) {
8450
- logger$6.info('WebRTC ignore', { id: callSession.getId() });
8972
+ logger$7.info('WebRTC ignore', { id: callSession.getId() });
8451
8973
 
8452
8974
  // kill the ring
8453
8975
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'ignoring call');
@@ -8456,7 +8978,7 @@ class WebRTCPhone extends Emitter {
8456
8978
  }
8457
8979
 
8458
8980
  hold(callSession , withEvent = true, isConference = false) {
8459
- logger$6.info('WebRTC hold', { id: callSession.getId() });
8981
+ logger$7.info('WebRTC hold', { id: callSession.getId() });
8460
8982
 
8461
8983
  const sipSession = this.findSipSession(callSession);
8462
8984
 
@@ -8467,7 +8989,7 @@ class WebRTCPhone extends Emitter {
8467
8989
 
8468
8990
  // @Deprecated
8469
8991
  unhold(callSession , withEvent = true, isConference = false) {
8470
- logger$6.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8992
+ logger$7.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8471
8993
 
8472
8994
  console.warn('Please note that `phone.unhold()` is being deprecated; `phone.resume()` is the preferred method');
8473
8995
 
@@ -8482,7 +9004,7 @@ class WebRTCPhone extends Emitter {
8482
9004
  const sipSession = this.findSipSession(callSession);
8483
9005
 
8484
9006
  if (sipSession) {
8485
- logger$6.info('WebRTC atxfer', { sipId: sipSession.id });
9007
+ logger$7.info('WebRTC atxfer', { sipId: sipSession.id });
8486
9008
 
8487
9009
  return this.client.atxfer(sipSession);
8488
9010
  }
@@ -8497,7 +9019,7 @@ class WebRTCPhone extends Emitter {
8497
9019
  if (!sipSession) {
8498
9020
  return new Promise((resolve, reject) => reject(new Error('No session to hold')));
8499
9021
  }
8500
- logger$6.info('WebRTC hold sip session', { sipId: sipSession.id });
9022
+ logger$7.info('WebRTC hold sip session', { sipId: sipSession.id });
8501
9023
 
8502
9024
  const promise = this.client.hold(sipSession, isConference);
8503
9025
  if (withEvent) {
@@ -8516,7 +9038,7 @@ class WebRTCPhone extends Emitter {
8516
9038
  if (!sipSession) {
8517
9039
  return new Promise((resolve, reject) => reject(new Error('No session to unhold')));
8518
9040
  }
8519
- logger$6.info('WebRTC unhold', { sipId: sipSession.id });
9041
+ logger$7.info('WebRTC unhold', { sipId: sipSession.id });
8520
9042
 
8521
9043
  const promise = this.client.unhold(sipSession, isConference);
8522
9044
  if (withEvent) {
@@ -8527,18 +9049,18 @@ class WebRTCPhone extends Emitter {
8527
9049
  }
8528
9050
 
8529
9051
  resume(callSession , isConference = false) {
8530
- logger$6.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
9052
+ logger$7.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8531
9053
 
8532
9054
  const sipSession = this.findSipSession(callSession);
8533
9055
  if (!sipSession) {
8534
9056
  return new Promise((resolve, reject) => reject(new Error('No session to resume')));
8535
9057
  }
8536
9058
 
8537
- logger$6.info('WebRTC resuming', { sipId: sipSession.id });
9059
+ logger$7.info('WebRTC resuming', { sipId: sipSession.id });
8538
9060
 
8539
9061
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
8540
9062
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
8541
- logger$6.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9063
+ logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8542
9064
  this.holdSipSession(this.currentSipSession, callSession);
8543
9065
  }
8544
9066
 
@@ -8553,14 +9075,14 @@ class WebRTCPhone extends Emitter {
8553
9075
  }
8554
9076
 
8555
9077
  mute(callSession , withEvent = true) {
8556
- logger$6.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
9078
+ logger$7.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8557
9079
 
8558
9080
  const sipSession = this.findSipSession(callSession);
8559
9081
  if (!sipSession) {
8560
9082
  return;
8561
9083
  }
8562
9084
 
8563
- logger$6.info('WebRTC muting', { sipId: sipSession.id });
9085
+ logger$7.info('WebRTC muting', { sipId: sipSession.id });
8564
9086
  this.client.mute(sipSession);
8565
9087
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: true });
8566
9088
 
@@ -8574,14 +9096,14 @@ class WebRTCPhone extends Emitter {
8574
9096
  }
8575
9097
 
8576
9098
  unmute(callSession , withEvent = true) {
8577
- logger$6.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
9099
+ logger$7.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8578
9100
 
8579
9101
  const sipSession = this.findSipSession(callSession);
8580
9102
  if (!sipSession) {
8581
9103
  return;
8582
9104
  }
8583
9105
 
8584
- logger$6.info('WebRTC unmuting', { sipId: sipSession.id });
9106
+ logger$7.info('WebRTC unmuting', { sipId: sipSession.id });
8585
9107
  this.client.unmute(sipSession);
8586
9108
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: false });
8587
9109
 
@@ -8608,7 +9130,7 @@ class WebRTCPhone extends Emitter {
8608
9130
  if (!sipSession) {
8609
9131
  return;
8610
9132
  }
8611
- logger$6.info('WebRTC turn camera on', { sipId: sipSession.id });
9133
+ logger$7.info('WebRTC turn camera on', { sipId: sipSession.id });
8612
9134
 
8613
9135
  this.client.toggleCameraOn(sipSession);
8614
9136
 
@@ -8620,7 +9142,7 @@ class WebRTCPhone extends Emitter {
8620
9142
  if (!sipSession) {
8621
9143
  return;
8622
9144
  }
8623
- logger$6.info('WebRTC turn camera off', { sipId: sipSession.id });
9145
+ logger$7.info('WebRTC turn camera off', { sipId: sipSession.id });
8624
9146
 
8625
9147
  this.client.toggleCameraOff(sipSession);
8626
9148
  this.eventEmitter.emit(ON_CAMERA_DISABLED, this._createCameraDisabledCallSession(sipSession, callSession));
@@ -8632,7 +9154,7 @@ class WebRTCPhone extends Emitter {
8632
9154
  return;
8633
9155
  }
8634
9156
 
8635
- logger$6.info('WebRTC send key', { sipId: sipSession.id, tone });
9157
+ logger$7.info('WebRTC send key', { sipId: sipSession.id, tone });
8636
9158
  this.client.sendDTMF(sipSession, tone);
8637
9159
  }
8638
9160
 
@@ -8640,7 +9162,7 @@ class WebRTCPhone extends Emitter {
8640
9162
  // @TODO: line is not used here
8641
9163
  async makeCall(number , line , cameraEnabled ,
8642
9164
  audioOnly = false, conference = false) {
8643
- logger$6.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9165
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8644
9166
  if (!number) {
8645
9167
  return Promise.resolve(null);
8646
9168
  }
@@ -8650,7 +9172,7 @@ class WebRTCPhone extends Emitter {
8650
9172
  }
8651
9173
  if (this.currentSipSession) {
8652
9174
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true).catch(e => {
8653
- logger$6.warn('Unable to hold current session when making another call', e);
9175
+ logger$7.warn('Unable to hold current session when making another call', e);
8654
9176
  });
8655
9177
  }
8656
9178
 
@@ -8660,7 +9182,7 @@ class WebRTCPhone extends Emitter {
8660
9182
  this._bindEvents(sipSession);
8661
9183
  } catch (error) {
8662
9184
  console.warn(error);
8663
- logger$6.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
9185
+ logger$7.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8664
9186
  return Promise.resolve(null);
8665
9187
  }
8666
9188
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
@@ -8688,7 +9210,7 @@ class WebRTCPhone extends Emitter {
8688
9210
  return;
8689
9211
  }
8690
9212
 
8691
- logger$6.info('WebRTC transfer', { sipId: sipSession.id, target });
9213
+ logger$7.info('WebRTC transfer', { sipId: sipSession.id, target });
8692
9214
 
8693
9215
  this.client.transfer(sipSession, target);
8694
9216
  }
@@ -8697,7 +9219,7 @@ class WebRTCPhone extends Emitter {
8697
9219
  const sipSession = this.client.getSipSession(source.sipCallId);
8698
9220
  const sipSessionTarget = this.client.getSipSession(destination.sipCallId);
8699
9221
 
8700
- logger$6.info('WebRTC indirect transfer', {
9222
+ logger$7.info('WebRTC indirect transfer', {
8701
9223
  sipId: sipSession ? sipSession.id : null,
8702
9224
  target: sipSessionTarget ? sipSessionTarget.id : null,
8703
9225
  });
@@ -8725,7 +9247,7 @@ class WebRTCPhone extends Emitter {
8725
9247
  return false;
8726
9248
  }
8727
9249
 
8728
- logger$6.info('WebRTC hangup', { sipId: sipSession.id });
9250
+ logger$7.info('WebRTC hangup', { sipId: sipSession.id });
8729
9251
 
8730
9252
  const sipSessionId = this.getSipSessionId(sipSession);
8731
9253
 
@@ -8770,7 +9292,7 @@ class WebRTCPhone extends Emitter {
8770
9292
  }
8771
9293
 
8772
9294
  async close() {
8773
- logger$6.info('WebRTC close');
9295
+ logger$7.info('WebRTC close');
8774
9296
 
8775
9297
  try {
8776
9298
  await Promise.race([
@@ -8778,7 +9300,7 @@ class WebRTCPhone extends Emitter {
8778
9300
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Unregister, timed out')), 3000)),
8779
9301
  ]);
8780
9302
  } catch (e) {
8781
- logger$6.error('WebRTC close, unregister error', e);
9303
+ logger$7.error('WebRTC close, unregister error', e);
8782
9304
  }
8783
9305
 
8784
9306
  this.client.close();
@@ -8796,12 +9318,12 @@ class WebRTCPhone extends Emitter {
8796
9318
  }
8797
9319
 
8798
9320
  enableRinging() {
8799
- logger$6.info('WebRTC enable ringing');
9321
+ logger$7.info('WebRTC enable ringing');
8800
9322
  this.ringingEnabled = true;
8801
9323
  }
8802
9324
 
8803
9325
  disableRinging() {
8804
- logger$6.info('WebRTC disable ringing');
9326
+ logger$7.info('WebRTC disable ringing');
8805
9327
  this.ringingEnabled = false;
8806
9328
  }
8807
9329
 
@@ -8841,7 +9363,7 @@ class WebRTCPhone extends Emitter {
8841
9363
 
8842
9364
  // Deprecated
8843
9365
  getLocalMediaStream(callSession ) {
8844
- logger$6.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
9366
+ logger$7.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
8845
9367
  return this.getLocalStream(callSession);
8846
9368
  }
8847
9369
 
@@ -8849,6 +9371,10 @@ class WebRTCPhone extends Emitter {
8849
9371
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
8850
9372
  }
8851
9373
 
9374
+ hasALocalVideoTrack(callSession ) {
9375
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
9376
+ }
9377
+
8852
9378
  getRemoteStream(callSession ) {
8853
9379
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
8854
9380
  }
@@ -8871,7 +9397,7 @@ class WebRTCPhone extends Emitter {
8871
9397
  this.client.on(this.client.INVITE, (sipSession , wantsToDoVideo ) => {
8872
9398
  const autoAnswer = sipSession.request.getHeader('Answer-Mode') === 'Auto';
8873
9399
  const withVideo = this.allowVideo ? wantsToDoVideo : false;
8874
- logger$6.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
9400
+ logger$7.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
8875
9401
 
8876
9402
  const callSession = this._createIncomingCallSession(sipSession, withVideo, null, autoAnswer);
8877
9403
  this.incomingSessions.push(callSession.getId());
@@ -8894,7 +9420,7 @@ class WebRTCPhone extends Emitter {
8894
9420
  });
8895
9421
 
8896
9422
  this.client.on(this.client.ON_REINVITE, (...args) => {
8897
- logger$6.info('WebRTC on reinvite', {
9423
+ logger$7.info('WebRTC on reinvite', {
8898
9424
  sessionId: args[0].id,
8899
9425
  inviteId: args[1].id,
8900
9426
  updatedCalleeName: args[2],
@@ -8914,7 +9440,7 @@ class WebRTCPhone extends Emitter {
8914
9440
  });
8915
9441
 
8916
9442
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
8917
- logger$6.info('WebRTC call accepted', { sipId: sipSession.id });
9443
+ logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
8918
9444
 
8919
9445
  this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
8920
9446
 
@@ -8925,17 +9451,17 @@ class WebRTCPhone extends Emitter {
8925
9451
  this.client.on('ended', () => {});
8926
9452
 
8927
9453
  this.client.on(this.client.ON_ERROR, e => {
8928
- logger$6.error('WebRTC error', e);
9454
+ logger$7.error('WebRTC error', e);
8929
9455
  this.eventEmitter.emit(ON_CALL_ERROR, e);
8930
9456
  });
8931
9457
 
8932
9458
  this.client.on(this.client.UNREGISTERED, () => {
8933
- logger$6.info('WebRTC unregistered');
9459
+ logger$7.info('WebRTC unregistered');
8934
9460
  this.eventEmitter.emit(ON_UNREGISTERED);
8935
9461
  });
8936
9462
 
8937
9463
  this.client.on(this.client.REGISTERED, () => {
8938
- logger$6.info('WebRTC registered', {
9464
+ logger$7.info('WebRTC registered', {
8939
9465
  shouldSendReinvite: this.shouldSendReinvite,
8940
9466
  state: this.currentSipSession ? this.currentSipSession.state : null,
8941
9467
  currentSipSession: !!this.currentSipSession,
@@ -8951,19 +9477,19 @@ class WebRTCPhone extends Emitter {
8951
9477
  try {
8952
9478
  this.sendReinvite(this.currentCallSession);
8953
9479
  } catch (e) {
8954
- logger$6.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9480
+ logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
8955
9481
  }
8956
9482
  }
8957
9483
  });
8958
9484
 
8959
9485
  this.client.on(this.client.CONNECTED, () => {
8960
- logger$6.info('WebRTC client connected');
9486
+ logger$7.info('WebRTC client connected');
8961
9487
 
8962
9488
  this.stopHeartbeat();
8963
9489
  });
8964
9490
 
8965
9491
  this.client.on(this.client.DISCONNECTED, () => {
8966
- logger$6.info('WebRTC client disconnected');
9492
+ logger$7.info('WebRTC client disconnected');
8967
9493
 
8968
9494
  this.eventEmitter.emit(ON_UNREGISTERED);
8969
9495
 
@@ -9195,7 +9721,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9195
9721
 
9196
9722
  //
9197
9723
 
9198
- const logger$5 = IssueReporter$1.loggerFor('simple-phone');
9724
+ const logger$6 = IssueReporter$1.loggerFor('simple-phone');
9199
9725
  const sipLogger = IssueReporter$1.loggerFor('sip.js');
9200
9726
  const protocolLogger = IssueReporter$1.loggerFor('sip');
9201
9727
 
@@ -9302,7 +9828,7 @@ class Phone extends Emitter {
9302
9828
  async disconnect() {
9303
9829
  if (this.phone) {
9304
9830
  if (this.phone.hasAnActiveCall()) {
9305
- logger$5.info('hangup call on disconnect');
9831
+ logger$6.info('hangup call on disconnect');
9306
9832
  // $FlowFixMe
9307
9833
  await this.phone.hangup();
9308
9834
  }
@@ -9325,13 +9851,13 @@ class Phone extends Emitter {
9325
9851
  }
9326
9852
 
9327
9853
  async hangup(callSession ) {
9328
- logger$5.info('hangup via simple phone', { callId: callSession.getId() });
9854
+ logger$6.info('hangup via simple phone', { callId: callSession.getId() });
9329
9855
 
9330
9856
  return this.phone && this.phone.hangup(callSession);
9331
9857
  }
9332
9858
 
9333
9859
  async accept(callSession , cameraEnabled ) {
9334
- logger$5.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9860
+ logger$6.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9335
9861
 
9336
9862
  return this.phone && this.phone.accept(callSession, cameraEnabled);
9337
9863
  }
@@ -9351,13 +9877,18 @@ class Phone extends Emitter {
9351
9877
  return adHocConference.start();
9352
9878
  }
9353
9879
 
9354
- mute(callSession ) {
9355
- this.muteViaAPI(callSession);
9880
+ mute(callSession , withApi = true) {
9881
+ if (withApi) {
9882
+ this.muteViaAPI(callSession);
9883
+ }
9884
+
9356
9885
  return this.phone && this.phone.mute(callSession);
9357
9886
  }
9358
9887
 
9359
- unmute(callSession ) {
9360
- this.unmuteViaAPI(callSession);
9888
+ unmute(callSession , withApi = true) {
9889
+ if (withApi) {
9890
+ this.unmuteViaAPI(callSession);
9891
+ }
9361
9892
 
9362
9893
  return this.phone && this.phone.unmute(callSession);
9363
9894
  }
@@ -9365,7 +9896,7 @@ class Phone extends Emitter {
9365
9896
  muteViaAPI(callSession ) {
9366
9897
  if (callSession && callSession.callId) {
9367
9898
  Wazo.getApiClient().calld.mute(callSession.callId).catch(e => {
9368
- logger$5.error('Mute via API, error', e);
9899
+ logger$6.error('Mute via API, error', e);
9369
9900
  });
9370
9901
  }
9371
9902
  }
@@ -9373,7 +9904,7 @@ class Phone extends Emitter {
9373
9904
  unmuteViaAPI(callSession ) {
9374
9905
  if (callSession && callSession.callId) {
9375
9906
  Wazo.getApiClient().calld.unmute(callSession.callId).catch(e => {
9376
- logger$5.error('Unmute via API, error', e);
9907
+ logger$6.error('Unmute via API, error', e);
9377
9908
  });
9378
9909
  }
9379
9910
  }
@@ -9463,9 +9994,13 @@ class Phone extends Emitter {
9463
9994
  return this.phone && this.phone.hasLocalVideo(callSession);
9464
9995
  }
9465
9996
 
9997
+ hasALocalVideoTrack(callSession ) {
9998
+ return this.phone && this.phone.hasALocalVideoTrack(callSession);
9999
+ }
10000
+
9466
10001
  // @Deprecated
9467
10002
  getLocalMediaStream(callSession ) {
9468
- logger$5.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
10003
+ logger$6.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9469
10004
 
9470
10005
  return this.phone && this.phone.getLocalStream(callSession);
9471
10006
  }
@@ -9484,20 +10019,20 @@ class Phone extends Emitter {
9484
10019
 
9485
10020
  // @Deprecated
9486
10021
  getRemoteStreamForCall(callSession ) {
9487
- logger$5.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
10022
+ logger$6.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9488
10023
  return this.getRemoteStream(callSession);
9489
10024
  }
9490
10025
 
9491
10026
  // Returns remote streams directly from the peerConnection
9492
10027
  // @Deprecated
9493
10028
  getRemoteStreamsForCall(callSession ) {
9494
- logger$5.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
10029
+ logger$6.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9495
10030
  return this.getLocalStream(callSession);
9496
10031
  }
9497
10032
 
9498
10033
  // @Deprecated
9499
10034
  getRemoteVideoStreamForCall(callSession ) {
9500
- logger$5.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
10035
+ logger$6.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9501
10036
 
9502
10037
  return this.getRemoteVideoStream(callSession);
9503
10038
  }
@@ -9627,6 +10162,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
9627
10162
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
9628
10163
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
9629
10164
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
10165
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
10166
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
9630
10167
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
9631
10168
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
9632
10169
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -9668,7 +10205,7 @@ const BLACKLIST_EVENTS = [
9668
10205
  ];
9669
10206
 
9670
10207
  const HEARTBEAT_ENGINE_VERSION = '20.09';
9671
- const logger$4 = IssueReporter$1.loggerFor('wazo-ws');
10208
+ const logger$5 = IssueReporter$1.loggerFor('wazo-ws');
9672
10209
  const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
9673
10210
 
9674
10211
  class WebSocketClient extends Emitter {
@@ -9717,19 +10254,19 @@ class WebSocketClient extends Emitter {
9717
10254
  }
9718
10255
 
9719
10256
  connect() {
9720
- logger$4.info('connect method started', { host: this.host, token: this.token });
10257
+ logger$5.info('connect method started', { host: this.host, token: this.token });
9721
10258
  this.socket = new ReconnectingWebSocket(this._getUrl.bind(this), [], this.options);
9722
10259
  if (this.options.binaryType) {
9723
10260
  this.socket.binaryType = this.options.binaryType;
9724
10261
  }
9725
10262
 
9726
10263
  this.socket.onopen = () => {
9727
- logger$4.info('on Wazo WS open', { method: 'connect', host: this.host });
10264
+ logger$5.info('on Wazo WS open', { method: 'connect', host: this.host });
9728
10265
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_OPEN);
9729
10266
  };
9730
10267
 
9731
10268
  this.socket.onerror = event => {
9732
- logger$4.error('on Wazo WS error', event.target);
10269
+ logger$5.error('on Wazo WS error', event.target);
9733
10270
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_ERROR, event);
9734
10271
  };
9735
10272
 
@@ -9759,7 +10296,7 @@ class WebSocketClient extends Emitter {
9759
10296
 
9760
10297
  this.socket.onclose = event => {
9761
10298
  // Can't be converted to JSON (circular structure)
9762
- logger$4.info('on Wazo WS close', {
10299
+ logger$5.info('on Wazo WS close', {
9763
10300
  reason: event.reason,
9764
10301
  code: event.code,
9765
10302
  readyState: event.target.readyState,
@@ -9777,12 +10314,12 @@ class WebSocketClient extends Emitter {
9777
10314
  };
9778
10315
 
9779
10316
  this.socket.onerror = event => {
9780
- logger$4.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
10317
+ logger$5.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
9781
10318
  };
9782
10319
  }
9783
10320
 
9784
10321
  close(force = false) {
9785
- logger$4.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
10322
+ logger$5.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
9786
10323
 
9787
10324
  if (!this.socket) {
9788
10325
  return;
@@ -9800,7 +10337,7 @@ class WebSocketClient extends Emitter {
9800
10337
 
9801
10338
  updateToken(token ) {
9802
10339
  this.token = token;
9803
- logger$4.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
10340
+ logger$5.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
9804
10341
 
9805
10342
  if (this.socket) {
9806
10343
  // If still connected, send the token to the WS
@@ -9818,7 +10355,7 @@ class WebSocketClient extends Emitter {
9818
10355
  }
9819
10356
 
9820
10357
  startHeartbeat() {
9821
- logger$4.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
10358
+ logger$5.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
9822
10359
 
9823
10360
  if (!this.socket) {
9824
10361
  this.heartbeat.stop();
@@ -9832,7 +10369,7 @@ class WebSocketClient extends Emitter {
9832
10369
  }
9833
10370
 
9834
10371
  stopHeartbeat() {
9835
- logger$4.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
10372
+ logger$5.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
9836
10373
 
9837
10374
  this.heartbeat.stop();
9838
10375
  }
@@ -9862,7 +10399,7 @@ class WebSocketClient extends Emitter {
9862
10399
  }
9863
10400
 
9864
10401
  reconnect(reason ) {
9865
- logger$4.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
10402
+ logger$5.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
9866
10403
  if (!this.socket) {
9867
10404
  return;
9868
10405
  }
@@ -9918,7 +10455,7 @@ class WebSocketClient extends Emitter {
9918
10455
  this.close();
9919
10456
  }
9920
10457
  const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
9921
- logger$4.log('Wazo WS url computed to reconnect', { url });
10458
+ logger$5.log('Wazo WS url computed to reconnect', { url });
9922
10459
 
9923
10460
  return url;
9924
10461
  }
@@ -9926,12 +10463,12 @@ class WebSocketClient extends Emitter {
9926
10463
  _onHeartbeat(message ) {
9927
10464
  if (message.payload === 'pong') {
9928
10465
  this.heartbeat.onHeartbeat();
9929
- logger$4.log('on heartbeat received from Wazo WS');
10466
+ logger$5.log('on heartbeat received from Wazo WS');
9930
10467
  }
9931
10468
  }
9932
10469
 
9933
10470
  async _onHeartbeatTimeout() {
9934
- logger$4.log('heartbeat timed out', { host: this.host, token: this.token });
10471
+ logger$5.log('heartbeat timed out', { host: this.host, token: this.token });
9935
10472
 
9936
10473
  this.close();
9937
10474
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_CLOSE, new Error('Websocket ping failure.'));
@@ -9973,6 +10510,8 @@ WebSocketClient.eventLists = [
9973
10510
  CHATD_USER_ROOM_CREATED,
9974
10511
  CONFERENCE_USER_PARTICIPANT_JOINED,
9975
10512
  CONFERENCE_USER_PARTICIPANT_LEFT,
10513
+ MEETING_USER_PARTICIPANT_JOINED,
10514
+ MEETING_USER_PARTICIPANT_LEFT,
9976
10515
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9977
10516
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
9978
10517
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -10043,6 +10582,8 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10043
10582
  CONFERENCE_USER_PARTICIPANT_LEFT: CONFERENCE_USER_PARTICIPANT_LEFT,
10044
10583
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED: CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
10045
10584
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED: CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
10585
+ MEETING_USER_PARTICIPANT_JOINED: MEETING_USER_PARTICIPANT_JOINED,
10586
+ MEETING_USER_PARTICIPANT_LEFT: MEETING_USER_PARTICIPANT_LEFT,
10046
10587
  SWITCHBOARD_QUEUED_CALLS_UPDATED: SWITCHBOARD_QUEUED_CALLS_UPDATED,
10047
10588
  SWITCHBOARD_QUEUED_CALL_ANSWERED: SWITCHBOARD_QUEUED_CALL_ANSWERED,
10048
10589
  SWITCHBOARD_HELD_CALLS_UPDATED: SWITCHBOARD_HELD_CALLS_UPDATED,
@@ -10084,7 +10625,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10084
10625
  const { SOCKET_EVENTS, ...OTHER_EVENTS } = WebSocketClient$1;
10085
10626
  const ALL_EVENTS = [...Object.values(SOCKET_EVENTS), ...Object.values(OTHER_EVENTS)];
10086
10627
 
10087
- const logger$3 = IssueReporter$1.loggerFor('simple-ws-client');
10628
+ const logger$4 = IssueReporter$1.loggerFor('simple-ws-client');
10088
10629
 
10089
10630
  class Websocket extends Emitter {
10090
10631
 
@@ -10108,7 +10649,7 @@ class Websocket extends Emitter {
10108
10649
  }
10109
10650
 
10110
10651
  open(host , session ) {
10111
- logger$3.info('open simple WebSocket', { host, token: session.token });
10652
+ logger$4.info('open simple WebSocket', { host, token: session.token });
10112
10653
  this.ws = new WebSocketClient(
10113
10654
  {
10114
10655
  host,
@@ -10136,7 +10677,7 @@ class Websocket extends Emitter {
10136
10677
  }
10137
10678
 
10138
10679
  updateToken(token ) {
10139
- logger$3.info('update token via simple Websocket', { token, ws: !!this.ws });
10680
+ logger$4.info('update token via simple Websocket', { token, ws: !!this.ws });
10140
10681
 
10141
10682
  if (!this.ws) {
10142
10683
  return;
@@ -10164,6 +10705,145 @@ var Websocket$1 = global.wazoWebsocketInstance;
10164
10705
 
10165
10706
  //
10166
10707
 
10708
+ const logger$3 = IssueReporter$1.loggerFor('sdk-sip-room');
10709
+
10710
+ class SipRoom extends Room {
10711
+
10712
+ static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
10713
+ logger$3.info('connecting to sip room', { extension, audioOnly, room: !!room });
10714
+
10715
+ if (!room) {
10716
+ await Wazo.Phone.connect();
10717
+
10718
+ const withCamera = constraints && !!constraints.video;
10719
+
10720
+ const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
10721
+ // eslint-disable-next-line no-param-reassign
10722
+ room = new SipRoom(callSession, extension, null, null, extra);
10723
+ }
10724
+
10725
+ if (room && room.callSession && room.callSession.call) {
10726
+ room.setCallId(room.callSession.call.id);
10727
+ }
10728
+
10729
+ logger$3.info('connected to room', {
10730
+ extension: room.extension,
10731
+ });
10732
+
10733
+ return room;
10734
+ }
10735
+
10736
+ mute() {
10737
+ logger$3.info('mute sip room');
10738
+
10739
+ Wazo.Phone.mute(this.callSession, false);
10740
+
10741
+ this.sendMuteStatus();
10742
+ }
10743
+
10744
+ unmute() {
10745
+ logger$3.info('unmute sip room');
10746
+
10747
+ Wazo.Phone.unmute(this.callSession, false);
10748
+
10749
+ this.sendUnMuteStatus();
10750
+ }
10751
+
10752
+ getLocalGuestName() {
10753
+ return Wazo.Phone.phone.client.userAgent.options.displayName;
10754
+ }
10755
+
10756
+ // Overridden to not listen to websocket messages
10757
+ _transferEvents() {
10758
+ // Phone events
10759
+ Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
10760
+ Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
10761
+ Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
10762
+ Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
10763
+
10764
+ [this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
10765
+ Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
10766
+ }
10767
+
10768
+ _onMessage(message ) {
10769
+ // eslint-disable-next-line no-underscore-dangle
10770
+ const body = super._onMessage(message);
10771
+ if (!body) {
10772
+ return;
10773
+ }
10774
+
10775
+ const getChannel = () => body.channels[0];
10776
+
10777
+ switch (body.type) {
10778
+ case 'ConfbridgeWelcome':
10779
+ body.channels.forEach(channel => {
10780
+ this._onParticipantJoined(channel);
10781
+ });
10782
+
10783
+ break;
10784
+ case 'ConfbridgeJoin': {
10785
+ const channel = getChannel();
10786
+ this._onParticipantJoined(channel);
10787
+ break;
10788
+ }
10789
+ case 'ConfbridgeLeave': {
10790
+ const channel = getChannel();
10791
+ this._onParticipantLeft({
10792
+ data: {
10793
+ call_id: channel.id,
10794
+ },
10795
+ });
10796
+ break;
10797
+ }
10798
+ }
10799
+ }
10800
+
10801
+ async _onParticipantJoined(channel ) {
10802
+ const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
10803
+ const callId = channel.id;
10804
+ const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
10805
+ const name = channel.caller ? channel.caller.name : null;
10806
+ const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
10807
+ const participant = new ParticipantClass(this, {
10808
+ caller_id_name: name,
10809
+ call_id: callId,
10810
+ }, extra);
10811
+
10812
+ const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
10813
+ if (participantIdx !== -1 && name) {
10814
+ this.participants[participantIdx].name = name;
10815
+ return;
10816
+ }
10817
+
10818
+ if (isLocal) {
10819
+ // Should be updated by the Wazo WS but we don't have it for now
10820
+ if (this.callSession) {
10821
+ this.callSession.ringing = false;
10822
+ }
10823
+
10824
+ this._onLocalParticipantJoined(participant);
10825
+
10826
+ // Give some time for the stream to be updated
10827
+ setTimeout(() => {
10828
+ this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
10829
+ }, 1000);
10830
+ }
10831
+
10832
+ this.participants.push(participant);
10833
+
10834
+ this._isParticipantJoining(participant);
10835
+
10836
+ return participant;
10837
+ }
10838
+
10839
+ _getCurrentSipCallIs() {
10840
+ return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
10841
+ }
10842
+
10843
+ }
10844
+
10845
+ //
10846
+
10167
10847
  class RemoteParticipant extends Participant {
10168
10848
  constructor(room , rawParticipant = {}, extra = {}) {
10169
10849
  super(room, rawParticipant, extra);
@@ -10228,9 +10908,7 @@ class Stream {
10228
10908
  return false;
10229
10909
  }
10230
10910
 
10231
- // With canvas track (used to fake upgrade in conference), we don't have a width
10232
- return this.htmlStream.getTracks().find(track => track.kind === 'video'
10233
- && track.readyState !== 'ended' && 'width' in track.getSettings());
10911
+ return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
10234
10912
  }
10235
10913
 
10236
10914
  get id() {
@@ -11131,6 +11809,7 @@ const Wazo = {
11131
11809
  Phone: Phone$1,
11132
11810
  Websocket: Websocket$1,
11133
11811
  Room,
11812
+ SipRoom,
11134
11813
  RemoteParticipant,
11135
11814
  LocalParticipant,
11136
11815
  Stream,
@@ -11150,6 +11829,7 @@ const Wazo = {
11150
11829
  ServerError,
11151
11830
  Call,
11152
11831
  CallLog,
11832
+ CTIPhone,
11153
11833
  Recording,
11154
11834
  ChatMessage,
11155
11835
  ChatRoom,
@@ -11165,6 +11845,8 @@ const Wazo = {
11165
11845
  CallSession,
11166
11846
  IndirectTransfer,
11167
11847
  SwitchboardCall,
11848
+ WebRTCPhone,
11849
+ Meeting,
11168
11850
  },
11169
11851
 
11170
11852
  // Api
@@ -11193,7 +11875,7 @@ if (global) {
11193
11875
  global.Wazo = Wazo;
11194
11876
  }
11195
11877
 
11196
- /* global document */
11878
+ //
11197
11879
 
11198
11880
  const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
11199
11881
  const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
@@ -11205,6 +11887,7 @@ class Room extends Emitter {
11205
11887
 
11206
11888
 
11207
11889
 
11890
+
11208
11891
 
11209
11892
 
11210
11893
 
@@ -11226,6 +11909,8 @@ class Room extends Emitter {
11226
11909
 
11227
11910
 
11228
11911
 
11912
+
11913
+
11229
11914
 
11230
11915
 
11231
11916
 
@@ -11243,6 +11928,7 @@ class Room extends Emitter {
11243
11928
  * @param extension string
11244
11929
  * @param sourceId number
11245
11930
  * @param callId string
11931
+ * @param meetingUuid string
11246
11932
  * @param extra Object
11247
11933
  */
11248
11934
  constructor(
@@ -11250,15 +11936,17 @@ class Room extends Emitter {
11250
11936
  extension ,
11251
11937
  sourceId ,
11252
11938
  callId ,
11939
+ meetingUuid ,
11253
11940
  extra = {},
11254
11941
  ) {
11255
11942
  super();
11256
- logger$1.info('room initialized', { callId, extension, sourceId });
11943
+ logger$1.info('room initialized', { callId, extension, sourceId, meetingUuid });
11257
11944
 
11258
11945
  // Represents the room callSession
11259
11946
  this.callSession = callSession;
11260
11947
  this.extension = extension;
11261
11948
  this.sourceId = sourceId;
11949
+ this.meetingUuid = meetingUuid;
11262
11950
  this.callId = callId;
11263
11951
  this.participants = [];
11264
11952
  this.connected = false;
@@ -11278,6 +11966,8 @@ class Room extends Emitter {
11278
11966
  // Sugar syntax for `room.EVENT_NAME`
11279
11967
  this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
11280
11968
  this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
11969
+ this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
11970
+ this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
11281
11971
  this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
11282
11972
  this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
11283
11973
  this.ON_CHAT = Wazo.Phone.ON_CHAT;
@@ -11312,9 +12002,10 @@ class Room extends Emitter {
11312
12002
  * @param audioOnly boolean
11313
12003
  * @param extra Object
11314
12004
  * @param room ?Room
12005
+ * @param meeting ?Meeting
11315
12006
  * @returns {Promise<Room>}
11316
12007
  */
11317
- static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
12008
+ static async connect({ extension, constraints, audioOnly = false, extra, room, meeting } ) {
11318
12009
  logger$1.info('connecting to room', { extension, audioOnly, room: !!room });
11319
12010
 
11320
12011
  if (!room) {
@@ -11349,21 +12040,31 @@ class Room extends Emitter {
11349
12040
  room.setCallId(room.callSession.call.id);
11350
12041
  }
11351
12042
 
11352
- // Fetch conference source
11353
- const sources = await getApiClient().dird.fetchConferenceSource('default');
11354
- // Retrieve conference sources
11355
- const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
11356
- // Retrieve conference
11357
- const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
12043
+ if (!meeting) {
12044
+ // Fetch conference source
12045
+ const sources = await getApiClient().dird.fetchConferenceSource('default');
12046
+ // Retrieve conference sources
12047
+ const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
12048
+ // Retrieve conference
12049
+ const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
11358
12050
 
11359
- logger$1.info('connected to room', {
11360
- sourceId: conference ? conference.sourceId : null,
11361
- name: conference ? conference.name : null,
11362
- });
12051
+ logger$1.info('connected to room', {
12052
+ sourceId: conference ? conference.sourceId : null,
12053
+ name: conference ? conference.name : null,
12054
+ });
11363
12055
 
11364
- if (conference) {
11365
- room.setSourceId(conference.sourceId);
11366
- room.setName(conference.name);
12056
+ if (conference) {
12057
+ room.setSourceId(conference.sourceId);
12058
+ room.setName(conference.name);
12059
+ }
12060
+ } else if (meeting) {
12061
+ logger$1.info('Already connected to meeting', {
12062
+ uuid: meeting.uuid,
12063
+ name: meeting.name,
12064
+ });
12065
+
12066
+ room.setMeetingUuid(meeting.uuid);
12067
+ room.setName(meeting.name);
11367
12068
  }
11368
12069
 
11369
12070
  return room;
@@ -11391,10 +12092,8 @@ class Room extends Emitter {
11391
12092
  Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
11392
12093
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11393
12094
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11394
-
11395
- if (this.roomAudioElement && document.body) {
11396
- document.body.removeChild(this.roomAudioElement);
11397
- }
12095
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
12096
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11398
12097
  }
11399
12098
 
11400
12099
  setSourceId(sourceId ) {
@@ -11403,6 +12102,12 @@ class Room extends Emitter {
11403
12102
  this.sourceId = sourceId;
11404
12103
  }
11405
12104
 
12105
+ setMeetingUuid(meetingUuid ) {
12106
+ logger$1.info('set meeting uuid', { meetingUuid });
12107
+
12108
+ this.meetingUuid = meetingUuid;
12109
+ }
12110
+
11406
12111
  setCallId(callId ) {
11407
12112
  logger$1.info('set room call id', { callId });
11408
12113
 
@@ -11444,14 +12149,22 @@ class Room extends Emitter {
11444
12149
  return screensharingStream;
11445
12150
  }
11446
12151
 
11447
- stopScreenSharing(restoreLocalStream = true) {
12152
+ async stopScreenSharing(restoreLocalStream = true) {
11448
12153
  logger$1.info('stop room screen sharing');
11449
12154
 
11450
- Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
12155
+ const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
11451
12156
 
11452
12157
  if (this.localParticipant) {
11453
12158
  this.localParticipant.onStopScreensharing();
11454
12159
  }
12160
+
12161
+ if (!reinvited && this.localParticipant) {
12162
+ // When we had video and we made a screenshare we don't reinvite when stopping the screensahre
12163
+ // So not REINVITE even is fired, we have to restore the video stream manually
12164
+ const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
12165
+ // $FlowFixMe
12166
+ this._associateStreamTo(localVideoStream, this.localParticipant);
12167
+ }
11455
12168
  }
11456
12169
 
11457
12170
  turnCameraOff() {
@@ -11554,6 +12267,22 @@ class Room extends Emitter {
11554
12267
  return response;
11555
12268
  }
11556
12269
 
12270
+ hasALocalVideoTrack() {
12271
+ return Wazo.Phone.hasALocalVideoTrack(this.callSession);
12272
+ }
12273
+
12274
+ getLocalStream() {
12275
+ return Wazo.Phone.getLocalStream(this.callSession);
12276
+ }
12277
+
12278
+ getRemoteStream() {
12279
+ return Wazo.Phone.getRemoteStream(this.callSession);
12280
+ }
12281
+
12282
+ getRemoteVideoStream() {
12283
+ return Wazo.Phone.getRemoteVideoStream(this.callSession);
12284
+ }
12285
+
11557
12286
  _bindEvents() {
11558
12287
  if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
11559
12288
  return;
@@ -11575,27 +12304,10 @@ class Room extends Emitter {
11575
12304
  logger$1.info('on room audio stream');
11576
12305
 
11577
12306
  this.audioStream = stream;
11578
- if (document.createElement) {
11579
- // $FlowFixMe
11580
- let roomAudioElement = document.getElementById('audio-room');
11581
- if (!this.roomAudioElement) {
11582
- roomAudioElement = document.createElement('audio');
11583
- // $FlowFixMe
11584
- document.body.appendChild(roomAudioElement);
11585
- }
11586
- if (!roomAudioElement) {
11587
- return;
11588
- }
11589
- this.roomAudioElement = roomAudioElement;
12307
+ if (!this.roomAudioElement) {
12308
+ const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
12309
+ this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
11590
12310
  this.roomAudioElement.srcObject = stream;
11591
- this.roomAudioElement.autoplay = true;
11592
- this.roomAudioElement.id = 'audio-room';
11593
-
11594
- // $FlowFixMe
11595
- if (this.roomAudioElement.setSinkId) {
11596
- // $FlowFixMe
11597
- this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
11598
- }
11599
12311
  }
11600
12312
  });
11601
12313
 
@@ -11670,6 +12382,9 @@ class Room extends Emitter {
11670
12382
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11671
12383
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11672
12384
 
12385
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
12386
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
12387
+
11673
12388
  // Phone events
11674
12389
  Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
11675
12390
  Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
@@ -11680,15 +12395,15 @@ class Room extends Emitter {
11680
12395
  Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
11681
12396
  }
11682
12397
 
11683
- _onMessage(message ) {
12398
+ _onMessage(message ) {
11684
12399
  if (message.method !== 'MESSAGE') {
11685
- return;
12400
+ return null;
11686
12401
  }
11687
12402
  let body;
11688
12403
  try {
11689
12404
  body = JSON.parse(message.body);
11690
12405
  } catch (e) {
11691
- return;
12406
+ return null;
11692
12407
  }
11693
12408
 
11694
12409
  switch (body.type) {
@@ -11707,6 +12422,8 @@ class Room extends Emitter {
11707
12422
  }
11708
12423
 
11709
12424
  this.eventEmitter.emit(this.ON_MESSAGE, body);
12425
+
12426
+ return body;
11710
12427
  }
11711
12428
 
11712
12429
  _onChat(content ) {
@@ -11771,23 +12488,24 @@ class Room extends Emitter {
11771
12488
  const session = Wazo.Auth.getSession();
11772
12489
  let participants = [];
11773
12490
 
11774
- // @TODO: we could use a better function name here
11775
- const isJoining = part => {
11776
- this.__associateStreams(part);
11777
- // @VALIDATE: no need to publicize ourselves, no?
11778
- if (part instanceof RemoteParticipant) {
11779
- this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
11780
- }
11781
- };
11782
-
11783
12491
  // When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
11784
12492
  if (participant.user_uuid === session.uuid) {
11785
12493
  logger$1.info('room current user joined');
11786
12494
 
11787
12495
  // Retrieve participants via an API calls
11788
12496
  const conferenceId = this.sourceId || payload.data.conference_id;
11789
- const response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
11790
- logger$1.info('fetching conference participants', { conferenceId });
12497
+ let response;
12498
+ try {
12499
+ if (this.meetingUuid) {
12500
+ logger$1.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
12501
+ response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
12502
+ } else {
12503
+ logger$1.info('fetching conference participants', { conferenceId });
12504
+ response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
12505
+ }
12506
+ } catch (e) {
12507
+ logger$1.error('room participants fetching, error', e);
12508
+ }
11791
12509
  if (response) {
11792
12510
  logger$1.info('conference participants fetched', { nb: response.items.length });
11793
12511
  participants = response.items.map(item => {
@@ -11802,25 +12520,10 @@ class Room extends Emitter {
11802
12520
 
11803
12521
  const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
11804
12522
  if (!this.localParticipant && localParticipant) {
11805
- this.localParticipant = localParticipant;
11806
-
11807
- const localVideoStream = this._getLocalVideoStream();
11808
- if (localVideoStream) {
11809
- this._saveLocalVideoStream(localVideoStream);
11810
- }
11811
-
11812
- this.connected = true;
11813
-
11814
- // we're in the room, now let's request everyone's status
11815
- if (this.localParticipant) {
11816
- this.sendSignal({
11817
- type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
11818
- origin: this.localParticipant.getStatus(),
11819
- });
11820
- }
12523
+ this._onLocalParticipantJoined(localParticipant);
11821
12524
  }
11822
12525
 
11823
- participants.forEach(someParticipant => isJoining(someParticipant));
12526
+ participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
11824
12527
  this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
11825
12528
  }
11826
12529
 
@@ -11835,12 +12538,41 @@ class Room extends Emitter {
11835
12538
 
11836
12539
  if (remoteParticipant) {
11837
12540
  this.participants.push(remoteParticipant);
11838
- isJoining(remoteParticipant);
12541
+ this._isParticipantJoining(remoteParticipant);
11839
12542
  }
11840
12543
 
11841
12544
  return remoteParticipant;
11842
12545
  }
11843
12546
 
12547
+ _onLocalParticipantJoined(localParticipant ) {
12548
+ this.localParticipant = localParticipant;
12549
+
12550
+ const localVideoStream = this._getLocalVideoStream();
12551
+ if (localVideoStream) {
12552
+ this._saveLocalVideoStream(localVideoStream);
12553
+ }
12554
+
12555
+ this.connected = true;
12556
+
12557
+ localParticipant.broadcastStatus();
12558
+
12559
+ // we're in the room, now let's request everyone's status
12560
+ if (this.localParticipant) {
12561
+ this.sendSignal({
12562
+ type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
12563
+ origin: this.localParticipant.getStatus(),
12564
+ });
12565
+ }
12566
+ }
12567
+
12568
+ _isParticipantJoining(participant ) {
12569
+ this.__associateStreams(participant);
12570
+ // @VALIDATE: no need to publicize ourselves, no?
12571
+ if (participant instanceof RemoteParticipant) {
12572
+ this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
12573
+ }
12574
+ }
12575
+
11844
12576
  _saveLocalVideoStream(stream ) {
11845
12577
  const { localParticipant } = this;
11846
12578
 
@@ -11886,9 +12618,11 @@ class Room extends Emitter {
11886
12618
  _onParticipantTrackUpdate(oldParticipant , update ) {
11887
12619
  const newParticipant = oldParticipant;
11888
12620
 
11889
- const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
12621
+ const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
11890
12622
  const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
11891
- const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
12623
+ // Can't use `getReceivers` here because on FF we make the mapping based on the streamId
12624
+ const stream = pc.getRemoteStreams().find(someStream =>
12625
+ someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
11892
12626
 
11893
12627
  if (update === 'downgrade') {
11894
12628
  newParticipant.streams = [];
@@ -11918,15 +12652,41 @@ class Room extends Emitter {
11918
12652
  return;
11919
12653
  }
11920
12654
 
11921
- if (this._unassociatedVideoStreams[trackId]) {
12655
+ const streamId = this._getStreamIdFrTrackId(trackId);
12656
+ const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
12657
+ const stream = this._unassociatedVideoStreams[key];
12658
+
12659
+ if (stream) {
11922
12660
  // Try to associate stream
11923
- this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
12661
+ this._associateStreamTo(stream, participant);
11924
12662
 
11925
- delete this._unassociatedVideoStreams[trackId];
12663
+ delete this._unassociatedVideoStreams[key];
11926
12664
  delete this._unassociatedParticipants[participant.callId];
11927
12665
  }
11928
12666
  }
11929
12667
 
12668
+ _getUnassociatedMapIdFromTrackIdOrStreamId(trackId , streamId ) {
12669
+ // Find by trackId
12670
+ if (trackId in this._unassociatedVideoStreams) {
12671
+ return trackId;
12672
+ }
12673
+
12674
+ // Find by streamId
12675
+ if (streamId && streamId in this._unassociatedVideoStreams) {
12676
+ return streamId;
12677
+ }
12678
+
12679
+ // Find in all the streams by streamId (used on FF where we can't map by trackId)
12680
+ const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream ) => stream.id === streamId);
12681
+ return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
12682
+ }
12683
+
12684
+ _getStreamIdFrTrackId(trackId ) {
12685
+ const mapping = Object.values(this._callIdStreamIdMap).find((map ) => map.trackId === trackId);
12686
+
12687
+ return mapping ? mapping.streamId : null;
12688
+ }
12689
+
11930
12690
  _associateStreamTo(rawStream , participant ) {
11931
12691
  const stream = new Wazo.Stream(rawStream, participant);
11932
12692
  participant.streams.push(stream);
@@ -11984,6 +12744,7 @@ class Participant extends Emitter {
11984
12744
 
11985
12745
 
11986
12746
  /**
12747
+ * @param room Room The room where the participant is
11987
12748
  * @param rawParticipant string Participant sent via the Wazo WS
11988
12749
  * @param extra Object extra status of the participant
11989
12750
  */
@@ -12211,6 +12972,11 @@ class Participant extends Emitter {
12211
12972
  // Poor man's object comparison
12212
12973
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
12213
12974
  this.extra = { ...this.extra, ...status.extra };
12975
+
12976
+ if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
12977
+ this.extra.contact = new Contact(this.extra.contact);
12978
+ }
12979
+
12214
12980
  this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
12215
12981
  }
12216
12982
  }