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