@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);
@@ -4869,7 +5340,7 @@ var getApiClient = (forServer ) => {
4869
5340
  class InvalidSubscription extends Error {}
4870
5341
  class InvalidAuthorization extends Error {}
4871
5342
 
4872
- const logger$8 = IssueReporter$1.loggerFor('simple-auth');
5343
+ const logger$9 = IssueReporter$1.loggerFor('simple-auth');
4873
5344
 
4874
5345
  class Auth {
4875
5346
 
@@ -4904,7 +5375,7 @@ class Auth {
4904
5375
  setApiClientId(this.clientId);
4905
5376
  setRefreshExpiration(this.expiration);
4906
5377
  setOnRefreshToken((token , session ) => {
4907
- logger$8.info('on refresh token done', { token });
5378
+ logger$9.info('on refresh token done', { token });
4908
5379
  setApiToken(token);
4909
5380
  Wazo.Websocket.updateToken(token);
4910
5381
 
@@ -5463,7 +5934,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5463
5934
  .then(() => {
5464
5935
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5465
5936
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5466
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5937
+ if (this.peerConnection.addTransceiver) {
5938
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5939
+ }
5467
5940
  }
5468
5941
  })
5469
5942
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5490,12 +5963,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5490
5963
  };
5491
5964
  })
5492
5965
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5493
- .then((sessionDescription) => {
5494
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5495
- this.localMediaStreamConstraints = options.constraints;
5496
-
5497
- return sessionDescription;
5498
- })
5499
5966
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5500
5967
  .catch((error) => {
5501
5968
  wazoLogger.error('error when creating media', error);
@@ -5690,6 +6157,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5690
6157
 
5691
6158
  // set the transceiver direction to the answer direction
5692
6159
  this._peerConnection.getTransceivers().forEach((transceiver) => {
6160
+ if (transceiver.stopped) {
6161
+ return;
6162
+ }
5693
6163
  if (transceiver.direction /* guarding, but should always be true */) {
5694
6164
  const { receiver } = transceiver;
5695
6165
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5734,10 +6204,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5734
6204
  if (kind !== 'audio' && kind !== 'video') {
5735
6205
  throw new Error(`Unknown new track kind ${kind}.`);
5736
6206
  }
5737
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
6207
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
6208
+ otherSender.track && otherSender.track.kind === kind);
5738
6209
 
5739
6210
  // Do not reuse sender video tracks in SFU
5740
6211
  if (sender && (!sfu || newTrack.kind === 'audio')) {
6212
+ if (sender.track) {
6213
+ // eslint-disable-next-line no-param-reassign
6214
+ newTrack.enabled = sender.track.enabled;
6215
+ }
5741
6216
  trackUpdates.push(
5742
6217
  new Promise((resolve) => {
5743
6218
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5771,7 +6246,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5771
6246
  // Review: could make streamless tracks a configurable option?
5772
6247
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5773
6248
  try {
5774
- pc.addTrack(newTrack, localStream);
6249
+ if (pc.addTrack) {
6250
+ pc.addTrack(newTrack, localStream);
6251
+ } else {
6252
+ pc.addStream(localStream);
6253
+ }
5775
6254
  } catch (error) {
5776
6255
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5777
6256
  throw error;
@@ -5907,7 +6386,7 @@ const DEFAULT_ICE_TIMEOUT = 3000;
5907
6386
  const SEND_STATS_DELAY = 5000;
5908
6387
 
5909
6388
  const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
5910
- const logger$7 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
6389
+ const logger$8 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
5911
6390
  const statsLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-stats') : console;
5912
6391
 
5913
6392
  // events
@@ -5953,6 +6432,7 @@ const MAX_REGISTER_TRIES = 10;
5953
6432
 
5954
6433
 
5955
6434
 
6435
+
5956
6436
 
5957
6437
 
5958
6438
 
@@ -5979,6 +6459,7 @@ class WebRTCClient extends Emitter {
5979
6459
 
5980
6460
 
5981
6461
 
6462
+
5982
6463
 
5983
6464
  // sugar
5984
6465
 
@@ -6017,6 +6498,8 @@ class WebRTCClient extends Emitter {
6017
6498
  super();
6018
6499
  this.uaConfigOverrides = uaConfigOverrides;
6019
6500
  this.config = config;
6501
+ this.skipRegister = config.skipRegister;
6502
+
6020
6503
  this._buildConfig(config, session).then((newConfig ) => {
6021
6504
  this.config = newConfig;
6022
6505
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -6072,13 +6555,13 @@ class WebRTCClient extends Emitter {
6072
6555
 
6073
6556
  createUserAgent(configOverrides ) {
6074
6557
  const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
6075
- logger$7.info('sdk webrtc, creating UA', { webRTCConfiguration });
6558
+ logger$8.info('sdk webrtc, creating UA', { webRTCConfiguration });
6076
6559
 
6077
6560
  webRTCConfiguration.delegate = {
6078
6561
  onConnect: this.onConnect.bind(this),
6079
6562
  onDisconnect: this.onDisconnect.bind(this),
6080
6563
  onInvite: (invitation ) => {
6081
- logger$7.info('sdk webrtc on invite', {
6564
+ logger$8.info('sdk webrtc on invite', {
6082
6565
  method: 'delegate.onInvite',
6083
6566
  id: invitation.id,
6084
6567
  remoteURI: invitation.remoteURI,
@@ -6121,7 +6604,7 @@ class WebRTCClient extends Emitter {
6121
6604
  }
6122
6605
 
6123
6606
  onConnect() {
6124
- logger$7.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6607
+ logger$8.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6125
6608
  this.eventEmitter.emit(CONNECTED);
6126
6609
  if (!this.isRegistered() && this.registerer && this.registerer.waiting) {
6127
6610
  this.registerer.waitingToggle(false);
@@ -6130,7 +6613,7 @@ class WebRTCClient extends Emitter {
6130
6613
  }
6131
6614
 
6132
6615
  async onDisconnect(error ) {
6133
- logger$7.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6616
+ logger$8.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6134
6617
  this.connectionPromise = null;
6135
6618
  // The UA will attempt to reconnect automatically when an error occurred
6136
6619
  this.eventEmitter.emit(DISCONNECTED, error);
@@ -6144,40 +6627,48 @@ class WebRTCClient extends Emitter {
6144
6627
  }
6145
6628
 
6146
6629
  register(tries = 0) {
6147
- logger$7.info('sdk webrtc registering...', {
6630
+ const logInfo = {
6148
6631
  userAgent: !!this.userAgent,
6149
6632
  registered: this.isRegistered(),
6150
6633
  connectionPromise: !!this.connectionPromise,
6151
6634
  registerer: !!this.registerer,
6152
6635
  waiting: this.registerer && this.registerer.waiting,
6153
6636
  tries,
6154
- });
6637
+ skipRegister: this.skipRegister,
6638
+ };
6639
+
6640
+ if (this.skipRegister) {
6641
+ logger$8.info('sdk webrtc skip register...', logInfo);
6642
+ return Promise.resolve();
6643
+ }
6644
+
6645
+ logger$8.info('sdk webrtc registering...', logInfo);
6155
6646
 
6156
6647
  if (!this.userAgent) {
6157
- logger$7.info('sdk webrtc recreating User Agent');
6648
+ logger$8.info('sdk webrtc recreating User Agent');
6158
6649
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6159
6650
  }
6160
6651
  if (!this.userAgent || this.isRegistered()) {
6161
- logger$7.info('sdk webrtc registering aborted, already registered or no UA can be created');
6652
+ logger$8.info('sdk webrtc registering aborted, already registered or no UA can be created');
6162
6653
  return Promise.resolve();
6163
6654
  }
6164
6655
 
6165
6656
  if (this.connectionPromise || (this.registerer && this.registerer.waiting)) {
6166
- logger$7.info('sdk webrtc registering aborted due to a registration in progress.');
6657
+ logger$8.info('sdk webrtc registering aborted due to a registration in progress.');
6167
6658
  return Promise.resolve();
6168
6659
  }
6169
6660
 
6170
6661
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6171
6662
 
6172
6663
  const onRegisterFailed = () => {
6173
- logger$7.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6664
+ logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6174
6665
  this.connectionPromise = null;
6175
6666
  if (this.registerer && this.registerer.waiting) {
6176
6667
  this.registerer.waitingToggle(false);
6177
6668
  }
6178
6669
 
6179
6670
  if (tries <= MAX_REGISTER_TRIES) {
6180
- logger$7.info('sdk webrtc registering, retrying...', { tries });
6671
+ logger$8.info('sdk webrtc registering, retrying...', { tries });
6181
6672
  setTimeout(() => this.register(tries + 1), 300);
6182
6673
  }
6183
6674
  };
@@ -6186,18 +6677,18 @@ class WebRTCClient extends Emitter {
6186
6677
  // Avoid race condition with the close method called just before register and setting userAgent to null
6187
6678
  // during the resolution of the primise.
6188
6679
  if (!this.userAgent) {
6189
- logger$7.info('sdk webrtc recreating User Agent after connection');
6680
+ logger$8.info('sdk webrtc recreating User Agent after connection');
6190
6681
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6191
6682
  }
6192
6683
 
6193
- logger$7.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6684
+ logger$8.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6194
6685
  this.registerer = new registerer.Registerer(this.userAgent, registerOptions);
6195
6686
  this.connectionPromise = null;
6196
6687
  this._monkeyPatchRegisterer(this.registerer);
6197
6688
 
6198
6689
  // Bind registerer events
6199
6690
  this.registerer.stateChange.addListener(newState => {
6200
- logger$7.info('sdk webrtc registering, state changed', { newState });
6691
+ logger$8.info('sdk webrtc registering, state changed', { newState });
6201
6692
 
6202
6693
  if (newState === registererState.RegistererState.Registered && this.registerer
6203
6694
  && this.registerer.state === registererState.RegistererState.Registered) {
@@ -6210,7 +6701,7 @@ class WebRTCClient extends Emitter {
6210
6701
  const options = {
6211
6702
  requestDelegate: {
6212
6703
  onReject: response => {
6213
- logger$7.error('sdk webrtc registering, rejected', { response });
6704
+ logger$8.error('sdk webrtc registering, rejected', { response });
6214
6705
 
6215
6706
  onRegisterFailed();
6216
6707
  },
@@ -6218,13 +6709,13 @@ class WebRTCClient extends Emitter {
6218
6709
  };
6219
6710
 
6220
6711
  return this.registerer.register(options).catch((e) => {
6221
- logger$7.error('sdk webrtc registering, error', e);
6712
+ logger$8.error('sdk webrtc registering, error', e);
6222
6713
 
6223
6714
  this.eventEmitter.emit(REGISTRATION_FAILED);
6224
6715
  return e;
6225
6716
  });
6226
6717
  }).catch(error => {
6227
- logger$7.error('sdk webrtc registering, transport error', error);
6718
+ logger$8.error('sdk webrtc registering, transport error', error);
6228
6719
  onRegisterFailed();
6229
6720
  });
6230
6721
  }
@@ -6253,21 +6744,21 @@ class WebRTCClient extends Emitter {
6253
6744
  }
6254
6745
 
6255
6746
  unregister() {
6256
- logger$7.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6747
+ logger$8.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6257
6748
  if (!this.registerer) {
6258
6749
  return Promise.resolve();
6259
6750
  }
6260
6751
 
6261
6752
  try {
6262
6753
  return this.registerer.unregister().then(() => {
6263
- logger$7.info('sdk webrtc unregistered');
6754
+ logger$8.info('sdk webrtc unregistered');
6264
6755
  this._cleanupRegister();
6265
6756
  }).catch(e => {
6266
- logger$7.error('sdk webrtc unregistering, promise error', e);
6757
+ logger$8.error('sdk webrtc unregistering, promise error', e);
6267
6758
  this._cleanupRegister();
6268
6759
  });
6269
6760
  } catch (e) {
6270
- logger$7.error('sdk webrtc unregistering, error', e);
6761
+ logger$8.error('sdk webrtc unregistering, error', e);
6271
6762
  // Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
6272
6763
  // error when the registerer is in a bad state
6273
6764
  this._cleanupRegister();
@@ -6275,7 +6766,7 @@ class WebRTCClient extends Emitter {
6275
6766
  }
6276
6767
 
6277
6768
  stop() {
6278
- logger$7.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6769
+ logger$8.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6279
6770
  if (!this.userAgent) {
6280
6771
  return Promise.resolve();
6281
6772
  }
@@ -6283,12 +6774,12 @@ class WebRTCClient extends Emitter {
6283
6774
  return this.userAgent.stop().then(() => {
6284
6775
  return this._cleanupRegister();
6285
6776
  }).catch(e => {
6286
- logger$7.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6777
+ logger$8.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6287
6778
  });
6288
6779
  }
6289
6780
 
6290
6781
  call(number , enableVideo , audioOnly = false, conference = false) {
6291
- logger$7.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6782
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6292
6783
  const inviterOptions = {
6293
6784
  sessionDescriptionHandlerOptionsReInvite: {
6294
6785
  conference,
@@ -6317,7 +6808,7 @@ class WebRTCClient extends Emitter {
6317
6808
  this._onAccepted(session, response.session, true);
6318
6809
  },
6319
6810
  onReject: (response ) => {
6320
- logger$7.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6811
+ logger$8.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6321
6812
  this._stopSendingStats(session);
6322
6813
 
6323
6814
  this.eventEmitter.emit(REJECTED, session, response);
@@ -6339,11 +6830,11 @@ class WebRTCClient extends Emitter {
6339
6830
  }
6340
6831
 
6341
6832
  answer(session , enableVideo ) {
6342
- logger$7.info('sdk webrtc answer call', { id: session.id, enableVideo });
6833
+ logger$8.info('sdk webrtc answer call', { id: session.id, enableVideo });
6343
6834
 
6344
6835
  if (!session || !session.accept) {
6345
6836
  const error = 'No session to answer, or not an invitation';
6346
- logger$7.warn(error);
6837
+ logger$8.warn(error);
6347
6838
  return Promise.reject(new Error(error));
6348
6839
  }
6349
6840
  const options = {
@@ -6353,15 +6844,15 @@ class WebRTCClient extends Emitter {
6353
6844
  return session.accept(options).then(() => {
6354
6845
  if (session.isCanceled) {
6355
6846
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
6356
- logger$7.error(message, { id: session.id });
6847
+ logger$8.error(message, { id: session.id });
6357
6848
  this.onCallEnded(session);
6358
6849
 
6359
6850
  throw new CanceledCallError(message);
6360
6851
  }
6361
- logger$7.info('sdk webrtc answer, accepted.');
6852
+ logger$8.info('sdk webrtc answer, accepted.');
6362
6853
  this._onAccepted(session);
6363
6854
  }).catch(e => {
6364
- logger$7.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6855
+ logger$8.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6365
6856
 
6366
6857
  throw e;
6367
6858
  });
@@ -6369,7 +6860,7 @@ class WebRTCClient extends Emitter {
6369
6860
 
6370
6861
  hangup(session ) {
6371
6862
  const { state, id } = session;
6372
- logger$7.info('sdk webrtc hangup call', { id, state });
6863
+ logger$8.info('sdk webrtc hangup call', { id, state });
6373
6864
 
6374
6865
  try {
6375
6866
  this._stopSendingStats(session);
@@ -6398,24 +6889,24 @@ class WebRTCClient extends Emitter {
6398
6889
 
6399
6890
  return bye();
6400
6891
  } catch (error) {
6401
- logger$7.warn('sdk webrtc hangup, error', error);
6892
+ logger$8.warn('sdk webrtc hangup, error', error);
6402
6893
  }
6403
6894
 
6404
6895
  return null;
6405
6896
  }
6406
6897
 
6407
6898
  reject(session ) {
6408
- logger$7.info('sdk webrtc reject call', { id: session.id });
6899
+ logger$8.info('sdk webrtc reject call', { id: session.id });
6409
6900
 
6410
6901
  try {
6411
6902
  return session.reject ? session.reject() : session.cancel();
6412
6903
  } catch (e) {
6413
- logger$7.warn('Error when rejecting call', e.message, e.stack);
6904
+ logger$8.warn('Error when rejecting call', e.message, e.stack);
6414
6905
  }
6415
6906
  }
6416
6907
 
6417
6908
  async close() {
6418
- logger$7.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6909
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6419
6910
  this._cleanupMedia();
6420
6911
  this.connectionPromise = null;
6421
6912
 
@@ -6446,7 +6937,7 @@ class WebRTCClient extends Emitter {
6446
6937
  // eg: "INVITE not rejectable in state Completed"
6447
6938
  }
6448
6939
  this.userAgent = null;
6449
- logger$7.info('sdk webrtc client closed');
6940
+ logger$8.info('sdk webrtc client closed');
6450
6941
  }
6451
6942
 
6452
6943
  getNumber(session ) {
@@ -6459,13 +6950,13 @@ class WebRTCClient extends Emitter {
6459
6950
  }
6460
6951
 
6461
6952
  mute(session ) {
6462
- logger$7.info('sdk webrtc mute', { id: session.id });
6953
+ logger$8.info('sdk webrtc mute', { id: session.id });
6463
6954
 
6464
6955
  this._toggleAudio(session, true);
6465
6956
  }
6466
6957
 
6467
6958
  unmute(session ) {
6468
- logger$7.info('sdk webrtc unmute', { id: session.id });
6959
+ logger$8.info('sdk webrtc unmute', { id: session.id });
6469
6960
 
6470
6961
  this._toggleAudio(session, false);
6471
6962
  }
@@ -6482,12 +6973,18 @@ class WebRTCClient extends Emitter {
6482
6973
  }
6483
6974
 
6484
6975
  if (pc.getSenders) {
6976
+ if (!pc.getSenders().length) {
6977
+ return false;
6978
+ }
6485
6979
  pc.getSenders().forEach(sender => {
6486
6980
  if (sender && sender.track && sender.track.kind === 'audio') {
6487
6981
  muted = muted && !sender.track.enabled;
6488
6982
  }
6489
6983
  });
6490
6984
  } else {
6985
+ if (!pc.getLocalStreams().length) {
6986
+ return false;
6987
+ }
6491
6988
  pc.getLocalStreams().forEach(stream => {
6492
6989
  stream.getAudioTracks().forEach(track => {
6493
6990
  muted = muted && !track.enabled;
@@ -6499,20 +6996,20 @@ class WebRTCClient extends Emitter {
6499
6996
  }
6500
6997
 
6501
6998
  toggleCameraOn(session ) {
6502
- logger$7.info('sdk webrtc toggle camera on', { id: session.id });
6999
+ logger$8.info('sdk webrtc toggle camera on', { id: session.id });
6503
7000
 
6504
7001
  this._toggleVideo(session, false);
6505
7002
  }
6506
7003
 
6507
7004
  toggleCameraOff(session ) {
6508
- logger$7.info('sdk webrtc toggle camera off', { id: session.id });
7005
+ logger$8.info('sdk webrtc toggle camera off', { id: session.id });
6509
7006
 
6510
7007
  this._toggleVideo(session, true);
6511
7008
  }
6512
7009
 
6513
7010
  hold(session , isConference = false) {
6514
7011
  const sessionId = this.getSipSessionId(session);
6515
- logger$7.info('sdk webrtc hold', {
7012
+ logger$8.info('sdk webrtc hold', {
6516
7013
  sessionId,
6517
7014
  keys: Object.keys(this.heldSessions),
6518
7015
  pendingReinvite: !!session.pendingReinvite,
@@ -6544,6 +7041,9 @@ class WebRTCClient extends Emitter {
6544
7041
  if (!this._isWeb()) {
6545
7042
  options.sessionDescriptionHandlerModifiers = [modifiers.holdModifier];
6546
7043
  }
7044
+ options.sessionDescriptionHandlerOptions = {
7045
+ constraints: options.constraints,
7046
+ };
6547
7047
 
6548
7048
  // Send re-INVITE
6549
7049
  return session.invite(options);
@@ -6552,7 +7052,7 @@ class WebRTCClient extends Emitter {
6552
7052
  unhold(session , isConference = false) {
6553
7053
  const sessionId = this.getSipSessionId(session);
6554
7054
 
6555
- logger$7.info('sdk webrtc unhold', {
7055
+ logger$8.info('sdk webrtc unhold', {
6556
7056
  sessionId,
6557
7057
  keys: Object.keys(this.heldSessions),
6558
7058
  pendingReinvite: !!session.pendingReinvite,
@@ -6583,6 +7083,9 @@ class WebRTCClient extends Emitter {
6583
7083
  // (eg: holdModifier)
6584
7084
  options.sessionDescriptionHandlerModifiers = [];
6585
7085
  }
7086
+ options.sessionDescriptionHandlerOptions = {
7087
+ constraints: options.constraints,
7088
+ };
6586
7089
 
6587
7090
  // Send re-INVITE
6588
7091
  return session.invite(options);
@@ -6640,7 +7143,7 @@ class WebRTCClient extends Emitter {
6640
7143
  return;
6641
7144
  }
6642
7145
 
6643
- logger$7.info('send WebRTC message', { sipId: sipSession.id, contentType });
7146
+ logger$8.info('send WebRTC message', { sipId: sipSession.id, contentType });
6644
7147
 
6645
7148
  try {
6646
7149
  sipSession.message({
@@ -6765,7 +7268,8 @@ class WebRTCClient extends Emitter {
6765
7268
  }
6766
7269
  const sdh = session.sessionDescriptionHandler;
6767
7270
  const pc = sdh.peerConnection;
6768
- const localStream = this.getLocalStream(this.getSipSessionId(session));
7271
+ const sessionId = this.getSipSessionId(session);
7272
+ const localStream = this.getLocalStream(sessionId);
6769
7273
 
6770
7274
  // Release old video stream
6771
7275
  if (localStream) {
@@ -6791,11 +7295,8 @@ class WebRTCClient extends Emitter {
6791
7295
 
6792
7296
  // let's update the local stream
6793
7297
  this.eventEmitter.emit('onVideoInputChange', stream);
6794
- try {
6795
- await sdh.setLocalMediaStream(stream);
6796
- } catch (_) {
6797
- // Nothing to do
6798
- }
7298
+ this.setLocalMediaStream(sessionId, stream);
7299
+
6799
7300
  return stream;
6800
7301
  });
6801
7302
  }
@@ -7007,7 +7508,7 @@ class WebRTCClient extends Emitter {
7007
7508
  }
7008
7509
 
7009
7510
  startHeartbeat() {
7010
- logger$7.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7511
+ logger$8.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7011
7512
  if (!this.userAgent) {
7012
7513
  this.heartbeat.stop();
7013
7514
  return;
@@ -7020,7 +7521,7 @@ class WebRTCClient extends Emitter {
7020
7521
  }
7021
7522
 
7022
7523
  stopHeartbeat() {
7023
- logger$7.info('sdk webrtc stop heartbeat');
7524
+ logger$8.info('sdk webrtc stop heartbeat');
7024
7525
  this.heartbeat.stop();
7025
7526
  }
7026
7527
 
@@ -7040,7 +7541,7 @@ class WebRTCClient extends Emitter {
7040
7541
  }
7041
7542
 
7042
7543
  attemptReconnection() {
7043
- logger$7.info('attempt reconnection', { userAgent: !!this.userAgent });
7544
+ logger$8.info('attempt reconnection', { userAgent: !!this.userAgent });
7044
7545
  if (!this.userAgent) {
7045
7546
  return;
7046
7547
  }
@@ -7097,9 +7598,11 @@ class WebRTCClient extends Emitter {
7097
7598
  remoteStream.removeTrack(track);
7098
7599
  });
7099
7600
 
7100
- pc.getReceivers().forEach(receiver => {
7101
- remoteStream.addTrack(receiver.track);
7102
- });
7601
+ if (pc.getReceivers) {
7602
+ pc.getReceivers().forEach(receiver => {
7603
+ remoteStream.addTrack(receiver.track);
7604
+ });
7605
+ }
7103
7606
  }
7104
7607
 
7105
7608
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -7134,6 +7637,25 @@ class WebRTCClient extends Emitter {
7134
7637
  return sessionId in this.conferences;
7135
7638
  }
7136
7639
 
7640
+ createAudioElementFor(sessionId ) {
7641
+ const audio = document.createElement('audio');
7642
+ audio.setAttribute('id', `audio-${sessionId}`);
7643
+
7644
+ if (audio.setSinkId && this.audioOutputDeviceId) {
7645
+ audio.setSinkId(this.audioOutputDeviceId);
7646
+ }
7647
+
7648
+ if (document.body) {
7649
+ document.body.appendChild(audio);
7650
+ }
7651
+ this.audioElements[sessionId] = audio;
7652
+
7653
+ audio.volume = this.audioOutputVolume;
7654
+ audio.autoplay = true;
7655
+
7656
+ return audio;
7657
+ }
7658
+
7137
7659
  _onTransportError() {
7138
7660
  this.eventEmitter.emit(TRANSPORT_ERROR);
7139
7661
  this.attemptReconnection();
@@ -7143,7 +7665,7 @@ class WebRTCClient extends Emitter {
7143
7665
  const body = message && typeof message === 'object' ? message.data : message;
7144
7666
  if (body && body.indexOf('200 OK') !== -1) {
7145
7667
  if (this.hasHeartbeat()) {
7146
- logger$7.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7668
+ logger$8.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7147
7669
 
7148
7670
  this.heartbeat.onHeartbeat();
7149
7671
  if (this.heartbeatCb) {
@@ -7154,7 +7676,7 @@ class WebRTCClient extends Emitter {
7154
7676
  }
7155
7677
 
7156
7678
  async _onHeartbeatTimeout() {
7157
- logger$7.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7679
+ logger$8.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7158
7680
 
7159
7681
  if (this.heartbeatTimeoutCb) {
7160
7682
  this.heartbeatTimeoutCb();
@@ -7166,7 +7688,7 @@ class WebRTCClient extends Emitter {
7166
7688
  try {
7167
7689
  await this.userAgent.transport.disconnect();
7168
7690
  } catch (e) {
7169
- logger$7.error('Transport disconnection after heartbeat timeout, error', e);
7691
+ logger$8.error('Transport disconnection after heartbeat timeout, error', e);
7170
7692
  }
7171
7693
  }
7172
7694
 
@@ -7199,31 +7721,31 @@ class WebRTCClient extends Emitter {
7199
7721
  }
7200
7722
 
7201
7723
  _connectIfNeeded() {
7202
- logger$7.info('connect if needed, checking', { connected: this.isConnected() });
7724
+ logger$8.info('connect if needed, checking', { connected: this.isConnected() });
7203
7725
  if (!this.userAgent) {
7204
- logger$7.info('need to recreate User Agent');
7726
+ logger$8.info('need to recreate User Agent');
7205
7727
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
7206
7728
  }
7207
7729
 
7208
7730
  if (this.isConnected()) {
7209
- logger$7.info('webrtc sdk, already connected');
7731
+ logger$8.info('webrtc sdk, already connected');
7210
7732
  return Promise.resolve();
7211
7733
  }
7212
7734
 
7213
7735
  if (this.isConnecting()) {
7214
- logger$7.info('webrtc sdk, already connecting...');
7736
+ logger$8.info('webrtc sdk, already connecting...');
7215
7737
 
7216
7738
  this.connectionPromise = this.userAgent.transport.connectPromise;
7217
7739
  return this.connectionPromise;
7218
7740
  }
7219
7741
 
7220
7742
  if (this.connectionPromise) {
7221
- logger$7.info('webrtc sdk, connection promise connecting...');
7743
+ logger$8.info('webrtc sdk, connection promise connecting...');
7222
7744
  // $FlowFixMe
7223
7745
  return this.connectionPromise;
7224
7746
  }
7225
7747
 
7226
- logger$7.info('WebRTC UA needs to connect');
7748
+ logger$8.info('WebRTC UA needs to connect');
7227
7749
 
7228
7750
  // Force UA to reconnect
7229
7751
  if (this.userAgent && this.userAgent.state !== userAgentState.UserAgentState.Stopped) {
@@ -7348,7 +7870,7 @@ class WebRTCClient extends Emitter {
7348
7870
 
7349
7871
  sdh.peerConnectionDelegate = {
7350
7872
  onicecandidateerror: (error ) => {
7351
- logger$7.error('on icecandidate error', {
7873
+ logger$8.error('on icecandidate error', {
7352
7874
  address: error.address,
7353
7875
  port: error.port,
7354
7876
  errorCode: error.errorCode,
@@ -7363,7 +7885,7 @@ class WebRTCClient extends Emitter {
7363
7885
  let hadRemoteVideo = false;
7364
7886
 
7365
7887
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7366
- // Becase when `onInvite` is called we already got the video track
7888
+ // Because when `onInvite` is called we already got the video track
7367
7889
  session.onInviteRequest = (request) => {
7368
7890
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7369
7891
 
@@ -7377,7 +7899,7 @@ class WebRTCClient extends Emitter {
7377
7899
  updatedNumber = session.assertedIdentity.uri.normal.user;
7378
7900
  updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
7379
7901
  }
7380
- logger$7.info('re-invite received', { updatedCalleeName, updatedNumber });
7902
+ logger$8.info('re-invite received', { updatedCalleeName, updatedNumber });
7381
7903
 
7382
7904
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
7383
7905
 
@@ -7398,7 +7920,7 @@ class WebRTCClient extends Emitter {
7398
7920
  }
7399
7921
 
7400
7922
  _onAccepted(session , sessionDialog , withEvent = true) {
7401
- logger$7.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7923
+ logger$8.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7402
7924
 
7403
7925
  this.storeSipSession(session);
7404
7926
 
@@ -7438,20 +7960,10 @@ class WebRTCClient extends Emitter {
7438
7960
  const isConference = this.isConference(sessionId);
7439
7961
 
7440
7962
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7441
- const audio = document.createElement('audio');
7442
- audio.setAttribute('id', `audio-${sessionId}`);
7443
-
7444
- if (audio.setSinkId && this.audioOutputDeviceId) {
7445
- audio.setSinkId(this.audioOutputDeviceId);
7446
- }
7447
-
7448
- if (document.body) {
7449
- document.body.appendChild(audio);
7450
- }
7451
- this.audioElements[sessionId] = audio;
7963
+ this.createAudioElementFor(sessionId);
7452
7964
  }
7453
7965
 
7454
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7966
+ const audioElement = this.audioElements[sessionId];
7455
7967
  const stream = newStream || this.getRemoteStream(sessionId);
7456
7968
 
7457
7969
  if (!this._isWeb() || !stream) {
@@ -7598,10 +8110,10 @@ class WebRTCClient extends Emitter {
7598
8110
 
7599
8111
  _stopSendingStats(session ) {
7600
8112
  const sessionId = this.getSipSessionId(session);
7601
- logger$7.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
8113
+ logger$8.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7602
8114
 
7603
8115
  if (sessionId in this.statsIntervals) {
7604
- logger$7.trace('Stop sending stats for call', { sessionId });
8116
+ logger$8.trace('Stop sending stats for call', { sessionId });
7605
8117
  this.statsIntervals[sessionId]();
7606
8118
  delete this.statsIntervals[sessionId];
7607
8119
  }
@@ -7617,7 +8129,7 @@ class WebRTCClient extends Emitter {
7617
8129
  try {
7618
8130
  await this.userAgent.transport.disconnect();
7619
8131
  } catch (e) {
7620
- logger$7.error('WebRTC transport disconnect, error', e);
8132
+ logger$8.error('WebRTC transport disconnect, error', e);
7621
8133
  }
7622
8134
  }
7623
8135
  }
@@ -7704,7 +8216,7 @@ const events = [
7704
8216
  ON_SIGNAL,
7705
8217
  ];
7706
8218
 
7707
- const logger$6 = IssueReporter$1.loggerFor('webrtc-phone');
8219
+ const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
7708
8220
 
7709
8221
  class WebRTCPhone extends Emitter {
7710
8222
 
@@ -7775,7 +8287,7 @@ class WebRTCPhone extends Emitter {
7775
8287
  }).catch(error => {
7776
8288
  // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
7777
8289
  console.error('register error', error, error.message, error.stack);
7778
- logger$6.error('WebRTC register error', { message: error.message, stack: error.stack });
8290
+ logger$7.error('WebRTC register error', { message: error.message, stack: error.stack });
7779
8291
  });
7780
8292
  }
7781
8293
 
@@ -7790,7 +8302,7 @@ class WebRTCPhone extends Emitter {
7790
8302
  if (!this.client) {
7791
8303
  return;
7792
8304
  }
7793
- logger$6.info('WebRTC phone stop');
8305
+ logger$7.info('WebRTC phone stop');
7794
8306
  this.client.stop();
7795
8307
  }
7796
8308
 
@@ -7805,14 +8317,14 @@ class WebRTCPhone extends Emitter {
7805
8317
  async sendReinvite(callSession , constraints = null, conference = false,
7806
8318
  audioOnly = false) {
7807
8319
  const sipSession = this.findSipSession(callSession);
7808
- logger$6.info('WebRTC phone - send reinvite', {
8320
+ logger$7.info('WebRTC phone - send reinvite', {
7809
8321
  sessionId: sipSession ? sipSession.id : null,
7810
8322
  constraints,
7811
8323
  audioOnly,
7812
8324
  });
7813
8325
 
7814
8326
  if (!sipSession) {
7815
- return null;
8327
+ return false;
7816
8328
  }
7817
8329
 
7818
8330
  // $FlowFixMe
@@ -7822,19 +8334,17 @@ class WebRTCPhone extends Emitter {
7822
8334
  // Downgrade
7823
8335
  if (constraints && !isUpgrade) {
7824
8336
  // No reinvite needed
7825
- return this._downgradeToAudio(callSession);
8337
+ this._downgradeToAudio(callSession);
8338
+ return false;
7826
8339
  }
7827
8340
 
7828
8341
  if (isUpgrade) {
7829
8342
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
7830
8343
  if (!shouldReinvite) {
7831
- return;
8344
+ return false;
7832
8345
  }
7833
8346
  }
7834
8347
 
7835
- // Force reinvite in SDH
7836
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
7837
-
7838
8348
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
7839
8349
  }
7840
8350
 
@@ -7843,7 +8353,7 @@ class WebRTCPhone extends Emitter {
7843
8353
  }
7844
8354
 
7845
8355
  startHeartbeat() {
7846
- logger$6.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
8356
+ logger$7.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
7847
8357
  if (!this.client || this.client.hasHeartbeat()) {
7848
8358
  return;
7849
8359
  }
@@ -7852,7 +8362,7 @@ class WebRTCPhone extends Emitter {
7852
8362
  }
7853
8363
 
7854
8364
  stopHeartbeat() {
7855
- logger$6.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
8365
+ logger$7.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
7856
8366
  if (!this.client) {
7857
8367
  return;
7858
8368
  }
@@ -7869,7 +8379,7 @@ class WebRTCPhone extends Emitter {
7869
8379
  }
7870
8380
 
7871
8381
  reconnect() {
7872
- logger$6.info('WebRTC phone - reconnect', { client: !!this.client });
8382
+ logger$7.info('WebRTC phone - reconnect', { client: !!this.client });
7873
8383
  if (!this.client) {
7874
8384
  return;
7875
8385
  }
@@ -7907,7 +8417,7 @@ class WebRTCPhone extends Emitter {
7907
8417
  _downgradeToAudio(callSession ) {
7908
8418
  const sipSession = this.findSipSession(callSession);
7909
8419
  if (!sipSession) {
7910
- return;
8420
+ return false;
7911
8421
  }
7912
8422
 
7913
8423
  // Release local video stream when downgrading to audio
@@ -8020,7 +8530,7 @@ class WebRTCPhone extends Emitter {
8020
8530
  // Monkey patch to know when canceled with the CANCEL message
8021
8531
  const onCancel = sipSession._onCancel.bind(sipSession);
8022
8532
  sipSession._onCancel = (message ) => {
8023
- logger$6.trace('on sip session canceled', { callId: message.callId });
8533
+ logger$7.trace('on sip session canceled', { callId: message.callId });
8024
8534
 
8025
8535
  onCancel(message);
8026
8536
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
@@ -8045,13 +8555,13 @@ class WebRTCPhone extends Emitter {
8045
8555
  this.audioOutputVolume,
8046
8556
  );
8047
8557
  case sessionState.SessionState.Terminating:
8048
- logger$6.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8558
+ logger$7.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8049
8559
 
8050
8560
  this.eventEmitter.emit(ON_CALL_ENDING, this._createCallSession(sipSession));
8051
8561
 
8052
8562
  break;
8053
8563
  case sessionState.SessionState.Terminated:
8054
- logger$6.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8564
+ logger$7.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8055
8565
 
8056
8566
  this._onCallTerminated(sipSession);
8057
8567
 
@@ -8087,7 +8597,7 @@ class WebRTCPhone extends Emitter {
8087
8597
  }
8088
8598
 
8089
8599
  async startScreenSharing(constraints , callSession ) {
8090
- logger$6.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8600
+ logger$7.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8091
8601
 
8092
8602
  const screenShareStream = await this._getStreamFromConstraints(constraints);
8093
8603
  if (!screenShareStream) {
@@ -8109,6 +8619,10 @@ class WebRTCPhone extends Emitter {
8109
8619
  localStream.removeTrack(videoTrack);
8110
8620
  }
8111
8621
 
8622
+ if (localStream) {
8623
+ localStream.addTrack(screenTrack);
8624
+ }
8625
+
8112
8626
  if (sender) {
8113
8627
  sender.replaceTrack(screenTrack);
8114
8628
  }
@@ -8123,7 +8637,8 @@ class WebRTCPhone extends Emitter {
8123
8637
  return;
8124
8638
  }
8125
8639
 
8126
- logger$6.info('WebRTC phone - stop screen sharing');
8640
+ logger$7.info('WebRTC phone - stop screen sharing');
8641
+ let reinvited = false;
8127
8642
 
8128
8643
  try {
8129
8644
  if (this.currentScreenShare.stream) {
@@ -8138,7 +8653,8 @@ class WebRTCPhone extends Emitter {
8138
8653
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
8139
8654
  // We have to downgrade to audio.
8140
8655
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
8141
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
8656
+ const constraints = { audio: false, video: screenshareStopped };
8657
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
8142
8658
  }
8143
8659
  } catch (e) {
8144
8660
  console.warn(e);
@@ -8152,6 +8668,8 @@ class WebRTCPhone extends Emitter {
8152
8668
  );
8153
8669
 
8154
8670
  this.currentScreenShare = null;
8671
+
8672
+ return reinvited;
8155
8673
  }
8156
8674
 
8157
8675
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -8189,7 +8707,7 @@ class WebRTCPhone extends Emitter {
8189
8707
  }
8190
8708
 
8191
8709
  _onCallAccepted(sipSession , cameraEnabled ) {
8192
- logger$6.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8710
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8193
8711
 
8194
8712
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
8195
8713
  this.currentSipSession = sipSession;
@@ -8207,11 +8725,15 @@ class WebRTCPhone extends Emitter {
8207
8725
  }
8208
8726
 
8209
8727
  changeAudioDevice(id ) {
8210
- logger$6.info('WebRTC phone - change audio device', { deviceId: id });
8728
+ logger$7.info('WebRTC phone - change audio device', { deviceId: id });
8211
8729
  this.audioOutputDeviceId = id;
8212
8730
  this.client.changeAudioOutputDevice(id);
8213
8731
  }
8214
8732
 
8733
+ createAudioElementFor(sessionId ) {
8734
+ return this.client.createAudioElementFor(sessionId);
8735
+ }
8736
+
8215
8737
  changeRingDevice(id ) {
8216
8738
  this.audioRingDeviceId = id;
8217
8739
  }
@@ -8228,25 +8750,25 @@ class WebRTCPhone extends Emitter {
8228
8750
  }
8229
8751
 
8230
8752
  changeAudioInputDevice(id ) {
8231
- logger$6.info('WebRTC phone - changeAudio input device', { deviceId: id });
8753
+ logger$7.info('WebRTC phone - changeAudio input device', { deviceId: id });
8232
8754
 
8233
8755
  return this.client.changeAudioInputDevice(id, this.currentSipSession);
8234
8756
  }
8235
8757
 
8236
8758
  changeVideoInputDevice(id ) {
8237
- logger$6.info('WebRTC phone - change video input device', { deviceId: id });
8759
+ logger$7.info('WebRTC phone - change video input device', { deviceId: id });
8238
8760
 
8239
8761
  return this.client.changeVideoInputDevice(id, this.currentSipSession);
8240
8762
  }
8241
8763
 
8242
8764
  changeSessionVideoInputDevice(id ) {
8243
- logger$6.info('WebRTC phone - change session video input device', { deviceId: id });
8765
+ logger$7.info('WebRTC phone - change session video input device', { deviceId: id });
8244
8766
 
8245
8767
  return this.client.changeSessionVideoInputDevice(id, this.currentSipSession);
8246
8768
  }
8247
8769
 
8248
8770
  _onCallTerminated(sipSession ) {
8249
- logger$6.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8771
+ logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8250
8772
 
8251
8773
  const callSession = this._createCallSession(sipSession);
8252
8774
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
@@ -8280,7 +8802,7 @@ class WebRTCPhone extends Emitter {
8280
8802
  const hasIncomingCallSession = this.hasIncomingCallSession();
8281
8803
 
8282
8804
  // Re-trigger incoming call event for remaining incoming calls
8283
- logger$6.info('WebRTC phone - check to re-trigger incoming call', {
8805
+ logger$7.info('WebRTC phone - check to re-trigger incoming call', {
8284
8806
  sipId: sipSession.id,
8285
8807
  shouldRetrigger,
8286
8808
  hasIncomingCallSession,
@@ -8369,37 +8891,37 @@ class WebRTCPhone extends Emitter {
8369
8891
 
8370
8892
  // Deprecated
8371
8893
  getLocalStreamForCall(callSession ) {
8372
- logger$6.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8894
+ logger$7.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8373
8895
 
8374
8896
  return this.getLocalStream(callSession);
8375
8897
  }
8376
8898
 
8377
8899
  // Deprecated
8378
8900
  getRemoteStreamForCall(callSession ) {
8379
- logger$6.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8901
+ logger$7.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8380
8902
 
8381
8903
  return this.getRemoteVideoStream(callSession);
8382
8904
  }
8383
8905
 
8384
8906
  getRemoteStreamsForCall(callSession ) {
8385
- logger$6.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8907
+ logger$7.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8386
8908
 
8387
8909
  return this.getRemoteStream(callSession);
8388
8910
  }
8389
8911
 
8390
8912
  accept(callSession , cameraEnabled ) {
8391
- logger$6.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8913
+ logger$7.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8392
8914
  if (this.currentSipSession) {
8393
8915
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
8394
8916
  }
8395
8917
 
8396
8918
  if (!callSession) {
8397
- logger$6.warn('no CallSession to accept.');
8919
+ logger$7.warn('no CallSession to accept.');
8398
8920
  return Promise.resolve(null);
8399
8921
  }
8400
8922
 
8401
8923
  if (callSession.getId() in this.acceptedSessions) {
8402
- logger$6.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8924
+ logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8403
8925
  return Promise.resolve(callSession.sipCallId);
8404
8926
  }
8405
8927
 
@@ -8411,24 +8933,24 @@ class WebRTCPhone extends Emitter {
8411
8933
  const sipSession = this.client.getSipSession(callSession.getId());
8412
8934
  if (sipSession) {
8413
8935
  if (sipSession.state === sessionState.SessionState.Terminated || sipSession.state === sessionState.SessionState.Terminating) {
8414
- logger$6.warn('Trying to answer a terminated sipSession.');
8936
+ logger$7.warn('Trying to answer a terminated sipSession.');
8415
8937
 
8416
8938
  return Promise.resolve(null);
8417
8939
  }
8418
8940
 
8419
- logger$6.info('accept call, session found', { sipId: sipSession.id });
8941
+ logger$7.info('accept call, session found', { sipId: sipSession.id });
8420
8942
 
8421
8943
  // $FlowFixMe
8422
8944
  return this.client.answer(sipSession, this.allowVideo ? cameraEnabled : false).then(() => {
8423
8945
  return callSession.sipCallId;
8424
8946
  }).catch(e => {
8425
- logger$6.error(e);
8947
+ logger$7.error(e);
8426
8948
  this.endCurrentCall(callSession);
8427
8949
  throw e;
8428
8950
  });
8429
8951
  }
8430
8952
 
8431
- logger$6.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8953
+ logger$7.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8432
8954
 
8433
8955
  return Promise.resolve(null);
8434
8956
  }
@@ -8438,7 +8960,7 @@ class WebRTCPhone extends Emitter {
8438
8960
  }
8439
8961
 
8440
8962
  async reject(callSession ) {
8441
- logger$6.info('reject WebRTC called', { id: callSession.getId() });
8963
+ logger$7.info('reject WebRTC called', { id: callSession.getId() });
8442
8964
 
8443
8965
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call rejected locally');
8444
8966
  if (!callSession || callSession.getId() in this.rejectedSessions) {
@@ -8450,14 +8972,14 @@ class WebRTCPhone extends Emitter {
8450
8972
 
8451
8973
  const sipSession = this.findSipSession(callSession);
8452
8974
  if (sipSession) {
8453
- logger$6.info('WebRTC rejecting', { sipId: sipSession.id });
8975
+ logger$7.info('WebRTC rejecting', { sipId: sipSession.id });
8454
8976
 
8455
8977
  this.client.hangup(sipSession);
8456
8978
  }
8457
8979
  }
8458
8980
 
8459
8981
  async ignore(callSession ) {
8460
- logger$6.info('WebRTC ignore', { id: callSession.getId() });
8982
+ logger$7.info('WebRTC ignore', { id: callSession.getId() });
8461
8983
 
8462
8984
  // kill the ring
8463
8985
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'ignoring call');
@@ -8466,7 +8988,7 @@ class WebRTCPhone extends Emitter {
8466
8988
  }
8467
8989
 
8468
8990
  hold(callSession , withEvent = true, isConference = false) {
8469
- logger$6.info('WebRTC hold', { id: callSession.getId() });
8991
+ logger$7.info('WebRTC hold', { id: callSession.getId() });
8470
8992
 
8471
8993
  const sipSession = this.findSipSession(callSession);
8472
8994
 
@@ -8477,7 +8999,7 @@ class WebRTCPhone extends Emitter {
8477
8999
 
8478
9000
  // @Deprecated
8479
9001
  unhold(callSession , withEvent = true, isConference = false) {
8480
- logger$6.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
9002
+ logger$7.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8481
9003
 
8482
9004
  console.warn('Please note that `phone.unhold()` is being deprecated; `phone.resume()` is the preferred method');
8483
9005
 
@@ -8492,7 +9014,7 @@ class WebRTCPhone extends Emitter {
8492
9014
  const sipSession = this.findSipSession(callSession);
8493
9015
 
8494
9016
  if (sipSession) {
8495
- logger$6.info('WebRTC atxfer', { sipId: sipSession.id });
9017
+ logger$7.info('WebRTC atxfer', { sipId: sipSession.id });
8496
9018
 
8497
9019
  return this.client.atxfer(sipSession);
8498
9020
  }
@@ -8507,7 +9029,7 @@ class WebRTCPhone extends Emitter {
8507
9029
  if (!sipSession) {
8508
9030
  return new Promise((resolve, reject) => reject(new Error('No session to hold')));
8509
9031
  }
8510
- logger$6.info('WebRTC hold sip session', { sipId: sipSession.id });
9032
+ logger$7.info('WebRTC hold sip session', { sipId: sipSession.id });
8511
9033
 
8512
9034
  const promise = this.client.hold(sipSession, isConference);
8513
9035
  if (withEvent) {
@@ -8526,7 +9048,7 @@ class WebRTCPhone extends Emitter {
8526
9048
  if (!sipSession) {
8527
9049
  return new Promise((resolve, reject) => reject(new Error('No session to unhold')));
8528
9050
  }
8529
- logger$6.info('WebRTC unhold', { sipId: sipSession.id });
9051
+ logger$7.info('WebRTC unhold', { sipId: sipSession.id });
8530
9052
 
8531
9053
  const promise = this.client.unhold(sipSession, isConference);
8532
9054
  if (withEvent) {
@@ -8537,18 +9059,18 @@ class WebRTCPhone extends Emitter {
8537
9059
  }
8538
9060
 
8539
9061
  resume(callSession , isConference = false) {
8540
- logger$6.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
9062
+ logger$7.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8541
9063
 
8542
9064
  const sipSession = this.findSipSession(callSession);
8543
9065
  if (!sipSession) {
8544
9066
  return new Promise((resolve, reject) => reject(new Error('No session to resume')));
8545
9067
  }
8546
9068
 
8547
- logger$6.info('WebRTC resuming', { sipId: sipSession.id });
9069
+ logger$7.info('WebRTC resuming', { sipId: sipSession.id });
8548
9070
 
8549
9071
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
8550
9072
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
8551
- logger$6.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9073
+ logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8552
9074
  this.holdSipSession(this.currentSipSession, callSession);
8553
9075
  }
8554
9076
 
@@ -8563,14 +9085,14 @@ class WebRTCPhone extends Emitter {
8563
9085
  }
8564
9086
 
8565
9087
  mute(callSession , withEvent = true) {
8566
- logger$6.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
9088
+ logger$7.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8567
9089
 
8568
9090
  const sipSession = this.findSipSession(callSession);
8569
9091
  if (!sipSession) {
8570
9092
  return;
8571
9093
  }
8572
9094
 
8573
- logger$6.info('WebRTC muting', { sipId: sipSession.id });
9095
+ logger$7.info('WebRTC muting', { sipId: sipSession.id });
8574
9096
  this.client.mute(sipSession);
8575
9097
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: true });
8576
9098
 
@@ -8584,14 +9106,14 @@ class WebRTCPhone extends Emitter {
8584
9106
  }
8585
9107
 
8586
9108
  unmute(callSession , withEvent = true) {
8587
- logger$6.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
9109
+ logger$7.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8588
9110
 
8589
9111
  const sipSession = this.findSipSession(callSession);
8590
9112
  if (!sipSession) {
8591
9113
  return;
8592
9114
  }
8593
9115
 
8594
- logger$6.info('WebRTC unmuting', { sipId: sipSession.id });
9116
+ logger$7.info('WebRTC unmuting', { sipId: sipSession.id });
8595
9117
  this.client.unmute(sipSession);
8596
9118
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: false });
8597
9119
 
@@ -8618,7 +9140,7 @@ class WebRTCPhone extends Emitter {
8618
9140
  if (!sipSession) {
8619
9141
  return;
8620
9142
  }
8621
- logger$6.info('WebRTC turn camera on', { sipId: sipSession.id });
9143
+ logger$7.info('WebRTC turn camera on', { sipId: sipSession.id });
8622
9144
 
8623
9145
  this.client.toggleCameraOn(sipSession);
8624
9146
 
@@ -8630,7 +9152,7 @@ class WebRTCPhone extends Emitter {
8630
9152
  if (!sipSession) {
8631
9153
  return;
8632
9154
  }
8633
- logger$6.info('WebRTC turn camera off', { sipId: sipSession.id });
9155
+ logger$7.info('WebRTC turn camera off', { sipId: sipSession.id });
8634
9156
 
8635
9157
  this.client.toggleCameraOff(sipSession);
8636
9158
  this.eventEmitter.emit(ON_CAMERA_DISABLED, this._createCameraDisabledCallSession(sipSession, callSession));
@@ -8642,7 +9164,7 @@ class WebRTCPhone extends Emitter {
8642
9164
  return;
8643
9165
  }
8644
9166
 
8645
- logger$6.info('WebRTC send key', { sipId: sipSession.id, tone });
9167
+ logger$7.info('WebRTC send key', { sipId: sipSession.id, tone });
8646
9168
  this.client.sendDTMF(sipSession, tone);
8647
9169
  }
8648
9170
 
@@ -8650,7 +9172,7 @@ class WebRTCPhone extends Emitter {
8650
9172
  // @TODO: line is not used here
8651
9173
  async makeCall(number , line , cameraEnabled ,
8652
9174
  audioOnly = false, conference = false) {
8653
- logger$6.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9175
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8654
9176
  if (!number) {
8655
9177
  return Promise.resolve(null);
8656
9178
  }
@@ -8660,7 +9182,7 @@ class WebRTCPhone extends Emitter {
8660
9182
  }
8661
9183
  if (this.currentSipSession) {
8662
9184
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true).catch(e => {
8663
- logger$6.warn('Unable to hold current session when making another call', e);
9185
+ logger$7.warn('Unable to hold current session when making another call', e);
8664
9186
  });
8665
9187
  }
8666
9188
 
@@ -8670,7 +9192,7 @@ class WebRTCPhone extends Emitter {
8670
9192
  this._bindEvents(sipSession);
8671
9193
  } catch (error) {
8672
9194
  console.warn(error);
8673
- logger$6.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
9195
+ logger$7.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8674
9196
  return Promise.resolve(null);
8675
9197
  }
8676
9198
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
@@ -8698,7 +9220,7 @@ class WebRTCPhone extends Emitter {
8698
9220
  return;
8699
9221
  }
8700
9222
 
8701
- logger$6.info('WebRTC transfer', { sipId: sipSession.id, target });
9223
+ logger$7.info('WebRTC transfer', { sipId: sipSession.id, target });
8702
9224
 
8703
9225
  this.client.transfer(sipSession, target);
8704
9226
  }
@@ -8707,7 +9229,7 @@ class WebRTCPhone extends Emitter {
8707
9229
  const sipSession = this.client.getSipSession(source.sipCallId);
8708
9230
  const sipSessionTarget = this.client.getSipSession(destination.sipCallId);
8709
9231
 
8710
- logger$6.info('WebRTC indirect transfer', {
9232
+ logger$7.info('WebRTC indirect transfer', {
8711
9233
  sipId: sipSession ? sipSession.id : null,
8712
9234
  target: sipSessionTarget ? sipSessionTarget.id : null,
8713
9235
  });
@@ -8735,7 +9257,7 @@ class WebRTCPhone extends Emitter {
8735
9257
  return false;
8736
9258
  }
8737
9259
 
8738
- logger$6.info('WebRTC hangup', { sipId: sipSession.id });
9260
+ logger$7.info('WebRTC hangup', { sipId: sipSession.id });
8739
9261
 
8740
9262
  const sipSessionId = this.getSipSessionId(sipSession);
8741
9263
 
@@ -8780,7 +9302,7 @@ class WebRTCPhone extends Emitter {
8780
9302
  }
8781
9303
 
8782
9304
  async close() {
8783
- logger$6.info('WebRTC close');
9305
+ logger$7.info('WebRTC close');
8784
9306
 
8785
9307
  try {
8786
9308
  await Promise.race([
@@ -8788,7 +9310,7 @@ class WebRTCPhone extends Emitter {
8788
9310
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Unregister, timed out')), 3000)),
8789
9311
  ]);
8790
9312
  } catch (e) {
8791
- logger$6.error('WebRTC close, unregister error', e);
9313
+ logger$7.error('WebRTC close, unregister error', e);
8792
9314
  }
8793
9315
 
8794
9316
  this.client.close();
@@ -8806,12 +9328,12 @@ class WebRTCPhone extends Emitter {
8806
9328
  }
8807
9329
 
8808
9330
  enableRinging() {
8809
- logger$6.info('WebRTC enable ringing');
9331
+ logger$7.info('WebRTC enable ringing');
8810
9332
  this.ringingEnabled = true;
8811
9333
  }
8812
9334
 
8813
9335
  disableRinging() {
8814
- logger$6.info('WebRTC disable ringing');
9336
+ logger$7.info('WebRTC disable ringing');
8815
9337
  this.ringingEnabled = false;
8816
9338
  }
8817
9339
 
@@ -8851,7 +9373,7 @@ class WebRTCPhone extends Emitter {
8851
9373
 
8852
9374
  // Deprecated
8853
9375
  getLocalMediaStream(callSession ) {
8854
- logger$6.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
9376
+ logger$7.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
8855
9377
  return this.getLocalStream(callSession);
8856
9378
  }
8857
9379
 
@@ -8859,6 +9381,10 @@ class WebRTCPhone extends Emitter {
8859
9381
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
8860
9382
  }
8861
9383
 
9384
+ hasALocalVideoTrack(callSession ) {
9385
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
9386
+ }
9387
+
8862
9388
  getRemoteStream(callSession ) {
8863
9389
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
8864
9390
  }
@@ -8881,7 +9407,7 @@ class WebRTCPhone extends Emitter {
8881
9407
  this.client.on(this.client.INVITE, (sipSession , wantsToDoVideo ) => {
8882
9408
  const autoAnswer = sipSession.request.getHeader('Answer-Mode') === 'Auto';
8883
9409
  const withVideo = this.allowVideo ? wantsToDoVideo : false;
8884
- logger$6.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
9410
+ logger$7.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
8885
9411
 
8886
9412
  const callSession = this._createIncomingCallSession(sipSession, withVideo, null, autoAnswer);
8887
9413
  this.incomingSessions.push(callSession.getId());
@@ -8904,7 +9430,7 @@ class WebRTCPhone extends Emitter {
8904
9430
  });
8905
9431
 
8906
9432
  this.client.on(this.client.ON_REINVITE, (...args) => {
8907
- logger$6.info('WebRTC on reinvite', {
9433
+ logger$7.info('WebRTC on reinvite', {
8908
9434
  sessionId: args[0].id,
8909
9435
  inviteId: args[1].id,
8910
9436
  updatedCalleeName: args[2],
@@ -8924,7 +9450,7 @@ class WebRTCPhone extends Emitter {
8924
9450
  });
8925
9451
 
8926
9452
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
8927
- logger$6.info('WebRTC call accepted', { sipId: sipSession.id });
9453
+ logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
8928
9454
 
8929
9455
  this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
8930
9456
 
@@ -8935,17 +9461,17 @@ class WebRTCPhone extends Emitter {
8935
9461
  this.client.on('ended', () => {});
8936
9462
 
8937
9463
  this.client.on(this.client.ON_ERROR, e => {
8938
- logger$6.error('WebRTC error', e);
9464
+ logger$7.error('WebRTC error', e);
8939
9465
  this.eventEmitter.emit(ON_CALL_ERROR, e);
8940
9466
  });
8941
9467
 
8942
9468
  this.client.on(this.client.UNREGISTERED, () => {
8943
- logger$6.info('WebRTC unregistered');
9469
+ logger$7.info('WebRTC unregistered');
8944
9470
  this.eventEmitter.emit(ON_UNREGISTERED);
8945
9471
  });
8946
9472
 
8947
9473
  this.client.on(this.client.REGISTERED, () => {
8948
- logger$6.info('WebRTC registered', {
9474
+ logger$7.info('WebRTC registered', {
8949
9475
  shouldSendReinvite: this.shouldSendReinvite,
8950
9476
  state: this.currentSipSession ? this.currentSipSession.state : null,
8951
9477
  currentSipSession: !!this.currentSipSession,
@@ -8961,19 +9487,19 @@ class WebRTCPhone extends Emitter {
8961
9487
  try {
8962
9488
  this.sendReinvite(this.currentCallSession);
8963
9489
  } catch (e) {
8964
- logger$6.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9490
+ logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
8965
9491
  }
8966
9492
  }
8967
9493
  });
8968
9494
 
8969
9495
  this.client.on(this.client.CONNECTED, () => {
8970
- logger$6.info('WebRTC client connected');
9496
+ logger$7.info('WebRTC client connected');
8971
9497
 
8972
9498
  this.stopHeartbeat();
8973
9499
  });
8974
9500
 
8975
9501
  this.client.on(this.client.DISCONNECTED, () => {
8976
- logger$6.info('WebRTC client disconnected');
9502
+ logger$7.info('WebRTC client disconnected');
8977
9503
 
8978
9504
  this.eventEmitter.emit(ON_UNREGISTERED);
8979
9505
 
@@ -9205,7 +9731,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9205
9731
 
9206
9732
  //
9207
9733
 
9208
- const logger$5 = IssueReporter$1.loggerFor('simple-phone');
9734
+ const logger$6 = IssueReporter$1.loggerFor('simple-phone');
9209
9735
  const sipLogger = IssueReporter$1.loggerFor('sip.js');
9210
9736
  const protocolLogger = IssueReporter$1.loggerFor('sip');
9211
9737
 
@@ -9312,7 +9838,7 @@ class Phone extends Emitter {
9312
9838
  async disconnect() {
9313
9839
  if (this.phone) {
9314
9840
  if (this.phone.hasAnActiveCall()) {
9315
- logger$5.info('hangup call on disconnect');
9841
+ logger$6.info('hangup call on disconnect');
9316
9842
  // $FlowFixMe
9317
9843
  await this.phone.hangup();
9318
9844
  }
@@ -9335,13 +9861,13 @@ class Phone extends Emitter {
9335
9861
  }
9336
9862
 
9337
9863
  async hangup(callSession ) {
9338
- logger$5.info('hangup via simple phone', { callId: callSession.getId() });
9864
+ logger$6.info('hangup via simple phone', { callId: callSession.getId() });
9339
9865
 
9340
9866
  return this.phone && this.phone.hangup(callSession);
9341
9867
  }
9342
9868
 
9343
9869
  async accept(callSession , cameraEnabled ) {
9344
- logger$5.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9870
+ logger$6.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9345
9871
 
9346
9872
  return this.phone && this.phone.accept(callSession, cameraEnabled);
9347
9873
  }
@@ -9361,13 +9887,18 @@ class Phone extends Emitter {
9361
9887
  return adHocConference.start();
9362
9888
  }
9363
9889
 
9364
- mute(callSession ) {
9365
- this.muteViaAPI(callSession);
9890
+ mute(callSession , withApi = true) {
9891
+ if (withApi) {
9892
+ this.muteViaAPI(callSession);
9893
+ }
9894
+
9366
9895
  return this.phone && this.phone.mute(callSession);
9367
9896
  }
9368
9897
 
9369
- unmute(callSession ) {
9370
- this.unmuteViaAPI(callSession);
9898
+ unmute(callSession , withApi = true) {
9899
+ if (withApi) {
9900
+ this.unmuteViaAPI(callSession);
9901
+ }
9371
9902
 
9372
9903
  return this.phone && this.phone.unmute(callSession);
9373
9904
  }
@@ -9375,7 +9906,7 @@ class Phone extends Emitter {
9375
9906
  muteViaAPI(callSession ) {
9376
9907
  if (callSession && callSession.callId) {
9377
9908
  Wazo.getApiClient().calld.mute(callSession.callId).catch(e => {
9378
- logger$5.error('Mute via API, error', e);
9909
+ logger$6.error('Mute via API, error', e);
9379
9910
  });
9380
9911
  }
9381
9912
  }
@@ -9383,7 +9914,7 @@ class Phone extends Emitter {
9383
9914
  unmuteViaAPI(callSession ) {
9384
9915
  if (callSession && callSession.callId) {
9385
9916
  Wazo.getApiClient().calld.unmute(callSession.callId).catch(e => {
9386
- logger$5.error('Unmute via API, error', e);
9917
+ logger$6.error('Unmute via API, error', e);
9387
9918
  });
9388
9919
  }
9389
9920
  }
@@ -9473,9 +10004,13 @@ class Phone extends Emitter {
9473
10004
  return this.phone && this.phone.hasLocalVideo(callSession);
9474
10005
  }
9475
10006
 
10007
+ hasALocalVideoTrack(callSession ) {
10008
+ return this.phone && this.phone.hasALocalVideoTrack(callSession);
10009
+ }
10010
+
9476
10011
  // @Deprecated
9477
10012
  getLocalMediaStream(callSession ) {
9478
- logger$5.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
10013
+ logger$6.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9479
10014
 
9480
10015
  return this.phone && this.phone.getLocalStream(callSession);
9481
10016
  }
@@ -9494,20 +10029,20 @@ class Phone extends Emitter {
9494
10029
 
9495
10030
  // @Deprecated
9496
10031
  getRemoteStreamForCall(callSession ) {
9497
- logger$5.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
10032
+ logger$6.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9498
10033
  return this.getRemoteStream(callSession);
9499
10034
  }
9500
10035
 
9501
10036
  // Returns remote streams directly from the peerConnection
9502
10037
  // @Deprecated
9503
10038
  getRemoteStreamsForCall(callSession ) {
9504
- logger$5.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
10039
+ logger$6.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9505
10040
  return this.getLocalStream(callSession);
9506
10041
  }
9507
10042
 
9508
10043
  // @Deprecated
9509
10044
  getRemoteVideoStreamForCall(callSession ) {
9510
- logger$5.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
10045
+ logger$6.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9511
10046
 
9512
10047
  return this.getRemoteVideoStream(callSession);
9513
10048
  }
@@ -9637,6 +10172,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
9637
10172
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
9638
10173
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
9639
10174
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
10175
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
10176
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
9640
10177
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
9641
10178
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
9642
10179
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -9678,7 +10215,7 @@ const BLACKLIST_EVENTS = [
9678
10215
  ];
9679
10216
 
9680
10217
  const HEARTBEAT_ENGINE_VERSION = '20.09';
9681
- const logger$4 = IssueReporter$1.loggerFor('wazo-ws');
10218
+ const logger$5 = IssueReporter$1.loggerFor('wazo-ws');
9682
10219
  const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
9683
10220
 
9684
10221
  class WebSocketClient extends Emitter {
@@ -9727,19 +10264,19 @@ class WebSocketClient extends Emitter {
9727
10264
  }
9728
10265
 
9729
10266
  connect() {
9730
- logger$4.info('connect method started', { host: this.host, token: this.token });
10267
+ logger$5.info('connect method started', { host: this.host, token: this.token });
9731
10268
  this.socket = new ReconnectingWebSocket__default['default'](this._getUrl.bind(this), [], this.options);
9732
10269
  if (this.options.binaryType) {
9733
10270
  this.socket.binaryType = this.options.binaryType;
9734
10271
  }
9735
10272
 
9736
10273
  this.socket.onopen = () => {
9737
- logger$4.info('on Wazo WS open', { method: 'connect', host: this.host });
10274
+ logger$5.info('on Wazo WS open', { method: 'connect', host: this.host });
9738
10275
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_OPEN);
9739
10276
  };
9740
10277
 
9741
10278
  this.socket.onerror = event => {
9742
- logger$4.error('on Wazo WS error', event.target);
10279
+ logger$5.error('on Wazo WS error', event.target);
9743
10280
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_ERROR, event);
9744
10281
  };
9745
10282
 
@@ -9769,7 +10306,7 @@ class WebSocketClient extends Emitter {
9769
10306
 
9770
10307
  this.socket.onclose = event => {
9771
10308
  // Can't be converted to JSON (circular structure)
9772
- logger$4.info('on Wazo WS close', {
10309
+ logger$5.info('on Wazo WS close', {
9773
10310
  reason: event.reason,
9774
10311
  code: event.code,
9775
10312
  readyState: event.target.readyState,
@@ -9787,12 +10324,12 @@ class WebSocketClient extends Emitter {
9787
10324
  };
9788
10325
 
9789
10326
  this.socket.onerror = event => {
9790
- logger$4.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
10327
+ logger$5.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
9791
10328
  };
9792
10329
  }
9793
10330
 
9794
10331
  close(force = false) {
9795
- logger$4.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
10332
+ logger$5.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
9796
10333
 
9797
10334
  if (!this.socket) {
9798
10335
  return;
@@ -9810,7 +10347,7 @@ class WebSocketClient extends Emitter {
9810
10347
 
9811
10348
  updateToken(token ) {
9812
10349
  this.token = token;
9813
- logger$4.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
10350
+ logger$5.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
9814
10351
 
9815
10352
  if (this.socket) {
9816
10353
  // If still connected, send the token to the WS
@@ -9828,7 +10365,7 @@ class WebSocketClient extends Emitter {
9828
10365
  }
9829
10366
 
9830
10367
  startHeartbeat() {
9831
- logger$4.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
10368
+ logger$5.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
9832
10369
 
9833
10370
  if (!this.socket) {
9834
10371
  this.heartbeat.stop();
@@ -9842,7 +10379,7 @@ class WebSocketClient extends Emitter {
9842
10379
  }
9843
10380
 
9844
10381
  stopHeartbeat() {
9845
- logger$4.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
10382
+ logger$5.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
9846
10383
 
9847
10384
  this.heartbeat.stop();
9848
10385
  }
@@ -9872,7 +10409,7 @@ class WebSocketClient extends Emitter {
9872
10409
  }
9873
10410
 
9874
10411
  reconnect(reason ) {
9875
- logger$4.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
10412
+ logger$5.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
9876
10413
  if (!this.socket) {
9877
10414
  return;
9878
10415
  }
@@ -9928,7 +10465,7 @@ class WebSocketClient extends Emitter {
9928
10465
  this.close();
9929
10466
  }
9930
10467
  const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
9931
- logger$4.log('Wazo WS url computed to reconnect', { url });
10468
+ logger$5.log('Wazo WS url computed to reconnect', { url });
9932
10469
 
9933
10470
  return url;
9934
10471
  }
@@ -9936,12 +10473,12 @@ class WebSocketClient extends Emitter {
9936
10473
  _onHeartbeat(message ) {
9937
10474
  if (message.payload === 'pong') {
9938
10475
  this.heartbeat.onHeartbeat();
9939
- logger$4.log('on heartbeat received from Wazo WS');
10476
+ logger$5.log('on heartbeat received from Wazo WS');
9940
10477
  }
9941
10478
  }
9942
10479
 
9943
10480
  async _onHeartbeatTimeout() {
9944
- logger$4.log('heartbeat timed out', { host: this.host, token: this.token });
10481
+ logger$5.log('heartbeat timed out', { host: this.host, token: this.token });
9945
10482
 
9946
10483
  this.close();
9947
10484
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_CLOSE, new Error('Websocket ping failure.'));
@@ -9983,6 +10520,8 @@ WebSocketClient.eventLists = [
9983
10520
  CHATD_USER_ROOM_CREATED,
9984
10521
  CONFERENCE_USER_PARTICIPANT_JOINED,
9985
10522
  CONFERENCE_USER_PARTICIPANT_LEFT,
10523
+ MEETING_USER_PARTICIPANT_JOINED,
10524
+ MEETING_USER_PARTICIPANT_LEFT,
9986
10525
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9987
10526
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
9988
10527
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -10053,6 +10592,8 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10053
10592
  CONFERENCE_USER_PARTICIPANT_LEFT: CONFERENCE_USER_PARTICIPANT_LEFT,
10054
10593
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED: CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
10055
10594
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED: CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
10595
+ MEETING_USER_PARTICIPANT_JOINED: MEETING_USER_PARTICIPANT_JOINED,
10596
+ MEETING_USER_PARTICIPANT_LEFT: MEETING_USER_PARTICIPANT_LEFT,
10056
10597
  SWITCHBOARD_QUEUED_CALLS_UPDATED: SWITCHBOARD_QUEUED_CALLS_UPDATED,
10057
10598
  SWITCHBOARD_QUEUED_CALL_ANSWERED: SWITCHBOARD_QUEUED_CALL_ANSWERED,
10058
10599
  SWITCHBOARD_HELD_CALLS_UPDATED: SWITCHBOARD_HELD_CALLS_UPDATED,
@@ -10094,7 +10635,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10094
10635
  const { SOCKET_EVENTS, ...OTHER_EVENTS } = WebSocketClient$1;
10095
10636
  const ALL_EVENTS = [...Object.values(SOCKET_EVENTS), ...Object.values(OTHER_EVENTS)];
10096
10637
 
10097
- const logger$3 = IssueReporter$1.loggerFor('simple-ws-client');
10638
+ const logger$4 = IssueReporter$1.loggerFor('simple-ws-client');
10098
10639
 
10099
10640
  class Websocket extends Emitter {
10100
10641
 
@@ -10118,7 +10659,7 @@ class Websocket extends Emitter {
10118
10659
  }
10119
10660
 
10120
10661
  open(host , session ) {
10121
- logger$3.info('open simple WebSocket', { host, token: session.token });
10662
+ logger$4.info('open simple WebSocket', { host, token: session.token });
10122
10663
  this.ws = new WebSocketClient(
10123
10664
  {
10124
10665
  host,
@@ -10146,7 +10687,7 @@ class Websocket extends Emitter {
10146
10687
  }
10147
10688
 
10148
10689
  updateToken(token ) {
10149
- logger$3.info('update token via simple Websocket', { token, ws: !!this.ws });
10690
+ logger$4.info('update token via simple Websocket', { token, ws: !!this.ws });
10150
10691
 
10151
10692
  if (!this.ws) {
10152
10693
  return;
@@ -10174,7 +10715,7 @@ var Websocket$1 = global.wazoWebsocketInstance;
10174
10715
 
10175
10716
  //
10176
10717
 
10177
- const logger$2 = IssueReporter$1.loggerFor('room');
10718
+ const logger$3 = IssueReporter$1.loggerFor('room');
10178
10719
 
10179
10720
  class Participant extends Emitter {
10180
10721
 
@@ -10208,6 +10749,7 @@ class Participant extends Emitter {
10208
10749
 
10209
10750
 
10210
10751
  /**
10752
+ * @param room Room The room where the participant is
10211
10753
  * @param rawParticipant string Participant sent via the Wazo WS
10212
10754
  * @param extra Object extra status of the participant
10213
10755
  */
@@ -10295,7 +10837,7 @@ class Participant extends Emitter {
10295
10837
  }
10296
10838
 
10297
10839
  onTalking(isTalking ) {
10298
- logger$2.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10840
+ logger$3.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10299
10841
  this.isTalking = isTalking;
10300
10842
  // you may notice we're not broadcasting: since all participants are getting this info
10301
10843
  // directly from asterisk, there's no need to do so
@@ -10398,7 +10940,7 @@ class Participant extends Emitter {
10398
10940
  }
10399
10941
 
10400
10942
  updateStatus(status , broadcast = true) {
10401
- logger$2.info('updating participant status', { name: this.name, status });
10943
+ logger$3.info('updating participant status', { name: this.name, status });
10402
10944
 
10403
10945
  if (typeof status.audioMuted !== 'undefined' && status.audioMuted !== this.audioMuted) {
10404
10946
  if (status.audioMuted) {
@@ -10435,13 +10977,18 @@ class Participant extends Emitter {
10435
10977
  // Poor man's object comparison
10436
10978
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
10437
10979
  this.extra = { ...this.extra, ...status.extra };
10980
+
10981
+ if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
10982
+ this.extra.contact = new Contact(this.extra.contact);
10983
+ }
10984
+
10438
10985
  this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
10439
10986
  }
10440
10987
  }
10441
10988
 
10442
10989
  broadcastStatus(inboundStatus = null) {
10443
10990
  const status = inboundStatus || this.getStatus();
10444
- logger$2.info('broadcasting participant status', { callId: this.callId, status });
10991
+ logger$3.info('broadcasting participant status', { callId: this.callId, status });
10445
10992
 
10446
10993
  this.room.sendSignal({
10447
10994
  type: SIGNAL_TYPE_PARTICIPANT_UPDATE,
@@ -10462,18 +11009,24 @@ class RemoteParticipant extends Participant {
10462
11009
  }
10463
11010
  }
10464
11011
 
10465
- /* global document */
11012
+ //
11013
+
11014
+ class LocalParticipant extends Participant {
11015
+ }
11016
+
11017
+ //
10466
11018
 
10467
11019
  const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
10468
11020
  const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
10469
11021
 
10470
- const logger$1 = IssueReporter$1.loggerFor('sdk-room');
11022
+ const logger$2 = IssueReporter$1.loggerFor('sdk-room');
10471
11023
 
10472
11024
  class Room$1 extends Emitter {
10473
11025
 
10474
11026
 
10475
11027
 
10476
11028
 
11029
+
10477
11030
 
10478
11031
 
10479
11032
 
@@ -10495,6 +11048,8 @@ class Room$1 extends Emitter {
10495
11048
 
10496
11049
 
10497
11050
 
11051
+
11052
+
10498
11053
 
10499
11054
 
10500
11055
 
@@ -10512,6 +11067,7 @@ class Room$1 extends Emitter {
10512
11067
  * @param extension string
10513
11068
  * @param sourceId number
10514
11069
  * @param callId string
11070
+ * @param meetingUuid string
10515
11071
  * @param extra Object
10516
11072
  */
10517
11073
  constructor(
@@ -10519,15 +11075,17 @@ class Room$1 extends Emitter {
10519
11075
  extension ,
10520
11076
  sourceId ,
10521
11077
  callId ,
11078
+ meetingUuid ,
10522
11079
  extra = {},
10523
11080
  ) {
10524
11081
  super();
10525
- logger$1.info('room initialized', { callId, extension, sourceId });
11082
+ logger$2.info('room initialized', { callId, extension, sourceId, meetingUuid });
10526
11083
 
10527
11084
  // Represents the room callSession
10528
11085
  this.callSession = callSession;
10529
11086
  this.extension = extension;
10530
11087
  this.sourceId = sourceId;
11088
+ this.meetingUuid = meetingUuid;
10531
11089
  this.callId = callId;
10532
11090
  this.participants = [];
10533
11091
  this.connected = false;
@@ -10547,6 +11105,8 @@ class Room$1 extends Emitter {
10547
11105
  // Sugar syntax for `room.EVENT_NAME`
10548
11106
  this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
10549
11107
  this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
11108
+ this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
11109
+ this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
10550
11110
  this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
10551
11111
  this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
10552
11112
  this.ON_CHAT = Wazo.Phone.ON_CHAT;
@@ -10581,10 +11141,11 @@ class Room$1 extends Emitter {
10581
11141
  * @param audioOnly boolean
10582
11142
  * @param extra Object
10583
11143
  * @param room ?Room
11144
+ * @param meeting ?Meeting
10584
11145
  * @returns {Promise<Room>}
10585
11146
  */
10586
- static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
10587
- logger$1.info('connecting to room', { extension, audioOnly, room: !!room });
11147
+ static async connect({ extension, constraints, audioOnly = false, extra, room, meeting } ) {
11148
+ logger$2.info('connecting to room', { extension, audioOnly, room: !!room });
10588
11149
 
10589
11150
  if (!room) {
10590
11151
  await Wazo.Phone.connect();
@@ -10597,7 +11158,7 @@ class Room$1 extends Emitter {
10597
11158
 
10598
11159
  // Call_created is triggered before call_accepted, so we have to listen for it here.
10599
11160
  Wazo.Websocket.once(Wazo.Websocket.CALL_CREATED, ({ data }) => {
10600
- logger$1.info('room call received via WS', { callId: data.call_id });
11161
+ logger$2.info('room call received via WS', { callId: data.call_id });
10601
11162
  if (room) {
10602
11163
  room.setCallId(data.call_id);
10603
11164
  }
@@ -10618,34 +11179,44 @@ class Room$1 extends Emitter {
10618
11179
  room.setCallId(room.callSession.call.id);
10619
11180
  }
10620
11181
 
10621
- // Fetch conference source
10622
- const sources = await getApiClient().dird.fetchConferenceSource('default');
10623
- // Retrieve conference sources
10624
- const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
10625
- // Retrieve conference
10626
- const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
11182
+ if (!meeting) {
11183
+ // Fetch conference source
11184
+ const sources = await getApiClient().dird.fetchConferenceSource('default');
11185
+ // Retrieve conference sources
11186
+ const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
11187
+ // Retrieve conference
11188
+ const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
10627
11189
 
10628
- logger$1.info('connected to room', {
10629
- sourceId: conference ? conference.sourceId : null,
10630
- name: conference ? conference.name : null,
10631
- });
11190
+ logger$2.info('connected to room', {
11191
+ sourceId: conference ? conference.sourceId : null,
11192
+ name: conference ? conference.name : null,
11193
+ });
10632
11194
 
10633
- if (conference) {
10634
- room.setSourceId(conference.sourceId);
10635
- room.setName(conference.name);
11195
+ if (conference) {
11196
+ room.setSourceId(conference.sourceId);
11197
+ room.setName(conference.name);
11198
+ }
11199
+ } else if (meeting) {
11200
+ logger$2.info('Already connected to meeting', {
11201
+ uuid: meeting.uuid,
11202
+ name: meeting.name,
11203
+ });
11204
+
11205
+ room.setMeetingUuid(meeting.uuid);
11206
+ room.setName(meeting.name);
10636
11207
  }
10637
11208
 
10638
11209
  return room;
10639
11210
  }
10640
11211
 
10641
11212
  static disconnect() {
10642
- logger$1.info('static disconnection to room');
11213
+ logger$2.info('static disconnection to room');
10643
11214
 
10644
11215
  Wazo.Phone.disconnect();
10645
11216
  }
10646
11217
 
10647
11218
  async disconnect() {
10648
- logger$1.info('disconnection to room called');
11219
+ logger$2.info('disconnection to room called');
10649
11220
 
10650
11221
  await Wazo.Phone.hangup(this.callSession);
10651
11222
  this.callSession = null;
@@ -10660,20 +11231,24 @@ class Room$1 extends Emitter {
10660
11231
  Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10661
11232
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10662
11233
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10663
-
10664
- if (this.roomAudioElement && document.body) {
10665
- document.body.removeChild(this.roomAudioElement);
10666
- }
11234
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11235
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10667
11236
  }
10668
11237
 
10669
11238
  setSourceId(sourceId ) {
10670
- logger$1.info('set room source id', { sourceId });
11239
+ logger$2.info('set room source id', { sourceId });
10671
11240
 
10672
11241
  this.sourceId = sourceId;
10673
11242
  }
10674
11243
 
11244
+ setMeetingUuid(meetingUuid ) {
11245
+ logger$2.info('set meeting uuid', { meetingUuid });
11246
+
11247
+ this.meetingUuid = meetingUuid;
11248
+ }
11249
+
10675
11250
  setCallId(callId ) {
10676
- logger$1.info('set room call id', { callId });
11251
+ logger$2.info('set room call id', { callId });
10677
11252
 
10678
11253
  if (callId) {
10679
11254
  this.callId = callId;
@@ -10681,7 +11256,7 @@ class Room$1 extends Emitter {
10681
11256
  }
10682
11257
 
10683
11258
  setName(name ) {
10684
- logger$1.info('set room name', { name });
11259
+ logger$2.info('set room name', { name });
10685
11260
 
10686
11261
  this.name = name;
10687
11262
  }
@@ -10700,7 +11275,7 @@ class Room$1 extends Emitter {
10700
11275
  }
10701
11276
 
10702
11277
  async startScreenSharing(constraints ) {
10703
- logger$1.info('start room screen sharing', { constraints });
11278
+ logger$2.info('start room screen sharing', { constraints });
10704
11279
 
10705
11280
  const screensharingStream = await Wazo.Phone.startScreenSharing(constraints, this.callSession);
10706
11281
  if (!screensharingStream) {
@@ -10713,18 +11288,26 @@ class Room$1 extends Emitter {
10713
11288
  return screensharingStream;
10714
11289
  }
10715
11290
 
10716
- stopScreenSharing(restoreLocalStream = true) {
10717
- logger$1.info('stop room screen sharing');
11291
+ async stopScreenSharing(restoreLocalStream = true) {
11292
+ logger$2.info('stop room screen sharing');
10718
11293
 
10719
- Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
11294
+ const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
10720
11295
 
10721
11296
  if (this.localParticipant) {
10722
11297
  this.localParticipant.onStopScreensharing();
10723
11298
  }
11299
+
11300
+ if (!reinvited && this.localParticipant) {
11301
+ // When we had video and we made a screenshare we don't reinvite when stopping the screensahre
11302
+ // So not REINVITE even is fired, we have to restore the video stream manually
11303
+ const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
11304
+ // $FlowFixMe
11305
+ this._associateStreamTo(localVideoStream, this.localParticipant);
11306
+ }
10724
11307
  }
10725
11308
 
10726
11309
  turnCameraOff() {
10727
- logger$1.info('turn room camera off');
11310
+ logger$2.info('turn room camera off');
10728
11311
 
10729
11312
  Wazo.Phone.turnCameraOff(this.callSession);
10730
11313
 
@@ -10734,7 +11317,7 @@ class Room$1 extends Emitter {
10734
11317
  }
10735
11318
 
10736
11319
  turnCameraOn() {
10737
- logger$1.info('turn room camera on');
11320
+ logger$2.info('turn room camera on');
10738
11321
 
10739
11322
  Wazo.Phone.turnCameraOn(this.callSession);
10740
11323
 
@@ -10744,7 +11327,7 @@ class Room$1 extends Emitter {
10744
11327
  }
10745
11328
 
10746
11329
  mute() {
10747
- logger$1.info('mute room');
11330
+ logger$2.info('mute room');
10748
11331
 
10749
11332
  Wazo.Phone.mute(this.callSession);
10750
11333
 
@@ -10752,7 +11335,7 @@ class Room$1 extends Emitter {
10752
11335
  }
10753
11336
 
10754
11337
  unmute() {
10755
- logger$1.info('unmute room');
11338
+ logger$2.info('unmute room');
10756
11339
 
10757
11340
  Wazo.Phone.unmute(this.callSession);
10758
11341
 
@@ -10772,7 +11355,7 @@ class Room$1 extends Emitter {
10772
11355
  }
10773
11356
 
10774
11357
  hold() {
10775
- logger$1.info('hold room');
11358
+ logger$2.info('hold room');
10776
11359
 
10777
11360
  Wazo.Phone.hold(this.callSession, true);
10778
11361
 
@@ -10782,7 +11365,7 @@ class Room$1 extends Emitter {
10782
11365
  }
10783
11366
 
10784
11367
  resume() {
10785
- logger$1.info('resume room');
11368
+ logger$2.info('resume room');
10786
11369
 
10787
11370
  Wazo.Phone.resume(this.callSession, true);
10788
11371
 
@@ -10792,13 +11375,13 @@ class Room$1 extends Emitter {
10792
11375
  }
10793
11376
 
10794
11377
  sendDTMF(tone ) {
10795
- logger$1.info('send room DTMF', { tone });
11378
+ logger$2.info('send room DTMF', { tone });
10796
11379
 
10797
11380
  Wazo.Phone.sendDTMF(tone, this.callSession);
10798
11381
  }
10799
11382
 
10800
11383
  async sendReinvite(newConstraints = null) {
10801
- logger$1.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
11384
+ logger$2.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
10802
11385
  const wasScreensharing = this.localParticipant && this.localParticipant.screensharing;
10803
11386
 
10804
11387
  Wazo.Phone.on(Wazo.Phone.ON_SHARE_SCREEN_STARTED, () => {
@@ -10823,6 +11406,22 @@ class Room$1 extends Emitter {
10823
11406
  return response;
10824
11407
  }
10825
11408
 
11409
+ hasALocalVideoTrack() {
11410
+ return Wazo.Phone.hasALocalVideoTrack(this.callSession);
11411
+ }
11412
+
11413
+ getLocalStream() {
11414
+ return Wazo.Phone.getLocalStream(this.callSession);
11415
+ }
11416
+
11417
+ getRemoteStream() {
11418
+ return Wazo.Phone.getRemoteStream(this.callSession);
11419
+ }
11420
+
11421
+ getRemoteVideoStream() {
11422
+ return Wazo.Phone.getRemoteVideoStream(this.callSession);
11423
+ }
11424
+
10826
11425
  _bindEvents() {
10827
11426
  if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
10828
11427
  return;
@@ -10841,35 +11440,18 @@ class Room$1 extends Emitter {
10841
11440
  Wazo.Phone.phone.on(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10842
11441
 
10843
11442
  this.on(this.ON_AUDIO_STREAM, stream => {
10844
- logger$1.info('on room audio stream');
11443
+ logger$2.info('on room audio stream');
10845
11444
 
10846
11445
  this.audioStream = stream;
10847
- if (document.createElement) {
10848
- // $FlowFixMe
10849
- let roomAudioElement = document.getElementById('audio-room');
10850
- if (!this.roomAudioElement) {
10851
- roomAudioElement = document.createElement('audio');
10852
- // $FlowFixMe
10853
- document.body.appendChild(roomAudioElement);
10854
- }
10855
- if (!roomAudioElement) {
10856
- return;
10857
- }
10858
- this.roomAudioElement = roomAudioElement;
11446
+ if (!this.roomAudioElement) {
11447
+ const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11448
+ this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
10859
11449
  this.roomAudioElement.srcObject = stream;
10860
- this.roomAudioElement.autoplay = true;
10861
- this.roomAudioElement.id = 'audio-room';
10862
-
10863
- // $FlowFixMe
10864
- if (this.roomAudioElement.setSinkId) {
10865
- // $FlowFixMe
10866
- this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
10867
- }
10868
11450
  }
10869
11451
  });
10870
11452
 
10871
11453
  this.on(this.ON_VIDEO_STREAM, (stream, streamId, event, sipSession) => {
10872
- logger$1.info('on room video stream', { streamId });
11454
+ logger$2.info('on room video stream', { streamId });
10873
11455
 
10874
11456
  this._mapMsid(sipSession.body.body);
10875
11457
 
@@ -10884,7 +11466,7 @@ class Room$1 extends Emitter {
10884
11466
  });
10885
11467
 
10886
11468
  this.on(this.ON_REMOVE_STREAM, stream => {
10887
- logger$1.info('on room remove stream');
11469
+ logger$2.info('on room remove stream');
10888
11470
 
10889
11471
  const participant = this.participants.find(someParticipant =>
10890
11472
  someParticipant.streams.find(someStream => someStream && someStream.id === stream.id));
@@ -10939,6 +11521,9 @@ class Room$1 extends Emitter {
10939
11521
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10940
11522
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10941
11523
 
11524
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11525
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11526
+
10942
11527
  // Phone events
10943
11528
  Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
10944
11529
  Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
@@ -10949,15 +11534,15 @@ class Room$1 extends Emitter {
10949
11534
  Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
10950
11535
  }
10951
11536
 
10952
- _onMessage(message ) {
11537
+ _onMessage(message ) {
10953
11538
  if (message.method !== 'MESSAGE') {
10954
- return;
11539
+ return null;
10955
11540
  }
10956
11541
  let body;
10957
11542
  try {
10958
11543
  body = JSON.parse(message.body);
10959
11544
  } catch (e) {
10960
- return;
11545
+ return null;
10961
11546
  }
10962
11547
 
10963
11548
  switch (body.type) {
@@ -10976,6 +11561,8 @@ class Room$1 extends Emitter {
10976
11561
  }
10977
11562
 
10978
11563
  this.eventEmitter.emit(this.ON_MESSAGE, body);
11564
+
11565
+ return body;
10979
11566
  }
10980
11567
 
10981
11568
  _onChat(content ) {
@@ -11011,7 +11598,7 @@ class Room$1 extends Emitter {
11011
11598
  const requester = this._getParticipantFromCallId(origin.callId);
11012
11599
  if (requester) {
11013
11600
  // @FIXME?: when need to trigger an update on join-in; this is a bit of a hack
11014
- logger$1.info('trigger room requester status', { origin });
11601
+ logger$2.info('trigger room requester status', { origin });
11015
11602
  requester.triggerUpdate('REQUESTER_UPDATE');
11016
11603
  }
11017
11604
  break;
@@ -11040,25 +11627,26 @@ class Room$1 extends Emitter {
11040
11627
  const session = Wazo.Auth.getSession();
11041
11628
  let participants = [];
11042
11629
 
11043
- // @TODO: we could use a better function name here
11044
- const isJoining = part => {
11045
- this.__associateStreams(part);
11046
- // @VALIDATE: no need to publicize ourselves, no?
11047
- if (part instanceof RemoteParticipant) {
11048
- this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
11049
- }
11050
- };
11051
-
11052
11630
  // When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
11053
11631
  if (participant.user_uuid === session.uuid) {
11054
- logger$1.info('room current user joined');
11632
+ logger$2.info('room current user joined');
11055
11633
 
11056
11634
  // Retrieve participants via an API calls
11057
11635
  const conferenceId = this.sourceId || payload.data.conference_id;
11058
- const response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
11059
- logger$1.info('fetching conference participants', { conferenceId });
11636
+ let response;
11637
+ try {
11638
+ if (this.meetingUuid) {
11639
+ logger$2.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
11640
+ response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
11641
+ } else {
11642
+ logger$2.info('fetching conference participants', { conferenceId });
11643
+ response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
11644
+ }
11645
+ } catch (e) {
11646
+ logger$2.error('room participants fetching, error', e);
11647
+ }
11060
11648
  if (response) {
11061
- logger$1.info('conference participants fetched', { nb: response.items.length });
11649
+ logger$2.info('conference participants fetched', { nb: response.items.length });
11062
11650
  participants = response.items.map(item => {
11063
11651
  const isMe = item.call_id === this.callId;
11064
11652
 
@@ -11071,25 +11659,10 @@ class Room$1 extends Emitter {
11071
11659
 
11072
11660
  const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
11073
11661
  if (!this.localParticipant && localParticipant) {
11074
- this.localParticipant = localParticipant;
11075
-
11076
- const localVideoStream = this._getLocalVideoStream();
11077
- if (localVideoStream) {
11078
- this._saveLocalVideoStream(localVideoStream);
11079
- }
11080
-
11081
- this.connected = true;
11082
-
11083
- // we're in the room, now let's request everyone's status
11084
- if (this.localParticipant) {
11085
- this.sendSignal({
11086
- type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
11087
- origin: this.localParticipant.getStatus(),
11088
- });
11089
- }
11662
+ this._onLocalParticipantJoined(localParticipant);
11090
11663
  }
11091
11664
 
11092
- participants.forEach(someParticipant => isJoining(someParticipant));
11665
+ participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
11093
11666
  this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
11094
11667
  }
11095
11668
 
@@ -11100,16 +11673,45 @@ class Room$1 extends Emitter {
11100
11673
  ? new Wazo.RemoteParticipant(this, participant)
11101
11674
  : null;
11102
11675
 
11103
- logger$1.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
11676
+ logger$2.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
11104
11677
 
11105
11678
  if (remoteParticipant) {
11106
11679
  this.participants.push(remoteParticipant);
11107
- isJoining(remoteParticipant);
11680
+ this._isParticipantJoining(remoteParticipant);
11108
11681
  }
11109
11682
 
11110
11683
  return remoteParticipant;
11111
11684
  }
11112
11685
 
11686
+ _onLocalParticipantJoined(localParticipant ) {
11687
+ this.localParticipant = localParticipant;
11688
+
11689
+ const localVideoStream = this._getLocalVideoStream();
11690
+ if (localVideoStream) {
11691
+ this._saveLocalVideoStream(localVideoStream);
11692
+ }
11693
+
11694
+ this.connected = true;
11695
+
11696
+ localParticipant.broadcastStatus();
11697
+
11698
+ // we're in the room, now let's request everyone's status
11699
+ if (this.localParticipant) {
11700
+ this.sendSignal({
11701
+ type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
11702
+ origin: this.localParticipant.getStatus(),
11703
+ });
11704
+ }
11705
+ }
11706
+
11707
+ _isParticipantJoining(participant ) {
11708
+ this.__associateStreams(participant);
11709
+ // @VALIDATE: no need to publicize ourselves, no?
11710
+ if (participant instanceof RemoteParticipant) {
11711
+ this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
11712
+ }
11713
+ }
11714
+
11113
11715
  _saveLocalVideoStream(stream ) {
11114
11716
  const { localParticipant } = this;
11115
11717
 
@@ -11155,9 +11757,11 @@ class Room$1 extends Emitter {
11155
11757
  _onParticipantTrackUpdate(oldParticipant , update ) {
11156
11758
  const newParticipant = oldParticipant;
11157
11759
 
11158
- const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
11760
+ const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
11159
11761
  const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
11160
- const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
11762
+ // Can't use `getReceivers` here because on FF we make the mapping based on the streamId
11763
+ const stream = pc.getRemoteStreams().find(someStream =>
11764
+ someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
11161
11765
 
11162
11766
  if (update === 'downgrade') {
11163
11767
  newParticipant.streams = [];
@@ -11187,15 +11791,41 @@ class Room$1 extends Emitter {
11187
11791
  return;
11188
11792
  }
11189
11793
 
11190
- if (this._unassociatedVideoStreams[trackId]) {
11794
+ const streamId = this._getStreamIdFrTrackId(trackId);
11795
+ const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
11796
+ const stream = this._unassociatedVideoStreams[key];
11797
+
11798
+ if (stream) {
11191
11799
  // Try to associate stream
11192
- this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
11800
+ this._associateStreamTo(stream, participant);
11193
11801
 
11194
- delete this._unassociatedVideoStreams[trackId];
11802
+ delete this._unassociatedVideoStreams[key];
11195
11803
  delete this._unassociatedParticipants[participant.callId];
11196
11804
  }
11197
11805
  }
11198
11806
 
11807
+ _getUnassociatedMapIdFromTrackIdOrStreamId(trackId , streamId ) {
11808
+ // Find by trackId
11809
+ if (trackId in this._unassociatedVideoStreams) {
11810
+ return trackId;
11811
+ }
11812
+
11813
+ // Find by streamId
11814
+ if (streamId && streamId in this._unassociatedVideoStreams) {
11815
+ return streamId;
11816
+ }
11817
+
11818
+ // Find in all the streams by streamId (used on FF where we can't map by trackId)
11819
+ const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream ) => stream.id === streamId);
11820
+ return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
11821
+ }
11822
+
11823
+ _getStreamIdFrTrackId(trackId ) {
11824
+ const mapping = Object.values(this._callIdStreamIdMap).find((map ) => map.trackId === trackId);
11825
+
11826
+ return mapping ? mapping.streamId : null;
11827
+ }
11828
+
11199
11829
  _associateStreamTo(rawStream , participant ) {
11200
11830
  const stream = new Wazo.Stream(rawStream, participant);
11201
11831
  participant.streams.push(stream);
@@ -11219,7 +11849,141 @@ class Room$1 extends Emitter {
11219
11849
 
11220
11850
  //
11221
11851
 
11222
- class LocalParticipant extends Participant {
11852
+ const logger$1 = IssueReporter$1.loggerFor('sdk-sip-room');
11853
+
11854
+ class SipRoom extends Room$1 {
11855
+
11856
+ static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
11857
+ logger$1.info('connecting to sip room', { extension, audioOnly, room: !!room });
11858
+
11859
+ if (!room) {
11860
+ await Wazo.Phone.connect();
11861
+
11862
+ const withCamera = constraints && !!constraints.video;
11863
+
11864
+ const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
11865
+ // eslint-disable-next-line no-param-reassign
11866
+ room = new SipRoom(callSession, extension, null, null, extra);
11867
+ }
11868
+
11869
+ if (room && room.callSession && room.callSession.call) {
11870
+ room.setCallId(room.callSession.call.id);
11871
+ }
11872
+
11873
+ logger$1.info('connected to room', {
11874
+ extension: room.extension,
11875
+ });
11876
+
11877
+ return room;
11878
+ }
11879
+
11880
+ mute() {
11881
+ logger$1.info('mute sip room');
11882
+
11883
+ Wazo.Phone.mute(this.callSession, false);
11884
+
11885
+ this.sendMuteStatus();
11886
+ }
11887
+
11888
+ unmute() {
11889
+ logger$1.info('unmute sip room');
11890
+
11891
+ Wazo.Phone.unmute(this.callSession, false);
11892
+
11893
+ this.sendUnMuteStatus();
11894
+ }
11895
+
11896
+ getLocalGuestName() {
11897
+ return Wazo.Phone.phone.client.userAgent.options.displayName;
11898
+ }
11899
+
11900
+ // Overridden to not listen to websocket messages
11901
+ _transferEvents() {
11902
+ // Phone events
11903
+ Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
11904
+ Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
11905
+ Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
11906
+ Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
11907
+
11908
+ [this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
11909
+ Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
11910
+ }
11911
+
11912
+ _onMessage(message ) {
11913
+ // eslint-disable-next-line no-underscore-dangle
11914
+ const body = super._onMessage(message);
11915
+ if (!body) {
11916
+ return;
11917
+ }
11918
+
11919
+ const getChannel = () => body.channels[0];
11920
+
11921
+ switch (body.type) {
11922
+ case 'ConfbridgeWelcome':
11923
+ body.channels.forEach(channel => {
11924
+ this._onParticipantJoined(channel);
11925
+ });
11926
+
11927
+ break;
11928
+ case 'ConfbridgeJoin': {
11929
+ const channel = getChannel();
11930
+ this._onParticipantJoined(channel);
11931
+ break;
11932
+ }
11933
+ case 'ConfbridgeLeave': {
11934
+ const channel = getChannel();
11935
+ this._onParticipantLeft({
11936
+ data: {
11937
+ call_id: channel.id,
11938
+ },
11939
+ });
11940
+ break;
11941
+ }
11942
+ }
11943
+ }
11944
+
11945
+ async _onParticipantJoined(channel ) {
11946
+ const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
11947
+ const callId = channel.id;
11948
+ const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
11949
+ const name = channel.caller ? channel.caller.name : null;
11950
+ const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
11951
+ const participant = new ParticipantClass(this, {
11952
+ caller_id_name: name,
11953
+ call_id: callId,
11954
+ }, extra);
11955
+
11956
+ const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
11957
+ if (participantIdx !== -1 && name) {
11958
+ this.participants[participantIdx].name = name;
11959
+ return;
11960
+ }
11961
+
11962
+ if (isLocal) {
11963
+ // Should be updated by the Wazo WS but we don't have it for now
11964
+ if (this.callSession) {
11965
+ this.callSession.ringing = false;
11966
+ }
11967
+
11968
+ this._onLocalParticipantJoined(participant);
11969
+
11970
+ // Give some time for the stream to be updated
11971
+ setTimeout(() => {
11972
+ this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
11973
+ }, 1000);
11974
+ }
11975
+
11976
+ this.participants.push(participant);
11977
+
11978
+ this._isParticipantJoining(participant);
11979
+
11980
+ return participant;
11981
+ }
11982
+
11983
+ _getCurrentSipCallIs() {
11984
+ return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11985
+ }
11986
+
11223
11987
  }
11224
11988
 
11225
11989
  /* global document */
@@ -11272,9 +12036,7 @@ class Stream {
11272
12036
  return false;
11273
12037
  }
11274
12038
 
11275
- // With canvas track (used to fake upgrade in conference), we don't have a width
11276
- return this.htmlStream.getTracks().find(track => track.kind === 'video'
11277
- && track.readyState !== 'ended' && 'width' in track.getSettings());
12039
+ return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
11278
12040
  }
11279
12041
 
11280
12042
  get id() {
@@ -12175,6 +12937,7 @@ const Wazo = {
12175
12937
  Phone: Phone$1,
12176
12938
  Websocket: Websocket$1,
12177
12939
  Room: Room$1,
12940
+ SipRoom,
12178
12941
  RemoteParticipant,
12179
12942
  LocalParticipant,
12180
12943
  Stream,
@@ -12194,6 +12957,7 @@ const Wazo = {
12194
12957
  ServerError,
12195
12958
  Call,
12196
12959
  CallLog,
12960
+ CTIPhone,
12197
12961
  Recording,
12198
12962
  ChatMessage,
12199
12963
  ChatRoom,
@@ -12209,6 +12973,8 @@ const Wazo = {
12209
12973
  CallSession,
12210
12974
  IndirectTransfer,
12211
12975
  SwitchboardCall,
12976
+ WebRTCPhone,
12977
+ Meeting,
12212
12978
  },
12213
12979
 
12214
12980
  // Api