@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
@@ -1819,7 +1819,13 @@ class IssueReporter {
1819
1819
  }
1820
1820
 
1821
1821
  _isLevelAbove(level1 , level2 ) {
1822
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
1822
+ const index1 = LOG_LEVELS.indexOf(level1);
1823
+ const index2 = LOG_LEVELS.indexOf(level2);
1824
+ if (index1 === -1 || index2 === -1) {
1825
+ return false;
1826
+ }
1827
+
1828
+ return index1 > index2;
1823
1829
  }
1824
1830
 
1825
1831
  _makeCategory(category ) {
@@ -1842,7 +1848,7 @@ var IssueReporter$1 = new IssueReporter();
1842
1848
 
1843
1849
  const methods = ['head', 'get', 'post', 'put', 'delete'];
1844
1850
 
1845
- const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1851
+ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1846
1852
 
1847
1853
  // Use a function here to be able to mock it in tests
1848
1854
  const realFetch = () => {
@@ -1981,7 +1987,7 @@ class ApiRequester {
1981
1987
  };
1982
1988
 
1983
1989
  if (this.refreshTokenPromise) {
1984
- logger$a.info('A token is already refreshing, waiting ...', { url });
1990
+ logger$c.info('A token is already refreshing, waiting ...', { url });
1985
1991
  await this.refreshTokenPromise;
1986
1992
  }
1987
1993
 
@@ -2001,7 +2007,7 @@ class ApiRequester {
2001
2007
  return promise.then(async (err ) => {
2002
2008
  // Check if the token is still valid
2003
2009
  if (firstCall && this._checkTokenExpired(response, err)) {
2004
- logger$a.warn('token expired', { error: err.reason });
2010
+ logger$c.warn('token expired', { error: err.reason });
2005
2011
  // Replay the call after refreshing the token
2006
2012
  return this._replayWithNewToken(err, path, method, body, headers, parse);
2007
2013
  }
@@ -2011,7 +2017,7 @@ class ApiRequester {
2011
2017
  : exceptionClass.fromResponse(err, response.status);
2012
2018
 
2013
2019
  if (this.shouldLogErrors) {
2014
- logger$a.error('API error', error);
2020
+ logger$c.error('API error', error);
2015
2021
  }
2016
2022
 
2017
2023
  throw error;
@@ -2021,7 +2027,7 @@ class ApiRequester {
2021
2027
  return newParse(response, isJson);
2022
2028
  }).catch(error => {
2023
2029
  if (this.shouldLogErrors) {
2024
- logger$a.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
2030
+ logger$c.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
2025
2031
  }
2026
2032
 
2027
2033
  throw error;
@@ -2049,13 +2055,13 @@ class ApiRequester {
2049
2055
  ) {
2050
2056
  const isTokenNotFound = this._isTokenNotFound(err);
2051
2057
  let newPath = path;
2052
- logger$a.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
2058
+ logger$c.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
2053
2059
 
2054
2060
  this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
2055
2061
 
2056
2062
  return this.refreshTokenPromise.then(() => {
2057
2063
  this.refreshTokenPromise = null;
2058
- logger$a.info('token refreshed', { isTokenNotFound });
2064
+ logger$c.info('token refreshed', { isTokenNotFound });
2059
2065
  if (isTokenNotFound) {
2060
2066
  const pathParts = path.split('/');
2061
2067
  pathParts.pop();
@@ -2516,6 +2522,65 @@ class ExternalApp {
2516
2522
  }
2517
2523
  }
2518
2524
 
2525
+ //
2526
+
2527
+
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+ class Meeting {
2538
+
2539
+
2540
+
2541
+
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+ static parse(plain ) {
2549
+ return new Meeting({
2550
+ guestSipAuthorization: plain.guest_sip_authorization,
2551
+ hostname: plain.hostname,
2552
+ name: plain.name,
2553
+ ownerUuids: plain.owner_uuids,
2554
+ port: plain.port,
2555
+ uuid: plain.uuid,
2556
+ number: plain.number,
2557
+ });
2558
+ }
2559
+
2560
+ static newFrom(meeting ) {
2561
+ return newFrom(meeting, Meeting);
2562
+ }
2563
+
2564
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2565
+ this.guestSipAuthorization = guestSipAuthorization;
2566
+ this.hostname = hostname;
2567
+ this.name = name;
2568
+ this.ownerUuids = ownerUuids;
2569
+ this.port = port;
2570
+ this.uuid = uuid;
2571
+ this.number = number;
2572
+
2573
+ // Useful to compare instead of instanceof with minified code
2574
+ this.type = 'Meeting';
2575
+ }
2576
+
2577
+ getGuestSipCredentials() {
2578
+ // eslint-disable-next-line no-undef
2579
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2580
+ return { username, secret };
2581
+ }
2582
+ }
2583
+
2519
2584
  /* */
2520
2585
 
2521
2586
  var confdMethods = (client , baseUrl ) => ({
@@ -2580,6 +2645,18 @@ var confdMethods = (client , baseUrl ) => ({
2580
2645
  return null;
2581
2646
  }
2582
2647
  },
2648
+
2649
+ createMyMeeting: (name ) =>
2650
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2651
+
2652
+ deleteMyMeeting: (meetingUuid ) =>
2653
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2654
+
2655
+ getMeeting: (meetingUuid ) =>
2656
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2657
+
2658
+ guestGetMeeting: (meetingUuid ) =>
2659
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2583
2660
  });
2584
2661
 
2585
2662
  //
@@ -3337,7 +3414,7 @@ class CallSession {
3337
3414
  return newFrom(callSession, CallSession);
3338
3415
  }
3339
3416
 
3340
- static parseCall(session , call ) {
3417
+ static parseCall(call ) {
3341
3418
  return new CallSession({
3342
3419
  callId: call.id,
3343
3420
  sipCallId: call.sipCallId,
@@ -3522,7 +3599,11 @@ class CallLog {
3522
3599
  answered: plain.answered,
3523
3600
  callDirection: plain.call_direction,
3524
3601
  destination: {
3525
- extension: plain.requested_extension || plain.destination_extension,
3602
+ // @TEMP: Temporarily assuming empty numbers are meetings
3603
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3604
+ extension: plain.requested_extension
3605
+ || plain.destination_extension
3606
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3526
3607
  name: plain.requested_name || plain.destination_name || '',
3527
3608
  },
3528
3609
  source: {
@@ -3538,27 +3619,11 @@ class CallLog {
3538
3619
  }
3539
3620
 
3540
3621
  static parseNew(plain , session ) {
3541
- return new CallLog({
3542
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3543
- answered: plain.answered,
3544
- callDirection: plain.call_direction,
3545
- destination: {
3546
- extension: plain.requested_extension || plain.destination_extension,
3547
- name: plain.requested_name || plain.destination_name || '',
3548
- },
3549
- source: {
3550
- extension: plain.source_extension,
3551
- name: plain.source_name,
3552
- },
3553
- id: plain.id,
3554
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3555
- start: moment__default['default'](plain.start).toDate(),
3556
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3557
- recordings: Recording.parseMany(plain.recordings),
3558
- // @TODO: FIXME add verification declined vs missed call
3559
- newMissedCall: session
3560
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3561
- });
3622
+ const callLog = CallLog.parse(plain);
3623
+ // @TODO: FIXME add verification declined vs missed call
3624
+ callLog.newMissedCall = session
3625
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3626
+ return callLog;
3562
3627
  }
3563
3628
 
3564
3629
  static newFrom(profile ) {
@@ -3718,29 +3783,432 @@ class IndirectTransfer {
3718
3783
  });
3719
3784
  }
3720
3785
 
3721
- destinationIs(callSession ) {
3722
- return callSession.isId(this.destinationId);
3786
+ destinationIs(callSession ) {
3787
+ return callSession.isId(this.destinationId);
3788
+ }
3789
+
3790
+ sourceIs(callSession ) {
3791
+ return callSession.isId(this.sourceId);
3792
+ }
3793
+
3794
+ updateFrom(indirectTransfer ) {
3795
+ updateFrom(this, indirectTransfer);
3796
+ }
3797
+
3798
+ static newFrom(indirectTransfer ) {
3799
+ return newFrom(indirectTransfer, IndirectTransfer);
3800
+ }
3801
+ }
3802
+
3803
+ //
3804
+
3805
+ class CallApi {
3806
+ static async fetchCallLogs(offset , limit ) {
3807
+ return getApiClient().callLogd.listCallLogs(offset, limit);
3808
+ }
3809
+
3810
+ static async fetchDistinctCallLogs(offset , limit , distinct = 'peer_exten') {
3811
+ return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
3812
+ }
3813
+
3814
+ static async fetchActiveCalls() {
3815
+ return getApiClient().calld.listCalls();
3816
+ }
3817
+
3818
+ static async fetchCallLogsFromDate(from , number ) {
3819
+ return getApiClient().callLogd.listCallLogsFromDate(from, number);
3820
+ }
3821
+
3822
+ static async search(query , limit ) {
3823
+ return getApiClient().callLogd.search(query, limit);
3824
+ }
3825
+
3826
+ static async searchBy(field , value , limit ) {
3827
+ return getApiClient().callLogd.searchBy(field, value, limit);
3828
+ }
3829
+
3830
+ static async fetchSIP(session , line ) {
3831
+ const lineToUse = line || session.primaryLine();
3832
+ return getApiClient().confd.getUserLineSip(session.uuid, lineToUse ? lineToUse.id : null);
3833
+ }
3834
+
3835
+ static async cancelCall(callSession ) {
3836
+ return getApiClient().calld.cancelCall(callSession.callId);
3837
+ }
3838
+
3839
+ static async makeCall(callFromLine , extension , isMobile = false,
3840
+ callbackAllLines = false) {
3841
+ const lineId = callFromLine ? callFromLine.id : null;
3842
+
3843
+ const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
3844
+ return Call.parse(response);
3845
+ }
3846
+
3847
+ static async relocateCall(callId , line , contactIdentifier ) {
3848
+ return getApiClient().calld.relocateCall(callId, 'line', line, contactIdentifier);
3849
+ }
3850
+
3851
+ static async hold(callId ) {
3852
+ return getApiClient().calld.hold(callId);
3853
+ }
3854
+
3855
+ static async resume(callId ) {
3856
+ return getApiClient().calld.resume(callId);
3857
+ }
3858
+
3859
+ static async mute(callId ) {
3860
+ return getApiClient().calld.mute(callId);
3861
+ }
3862
+
3863
+ static async sendDTMF(callId , digits ) {
3864
+ return getApiClient().calld.sendDTMF(callId, digits);
3865
+ }
3866
+
3867
+ static async unmute(callId ) {
3868
+ return getApiClient().calld.unmute(callId);
3869
+ }
3870
+
3871
+ static async transferCall(callId , number , flow ) {
3872
+ return getApiClient().calld.transferCall(callId, number, flow);
3873
+ }
3874
+
3875
+ static async cancelCallTransfer(transferId ) {
3876
+ return getApiClient().calld.cancelCallTransfer(transferId);
3877
+ }
3878
+
3879
+ static async confirmCallTransfer(transferId ) {
3880
+ return getApiClient().calld.confirmCallTransfer(transferId);
3881
+ }
3882
+ }
3883
+
3884
+ //
3885
+
3886
+ const TRANSFER_FLOW_ATTENDED = 'attended';
3887
+ const TRANSFER_FLOW_BLIND = 'blind';
3888
+
3889
+ // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
3890
+
3891
+ const logger$b = IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
3892
+
3893
+ class CTIPhone extends Emitter {
3894
+
3895
+
3896
+
3897
+
3898
+
3899
+
3900
+
3901
+
3902
+ constructor(session , isMobile = false, callbackAllLines = false) {
3903
+ super();
3904
+ logger$b.info('CTI Phone created');
3905
+ this.session = session;
3906
+ this.isMobile = isMobile;
3907
+ this.callbackAllLines = callbackAllLines;
3908
+ }
3909
+
3910
+ getOptions() {
3911
+ // @FIXME: temporarily disabling this option
3912
+ // const hold = this.session.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD);
3913
+
3914
+ return {
3915
+ accept: false,
3916
+ decline: true,
3917
+ mute: true,
3918
+ hold: false,
3919
+ transfer: true,
3920
+ sendKey: true,
3921
+ addParticipant: false,
3922
+ record: true,
3923
+ merge: false,
3924
+ };
3925
+ }
3926
+
3927
+ hasAnActiveCall() {
3928
+ return !!this.currentCall;
3929
+ }
3930
+
3931
+ callCount() {
3932
+ return this.currentCall ? 1 : 0;
3933
+ }
3934
+
3935
+ isWebRTC() {
3936
+ return false;
3937
+ }
3938
+
3939
+ getUserAgent() {
3940
+ return 'cti-phone';
3941
+ }
3942
+
3943
+ startHeartbeat() {
3944
+ }
3945
+
3946
+ setOnHeartbeatTimeout() {
3947
+ }
3948
+
3949
+ setOnHeartbeatCallback() {
3950
+ }
3951
+
3952
+ stopHeartbeat() {
3953
+ }
3954
+
3955
+ bindClientEvents() {
3956
+ }
3957
+
3958
+ onConnect() {
3959
+ }
3960
+
3961
+ onDisconnect() {
3962
+ }
3963
+
3964
+ async makeCall(number , line ) {
3965
+ logger$b.info('make CTI call', { number });
3966
+
3967
+ if (!number) {
3968
+ return null;
3969
+ }
3970
+ try {
3971
+ this.currentCall = await CallApi.makeCall(line, number, this.isMobile, this.callbackAllLines);
3972
+ } catch (_) {
3973
+ // We have to deal with error like `User has no mobile phone number` error in the UI.
3974
+ }
3975
+ if (!this.currentCall) {
3976
+ return null;
3977
+ }
3978
+ const callSession = CallSession.parseCall(this.currentCall);
3979
+ this.eventEmitter.emit('onCallOutgoing', callSession);
3980
+
3981
+ return callSession;
3982
+ }
3983
+
3984
+ accept(callSession ) {
3985
+ if (!callSession) {
3986
+ return Promise.resolve(null);
3987
+ }
3988
+ logger$b.info('accept CTI call', { callId: callSession.getId(), number: callSession.number });
3989
+
3990
+ if (!this.currentCall) {
3991
+ this.currentCall = callSession.call;
3992
+ }
3993
+
3994
+ return Promise.resolve(callSession.getId());
3995
+ }
3996
+
3997
+ endCurrentCall(callSession ) {
3998
+ if (!callSession) {
3999
+ return;
4000
+ }
4001
+ logger$b.info('end current CTI call', { callId: callSession.getId(), number: callSession.number });
4002
+
4003
+ this.currentCall = undefined;
4004
+ this.eventEmitter.emit('onCallEnded', callSession);
4005
+ }
4006
+
4007
+ async hangup(callSession ) {
4008
+ if (!callSession) {
4009
+ return Promise.resolve(false);
4010
+ }
4011
+ logger$b.info('hangup CTI call', { callId: callSession.getId(), number: callSession.number });
4012
+
4013
+ try {
4014
+ await CallApi.cancelCall(callSession);
4015
+ if (this.currentCall && callSession.callId === this.currentCall.id) {
4016
+ this.endCurrentCall(callSession);
4017
+ }
4018
+
4019
+ this.eventEmitter.emit('onCallEnded', callSession);
4020
+ return true;
4021
+ } catch (e) {
4022
+ logger$b.error('hangup CTI call, error', e);
4023
+
4024
+ this.eventEmitter.emit('onCallFailed', callSession);
4025
+ return false;
4026
+ }
4027
+ }
4028
+
4029
+ ignore() {}
4030
+
4031
+ async reject(callSession ) {
4032
+ if (!callSession) {
4033
+ return;
4034
+ }
4035
+ logger$b.info('reject CTI call', { callId: callSession.getId(), number: callSession.number });
4036
+
4037
+ await CallApi.cancelCall(callSession);
4038
+ this.eventEmitter.emit('onCallEnded', callSession);
4039
+ }
4040
+
4041
+ async transfer(callSession , number ) {
4042
+ if (!callSession) {
4043
+ return;
4044
+ }
4045
+ logger$b.info('transfer CTI call', { callId: callSession.getId(), number: callSession.number, to: number });
4046
+
4047
+ await CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_BLIND);
4048
+ }
4049
+
4050
+ indirectTransfer() {}
4051
+
4052
+ async initiateCTIIndirectTransfer(callSession , number ) {
4053
+ if (!callSession) {
4054
+ return;
4055
+ }
4056
+ logger$b.info('indirect CTI transfer', { callId: callSession.getId(), number: callSession.number, to: number });
4057
+
4058
+ return CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_ATTENDED);
4059
+ }
4060
+
4061
+ async cancelCTIIndirectTransfer(transferId ) {
4062
+ logger$b.info('cancel CTI transfer', { transferId });
4063
+
4064
+ return CallApi.cancelCallTransfer(transferId);
4065
+ }
4066
+
4067
+ async confirmCTIIndirectTransfer(transferId ) {
4068
+ logger$b.info('confirm CTI transfer', { transferId });
4069
+
4070
+ return CallApi.confirmCallTransfer(transferId);
4071
+ }
4072
+
4073
+ sendKey(callSession , digits ) {
4074
+ if (!callSession) {
4075
+ return;
4076
+ }
4077
+ logger$b.info('send CTI key', { callId: callSession.getId(), number: callSession.number, digits });
4078
+
4079
+ return CallApi.sendDTMF(callSession.callId, digits);
4080
+ }
4081
+
4082
+ onConnectionMade() {
4083
+ logger$b.info('on CTI connection made');
4084
+
4085
+ this.eventEmitter.emit('onCallAccepted');
4086
+ }
4087
+
4088
+ async close() {
4089
+ logger$b.info('CTI close');
4090
+
4091
+ return Promise.resolve();
4092
+ }
4093
+
4094
+ async hold(callSession ) {
4095
+ if (!callSession) {
4096
+ return;
4097
+ }
4098
+ logger$b.info('CTI hold', { callId: callSession.getId(), number: callSession.number });
4099
+
4100
+ return CallApi.hold(callSession.callId);
4101
+ }
4102
+
4103
+ async resume(callSession ) {
4104
+ if (!callSession) {
4105
+ return;
4106
+ }
4107
+ logger$b.info('CTI resume', { callId: callSession.getId(), number: callSession.number });
4108
+
4109
+ return CallApi.resume(callSession.callId);
4110
+ }
4111
+
4112
+ async mute(callSession ) {
4113
+ if (!callSession) {
4114
+ return;
4115
+ }
4116
+ logger$b.info('CTI mute', { callId: callSession.getId(), number: callSession.number });
4117
+
4118
+ return CallApi.mute(callSession.callId);
4119
+ }
4120
+
4121
+ async unmute(callSession ) {
4122
+ if (!callSession) {
4123
+ return;
4124
+ }
4125
+ logger$b.info('CTI unmute', { callId: callSession.getId(), number: callSession.number });
4126
+
4127
+ return CallApi.unmute(callSession.callId);
4128
+ }
4129
+
4130
+ putOnSpeaker() {}
4131
+
4132
+ putOffSpeaker() {}
4133
+
4134
+ turnCameraOff() {}
4135
+
4136
+ turnCameraOn() {}
4137
+
4138
+ changeAudioInputDevice() {}
4139
+
4140
+ changeVideoInputDevice() {}
4141
+
4142
+ changeAudioDevice() {}
4143
+
4144
+ changeRingDevice() {}
4145
+
4146
+ changeAudioVolume() {}
4147
+
4148
+ changeRingVolume() {}
4149
+
4150
+ hasVideo() {
4151
+ return false;
4152
+ }
4153
+
4154
+ getLocalStreamForCall() {
4155
+ return null;
4156
+ }
4157
+
4158
+ getRemoteStreamForCall() {
4159
+ return null;
4160
+ }
4161
+
4162
+ getLocalVideoStream() {
4163
+ return null;
4164
+ }
4165
+
4166
+ setActiveSipSession() {}
4167
+
4168
+ isRegistered() {
4169
+ return true;
4170
+ }
4171
+
4172
+ hasIncomingCallSession() {
4173
+ return true;
4174
+ }
4175
+
4176
+ hasActiveRemoteVideoStream() {
4177
+ return false;
4178
+ }
4179
+
4180
+ getCurrentCallSession() {
4181
+ return this.currentCall ? CallSession.parseCall(this.currentCall) : null;
4182
+ }
4183
+
4184
+ enableRinging() {}
4185
+
4186
+ sendMessage() {}
4187
+
4188
+ disableRinging() {}
4189
+
4190
+ getLocalStream() {
4191
+ return null;
3723
4192
  }
3724
4193
 
3725
- sourceIs(callSession ) {
3726
- return callSession.isId(this.sourceId);
4194
+ getRemoteStream() {
4195
+ return null;
3727
4196
  }
3728
4197
 
3729
- updateFrom(indirectTransfer ) {
3730
- updateFrom(this, indirectTransfer);
4198
+ getRemoteVideoStream() {
4199
+ return null;
3731
4200
  }
3732
4201
 
3733
- static newFrom(indirectTransfer ) {
3734
- return newFrom(indirectTransfer, IndirectTransfer);
4202
+ getRemoteAudioStream() {
4203
+ return null;
3735
4204
  }
3736
- }
3737
-
3738
- //
3739
- const TRANSFER_FLOW_BLIND = 'blind';
3740
4205
 
3741
- // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
4206
+ hasLocalVideo() {
4207
+ return false;
4208
+ }
3742
4209
 
3743
- IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
4210
+ useLocalVideoElement() {}
4211
+ }
3744
4212
 
3745
4213
  /* */
3746
4214
 
@@ -4300,6 +4768,9 @@ var calldMethods = (client , baseUrl ) => ({
4300
4768
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4301
4769
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4302
4770
 
4771
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4772
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4773
+
4303
4774
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4304
4775
 
4305
4776
  mute: (callId ) =>
@@ -4653,7 +5124,7 @@ const AGENTD_VERSION = '1.0';
4653
5124
  const WEBHOOKD_VERSION = '1.0';
4654
5125
  const AMID_VERSION = '1.0';
4655
5126
 
4656
- const logger$9 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
5127
+ const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
4657
5128
 
4658
5129
  class ApiClient {
4659
5130
 
@@ -4705,12 +5176,12 @@ class ApiClient {
4705
5176
  }
4706
5177
 
4707
5178
  async forceRefreshToken() {
4708
- logger$9.info('forcing refresh token, calling callback');
5179
+ logger$a.info('forcing refresh token, calling callback');
4709
5180
  return this.refreshTokenCallback();
4710
5181
  }
4711
5182
 
4712
5183
  async refreshTokenCallback() {
4713
- logger$9.info('refresh token callback called', {
5184
+ logger$a.info('refresh token callback called', {
4714
5185
  refreshToken: this.refreshToken,
4715
5186
  refreshBackend: this.refreshBackend,
4716
5187
  refreshExpiration: this.refreshExpiration,
@@ -4728,7 +5199,7 @@ class ApiClient {
4728
5199
  this.isMobile,
4729
5200
  );
4730
5201
 
4731
- logger$9.info('token refreshed', { token: session.token });
5202
+ logger$a.info('token refreshed', { token: session.token });
4732
5203
 
4733
5204
  if (this.onRefreshToken) {
4734
5205
  this.onRefreshToken(session.token, session);
@@ -5201,7 +5672,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5201
5672
  .then(() => {
5202
5673
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5203
5674
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5204
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5675
+ if (this.peerConnection.addTransceiver) {
5676
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5677
+ }
5205
5678
  }
5206
5679
  })
5207
5680
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5228,12 +5701,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5228
5701
  };
5229
5702
  })
5230
5703
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5231
- .then((sessionDescription) => {
5232
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5233
- this.localMediaStreamConstraints = options.constraints;
5234
-
5235
- return sessionDescription;
5236
- })
5237
5704
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5238
5705
  .catch((error) => {
5239
5706
  wazoLogger.error('error when creating media', error);
@@ -5428,6 +5895,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5428
5895
 
5429
5896
  // set the transceiver direction to the answer direction
5430
5897
  this._peerConnection.getTransceivers().forEach((transceiver) => {
5898
+ if (transceiver.stopped) {
5899
+ return;
5900
+ }
5431
5901
  if (transceiver.direction /* guarding, but should always be true */) {
5432
5902
  const { receiver } = transceiver;
5433
5903
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5472,10 +5942,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5472
5942
  if (kind !== 'audio' && kind !== 'video') {
5473
5943
  throw new Error(`Unknown new track kind ${kind}.`);
5474
5944
  }
5475
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
5945
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
5946
+ otherSender.track && otherSender.track.kind === kind);
5476
5947
 
5477
5948
  // Do not reuse sender video tracks in SFU
5478
5949
  if (sender && (!sfu || newTrack.kind === 'audio')) {
5950
+ if (sender.track) {
5951
+ // eslint-disable-next-line no-param-reassign
5952
+ newTrack.enabled = sender.track.enabled;
5953
+ }
5479
5954
  trackUpdates.push(
5480
5955
  new Promise((resolve) => {
5481
5956
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5509,7 +5984,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5509
5984
  // Review: could make streamless tracks a configurable option?
5510
5985
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5511
5986
  try {
5512
- pc.addTrack(newTrack, localStream);
5987
+ if (pc.addTrack) {
5988
+ pc.addTrack(newTrack, localStream);
5989
+ } else {
5990
+ pc.addStream(localStream);
5991
+ }
5513
5992
  } catch (error) {
5514
5993
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5515
5994
  throw error;
@@ -5645,7 +6124,7 @@ const DEFAULT_ICE_TIMEOUT = 3000;
5645
6124
  const SEND_STATS_DELAY = 5000;
5646
6125
 
5647
6126
  const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
5648
- const logger$8 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
6127
+ const logger$9 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
5649
6128
  const statsLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-stats') : console;
5650
6129
 
5651
6130
  // events
@@ -5691,6 +6170,7 @@ const MAX_REGISTER_TRIES = 10;
5691
6170
 
5692
6171
 
5693
6172
 
6173
+
5694
6174
 
5695
6175
 
5696
6176
 
@@ -5717,6 +6197,7 @@ class WebRTCClient extends Emitter {
5717
6197
 
5718
6198
 
5719
6199
 
6200
+
5720
6201
 
5721
6202
  // sugar
5722
6203
 
@@ -5755,6 +6236,8 @@ class WebRTCClient extends Emitter {
5755
6236
  super();
5756
6237
  this.uaConfigOverrides = uaConfigOverrides;
5757
6238
  this.config = config;
6239
+ this.skipRegister = config.skipRegister;
6240
+
5758
6241
  this._buildConfig(config, session).then((newConfig ) => {
5759
6242
  this.config = newConfig;
5760
6243
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5810,13 +6293,13 @@ class WebRTCClient extends Emitter {
5810
6293
 
5811
6294
  createUserAgent(configOverrides ) {
5812
6295
  const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
5813
- logger$8.info('sdk webrtc, creating UA', { webRTCConfiguration });
6296
+ logger$9.info('sdk webrtc, creating UA', { webRTCConfiguration });
5814
6297
 
5815
6298
  webRTCConfiguration.delegate = {
5816
6299
  onConnect: this.onConnect.bind(this),
5817
6300
  onDisconnect: this.onDisconnect.bind(this),
5818
6301
  onInvite: (invitation ) => {
5819
- logger$8.info('sdk webrtc on invite', {
6302
+ logger$9.info('sdk webrtc on invite', {
5820
6303
  method: 'delegate.onInvite',
5821
6304
  id: invitation.id,
5822
6305
  remoteURI: invitation.remoteURI,
@@ -5859,7 +6342,7 @@ class WebRTCClient extends Emitter {
5859
6342
  }
5860
6343
 
5861
6344
  onConnect() {
5862
- logger$8.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6345
+ logger$9.info('sdk webrtc connected', { method: 'delegate.onConnect' });
5863
6346
  this.eventEmitter.emit(CONNECTED);
5864
6347
  if (!this.isRegistered() && this.registerer && this.registerer.waiting) {
5865
6348
  this.registerer.waitingToggle(false);
@@ -5868,7 +6351,7 @@ class WebRTCClient extends Emitter {
5868
6351
  }
5869
6352
 
5870
6353
  async onDisconnect(error ) {
5871
- logger$8.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6354
+ logger$9.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
5872
6355
  this.connectionPromise = null;
5873
6356
  // The UA will attempt to reconnect automatically when an error occurred
5874
6357
  this.eventEmitter.emit(DISCONNECTED, error);
@@ -5882,40 +6365,48 @@ class WebRTCClient extends Emitter {
5882
6365
  }
5883
6366
 
5884
6367
  register(tries = 0) {
5885
- logger$8.info('sdk webrtc registering...', {
6368
+ const logInfo = {
5886
6369
  userAgent: !!this.userAgent,
5887
6370
  registered: this.isRegistered(),
5888
6371
  connectionPromise: !!this.connectionPromise,
5889
6372
  registerer: !!this.registerer,
5890
6373
  waiting: this.registerer && this.registerer.waiting,
5891
6374
  tries,
5892
- });
6375
+ skipRegister: this.skipRegister,
6376
+ };
6377
+
6378
+ if (this.skipRegister) {
6379
+ logger$9.info('sdk webrtc skip register...', logInfo);
6380
+ return Promise.resolve();
6381
+ }
6382
+
6383
+ logger$9.info('sdk webrtc registering...', logInfo);
5893
6384
 
5894
6385
  if (!this.userAgent) {
5895
- logger$8.info('sdk webrtc recreating User Agent');
6386
+ logger$9.info('sdk webrtc recreating User Agent');
5896
6387
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
5897
6388
  }
5898
6389
  if (!this.userAgent || this.isRegistered()) {
5899
- logger$8.info('sdk webrtc registering aborted, already registered or no UA can be created');
6390
+ logger$9.info('sdk webrtc registering aborted, already registered or no UA can be created');
5900
6391
  return Promise.resolve();
5901
6392
  }
5902
6393
 
5903
6394
  if (this.connectionPromise || (this.registerer && this.registerer.waiting)) {
5904
- logger$8.info('sdk webrtc registering aborted due to a registration in progress.');
6395
+ logger$9.info('sdk webrtc registering aborted due to a registration in progress.');
5905
6396
  return Promise.resolve();
5906
6397
  }
5907
6398
 
5908
6399
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
5909
6400
 
5910
6401
  const onRegisterFailed = () => {
5911
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6402
+ logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
5912
6403
  this.connectionPromise = null;
5913
6404
  if (this.registerer && this.registerer.waiting) {
5914
6405
  this.registerer.waitingToggle(false);
5915
6406
  }
5916
6407
 
5917
6408
  if (tries <= MAX_REGISTER_TRIES) {
5918
- logger$8.info('sdk webrtc registering, retrying...', { tries });
6409
+ logger$9.info('sdk webrtc registering, retrying...', { tries });
5919
6410
  setTimeout(() => this.register(tries + 1), 300);
5920
6411
  }
5921
6412
  };
@@ -5924,18 +6415,18 @@ class WebRTCClient extends Emitter {
5924
6415
  // Avoid race condition with the close method called just before register and setting userAgent to null
5925
6416
  // during the resolution of the primise.
5926
6417
  if (!this.userAgent) {
5927
- logger$8.info('sdk webrtc recreating User Agent after connection');
6418
+ logger$9.info('sdk webrtc recreating User Agent after connection');
5928
6419
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
5929
6420
  }
5930
6421
 
5931
- logger$8.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6422
+ logger$9.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
5932
6423
  this.registerer = new registerer.Registerer(this.userAgent, registerOptions);
5933
6424
  this.connectionPromise = null;
5934
6425
  this._monkeyPatchRegisterer(this.registerer);
5935
6426
 
5936
6427
  // Bind registerer events
5937
6428
  this.registerer.stateChange.addListener(newState => {
5938
- logger$8.info('sdk webrtc registering, state changed', { newState });
6429
+ logger$9.info('sdk webrtc registering, state changed', { newState });
5939
6430
 
5940
6431
  if (newState === registererState.RegistererState.Registered && this.registerer
5941
6432
  && this.registerer.state === registererState.RegistererState.Registered) {
@@ -5948,7 +6439,7 @@ class WebRTCClient extends Emitter {
5948
6439
  const options = {
5949
6440
  requestDelegate: {
5950
6441
  onReject: response => {
5951
- logger$8.error('sdk webrtc registering, rejected', { response });
6442
+ logger$9.error('sdk webrtc registering, rejected', { response });
5952
6443
 
5953
6444
  onRegisterFailed();
5954
6445
  },
@@ -5956,13 +6447,13 @@ class WebRTCClient extends Emitter {
5956
6447
  };
5957
6448
 
5958
6449
  return this.registerer.register(options).catch((e) => {
5959
- logger$8.error('sdk webrtc registering, error', e);
6450
+ logger$9.error('sdk webrtc registering, error', e);
5960
6451
 
5961
6452
  this.eventEmitter.emit(REGISTRATION_FAILED);
5962
6453
  return e;
5963
6454
  });
5964
6455
  }).catch(error => {
5965
- logger$8.error('sdk webrtc registering, transport error', error);
6456
+ logger$9.error('sdk webrtc registering, transport error', error);
5966
6457
  onRegisterFailed();
5967
6458
  });
5968
6459
  }
@@ -5991,21 +6482,21 @@ class WebRTCClient extends Emitter {
5991
6482
  }
5992
6483
 
5993
6484
  unregister() {
5994
- logger$8.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6485
+ logger$9.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
5995
6486
  if (!this.registerer) {
5996
6487
  return Promise.resolve();
5997
6488
  }
5998
6489
 
5999
6490
  try {
6000
6491
  return this.registerer.unregister().then(() => {
6001
- logger$8.info('sdk webrtc unregistered');
6492
+ logger$9.info('sdk webrtc unregistered');
6002
6493
  this._cleanupRegister();
6003
6494
  }).catch(e => {
6004
- logger$8.error('sdk webrtc unregistering, promise error', e);
6495
+ logger$9.error('sdk webrtc unregistering, promise error', e);
6005
6496
  this._cleanupRegister();
6006
6497
  });
6007
6498
  } catch (e) {
6008
- logger$8.error('sdk webrtc unregistering, error', e);
6499
+ logger$9.error('sdk webrtc unregistering, error', e);
6009
6500
  // Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
6010
6501
  // error when the registerer is in a bad state
6011
6502
  this._cleanupRegister();
@@ -6013,7 +6504,7 @@ class WebRTCClient extends Emitter {
6013
6504
  }
6014
6505
 
6015
6506
  stop() {
6016
- logger$8.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6507
+ logger$9.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6017
6508
  if (!this.userAgent) {
6018
6509
  return Promise.resolve();
6019
6510
  }
@@ -6021,12 +6512,12 @@ class WebRTCClient extends Emitter {
6021
6512
  return this.userAgent.stop().then(() => {
6022
6513
  return this._cleanupRegister();
6023
6514
  }).catch(e => {
6024
- logger$8.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6515
+ logger$9.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6025
6516
  });
6026
6517
  }
6027
6518
 
6028
6519
  call(number , enableVideo , audioOnly = false, conference = false) {
6029
- logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6520
+ logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6030
6521
  const inviterOptions = {
6031
6522
  sessionDescriptionHandlerOptionsReInvite: {
6032
6523
  conference,
@@ -6055,7 +6546,7 @@ class WebRTCClient extends Emitter {
6055
6546
  this._onAccepted(session, response.session, true);
6056
6547
  },
6057
6548
  onReject: (response ) => {
6058
- logger$8.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6549
+ logger$9.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6059
6550
  this._stopSendingStats(session);
6060
6551
 
6061
6552
  this.eventEmitter.emit(REJECTED, session, response);
@@ -6077,11 +6568,11 @@ class WebRTCClient extends Emitter {
6077
6568
  }
6078
6569
 
6079
6570
  answer(session , enableVideo ) {
6080
- logger$8.info('sdk webrtc answer call', { id: session.id, enableVideo });
6571
+ logger$9.info('sdk webrtc answer call', { id: session.id, enableVideo });
6081
6572
 
6082
6573
  if (!session || !session.accept) {
6083
6574
  const error = 'No session to answer, or not an invitation';
6084
- logger$8.warn(error);
6575
+ logger$9.warn(error);
6085
6576
  return Promise.reject(new Error(error));
6086
6577
  }
6087
6578
  const options = {
@@ -6091,15 +6582,15 @@ class WebRTCClient extends Emitter {
6091
6582
  return session.accept(options).then(() => {
6092
6583
  if (session.isCanceled) {
6093
6584
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
6094
- logger$8.error(message, { id: session.id });
6585
+ logger$9.error(message, { id: session.id });
6095
6586
  this.onCallEnded(session);
6096
6587
 
6097
6588
  throw new CanceledCallError(message);
6098
6589
  }
6099
- logger$8.info('sdk webrtc answer, accepted.');
6590
+ logger$9.info('sdk webrtc answer, accepted.');
6100
6591
  this._onAccepted(session);
6101
6592
  }).catch(e => {
6102
- logger$8.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6593
+ logger$9.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6103
6594
 
6104
6595
  throw e;
6105
6596
  });
@@ -6107,7 +6598,7 @@ class WebRTCClient extends Emitter {
6107
6598
 
6108
6599
  hangup(session ) {
6109
6600
  const { state, id } = session;
6110
- logger$8.info('sdk webrtc hangup call', { id, state });
6601
+ logger$9.info('sdk webrtc hangup call', { id, state });
6111
6602
 
6112
6603
  try {
6113
6604
  this._stopSendingStats(session);
@@ -6136,24 +6627,24 @@ class WebRTCClient extends Emitter {
6136
6627
 
6137
6628
  return bye();
6138
6629
  } catch (error) {
6139
- logger$8.warn('sdk webrtc hangup, error', error);
6630
+ logger$9.warn('sdk webrtc hangup, error', error);
6140
6631
  }
6141
6632
 
6142
6633
  return null;
6143
6634
  }
6144
6635
 
6145
6636
  reject(session ) {
6146
- logger$8.info('sdk webrtc reject call', { id: session.id });
6637
+ logger$9.info('sdk webrtc reject call', { id: session.id });
6147
6638
 
6148
6639
  try {
6149
6640
  return session.reject ? session.reject() : session.cancel();
6150
6641
  } catch (e) {
6151
- logger$8.warn('Error when rejecting call', e.message, e.stack);
6642
+ logger$9.warn('Error when rejecting call', e.message, e.stack);
6152
6643
  }
6153
6644
  }
6154
6645
 
6155
6646
  async close() {
6156
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6647
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6157
6648
  this._cleanupMedia();
6158
6649
  this.connectionPromise = null;
6159
6650
 
@@ -6184,7 +6675,7 @@ class WebRTCClient extends Emitter {
6184
6675
  // eg: "INVITE not rejectable in state Completed"
6185
6676
  }
6186
6677
  this.userAgent = null;
6187
- logger$8.info('sdk webrtc client closed');
6678
+ logger$9.info('sdk webrtc client closed');
6188
6679
  }
6189
6680
 
6190
6681
  getNumber(session ) {
@@ -6197,13 +6688,13 @@ class WebRTCClient extends Emitter {
6197
6688
  }
6198
6689
 
6199
6690
  mute(session ) {
6200
- logger$8.info('sdk webrtc mute', { id: session.id });
6691
+ logger$9.info('sdk webrtc mute', { id: session.id });
6201
6692
 
6202
6693
  this._toggleAudio(session, true);
6203
6694
  }
6204
6695
 
6205
6696
  unmute(session ) {
6206
- logger$8.info('sdk webrtc unmute', { id: session.id });
6697
+ logger$9.info('sdk webrtc unmute', { id: session.id });
6207
6698
 
6208
6699
  this._toggleAudio(session, false);
6209
6700
  }
@@ -6220,12 +6711,18 @@ class WebRTCClient extends Emitter {
6220
6711
  }
6221
6712
 
6222
6713
  if (pc.getSenders) {
6714
+ if (!pc.getSenders().length) {
6715
+ return false;
6716
+ }
6223
6717
  pc.getSenders().forEach(sender => {
6224
6718
  if (sender && sender.track && sender.track.kind === 'audio') {
6225
6719
  muted = muted && !sender.track.enabled;
6226
6720
  }
6227
6721
  });
6228
6722
  } else {
6723
+ if (!pc.getLocalStreams().length) {
6724
+ return false;
6725
+ }
6229
6726
  pc.getLocalStreams().forEach(stream => {
6230
6727
  stream.getAudioTracks().forEach(track => {
6231
6728
  muted = muted && !track.enabled;
@@ -6237,20 +6734,20 @@ class WebRTCClient extends Emitter {
6237
6734
  }
6238
6735
 
6239
6736
  toggleCameraOn(session ) {
6240
- logger$8.info('sdk webrtc toggle camera on', { id: session.id });
6737
+ logger$9.info('sdk webrtc toggle camera on', { id: session.id });
6241
6738
 
6242
6739
  this._toggleVideo(session, false);
6243
6740
  }
6244
6741
 
6245
6742
  toggleCameraOff(session ) {
6246
- logger$8.info('sdk webrtc toggle camera off', { id: session.id });
6743
+ logger$9.info('sdk webrtc toggle camera off', { id: session.id });
6247
6744
 
6248
6745
  this._toggleVideo(session, true);
6249
6746
  }
6250
6747
 
6251
6748
  hold(session , isConference = false) {
6252
6749
  const sessionId = this.getSipSessionId(session);
6253
- logger$8.info('sdk webrtc hold', {
6750
+ logger$9.info('sdk webrtc hold', {
6254
6751
  sessionId,
6255
6752
  keys: Object.keys(this.heldSessions),
6256
6753
  pendingReinvite: !!session.pendingReinvite,
@@ -6282,6 +6779,9 @@ class WebRTCClient extends Emitter {
6282
6779
  if (!this._isWeb()) {
6283
6780
  options.sessionDescriptionHandlerModifiers = [modifiers.holdModifier];
6284
6781
  }
6782
+ options.sessionDescriptionHandlerOptions = {
6783
+ constraints: options.constraints,
6784
+ };
6285
6785
 
6286
6786
  // Send re-INVITE
6287
6787
  return session.invite(options);
@@ -6290,7 +6790,7 @@ class WebRTCClient extends Emitter {
6290
6790
  unhold(session , isConference = false) {
6291
6791
  const sessionId = this.getSipSessionId(session);
6292
6792
 
6293
- logger$8.info('sdk webrtc unhold', {
6793
+ logger$9.info('sdk webrtc unhold', {
6294
6794
  sessionId,
6295
6795
  keys: Object.keys(this.heldSessions),
6296
6796
  pendingReinvite: !!session.pendingReinvite,
@@ -6321,6 +6821,9 @@ class WebRTCClient extends Emitter {
6321
6821
  // (eg: holdModifier)
6322
6822
  options.sessionDescriptionHandlerModifiers = [];
6323
6823
  }
6824
+ options.sessionDescriptionHandlerOptions = {
6825
+ constraints: options.constraints,
6826
+ };
6324
6827
 
6325
6828
  // Send re-INVITE
6326
6829
  return session.invite(options);
@@ -6378,7 +6881,7 @@ class WebRTCClient extends Emitter {
6378
6881
  return;
6379
6882
  }
6380
6883
 
6381
- logger$8.info('send WebRTC message', { sipId: sipSession.id, contentType });
6884
+ logger$9.info('send WebRTC message', { sipId: sipSession.id, contentType });
6382
6885
 
6383
6886
  try {
6384
6887
  sipSession.message({
@@ -6503,7 +7006,8 @@ class WebRTCClient extends Emitter {
6503
7006
  }
6504
7007
  const sdh = session.sessionDescriptionHandler;
6505
7008
  const pc = sdh.peerConnection;
6506
- const localStream = this.getLocalStream(this.getSipSessionId(session));
7009
+ const sessionId = this.getSipSessionId(session);
7010
+ const localStream = this.getLocalStream(sessionId);
6507
7011
 
6508
7012
  // Release old video stream
6509
7013
  if (localStream) {
@@ -6529,11 +7033,8 @@ class WebRTCClient extends Emitter {
6529
7033
 
6530
7034
  // let's update the local stream
6531
7035
  this.eventEmitter.emit('onVideoInputChange', stream);
6532
- try {
6533
- await sdh.setLocalMediaStream(stream);
6534
- } catch (_) {
6535
- // Nothing to do
6536
- }
7036
+ this.setLocalMediaStream(sessionId, stream);
7037
+
6537
7038
  return stream;
6538
7039
  });
6539
7040
  }
@@ -6745,7 +7246,7 @@ class WebRTCClient extends Emitter {
6745
7246
  }
6746
7247
 
6747
7248
  startHeartbeat() {
6748
- logger$8.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7249
+ logger$9.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
6749
7250
  if (!this.userAgent) {
6750
7251
  this.heartbeat.stop();
6751
7252
  return;
@@ -6758,7 +7259,7 @@ class WebRTCClient extends Emitter {
6758
7259
  }
6759
7260
 
6760
7261
  stopHeartbeat() {
6761
- logger$8.info('sdk webrtc stop heartbeat');
7262
+ logger$9.info('sdk webrtc stop heartbeat');
6762
7263
  this.heartbeat.stop();
6763
7264
  }
6764
7265
 
@@ -6778,7 +7279,7 @@ class WebRTCClient extends Emitter {
6778
7279
  }
6779
7280
 
6780
7281
  attemptReconnection() {
6781
- logger$8.info('attempt reconnection', { userAgent: !!this.userAgent });
7282
+ logger$9.info('attempt reconnection', { userAgent: !!this.userAgent });
6782
7283
  if (!this.userAgent) {
6783
7284
  return;
6784
7285
  }
@@ -6835,9 +7336,11 @@ class WebRTCClient extends Emitter {
6835
7336
  remoteStream.removeTrack(track);
6836
7337
  });
6837
7338
 
6838
- pc.getReceivers().forEach(receiver => {
6839
- remoteStream.addTrack(receiver.track);
6840
- });
7339
+ if (pc.getReceivers) {
7340
+ pc.getReceivers().forEach(receiver => {
7341
+ remoteStream.addTrack(receiver.track);
7342
+ });
7343
+ }
6841
7344
  }
6842
7345
 
6843
7346
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6872,6 +7375,25 @@ class WebRTCClient extends Emitter {
6872
7375
  return sessionId in this.conferences;
6873
7376
  }
6874
7377
 
7378
+ createAudioElementFor(sessionId ) {
7379
+ const audio = document.createElement('audio');
7380
+ audio.setAttribute('id', `audio-${sessionId}`);
7381
+
7382
+ if (audio.setSinkId && this.audioOutputDeviceId) {
7383
+ audio.setSinkId(this.audioOutputDeviceId);
7384
+ }
7385
+
7386
+ if (document.body) {
7387
+ document.body.appendChild(audio);
7388
+ }
7389
+ this.audioElements[sessionId] = audio;
7390
+
7391
+ audio.volume = this.audioOutputVolume;
7392
+ audio.autoplay = true;
7393
+
7394
+ return audio;
7395
+ }
7396
+
6875
7397
  _onTransportError() {
6876
7398
  this.eventEmitter.emit(TRANSPORT_ERROR);
6877
7399
  this.attemptReconnection();
@@ -6881,7 +7403,7 @@ class WebRTCClient extends Emitter {
6881
7403
  const body = message && typeof message === 'object' ? message.data : message;
6882
7404
  if (body && body.indexOf('200 OK') !== -1) {
6883
7405
  if (this.hasHeartbeat()) {
6884
- logger$8.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7406
+ logger$9.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
6885
7407
 
6886
7408
  this.heartbeat.onHeartbeat();
6887
7409
  if (this.heartbeatCb) {
@@ -6892,7 +7414,7 @@ class WebRTCClient extends Emitter {
6892
7414
  }
6893
7415
 
6894
7416
  async _onHeartbeatTimeout() {
6895
- logger$8.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7417
+ logger$9.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
6896
7418
 
6897
7419
  if (this.heartbeatTimeoutCb) {
6898
7420
  this.heartbeatTimeoutCb();
@@ -6904,7 +7426,7 @@ class WebRTCClient extends Emitter {
6904
7426
  try {
6905
7427
  await this.userAgent.transport.disconnect();
6906
7428
  } catch (e) {
6907
- logger$8.error('Transport disconnection after heartbeat timeout, error', e);
7429
+ logger$9.error('Transport disconnection after heartbeat timeout, error', e);
6908
7430
  }
6909
7431
  }
6910
7432
 
@@ -6937,31 +7459,31 @@ class WebRTCClient extends Emitter {
6937
7459
  }
6938
7460
 
6939
7461
  _connectIfNeeded() {
6940
- logger$8.info('connect if needed, checking', { connected: this.isConnected() });
7462
+ logger$9.info('connect if needed, checking', { connected: this.isConnected() });
6941
7463
  if (!this.userAgent) {
6942
- logger$8.info('need to recreate User Agent');
7464
+ logger$9.info('need to recreate User Agent');
6943
7465
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6944
7466
  }
6945
7467
 
6946
7468
  if (this.isConnected()) {
6947
- logger$8.info('webrtc sdk, already connected');
7469
+ logger$9.info('webrtc sdk, already connected');
6948
7470
  return Promise.resolve();
6949
7471
  }
6950
7472
 
6951
7473
  if (this.isConnecting()) {
6952
- logger$8.info('webrtc sdk, already connecting...');
7474
+ logger$9.info('webrtc sdk, already connecting...');
6953
7475
 
6954
7476
  this.connectionPromise = this.userAgent.transport.connectPromise;
6955
7477
  return this.connectionPromise;
6956
7478
  }
6957
7479
 
6958
7480
  if (this.connectionPromise) {
6959
- logger$8.info('webrtc sdk, connection promise connecting...');
7481
+ logger$9.info('webrtc sdk, connection promise connecting...');
6960
7482
  // $FlowFixMe
6961
7483
  return this.connectionPromise;
6962
7484
  }
6963
7485
 
6964
- logger$8.info('WebRTC UA needs to connect');
7486
+ logger$9.info('WebRTC UA needs to connect');
6965
7487
 
6966
7488
  // Force UA to reconnect
6967
7489
  if (this.userAgent && this.userAgent.state !== userAgentState.UserAgentState.Stopped) {
@@ -7086,7 +7608,7 @@ class WebRTCClient extends Emitter {
7086
7608
 
7087
7609
  sdh.peerConnectionDelegate = {
7088
7610
  onicecandidateerror: (error ) => {
7089
- logger$8.error('on icecandidate error', {
7611
+ logger$9.error('on icecandidate error', {
7090
7612
  address: error.address,
7091
7613
  port: error.port,
7092
7614
  errorCode: error.errorCode,
@@ -7101,7 +7623,7 @@ class WebRTCClient extends Emitter {
7101
7623
  let hadRemoteVideo = false;
7102
7624
 
7103
7625
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7104
- // Becase when `onInvite` is called we already got the video track
7626
+ // Because when `onInvite` is called we already got the video track
7105
7627
  session.onInviteRequest = (request) => {
7106
7628
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7107
7629
 
@@ -7115,7 +7637,7 @@ class WebRTCClient extends Emitter {
7115
7637
  updatedNumber = session.assertedIdentity.uri.normal.user;
7116
7638
  updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
7117
7639
  }
7118
- logger$8.info('re-invite received', { updatedCalleeName, updatedNumber });
7640
+ logger$9.info('re-invite received', { updatedCalleeName, updatedNumber });
7119
7641
 
7120
7642
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
7121
7643
 
@@ -7136,7 +7658,7 @@ class WebRTCClient extends Emitter {
7136
7658
  }
7137
7659
 
7138
7660
  _onAccepted(session , sessionDialog , withEvent = true) {
7139
- logger$8.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7661
+ logger$9.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7140
7662
 
7141
7663
  this.storeSipSession(session);
7142
7664
 
@@ -7176,20 +7698,10 @@ class WebRTCClient extends Emitter {
7176
7698
  const isConference = this.isConference(sessionId);
7177
7699
 
7178
7700
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7179
- const audio = document.createElement('audio');
7180
- audio.setAttribute('id', `audio-${sessionId}`);
7181
-
7182
- if (audio.setSinkId && this.audioOutputDeviceId) {
7183
- audio.setSinkId(this.audioOutputDeviceId);
7184
- }
7185
-
7186
- if (document.body) {
7187
- document.body.appendChild(audio);
7188
- }
7189
- this.audioElements[sessionId] = audio;
7701
+ this.createAudioElementFor(sessionId);
7190
7702
  }
7191
7703
 
7192
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7704
+ const audioElement = this.audioElements[sessionId];
7193
7705
  const stream = newStream || this.getRemoteStream(sessionId);
7194
7706
 
7195
7707
  if (!this._isWeb() || !stream) {
@@ -7336,10 +7848,10 @@ class WebRTCClient extends Emitter {
7336
7848
 
7337
7849
  _stopSendingStats(session ) {
7338
7850
  const sessionId = this.getSipSessionId(session);
7339
- logger$8.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7851
+ logger$9.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7340
7852
 
7341
7853
  if (sessionId in this.statsIntervals) {
7342
- logger$8.trace('Stop sending stats for call', { sessionId });
7854
+ logger$9.trace('Stop sending stats for call', { sessionId });
7343
7855
  this.statsIntervals[sessionId]();
7344
7856
  delete this.statsIntervals[sessionId];
7345
7857
  }
@@ -7355,7 +7867,7 @@ class WebRTCClient extends Emitter {
7355
7867
  try {
7356
7868
  await this.userAgent.transport.disconnect();
7357
7869
  } catch (e) {
7358
- logger$8.error('WebRTC transport disconnect, error', e);
7870
+ logger$9.error('WebRTC transport disconnect, error', e);
7359
7871
  }
7360
7872
  }
7361
7873
  }
@@ -7442,7 +7954,7 @@ const events = [
7442
7954
  ON_SIGNAL,
7443
7955
  ];
7444
7956
 
7445
- const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
7957
+ const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
7446
7958
 
7447
7959
  class WebRTCPhone extends Emitter {
7448
7960
 
@@ -7513,7 +8025,7 @@ class WebRTCPhone extends Emitter {
7513
8025
  }).catch(error => {
7514
8026
  // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
7515
8027
  console.error('register error', error, error.message, error.stack);
7516
- logger$7.error('WebRTC register error', { message: error.message, stack: error.stack });
8028
+ logger$8.error('WebRTC register error', { message: error.message, stack: error.stack });
7517
8029
  });
7518
8030
  }
7519
8031
 
@@ -7528,7 +8040,7 @@ class WebRTCPhone extends Emitter {
7528
8040
  if (!this.client) {
7529
8041
  return;
7530
8042
  }
7531
- logger$7.info('WebRTC phone stop');
8043
+ logger$8.info('WebRTC phone stop');
7532
8044
  this.client.stop();
7533
8045
  }
7534
8046
 
@@ -7543,14 +8055,14 @@ class WebRTCPhone extends Emitter {
7543
8055
  async sendReinvite(callSession , constraints = null, conference = false,
7544
8056
  audioOnly = false) {
7545
8057
  const sipSession = this.findSipSession(callSession);
7546
- logger$7.info('WebRTC phone - send reinvite', {
8058
+ logger$8.info('WebRTC phone - send reinvite', {
7547
8059
  sessionId: sipSession ? sipSession.id : null,
7548
8060
  constraints,
7549
8061
  audioOnly,
7550
8062
  });
7551
8063
 
7552
8064
  if (!sipSession) {
7553
- return null;
8065
+ return false;
7554
8066
  }
7555
8067
 
7556
8068
  // $FlowFixMe
@@ -7560,19 +8072,17 @@ class WebRTCPhone extends Emitter {
7560
8072
  // Downgrade
7561
8073
  if (constraints && !isUpgrade) {
7562
8074
  // No reinvite needed
7563
- return this._downgradeToAudio(callSession);
8075
+ this._downgradeToAudio(callSession);
8076
+ return false;
7564
8077
  }
7565
8078
 
7566
8079
  if (isUpgrade) {
7567
8080
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
7568
8081
  if (!shouldReinvite) {
7569
- return;
8082
+ return false;
7570
8083
  }
7571
8084
  }
7572
8085
 
7573
- // Force reinvite in SDH
7574
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
7575
-
7576
8086
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
7577
8087
  }
7578
8088
 
@@ -7581,7 +8091,7 @@ class WebRTCPhone extends Emitter {
7581
8091
  }
7582
8092
 
7583
8093
  startHeartbeat() {
7584
- logger$7.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
8094
+ logger$8.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
7585
8095
  if (!this.client || this.client.hasHeartbeat()) {
7586
8096
  return;
7587
8097
  }
@@ -7590,7 +8100,7 @@ class WebRTCPhone extends Emitter {
7590
8100
  }
7591
8101
 
7592
8102
  stopHeartbeat() {
7593
- logger$7.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
8103
+ logger$8.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
7594
8104
  if (!this.client) {
7595
8105
  return;
7596
8106
  }
@@ -7607,7 +8117,7 @@ class WebRTCPhone extends Emitter {
7607
8117
  }
7608
8118
 
7609
8119
  reconnect() {
7610
- logger$7.info('WebRTC phone - reconnect', { client: !!this.client });
8120
+ logger$8.info('WebRTC phone - reconnect', { client: !!this.client });
7611
8121
  if (!this.client) {
7612
8122
  return;
7613
8123
  }
@@ -7645,7 +8155,7 @@ class WebRTCPhone extends Emitter {
7645
8155
  _downgradeToAudio(callSession ) {
7646
8156
  const sipSession = this.findSipSession(callSession);
7647
8157
  if (!sipSession) {
7648
- return;
8158
+ return false;
7649
8159
  }
7650
8160
 
7651
8161
  // Release local video stream when downgrading to audio
@@ -7758,7 +8268,7 @@ class WebRTCPhone extends Emitter {
7758
8268
  // Monkey patch to know when canceled with the CANCEL message
7759
8269
  const onCancel = sipSession._onCancel.bind(sipSession);
7760
8270
  sipSession._onCancel = (message ) => {
7761
- logger$7.trace('on sip session canceled', { callId: message.callId });
8271
+ logger$8.trace('on sip session canceled', { callId: message.callId });
7762
8272
 
7763
8273
  onCancel(message);
7764
8274
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
@@ -7783,13 +8293,13 @@ class WebRTCPhone extends Emitter {
7783
8293
  this.audioOutputVolume,
7784
8294
  );
7785
8295
  case sessionState.SessionState.Terminating:
7786
- logger$7.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8296
+ logger$8.info('WebRTC phone - call terminating', { sipId: sipSession.id });
7787
8297
 
7788
8298
  this.eventEmitter.emit(ON_CALL_ENDING, this._createCallSession(sipSession));
7789
8299
 
7790
8300
  break;
7791
8301
  case sessionState.SessionState.Terminated:
7792
- logger$7.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8302
+ logger$8.info('WebRTC phone - call terminated', { sipId: sipSession.id });
7793
8303
 
7794
8304
  this._onCallTerminated(sipSession);
7795
8305
 
@@ -7825,7 +8335,7 @@ class WebRTCPhone extends Emitter {
7825
8335
  }
7826
8336
 
7827
8337
  async startScreenSharing(constraints , callSession ) {
7828
- logger$7.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8338
+ logger$8.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
7829
8339
 
7830
8340
  const screenShareStream = await this._getStreamFromConstraints(constraints);
7831
8341
  if (!screenShareStream) {
@@ -7847,6 +8357,10 @@ class WebRTCPhone extends Emitter {
7847
8357
  localStream.removeTrack(videoTrack);
7848
8358
  }
7849
8359
 
8360
+ if (localStream) {
8361
+ localStream.addTrack(screenTrack);
8362
+ }
8363
+
7850
8364
  if (sender) {
7851
8365
  sender.replaceTrack(screenTrack);
7852
8366
  }
@@ -7861,7 +8375,8 @@ class WebRTCPhone extends Emitter {
7861
8375
  return;
7862
8376
  }
7863
8377
 
7864
- logger$7.info('WebRTC phone - stop screen sharing');
8378
+ logger$8.info('WebRTC phone - stop screen sharing');
8379
+ let reinvited = false;
7865
8380
 
7866
8381
  try {
7867
8382
  if (this.currentScreenShare.stream) {
@@ -7876,7 +8391,8 @@ class WebRTCPhone extends Emitter {
7876
8391
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
7877
8392
  // We have to downgrade to audio.
7878
8393
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
7879
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
8394
+ const constraints = { audio: false, video: screenshareStopped };
8395
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
7880
8396
  }
7881
8397
  } catch (e) {
7882
8398
  console.warn(e);
@@ -7890,6 +8406,8 @@ class WebRTCPhone extends Emitter {
7890
8406
  );
7891
8407
 
7892
8408
  this.currentScreenShare = null;
8409
+
8410
+ return reinvited;
7893
8411
  }
7894
8412
 
7895
8413
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -7927,7 +8445,7 @@ class WebRTCPhone extends Emitter {
7927
8445
  }
7928
8446
 
7929
8447
  _onCallAccepted(sipSession , cameraEnabled ) {
7930
- logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8448
+ logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
7931
8449
 
7932
8450
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
7933
8451
  this.currentSipSession = sipSession;
@@ -7945,11 +8463,15 @@ class WebRTCPhone extends Emitter {
7945
8463
  }
7946
8464
 
7947
8465
  changeAudioDevice(id ) {
7948
- logger$7.info('WebRTC phone - change audio device', { deviceId: id });
8466
+ logger$8.info('WebRTC phone - change audio device', { deviceId: id });
7949
8467
  this.audioOutputDeviceId = id;
7950
8468
  this.client.changeAudioOutputDevice(id);
7951
8469
  }
7952
8470
 
8471
+ createAudioElementFor(sessionId ) {
8472
+ return this.client.createAudioElementFor(sessionId);
8473
+ }
8474
+
7953
8475
  changeRingDevice(id ) {
7954
8476
  this.audioRingDeviceId = id;
7955
8477
  }
@@ -7966,25 +8488,25 @@ class WebRTCPhone extends Emitter {
7966
8488
  }
7967
8489
 
7968
8490
  changeAudioInputDevice(id ) {
7969
- logger$7.info('WebRTC phone - changeAudio input device', { deviceId: id });
8491
+ logger$8.info('WebRTC phone - changeAudio input device', { deviceId: id });
7970
8492
 
7971
8493
  return this.client.changeAudioInputDevice(id, this.currentSipSession);
7972
8494
  }
7973
8495
 
7974
8496
  changeVideoInputDevice(id ) {
7975
- logger$7.info('WebRTC phone - change video input device', { deviceId: id });
8497
+ logger$8.info('WebRTC phone - change video input device', { deviceId: id });
7976
8498
 
7977
8499
  return this.client.changeVideoInputDevice(id, this.currentSipSession);
7978
8500
  }
7979
8501
 
7980
8502
  changeSessionVideoInputDevice(id ) {
7981
- logger$7.info('WebRTC phone - change session video input device', { deviceId: id });
8503
+ logger$8.info('WebRTC phone - change session video input device', { deviceId: id });
7982
8504
 
7983
8505
  return this.client.changeSessionVideoInputDevice(id, this.currentSipSession);
7984
8506
  }
7985
8507
 
7986
8508
  _onCallTerminated(sipSession ) {
7987
- logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8509
+ logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
7988
8510
 
7989
8511
  const callSession = this._createCallSession(sipSession);
7990
8512
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
@@ -8018,7 +8540,7 @@ class WebRTCPhone extends Emitter {
8018
8540
  const hasIncomingCallSession = this.hasIncomingCallSession();
8019
8541
 
8020
8542
  // Re-trigger incoming call event for remaining incoming calls
8021
- logger$7.info('WebRTC phone - check to re-trigger incoming call', {
8543
+ logger$8.info('WebRTC phone - check to re-trigger incoming call', {
8022
8544
  sipId: sipSession.id,
8023
8545
  shouldRetrigger,
8024
8546
  hasIncomingCallSession,
@@ -8107,37 +8629,37 @@ class WebRTCPhone extends Emitter {
8107
8629
 
8108
8630
  // Deprecated
8109
8631
  getLocalStreamForCall(callSession ) {
8110
- logger$7.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8632
+ logger$8.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8111
8633
 
8112
8634
  return this.getLocalStream(callSession);
8113
8635
  }
8114
8636
 
8115
8637
  // Deprecated
8116
8638
  getRemoteStreamForCall(callSession ) {
8117
- logger$7.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8639
+ logger$8.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8118
8640
 
8119
8641
  return this.getRemoteVideoStream(callSession);
8120
8642
  }
8121
8643
 
8122
8644
  getRemoteStreamsForCall(callSession ) {
8123
- logger$7.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8645
+ logger$8.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8124
8646
 
8125
8647
  return this.getRemoteStream(callSession);
8126
8648
  }
8127
8649
 
8128
8650
  accept(callSession , cameraEnabled ) {
8129
- logger$7.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8651
+ logger$8.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8130
8652
  if (this.currentSipSession) {
8131
8653
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
8132
8654
  }
8133
8655
 
8134
8656
  if (!callSession) {
8135
- logger$7.warn('no CallSession to accept.');
8657
+ logger$8.warn('no CallSession to accept.');
8136
8658
  return Promise.resolve(null);
8137
8659
  }
8138
8660
 
8139
8661
  if (callSession.getId() in this.acceptedSessions) {
8140
- logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8662
+ logger$8.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8141
8663
  return Promise.resolve(callSession.sipCallId);
8142
8664
  }
8143
8665
 
@@ -8149,24 +8671,24 @@ class WebRTCPhone extends Emitter {
8149
8671
  const sipSession = this.client.getSipSession(callSession.getId());
8150
8672
  if (sipSession) {
8151
8673
  if (sipSession.state === sessionState.SessionState.Terminated || sipSession.state === sessionState.SessionState.Terminating) {
8152
- logger$7.warn('Trying to answer a terminated sipSession.');
8674
+ logger$8.warn('Trying to answer a terminated sipSession.');
8153
8675
 
8154
8676
  return Promise.resolve(null);
8155
8677
  }
8156
8678
 
8157
- logger$7.info('accept call, session found', { sipId: sipSession.id });
8679
+ logger$8.info('accept call, session found', { sipId: sipSession.id });
8158
8680
 
8159
8681
  // $FlowFixMe
8160
8682
  return this.client.answer(sipSession, this.allowVideo ? cameraEnabled : false).then(() => {
8161
8683
  return callSession.sipCallId;
8162
8684
  }).catch(e => {
8163
- logger$7.error(e);
8685
+ logger$8.error(e);
8164
8686
  this.endCurrentCall(callSession);
8165
8687
  throw e;
8166
8688
  });
8167
8689
  }
8168
8690
 
8169
- logger$7.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8691
+ logger$8.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8170
8692
 
8171
8693
  return Promise.resolve(null);
8172
8694
  }
@@ -8176,7 +8698,7 @@ class WebRTCPhone extends Emitter {
8176
8698
  }
8177
8699
 
8178
8700
  async reject(callSession ) {
8179
- logger$7.info('reject WebRTC called', { id: callSession.getId() });
8701
+ logger$8.info('reject WebRTC called', { id: callSession.getId() });
8180
8702
 
8181
8703
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call rejected locally');
8182
8704
  if (!callSession || callSession.getId() in this.rejectedSessions) {
@@ -8188,14 +8710,14 @@ class WebRTCPhone extends Emitter {
8188
8710
 
8189
8711
  const sipSession = this.findSipSession(callSession);
8190
8712
  if (sipSession) {
8191
- logger$7.info('WebRTC rejecting', { sipId: sipSession.id });
8713
+ logger$8.info('WebRTC rejecting', { sipId: sipSession.id });
8192
8714
 
8193
8715
  this.client.hangup(sipSession);
8194
8716
  }
8195
8717
  }
8196
8718
 
8197
8719
  async ignore(callSession ) {
8198
- logger$7.info('WebRTC ignore', { id: callSession.getId() });
8720
+ logger$8.info('WebRTC ignore', { id: callSession.getId() });
8199
8721
 
8200
8722
  // kill the ring
8201
8723
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'ignoring call');
@@ -8204,7 +8726,7 @@ class WebRTCPhone extends Emitter {
8204
8726
  }
8205
8727
 
8206
8728
  hold(callSession , withEvent = true, isConference = false) {
8207
- logger$7.info('WebRTC hold', { id: callSession.getId() });
8729
+ logger$8.info('WebRTC hold', { id: callSession.getId() });
8208
8730
 
8209
8731
  const sipSession = this.findSipSession(callSession);
8210
8732
 
@@ -8215,7 +8737,7 @@ class WebRTCPhone extends Emitter {
8215
8737
 
8216
8738
  // @Deprecated
8217
8739
  unhold(callSession , withEvent = true, isConference = false) {
8218
- logger$7.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8740
+ logger$8.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8219
8741
 
8220
8742
  console.warn('Please note that `phone.unhold()` is being deprecated; `phone.resume()` is the preferred method');
8221
8743
 
@@ -8230,7 +8752,7 @@ class WebRTCPhone extends Emitter {
8230
8752
  const sipSession = this.findSipSession(callSession);
8231
8753
 
8232
8754
  if (sipSession) {
8233
- logger$7.info('WebRTC atxfer', { sipId: sipSession.id });
8755
+ logger$8.info('WebRTC atxfer', { sipId: sipSession.id });
8234
8756
 
8235
8757
  return this.client.atxfer(sipSession);
8236
8758
  }
@@ -8245,7 +8767,7 @@ class WebRTCPhone extends Emitter {
8245
8767
  if (!sipSession) {
8246
8768
  return new Promise((resolve, reject) => reject(new Error('No session to hold')));
8247
8769
  }
8248
- logger$7.info('WebRTC hold sip session', { sipId: sipSession.id });
8770
+ logger$8.info('WebRTC hold sip session', { sipId: sipSession.id });
8249
8771
 
8250
8772
  const promise = this.client.hold(sipSession, isConference);
8251
8773
  if (withEvent) {
@@ -8264,7 +8786,7 @@ class WebRTCPhone extends Emitter {
8264
8786
  if (!sipSession) {
8265
8787
  return new Promise((resolve, reject) => reject(new Error('No session to unhold')));
8266
8788
  }
8267
- logger$7.info('WebRTC unhold', { sipId: sipSession.id });
8789
+ logger$8.info('WebRTC unhold', { sipId: sipSession.id });
8268
8790
 
8269
8791
  const promise = this.client.unhold(sipSession, isConference);
8270
8792
  if (withEvent) {
@@ -8275,18 +8797,18 @@ class WebRTCPhone extends Emitter {
8275
8797
  }
8276
8798
 
8277
8799
  resume(callSession , isConference = false) {
8278
- logger$7.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8800
+ logger$8.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8279
8801
 
8280
8802
  const sipSession = this.findSipSession(callSession);
8281
8803
  if (!sipSession) {
8282
8804
  return new Promise((resolve, reject) => reject(new Error('No session to resume')));
8283
8805
  }
8284
8806
 
8285
- logger$7.info('WebRTC resuming', { sipId: sipSession.id });
8807
+ logger$8.info('WebRTC resuming', { sipId: sipSession.id });
8286
8808
 
8287
8809
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
8288
8810
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
8289
- logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8811
+ logger$8.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8290
8812
  this.holdSipSession(this.currentSipSession, callSession);
8291
8813
  }
8292
8814
 
@@ -8301,14 +8823,14 @@ class WebRTCPhone extends Emitter {
8301
8823
  }
8302
8824
 
8303
8825
  mute(callSession , withEvent = true) {
8304
- logger$7.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8826
+ logger$8.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8305
8827
 
8306
8828
  const sipSession = this.findSipSession(callSession);
8307
8829
  if (!sipSession) {
8308
8830
  return;
8309
8831
  }
8310
8832
 
8311
- logger$7.info('WebRTC muting', { sipId: sipSession.id });
8833
+ logger$8.info('WebRTC muting', { sipId: sipSession.id });
8312
8834
  this.client.mute(sipSession);
8313
8835
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: true });
8314
8836
 
@@ -8322,14 +8844,14 @@ class WebRTCPhone extends Emitter {
8322
8844
  }
8323
8845
 
8324
8846
  unmute(callSession , withEvent = true) {
8325
- logger$7.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8847
+ logger$8.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8326
8848
 
8327
8849
  const sipSession = this.findSipSession(callSession);
8328
8850
  if (!sipSession) {
8329
8851
  return;
8330
8852
  }
8331
8853
 
8332
- logger$7.info('WebRTC unmuting', { sipId: sipSession.id });
8854
+ logger$8.info('WebRTC unmuting', { sipId: sipSession.id });
8333
8855
  this.client.unmute(sipSession);
8334
8856
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: false });
8335
8857
 
@@ -8356,7 +8878,7 @@ class WebRTCPhone extends Emitter {
8356
8878
  if (!sipSession) {
8357
8879
  return;
8358
8880
  }
8359
- logger$7.info('WebRTC turn camera on', { sipId: sipSession.id });
8881
+ logger$8.info('WebRTC turn camera on', { sipId: sipSession.id });
8360
8882
 
8361
8883
  this.client.toggleCameraOn(sipSession);
8362
8884
 
@@ -8368,7 +8890,7 @@ class WebRTCPhone extends Emitter {
8368
8890
  if (!sipSession) {
8369
8891
  return;
8370
8892
  }
8371
- logger$7.info('WebRTC turn camera off', { sipId: sipSession.id });
8893
+ logger$8.info('WebRTC turn camera off', { sipId: sipSession.id });
8372
8894
 
8373
8895
  this.client.toggleCameraOff(sipSession);
8374
8896
  this.eventEmitter.emit(ON_CAMERA_DISABLED, this._createCameraDisabledCallSession(sipSession, callSession));
@@ -8380,7 +8902,7 @@ class WebRTCPhone extends Emitter {
8380
8902
  return;
8381
8903
  }
8382
8904
 
8383
- logger$7.info('WebRTC send key', { sipId: sipSession.id, tone });
8905
+ logger$8.info('WebRTC send key', { sipId: sipSession.id, tone });
8384
8906
  this.client.sendDTMF(sipSession, tone);
8385
8907
  }
8386
8908
 
@@ -8388,7 +8910,7 @@ class WebRTCPhone extends Emitter {
8388
8910
  // @TODO: line is not used here
8389
8911
  async makeCall(number , line , cameraEnabled ,
8390
8912
  audioOnly = false, conference = false) {
8391
- logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8913
+ logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8392
8914
  if (!number) {
8393
8915
  return Promise.resolve(null);
8394
8916
  }
@@ -8398,7 +8920,7 @@ class WebRTCPhone extends Emitter {
8398
8920
  }
8399
8921
  if (this.currentSipSession) {
8400
8922
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true).catch(e => {
8401
- logger$7.warn('Unable to hold current session when making another call', e);
8923
+ logger$8.warn('Unable to hold current session when making another call', e);
8402
8924
  });
8403
8925
  }
8404
8926
 
@@ -8408,7 +8930,7 @@ class WebRTCPhone extends Emitter {
8408
8930
  this._bindEvents(sipSession);
8409
8931
  } catch (error) {
8410
8932
  console.warn(error);
8411
- logger$7.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8933
+ logger$8.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8412
8934
  return Promise.resolve(null);
8413
8935
  }
8414
8936
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
@@ -8436,7 +8958,7 @@ class WebRTCPhone extends Emitter {
8436
8958
  return;
8437
8959
  }
8438
8960
 
8439
- logger$7.info('WebRTC transfer', { sipId: sipSession.id, target });
8961
+ logger$8.info('WebRTC transfer', { sipId: sipSession.id, target });
8440
8962
 
8441
8963
  this.client.transfer(sipSession, target);
8442
8964
  }
@@ -8445,7 +8967,7 @@ class WebRTCPhone extends Emitter {
8445
8967
  const sipSession = this.client.getSipSession(source.sipCallId);
8446
8968
  const sipSessionTarget = this.client.getSipSession(destination.sipCallId);
8447
8969
 
8448
- logger$7.info('WebRTC indirect transfer', {
8970
+ logger$8.info('WebRTC indirect transfer', {
8449
8971
  sipId: sipSession ? sipSession.id : null,
8450
8972
  target: sipSessionTarget ? sipSessionTarget.id : null,
8451
8973
  });
@@ -8473,7 +8995,7 @@ class WebRTCPhone extends Emitter {
8473
8995
  return false;
8474
8996
  }
8475
8997
 
8476
- logger$7.info('WebRTC hangup', { sipId: sipSession.id });
8998
+ logger$8.info('WebRTC hangup', { sipId: sipSession.id });
8477
8999
 
8478
9000
  const sipSessionId = this.getSipSessionId(sipSession);
8479
9001
 
@@ -8518,7 +9040,7 @@ class WebRTCPhone extends Emitter {
8518
9040
  }
8519
9041
 
8520
9042
  async close() {
8521
- logger$7.info('WebRTC close');
9043
+ logger$8.info('WebRTC close');
8522
9044
 
8523
9045
  try {
8524
9046
  await Promise.race([
@@ -8526,7 +9048,7 @@ class WebRTCPhone extends Emitter {
8526
9048
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Unregister, timed out')), 3000)),
8527
9049
  ]);
8528
9050
  } catch (e) {
8529
- logger$7.error('WebRTC close, unregister error', e);
9051
+ logger$8.error('WebRTC close, unregister error', e);
8530
9052
  }
8531
9053
 
8532
9054
  this.client.close();
@@ -8544,12 +9066,12 @@ class WebRTCPhone extends Emitter {
8544
9066
  }
8545
9067
 
8546
9068
  enableRinging() {
8547
- logger$7.info('WebRTC enable ringing');
9069
+ logger$8.info('WebRTC enable ringing');
8548
9070
  this.ringingEnabled = true;
8549
9071
  }
8550
9072
 
8551
9073
  disableRinging() {
8552
- logger$7.info('WebRTC disable ringing');
9074
+ logger$8.info('WebRTC disable ringing');
8553
9075
  this.ringingEnabled = false;
8554
9076
  }
8555
9077
 
@@ -8589,7 +9111,7 @@ class WebRTCPhone extends Emitter {
8589
9111
 
8590
9112
  // Deprecated
8591
9113
  getLocalMediaStream(callSession ) {
8592
- logger$7.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
9114
+ logger$8.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
8593
9115
  return this.getLocalStream(callSession);
8594
9116
  }
8595
9117
 
@@ -8597,6 +9119,10 @@ class WebRTCPhone extends Emitter {
8597
9119
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
8598
9120
  }
8599
9121
 
9122
+ hasALocalVideoTrack(callSession ) {
9123
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
9124
+ }
9125
+
8600
9126
  getRemoteStream(callSession ) {
8601
9127
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
8602
9128
  }
@@ -8619,7 +9145,7 @@ class WebRTCPhone extends Emitter {
8619
9145
  this.client.on(this.client.INVITE, (sipSession , wantsToDoVideo ) => {
8620
9146
  const autoAnswer = sipSession.request.getHeader('Answer-Mode') === 'Auto';
8621
9147
  const withVideo = this.allowVideo ? wantsToDoVideo : false;
8622
- logger$7.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
9148
+ logger$8.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
8623
9149
 
8624
9150
  const callSession = this._createIncomingCallSession(sipSession, withVideo, null, autoAnswer);
8625
9151
  this.incomingSessions.push(callSession.getId());
@@ -8642,7 +9168,7 @@ class WebRTCPhone extends Emitter {
8642
9168
  });
8643
9169
 
8644
9170
  this.client.on(this.client.ON_REINVITE, (...args) => {
8645
- logger$7.info('WebRTC on reinvite', {
9171
+ logger$8.info('WebRTC on reinvite', {
8646
9172
  sessionId: args[0].id,
8647
9173
  inviteId: args[1].id,
8648
9174
  updatedCalleeName: args[2],
@@ -8662,7 +9188,7 @@ class WebRTCPhone extends Emitter {
8662
9188
  });
8663
9189
 
8664
9190
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
8665
- logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
9191
+ logger$8.info('WebRTC call accepted', { sipId: sipSession.id });
8666
9192
 
8667
9193
  this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
8668
9194
 
@@ -8673,17 +9199,17 @@ class WebRTCPhone extends Emitter {
8673
9199
  this.client.on('ended', () => {});
8674
9200
 
8675
9201
  this.client.on(this.client.ON_ERROR, e => {
8676
- logger$7.error('WebRTC error', e);
9202
+ logger$8.error('WebRTC error', e);
8677
9203
  this.eventEmitter.emit(ON_CALL_ERROR, e);
8678
9204
  });
8679
9205
 
8680
9206
  this.client.on(this.client.UNREGISTERED, () => {
8681
- logger$7.info('WebRTC unregistered');
9207
+ logger$8.info('WebRTC unregistered');
8682
9208
  this.eventEmitter.emit(ON_UNREGISTERED);
8683
9209
  });
8684
9210
 
8685
9211
  this.client.on(this.client.REGISTERED, () => {
8686
- logger$7.info('WebRTC registered', {
9212
+ logger$8.info('WebRTC registered', {
8687
9213
  shouldSendReinvite: this.shouldSendReinvite,
8688
9214
  state: this.currentSipSession ? this.currentSipSession.state : null,
8689
9215
  currentSipSession: !!this.currentSipSession,
@@ -8699,19 +9225,19 @@ class WebRTCPhone extends Emitter {
8699
9225
  try {
8700
9226
  this.sendReinvite(this.currentCallSession);
8701
9227
  } catch (e) {
8702
- logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9228
+ logger$8.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
8703
9229
  }
8704
9230
  }
8705
9231
  });
8706
9232
 
8707
9233
  this.client.on(this.client.CONNECTED, () => {
8708
- logger$7.info('WebRTC client connected');
9234
+ logger$8.info('WebRTC client connected');
8709
9235
 
8710
9236
  this.stopHeartbeat();
8711
9237
  });
8712
9238
 
8713
9239
  this.client.on(this.client.DISCONNECTED, () => {
8714
- logger$7.info('WebRTC client disconnected');
9240
+ logger$8.info('WebRTC client disconnected');
8715
9241
 
8716
9242
  this.eventEmitter.emit(ON_UNREGISTERED);
8717
9243
 
@@ -8943,7 +9469,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
8943
9469
 
8944
9470
  //
8945
9471
 
8946
- const logger$6 = IssueReporter$1.loggerFor('simple-phone');
9472
+ const logger$7 = IssueReporter$1.loggerFor('simple-phone');
8947
9473
  const sipLogger = IssueReporter$1.loggerFor('sip.js');
8948
9474
  const protocolLogger = IssueReporter$1.loggerFor('sip');
8949
9475
 
@@ -9050,7 +9576,7 @@ class Phone extends Emitter {
9050
9576
  async disconnect() {
9051
9577
  if (this.phone) {
9052
9578
  if (this.phone.hasAnActiveCall()) {
9053
- logger$6.info('hangup call on disconnect');
9579
+ logger$7.info('hangup call on disconnect');
9054
9580
  // $FlowFixMe
9055
9581
  await this.phone.hangup();
9056
9582
  }
@@ -9073,13 +9599,13 @@ class Phone extends Emitter {
9073
9599
  }
9074
9600
 
9075
9601
  async hangup(callSession ) {
9076
- logger$6.info('hangup via simple phone', { callId: callSession.getId() });
9602
+ logger$7.info('hangup via simple phone', { callId: callSession.getId() });
9077
9603
 
9078
9604
  return this.phone && this.phone.hangup(callSession);
9079
9605
  }
9080
9606
 
9081
9607
  async accept(callSession , cameraEnabled ) {
9082
- logger$6.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9608
+ logger$7.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9083
9609
 
9084
9610
  return this.phone && this.phone.accept(callSession, cameraEnabled);
9085
9611
  }
@@ -9099,13 +9625,18 @@ class Phone extends Emitter {
9099
9625
  return adHocConference.start();
9100
9626
  }
9101
9627
 
9102
- mute(callSession ) {
9103
- this.muteViaAPI(callSession);
9628
+ mute(callSession , withApi = true) {
9629
+ if (withApi) {
9630
+ this.muteViaAPI(callSession);
9631
+ }
9632
+
9104
9633
  return this.phone && this.phone.mute(callSession);
9105
9634
  }
9106
9635
 
9107
- unmute(callSession ) {
9108
- this.unmuteViaAPI(callSession);
9636
+ unmute(callSession , withApi = true) {
9637
+ if (withApi) {
9638
+ this.unmuteViaAPI(callSession);
9639
+ }
9109
9640
 
9110
9641
  return this.phone && this.phone.unmute(callSession);
9111
9642
  }
@@ -9113,7 +9644,7 @@ class Phone extends Emitter {
9113
9644
  muteViaAPI(callSession ) {
9114
9645
  if (callSession && callSession.callId) {
9115
9646
  Wazo.getApiClient().calld.mute(callSession.callId).catch(e => {
9116
- logger$6.error('Mute via API, error', e);
9647
+ logger$7.error('Mute via API, error', e);
9117
9648
  });
9118
9649
  }
9119
9650
  }
@@ -9121,7 +9652,7 @@ class Phone extends Emitter {
9121
9652
  unmuteViaAPI(callSession ) {
9122
9653
  if (callSession && callSession.callId) {
9123
9654
  Wazo.getApiClient().calld.unmute(callSession.callId).catch(e => {
9124
- logger$6.error('Unmute via API, error', e);
9655
+ logger$7.error('Unmute via API, error', e);
9125
9656
  });
9126
9657
  }
9127
9658
  }
@@ -9211,9 +9742,13 @@ class Phone extends Emitter {
9211
9742
  return this.phone && this.phone.hasLocalVideo(callSession);
9212
9743
  }
9213
9744
 
9745
+ hasALocalVideoTrack(callSession ) {
9746
+ return this.phone && this.phone.hasALocalVideoTrack(callSession);
9747
+ }
9748
+
9214
9749
  // @Deprecated
9215
9750
  getLocalMediaStream(callSession ) {
9216
- logger$6.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9751
+ logger$7.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9217
9752
 
9218
9753
  return this.phone && this.phone.getLocalStream(callSession);
9219
9754
  }
@@ -9232,20 +9767,20 @@ class Phone extends Emitter {
9232
9767
 
9233
9768
  // @Deprecated
9234
9769
  getRemoteStreamForCall(callSession ) {
9235
- logger$6.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9770
+ logger$7.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9236
9771
  return this.getRemoteStream(callSession);
9237
9772
  }
9238
9773
 
9239
9774
  // Returns remote streams directly from the peerConnection
9240
9775
  // @Deprecated
9241
9776
  getRemoteStreamsForCall(callSession ) {
9242
- logger$6.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9777
+ logger$7.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9243
9778
  return this.getLocalStream(callSession);
9244
9779
  }
9245
9780
 
9246
9781
  // @Deprecated
9247
9782
  getRemoteVideoStreamForCall(callSession ) {
9248
- logger$6.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9783
+ logger$7.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9249
9784
 
9250
9785
  return this.getRemoteVideoStream(callSession);
9251
9786
  }
@@ -9375,6 +9910,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
9375
9910
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
9376
9911
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
9377
9912
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
9913
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
9914
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
9378
9915
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
9379
9916
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
9380
9917
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -9416,7 +9953,7 @@ const BLACKLIST_EVENTS = [
9416
9953
  ];
9417
9954
 
9418
9955
  const HEARTBEAT_ENGINE_VERSION = '20.09';
9419
- const logger$5 = IssueReporter$1.loggerFor('wazo-ws');
9956
+ const logger$6 = IssueReporter$1.loggerFor('wazo-ws');
9420
9957
  const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
9421
9958
 
9422
9959
  class WebSocketClient extends Emitter {
@@ -9465,19 +10002,19 @@ class WebSocketClient extends Emitter {
9465
10002
  }
9466
10003
 
9467
10004
  connect() {
9468
- logger$5.info('connect method started', { host: this.host, token: this.token });
10005
+ logger$6.info('connect method started', { host: this.host, token: this.token });
9469
10006
  this.socket = new ReconnectingWebSocket__default['default'](this._getUrl.bind(this), [], this.options);
9470
10007
  if (this.options.binaryType) {
9471
10008
  this.socket.binaryType = this.options.binaryType;
9472
10009
  }
9473
10010
 
9474
10011
  this.socket.onopen = () => {
9475
- logger$5.info('on Wazo WS open', { method: 'connect', host: this.host });
10012
+ logger$6.info('on Wazo WS open', { method: 'connect', host: this.host });
9476
10013
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_OPEN);
9477
10014
  };
9478
10015
 
9479
10016
  this.socket.onerror = event => {
9480
- logger$5.error('on Wazo WS error', event.target);
10017
+ logger$6.error('on Wazo WS error', event.target);
9481
10018
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_ERROR, event);
9482
10019
  };
9483
10020
 
@@ -9507,7 +10044,7 @@ class WebSocketClient extends Emitter {
9507
10044
 
9508
10045
  this.socket.onclose = event => {
9509
10046
  // Can't be converted to JSON (circular structure)
9510
- logger$5.info('on Wazo WS close', {
10047
+ logger$6.info('on Wazo WS close', {
9511
10048
  reason: event.reason,
9512
10049
  code: event.code,
9513
10050
  readyState: event.target.readyState,
@@ -9525,12 +10062,12 @@ class WebSocketClient extends Emitter {
9525
10062
  };
9526
10063
 
9527
10064
  this.socket.onerror = event => {
9528
- logger$5.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
10065
+ logger$6.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
9529
10066
  };
9530
10067
  }
9531
10068
 
9532
10069
  close(force = false) {
9533
- logger$5.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
10070
+ logger$6.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
9534
10071
 
9535
10072
  if (!this.socket) {
9536
10073
  return;
@@ -9548,7 +10085,7 @@ class WebSocketClient extends Emitter {
9548
10085
 
9549
10086
  updateToken(token ) {
9550
10087
  this.token = token;
9551
- logger$5.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
10088
+ logger$6.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
9552
10089
 
9553
10090
  if (this.socket) {
9554
10091
  // If still connected, send the token to the WS
@@ -9566,7 +10103,7 @@ class WebSocketClient extends Emitter {
9566
10103
  }
9567
10104
 
9568
10105
  startHeartbeat() {
9569
- logger$5.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
10106
+ logger$6.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
9570
10107
 
9571
10108
  if (!this.socket) {
9572
10109
  this.heartbeat.stop();
@@ -9580,7 +10117,7 @@ class WebSocketClient extends Emitter {
9580
10117
  }
9581
10118
 
9582
10119
  stopHeartbeat() {
9583
- logger$5.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
10120
+ logger$6.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
9584
10121
 
9585
10122
  this.heartbeat.stop();
9586
10123
  }
@@ -9610,7 +10147,7 @@ class WebSocketClient extends Emitter {
9610
10147
  }
9611
10148
 
9612
10149
  reconnect(reason ) {
9613
- logger$5.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
10150
+ logger$6.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
9614
10151
  if (!this.socket) {
9615
10152
  return;
9616
10153
  }
@@ -9666,7 +10203,7 @@ class WebSocketClient extends Emitter {
9666
10203
  this.close();
9667
10204
  }
9668
10205
  const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
9669
- logger$5.log('Wazo WS url computed to reconnect', { url });
10206
+ logger$6.log('Wazo WS url computed to reconnect', { url });
9670
10207
 
9671
10208
  return url;
9672
10209
  }
@@ -9674,12 +10211,12 @@ class WebSocketClient extends Emitter {
9674
10211
  _onHeartbeat(message ) {
9675
10212
  if (message.payload === 'pong') {
9676
10213
  this.heartbeat.onHeartbeat();
9677
- logger$5.log('on heartbeat received from Wazo WS');
10214
+ logger$6.log('on heartbeat received from Wazo WS');
9678
10215
  }
9679
10216
  }
9680
10217
 
9681
10218
  async _onHeartbeatTimeout() {
9682
- logger$5.log('heartbeat timed out', { host: this.host, token: this.token });
10219
+ logger$6.log('heartbeat timed out', { host: this.host, token: this.token });
9683
10220
 
9684
10221
  this.close();
9685
10222
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_CLOSE, new Error('Websocket ping failure.'));
@@ -9721,6 +10258,8 @@ WebSocketClient.eventLists = [
9721
10258
  CHATD_USER_ROOM_CREATED,
9722
10259
  CONFERENCE_USER_PARTICIPANT_JOINED,
9723
10260
  CONFERENCE_USER_PARTICIPANT_LEFT,
10261
+ MEETING_USER_PARTICIPANT_JOINED,
10262
+ MEETING_USER_PARTICIPANT_LEFT,
9724
10263
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9725
10264
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
9726
10265
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -9791,6 +10330,8 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
9791
10330
  CONFERENCE_USER_PARTICIPANT_LEFT: CONFERENCE_USER_PARTICIPANT_LEFT,
9792
10331
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED: CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9793
10332
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED: CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
10333
+ MEETING_USER_PARTICIPANT_JOINED: MEETING_USER_PARTICIPANT_JOINED,
10334
+ MEETING_USER_PARTICIPANT_LEFT: MEETING_USER_PARTICIPANT_LEFT,
9794
10335
  SWITCHBOARD_QUEUED_CALLS_UPDATED: SWITCHBOARD_QUEUED_CALLS_UPDATED,
9795
10336
  SWITCHBOARD_QUEUED_CALL_ANSWERED: SWITCHBOARD_QUEUED_CALL_ANSWERED,
9796
10337
  SWITCHBOARD_HELD_CALLS_UPDATED: SWITCHBOARD_HELD_CALLS_UPDATED,
@@ -9832,7 +10373,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
9832
10373
  const { SOCKET_EVENTS, ...OTHER_EVENTS } = WebSocketClient$1;
9833
10374
  const ALL_EVENTS = [...Object.values(SOCKET_EVENTS), ...Object.values(OTHER_EVENTS)];
9834
10375
 
9835
- const logger$4 = IssueReporter$1.loggerFor('simple-ws-client');
10376
+ const logger$5 = IssueReporter$1.loggerFor('simple-ws-client');
9836
10377
 
9837
10378
  class Websocket extends Emitter {
9838
10379
 
@@ -9856,7 +10397,7 @@ class Websocket extends Emitter {
9856
10397
  }
9857
10398
 
9858
10399
  open(host , session ) {
9859
- logger$4.info('open simple WebSocket', { host, token: session.token });
10400
+ logger$5.info('open simple WebSocket', { host, token: session.token });
9860
10401
  this.ws = new WebSocketClient(
9861
10402
  {
9862
10403
  host,
@@ -9884,7 +10425,7 @@ class Websocket extends Emitter {
9884
10425
  }
9885
10426
 
9886
10427
  updateToken(token ) {
9887
- logger$4.info('update token via simple Websocket', { token, ws: !!this.ws });
10428
+ logger$5.info('update token via simple Websocket', { token, ws: !!this.ws });
9888
10429
 
9889
10430
  if (!this.ws) {
9890
10431
  return;
@@ -9912,7 +10453,7 @@ var Websocket$1 = global.wazoWebsocketInstance;
9912
10453
 
9913
10454
  //
9914
10455
 
9915
- const logger$3 = IssueReporter$1.loggerFor('room');
10456
+ const logger$4 = IssueReporter$1.loggerFor('room');
9916
10457
 
9917
10458
  class Participant extends Emitter {
9918
10459
 
@@ -9946,6 +10487,7 @@ class Participant extends Emitter {
9946
10487
 
9947
10488
 
9948
10489
  /**
10490
+ * @param room Room The room where the participant is
9949
10491
  * @param rawParticipant string Participant sent via the Wazo WS
9950
10492
  * @param extra Object extra status of the participant
9951
10493
  */
@@ -10033,7 +10575,7 @@ class Participant extends Emitter {
10033
10575
  }
10034
10576
 
10035
10577
  onTalking(isTalking ) {
10036
- logger$3.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10578
+ logger$4.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10037
10579
  this.isTalking = isTalking;
10038
10580
  // you may notice we're not broadcasting: since all participants are getting this info
10039
10581
  // directly from asterisk, there's no need to do so
@@ -10136,7 +10678,7 @@ class Participant extends Emitter {
10136
10678
  }
10137
10679
 
10138
10680
  updateStatus(status , broadcast = true) {
10139
- logger$3.info('updating participant status', { name: this.name, status });
10681
+ logger$4.info('updating participant status', { name: this.name, status });
10140
10682
 
10141
10683
  if (typeof status.audioMuted !== 'undefined' && status.audioMuted !== this.audioMuted) {
10142
10684
  if (status.audioMuted) {
@@ -10173,13 +10715,18 @@ class Participant extends Emitter {
10173
10715
  // Poor man's object comparison
10174
10716
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
10175
10717
  this.extra = { ...this.extra, ...status.extra };
10718
+
10719
+ if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
10720
+ this.extra.contact = new Contact(this.extra.contact);
10721
+ }
10722
+
10176
10723
  this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
10177
10724
  }
10178
10725
  }
10179
10726
 
10180
10727
  broadcastStatus(inboundStatus = null) {
10181
10728
  const status = inboundStatus || this.getStatus();
10182
- logger$3.info('broadcasting participant status', { callId: this.callId, status });
10729
+ logger$4.info('broadcasting participant status', { callId: this.callId, status });
10183
10730
 
10184
10731
  this.room.sendSignal({
10185
10732
  type: SIGNAL_TYPE_PARTICIPANT_UPDATE,
@@ -10200,18 +10747,24 @@ class RemoteParticipant extends Participant {
10200
10747
  }
10201
10748
  }
10202
10749
 
10203
- /* global document */
10750
+ //
10751
+
10752
+ class LocalParticipant extends Participant {
10753
+ }
10754
+
10755
+ //
10204
10756
 
10205
10757
  const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
10206
10758
  const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
10207
10759
 
10208
- const logger$2 = IssueReporter$1.loggerFor('sdk-room');
10760
+ const logger$3 = IssueReporter$1.loggerFor('sdk-room');
10209
10761
 
10210
10762
  class Room$1 extends Emitter {
10211
10763
 
10212
10764
 
10213
10765
 
10214
10766
 
10767
+
10215
10768
 
10216
10769
 
10217
10770
 
@@ -10233,6 +10786,8 @@ class Room$1 extends Emitter {
10233
10786
 
10234
10787
 
10235
10788
 
10789
+
10790
+
10236
10791
 
10237
10792
 
10238
10793
 
@@ -10250,6 +10805,7 @@ class Room$1 extends Emitter {
10250
10805
  * @param extension string
10251
10806
  * @param sourceId number
10252
10807
  * @param callId string
10808
+ * @param meetingUuid string
10253
10809
  * @param extra Object
10254
10810
  */
10255
10811
  constructor(
@@ -10257,15 +10813,17 @@ class Room$1 extends Emitter {
10257
10813
  extension ,
10258
10814
  sourceId ,
10259
10815
  callId ,
10816
+ meetingUuid ,
10260
10817
  extra = {},
10261
10818
  ) {
10262
10819
  super();
10263
- logger$2.info('room initialized', { callId, extension, sourceId });
10820
+ logger$3.info('room initialized', { callId, extension, sourceId, meetingUuid });
10264
10821
 
10265
10822
  // Represents the room callSession
10266
10823
  this.callSession = callSession;
10267
10824
  this.extension = extension;
10268
10825
  this.sourceId = sourceId;
10826
+ this.meetingUuid = meetingUuid;
10269
10827
  this.callId = callId;
10270
10828
  this.participants = [];
10271
10829
  this.connected = false;
@@ -10285,6 +10843,8 @@ class Room$1 extends Emitter {
10285
10843
  // Sugar syntax for `room.EVENT_NAME`
10286
10844
  this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
10287
10845
  this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
10846
+ this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
10847
+ this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
10288
10848
  this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
10289
10849
  this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
10290
10850
  this.ON_CHAT = Wazo.Phone.ON_CHAT;
@@ -10319,10 +10879,11 @@ class Room$1 extends Emitter {
10319
10879
  * @param audioOnly boolean
10320
10880
  * @param extra Object
10321
10881
  * @param room ?Room
10882
+ * @param meeting ?Meeting
10322
10883
  * @returns {Promise<Room>}
10323
10884
  */
10324
- static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
10325
- logger$2.info('connecting to room', { extension, audioOnly, room: !!room });
10885
+ static async connect({ extension, constraints, audioOnly = false, extra, room, meeting } ) {
10886
+ logger$3.info('connecting to room', { extension, audioOnly, room: !!room });
10326
10887
 
10327
10888
  if (!room) {
10328
10889
  await Wazo.Phone.connect();
@@ -10335,7 +10896,7 @@ class Room$1 extends Emitter {
10335
10896
 
10336
10897
  // Call_created is triggered before call_accepted, so we have to listen for it here.
10337
10898
  Wazo.Websocket.once(Wazo.Websocket.CALL_CREATED, ({ data }) => {
10338
- logger$2.info('room call received via WS', { callId: data.call_id });
10899
+ logger$3.info('room call received via WS', { callId: data.call_id });
10339
10900
  if (room) {
10340
10901
  room.setCallId(data.call_id);
10341
10902
  }
@@ -10356,34 +10917,44 @@ class Room$1 extends Emitter {
10356
10917
  room.setCallId(room.callSession.call.id);
10357
10918
  }
10358
10919
 
10359
- // Fetch conference source
10360
- const sources = await getApiClient().dird.fetchConferenceSource('default');
10361
- // Retrieve conference sources
10362
- const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
10363
- // Retrieve conference
10364
- const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
10920
+ if (!meeting) {
10921
+ // Fetch conference source
10922
+ const sources = await getApiClient().dird.fetchConferenceSource('default');
10923
+ // Retrieve conference sources
10924
+ const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
10925
+ // Retrieve conference
10926
+ const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
10365
10927
 
10366
- logger$2.info('connected to room', {
10367
- sourceId: conference ? conference.sourceId : null,
10368
- name: conference ? conference.name : null,
10369
- });
10928
+ logger$3.info('connected to room', {
10929
+ sourceId: conference ? conference.sourceId : null,
10930
+ name: conference ? conference.name : null,
10931
+ });
10370
10932
 
10371
- if (conference) {
10372
- room.setSourceId(conference.sourceId);
10373
- room.setName(conference.name);
10933
+ if (conference) {
10934
+ room.setSourceId(conference.sourceId);
10935
+ room.setName(conference.name);
10936
+ }
10937
+ } else if (meeting) {
10938
+ logger$3.info('Already connected to meeting', {
10939
+ uuid: meeting.uuid,
10940
+ name: meeting.name,
10941
+ });
10942
+
10943
+ room.setMeetingUuid(meeting.uuid);
10944
+ room.setName(meeting.name);
10374
10945
  }
10375
10946
 
10376
10947
  return room;
10377
10948
  }
10378
10949
 
10379
10950
  static disconnect() {
10380
- logger$2.info('static disconnection to room');
10951
+ logger$3.info('static disconnection to room');
10381
10952
 
10382
10953
  Wazo.Phone.disconnect();
10383
10954
  }
10384
10955
 
10385
10956
  async disconnect() {
10386
- logger$2.info('disconnection to room called');
10957
+ logger$3.info('disconnection to room called');
10387
10958
 
10388
10959
  await Wazo.Phone.hangup(this.callSession);
10389
10960
  this.callSession = null;
@@ -10398,20 +10969,24 @@ class Room$1 extends Emitter {
10398
10969
  Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10399
10970
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10400
10971
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10401
-
10402
- if (this.roomAudioElement && document.body) {
10403
- document.body.removeChild(this.roomAudioElement);
10404
- }
10972
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10973
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10405
10974
  }
10406
10975
 
10407
10976
  setSourceId(sourceId ) {
10408
- logger$2.info('set room source id', { sourceId });
10977
+ logger$3.info('set room source id', { sourceId });
10409
10978
 
10410
10979
  this.sourceId = sourceId;
10411
10980
  }
10412
10981
 
10982
+ setMeetingUuid(meetingUuid ) {
10983
+ logger$3.info('set meeting uuid', { meetingUuid });
10984
+
10985
+ this.meetingUuid = meetingUuid;
10986
+ }
10987
+
10413
10988
  setCallId(callId ) {
10414
- logger$2.info('set room call id', { callId });
10989
+ logger$3.info('set room call id', { callId });
10415
10990
 
10416
10991
  if (callId) {
10417
10992
  this.callId = callId;
@@ -10419,7 +10994,7 @@ class Room$1 extends Emitter {
10419
10994
  }
10420
10995
 
10421
10996
  setName(name ) {
10422
- logger$2.info('set room name', { name });
10997
+ logger$3.info('set room name', { name });
10423
10998
 
10424
10999
  this.name = name;
10425
11000
  }
@@ -10438,7 +11013,7 @@ class Room$1 extends Emitter {
10438
11013
  }
10439
11014
 
10440
11015
  async startScreenSharing(constraints ) {
10441
- logger$2.info('start room screen sharing', { constraints });
11016
+ logger$3.info('start room screen sharing', { constraints });
10442
11017
 
10443
11018
  const screensharingStream = await Wazo.Phone.startScreenSharing(constraints, this.callSession);
10444
11019
  if (!screensharingStream) {
@@ -10451,18 +11026,26 @@ class Room$1 extends Emitter {
10451
11026
  return screensharingStream;
10452
11027
  }
10453
11028
 
10454
- stopScreenSharing(restoreLocalStream = true) {
10455
- logger$2.info('stop room screen sharing');
11029
+ async stopScreenSharing(restoreLocalStream = true) {
11030
+ logger$3.info('stop room screen sharing');
10456
11031
 
10457
- Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
11032
+ const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
10458
11033
 
10459
11034
  if (this.localParticipant) {
10460
11035
  this.localParticipant.onStopScreensharing();
10461
11036
  }
11037
+
11038
+ if (!reinvited && this.localParticipant) {
11039
+ // When we had video and we made a screenshare we don't reinvite when stopping the screensahre
11040
+ // So not REINVITE even is fired, we have to restore the video stream manually
11041
+ const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
11042
+ // $FlowFixMe
11043
+ this._associateStreamTo(localVideoStream, this.localParticipant);
11044
+ }
10462
11045
  }
10463
11046
 
10464
11047
  turnCameraOff() {
10465
- logger$2.info('turn room camera off');
11048
+ logger$3.info('turn room camera off');
10466
11049
 
10467
11050
  Wazo.Phone.turnCameraOff(this.callSession);
10468
11051
 
@@ -10472,7 +11055,7 @@ class Room$1 extends Emitter {
10472
11055
  }
10473
11056
 
10474
11057
  turnCameraOn() {
10475
- logger$2.info('turn room camera on');
11058
+ logger$3.info('turn room camera on');
10476
11059
 
10477
11060
  Wazo.Phone.turnCameraOn(this.callSession);
10478
11061
 
@@ -10482,7 +11065,7 @@ class Room$1 extends Emitter {
10482
11065
  }
10483
11066
 
10484
11067
  mute() {
10485
- logger$2.info('mute room');
11068
+ logger$3.info('mute room');
10486
11069
 
10487
11070
  Wazo.Phone.mute(this.callSession);
10488
11071
 
@@ -10490,7 +11073,7 @@ class Room$1 extends Emitter {
10490
11073
  }
10491
11074
 
10492
11075
  unmute() {
10493
- logger$2.info('unmute room');
11076
+ logger$3.info('unmute room');
10494
11077
 
10495
11078
  Wazo.Phone.unmute(this.callSession);
10496
11079
 
@@ -10510,7 +11093,7 @@ class Room$1 extends Emitter {
10510
11093
  }
10511
11094
 
10512
11095
  hold() {
10513
- logger$2.info('hold room');
11096
+ logger$3.info('hold room');
10514
11097
 
10515
11098
  Wazo.Phone.hold(this.callSession, true);
10516
11099
 
@@ -10520,7 +11103,7 @@ class Room$1 extends Emitter {
10520
11103
  }
10521
11104
 
10522
11105
  resume() {
10523
- logger$2.info('resume room');
11106
+ logger$3.info('resume room');
10524
11107
 
10525
11108
  Wazo.Phone.resume(this.callSession, true);
10526
11109
 
@@ -10530,13 +11113,13 @@ class Room$1 extends Emitter {
10530
11113
  }
10531
11114
 
10532
11115
  sendDTMF(tone ) {
10533
- logger$2.info('send room DTMF', { tone });
11116
+ logger$3.info('send room DTMF', { tone });
10534
11117
 
10535
11118
  Wazo.Phone.sendDTMF(tone, this.callSession);
10536
11119
  }
10537
11120
 
10538
11121
  async sendReinvite(newConstraints = null) {
10539
- logger$2.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
11122
+ logger$3.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
10540
11123
  const wasScreensharing = this.localParticipant && this.localParticipant.screensharing;
10541
11124
 
10542
11125
  Wazo.Phone.on(Wazo.Phone.ON_SHARE_SCREEN_STARTED, () => {
@@ -10561,6 +11144,22 @@ class Room$1 extends Emitter {
10561
11144
  return response;
10562
11145
  }
10563
11146
 
11147
+ hasALocalVideoTrack() {
11148
+ return Wazo.Phone.hasALocalVideoTrack(this.callSession);
11149
+ }
11150
+
11151
+ getLocalStream() {
11152
+ return Wazo.Phone.getLocalStream(this.callSession);
11153
+ }
11154
+
11155
+ getRemoteStream() {
11156
+ return Wazo.Phone.getRemoteStream(this.callSession);
11157
+ }
11158
+
11159
+ getRemoteVideoStream() {
11160
+ return Wazo.Phone.getRemoteVideoStream(this.callSession);
11161
+ }
11162
+
10564
11163
  _bindEvents() {
10565
11164
  if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
10566
11165
  return;
@@ -10579,35 +11178,18 @@ class Room$1 extends Emitter {
10579
11178
  Wazo.Phone.phone.on(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10580
11179
 
10581
11180
  this.on(this.ON_AUDIO_STREAM, stream => {
10582
- logger$2.info('on room audio stream');
11181
+ logger$3.info('on room audio stream');
10583
11182
 
10584
11183
  this.audioStream = stream;
10585
- if (document.createElement) {
10586
- // $FlowFixMe
10587
- let roomAudioElement = document.getElementById('audio-room');
10588
- if (!this.roomAudioElement) {
10589
- roomAudioElement = document.createElement('audio');
10590
- // $FlowFixMe
10591
- document.body.appendChild(roomAudioElement);
10592
- }
10593
- if (!roomAudioElement) {
10594
- return;
10595
- }
10596
- this.roomAudioElement = roomAudioElement;
11184
+ if (!this.roomAudioElement) {
11185
+ const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11186
+ this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
10597
11187
  this.roomAudioElement.srcObject = stream;
10598
- this.roomAudioElement.autoplay = true;
10599
- this.roomAudioElement.id = 'audio-room';
10600
-
10601
- // $FlowFixMe
10602
- if (this.roomAudioElement.setSinkId) {
10603
- // $FlowFixMe
10604
- this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
10605
- }
10606
11188
  }
10607
11189
  });
10608
11190
 
10609
11191
  this.on(this.ON_VIDEO_STREAM, (stream, streamId, event, sipSession) => {
10610
- logger$2.info('on room video stream', { streamId });
11192
+ logger$3.info('on room video stream', { streamId });
10611
11193
 
10612
11194
  this._mapMsid(sipSession.body.body);
10613
11195
 
@@ -10622,7 +11204,7 @@ class Room$1 extends Emitter {
10622
11204
  });
10623
11205
 
10624
11206
  this.on(this.ON_REMOVE_STREAM, stream => {
10625
- logger$2.info('on room remove stream');
11207
+ logger$3.info('on room remove stream');
10626
11208
 
10627
11209
  const participant = this.participants.find(someParticipant =>
10628
11210
  someParticipant.streams.find(someStream => someStream && someStream.id === stream.id));
@@ -10677,6 +11259,9 @@ class Room$1 extends Emitter {
10677
11259
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10678
11260
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10679
11261
 
11262
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11263
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11264
+
10680
11265
  // Phone events
10681
11266
  Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
10682
11267
  Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
@@ -10687,15 +11272,15 @@ class Room$1 extends Emitter {
10687
11272
  Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
10688
11273
  }
10689
11274
 
10690
- _onMessage(message ) {
11275
+ _onMessage(message ) {
10691
11276
  if (message.method !== 'MESSAGE') {
10692
- return;
11277
+ return null;
10693
11278
  }
10694
11279
  let body;
10695
11280
  try {
10696
11281
  body = JSON.parse(message.body);
10697
11282
  } catch (e) {
10698
- return;
11283
+ return null;
10699
11284
  }
10700
11285
 
10701
11286
  switch (body.type) {
@@ -10714,6 +11299,8 @@ class Room$1 extends Emitter {
10714
11299
  }
10715
11300
 
10716
11301
  this.eventEmitter.emit(this.ON_MESSAGE, body);
11302
+
11303
+ return body;
10717
11304
  }
10718
11305
 
10719
11306
  _onChat(content ) {
@@ -10749,7 +11336,7 @@ class Room$1 extends Emitter {
10749
11336
  const requester = this._getParticipantFromCallId(origin.callId);
10750
11337
  if (requester) {
10751
11338
  // @FIXME?: when need to trigger an update on join-in; this is a bit of a hack
10752
- logger$2.info('trigger room requester status', { origin });
11339
+ logger$3.info('trigger room requester status', { origin });
10753
11340
  requester.triggerUpdate('REQUESTER_UPDATE');
10754
11341
  }
10755
11342
  break;
@@ -10778,25 +11365,26 @@ class Room$1 extends Emitter {
10778
11365
  const session = Wazo.Auth.getSession();
10779
11366
  let participants = [];
10780
11367
 
10781
- // @TODO: we could use a better function name here
10782
- const isJoining = part => {
10783
- this.__associateStreams(part);
10784
- // @VALIDATE: no need to publicize ourselves, no?
10785
- if (part instanceof RemoteParticipant) {
10786
- this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
10787
- }
10788
- };
10789
-
10790
11368
  // When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
10791
11369
  if (participant.user_uuid === session.uuid) {
10792
- logger$2.info('room current user joined');
11370
+ logger$3.info('room current user joined');
10793
11371
 
10794
11372
  // Retrieve participants via an API calls
10795
11373
  const conferenceId = this.sourceId || payload.data.conference_id;
10796
- const response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
10797
- logger$2.info('fetching conference participants', { conferenceId });
11374
+ let response;
11375
+ try {
11376
+ if (this.meetingUuid) {
11377
+ logger$3.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
11378
+ response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
11379
+ } else {
11380
+ logger$3.info('fetching conference participants', { conferenceId });
11381
+ response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
11382
+ }
11383
+ } catch (e) {
11384
+ logger$3.error('room participants fetching, error', e);
11385
+ }
10798
11386
  if (response) {
10799
- logger$2.info('conference participants fetched', { nb: response.items.length });
11387
+ logger$3.info('conference participants fetched', { nb: response.items.length });
10800
11388
  participants = response.items.map(item => {
10801
11389
  const isMe = item.call_id === this.callId;
10802
11390
 
@@ -10809,25 +11397,10 @@ class Room$1 extends Emitter {
10809
11397
 
10810
11398
  const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
10811
11399
  if (!this.localParticipant && localParticipant) {
10812
- this.localParticipant = localParticipant;
10813
-
10814
- const localVideoStream = this._getLocalVideoStream();
10815
- if (localVideoStream) {
10816
- this._saveLocalVideoStream(localVideoStream);
10817
- }
10818
-
10819
- this.connected = true;
10820
-
10821
- // we're in the room, now let's request everyone's status
10822
- if (this.localParticipant) {
10823
- this.sendSignal({
10824
- type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
10825
- origin: this.localParticipant.getStatus(),
10826
- });
10827
- }
11400
+ this._onLocalParticipantJoined(localParticipant);
10828
11401
  }
10829
11402
 
10830
- participants.forEach(someParticipant => isJoining(someParticipant));
11403
+ participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
10831
11404
  this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
10832
11405
  }
10833
11406
 
@@ -10838,16 +11411,45 @@ class Room$1 extends Emitter {
10838
11411
  ? new Wazo.RemoteParticipant(this, participant)
10839
11412
  : null;
10840
11413
 
10841
- logger$2.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
11414
+ logger$3.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
10842
11415
 
10843
11416
  if (remoteParticipant) {
10844
11417
  this.participants.push(remoteParticipant);
10845
- isJoining(remoteParticipant);
11418
+ this._isParticipantJoining(remoteParticipant);
10846
11419
  }
10847
11420
 
10848
11421
  return remoteParticipant;
10849
11422
  }
10850
11423
 
11424
+ _onLocalParticipantJoined(localParticipant ) {
11425
+ this.localParticipant = localParticipant;
11426
+
11427
+ const localVideoStream = this._getLocalVideoStream();
11428
+ if (localVideoStream) {
11429
+ this._saveLocalVideoStream(localVideoStream);
11430
+ }
11431
+
11432
+ this.connected = true;
11433
+
11434
+ localParticipant.broadcastStatus();
11435
+
11436
+ // we're in the room, now let's request everyone's status
11437
+ if (this.localParticipant) {
11438
+ this.sendSignal({
11439
+ type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
11440
+ origin: this.localParticipant.getStatus(),
11441
+ });
11442
+ }
11443
+ }
11444
+
11445
+ _isParticipantJoining(participant ) {
11446
+ this.__associateStreams(participant);
11447
+ // @VALIDATE: no need to publicize ourselves, no?
11448
+ if (participant instanceof RemoteParticipant) {
11449
+ this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
11450
+ }
11451
+ }
11452
+
10851
11453
  _saveLocalVideoStream(stream ) {
10852
11454
  const { localParticipant } = this;
10853
11455
 
@@ -10893,9 +11495,11 @@ class Room$1 extends Emitter {
10893
11495
  _onParticipantTrackUpdate(oldParticipant , update ) {
10894
11496
  const newParticipant = oldParticipant;
10895
11497
 
10896
- const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
11498
+ const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
10897
11499
  const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
10898
- const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
11500
+ // Can't use `getReceivers` here because on FF we make the mapping based on the streamId
11501
+ const stream = pc.getRemoteStreams().find(someStream =>
11502
+ someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
10899
11503
 
10900
11504
  if (update === 'downgrade') {
10901
11505
  newParticipant.streams = [];
@@ -10925,15 +11529,41 @@ class Room$1 extends Emitter {
10925
11529
  return;
10926
11530
  }
10927
11531
 
10928
- if (this._unassociatedVideoStreams[trackId]) {
11532
+ const streamId = this._getStreamIdFrTrackId(trackId);
11533
+ const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
11534
+ const stream = this._unassociatedVideoStreams[key];
11535
+
11536
+ if (stream) {
10929
11537
  // Try to associate stream
10930
- this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
11538
+ this._associateStreamTo(stream, participant);
10931
11539
 
10932
- delete this._unassociatedVideoStreams[trackId];
11540
+ delete this._unassociatedVideoStreams[key];
10933
11541
  delete this._unassociatedParticipants[participant.callId];
10934
11542
  }
10935
11543
  }
10936
11544
 
11545
+ _getUnassociatedMapIdFromTrackIdOrStreamId(trackId , streamId ) {
11546
+ // Find by trackId
11547
+ if (trackId in this._unassociatedVideoStreams) {
11548
+ return trackId;
11549
+ }
11550
+
11551
+ // Find by streamId
11552
+ if (streamId && streamId in this._unassociatedVideoStreams) {
11553
+ return streamId;
11554
+ }
11555
+
11556
+ // Find in all the streams by streamId (used on FF where we can't map by trackId)
11557
+ const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream ) => stream.id === streamId);
11558
+ return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
11559
+ }
11560
+
11561
+ _getStreamIdFrTrackId(trackId ) {
11562
+ const mapping = Object.values(this._callIdStreamIdMap).find((map ) => map.trackId === trackId);
11563
+
11564
+ return mapping ? mapping.streamId : null;
11565
+ }
11566
+
10937
11567
  _associateStreamTo(rawStream , participant ) {
10938
11568
  const stream = new Wazo.Stream(rawStream, participant);
10939
11569
  participant.streams.push(stream);
@@ -10957,7 +11587,141 @@ class Room$1 extends Emitter {
10957
11587
 
10958
11588
  //
10959
11589
 
10960
- class LocalParticipant extends Participant {
11590
+ const logger$2 = IssueReporter$1.loggerFor('sdk-sip-room');
11591
+
11592
+ class SipRoom extends Room$1 {
11593
+
11594
+ static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
11595
+ logger$2.info('connecting to sip room', { extension, audioOnly, room: !!room });
11596
+
11597
+ if (!room) {
11598
+ await Wazo.Phone.connect();
11599
+
11600
+ const withCamera = constraints && !!constraints.video;
11601
+
11602
+ const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
11603
+ // eslint-disable-next-line no-param-reassign
11604
+ room = new SipRoom(callSession, extension, null, null, extra);
11605
+ }
11606
+
11607
+ if (room && room.callSession && room.callSession.call) {
11608
+ room.setCallId(room.callSession.call.id);
11609
+ }
11610
+
11611
+ logger$2.info('connected to room', {
11612
+ extension: room.extension,
11613
+ });
11614
+
11615
+ return room;
11616
+ }
11617
+
11618
+ mute() {
11619
+ logger$2.info('mute sip room');
11620
+
11621
+ Wazo.Phone.mute(this.callSession, false);
11622
+
11623
+ this.sendMuteStatus();
11624
+ }
11625
+
11626
+ unmute() {
11627
+ logger$2.info('unmute sip room');
11628
+
11629
+ Wazo.Phone.unmute(this.callSession, false);
11630
+
11631
+ this.sendUnMuteStatus();
11632
+ }
11633
+
11634
+ getLocalGuestName() {
11635
+ return Wazo.Phone.phone.client.userAgent.options.displayName;
11636
+ }
11637
+
11638
+ // Overridden to not listen to websocket messages
11639
+ _transferEvents() {
11640
+ // Phone events
11641
+ Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
11642
+ Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
11643
+ Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
11644
+ Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
11645
+
11646
+ [this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
11647
+ Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
11648
+ }
11649
+
11650
+ _onMessage(message ) {
11651
+ // eslint-disable-next-line no-underscore-dangle
11652
+ const body = super._onMessage(message);
11653
+ if (!body) {
11654
+ return;
11655
+ }
11656
+
11657
+ const getChannel = () => body.channels[0];
11658
+
11659
+ switch (body.type) {
11660
+ case 'ConfbridgeWelcome':
11661
+ body.channels.forEach(channel => {
11662
+ this._onParticipantJoined(channel);
11663
+ });
11664
+
11665
+ break;
11666
+ case 'ConfbridgeJoin': {
11667
+ const channel = getChannel();
11668
+ this._onParticipantJoined(channel);
11669
+ break;
11670
+ }
11671
+ case 'ConfbridgeLeave': {
11672
+ const channel = getChannel();
11673
+ this._onParticipantLeft({
11674
+ data: {
11675
+ call_id: channel.id,
11676
+ },
11677
+ });
11678
+ break;
11679
+ }
11680
+ }
11681
+ }
11682
+
11683
+ async _onParticipantJoined(channel ) {
11684
+ const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
11685
+ const callId = channel.id;
11686
+ const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
11687
+ const name = channel.caller ? channel.caller.name : null;
11688
+ const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
11689
+ const participant = new ParticipantClass(this, {
11690
+ caller_id_name: name,
11691
+ call_id: callId,
11692
+ }, extra);
11693
+
11694
+ const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
11695
+ if (participantIdx !== -1 && name) {
11696
+ this.participants[participantIdx].name = name;
11697
+ return;
11698
+ }
11699
+
11700
+ if (isLocal) {
11701
+ // Should be updated by the Wazo WS but we don't have it for now
11702
+ if (this.callSession) {
11703
+ this.callSession.ringing = false;
11704
+ }
11705
+
11706
+ this._onLocalParticipantJoined(participant);
11707
+
11708
+ // Give some time for the stream to be updated
11709
+ setTimeout(() => {
11710
+ this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
11711
+ }, 1000);
11712
+ }
11713
+
11714
+ this.participants.push(participant);
11715
+
11716
+ this._isParticipantJoining(participant);
11717
+
11718
+ return participant;
11719
+ }
11720
+
11721
+ _getCurrentSipCallIs() {
11722
+ return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11723
+ }
11724
+
10961
11725
  }
10962
11726
 
10963
11727
  /* global document */
@@ -11010,9 +11774,7 @@ class Stream {
11010
11774
  return false;
11011
11775
  }
11012
11776
 
11013
- // With canvas track (used to fake upgrade in conference), we don't have a width
11014
- return this.htmlStream.getTracks().find(track => track.kind === 'video'
11015
- && track.readyState !== 'ended' && 'width' in track.getSettings());
11777
+ return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
11016
11778
  }
11017
11779
 
11018
11780
  get id() {
@@ -11896,6 +12658,7 @@ const Wazo = {
11896
12658
  Phone: Phone$1,
11897
12659
  Websocket: Websocket$1,
11898
12660
  Room: Room$1,
12661
+ SipRoom,
11899
12662
  RemoteParticipant,
11900
12663
  LocalParticipant,
11901
12664
  Stream,
@@ -11915,6 +12678,7 @@ const Wazo = {
11915
12678
  ServerError,
11916
12679
  Call,
11917
12680
  CallLog,
12681
+ CTIPhone,
11918
12682
  Recording,
11919
12683
  ChatMessage,
11920
12684
  ChatRoom,
@@ -11930,6 +12694,8 @@ const Wazo = {
11930
12694
  CallSession,
11931
12695
  IndirectTransfer,
11932
12696
  SwitchboardCall,
12697
+ WebRTCPhone,
12698
+ Meeting,
11933
12699
  },
11934
12700
 
11935
12701
  // Api