@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
@@ -1809,7 +1809,13 @@ class IssueReporter {
1809
1809
  }
1810
1810
 
1811
1811
  _isLevelAbove(level1 , level2 ) {
1812
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
1812
+ const index1 = LOG_LEVELS.indexOf(level1);
1813
+ const index2 = LOG_LEVELS.indexOf(level2);
1814
+ if (index1 === -1 || index2 === -1) {
1815
+ return false;
1816
+ }
1817
+
1818
+ return index1 > index2;
1813
1819
  }
1814
1820
 
1815
1821
  _makeCategory(category ) {
@@ -1832,7 +1838,7 @@ var IssueReporter$1 = new IssueReporter();
1832
1838
 
1833
1839
  const methods = ['head', 'get', 'post', 'put', 'delete'];
1834
1840
 
1835
- const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1841
+ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1836
1842
 
1837
1843
  // Use a function here to be able to mock it in tests
1838
1844
  const realFetch = () => {
@@ -1971,7 +1977,7 @@ class ApiRequester {
1971
1977
  };
1972
1978
 
1973
1979
  if (this.refreshTokenPromise) {
1974
- logger$a.info('A token is already refreshing, waiting ...', { url });
1980
+ logger$c.info('A token is already refreshing, waiting ...', { url });
1975
1981
  await this.refreshTokenPromise;
1976
1982
  }
1977
1983
 
@@ -1991,7 +1997,7 @@ class ApiRequester {
1991
1997
  return promise.then(async (err ) => {
1992
1998
  // Check if the token is still valid
1993
1999
  if (firstCall && this._checkTokenExpired(response, err)) {
1994
- logger$a.warn('token expired', { error: err.reason });
2000
+ logger$c.warn('token expired', { error: err.reason });
1995
2001
  // Replay the call after refreshing the token
1996
2002
  return this._replayWithNewToken(err, path, method, body, headers, parse);
1997
2003
  }
@@ -2001,7 +2007,7 @@ class ApiRequester {
2001
2007
  : exceptionClass.fromResponse(err, response.status);
2002
2008
 
2003
2009
  if (this.shouldLogErrors) {
2004
- logger$a.error('API error', error);
2010
+ logger$c.error('API error', error);
2005
2011
  }
2006
2012
 
2007
2013
  throw error;
@@ -2011,7 +2017,7 @@ class ApiRequester {
2011
2017
  return newParse(response, isJson);
2012
2018
  }).catch(error => {
2013
2019
  if (this.shouldLogErrors) {
2014
- logger$a.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
2020
+ logger$c.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
2015
2021
  }
2016
2022
 
2017
2023
  throw error;
@@ -2039,13 +2045,13 @@ class ApiRequester {
2039
2045
  ) {
2040
2046
  const isTokenNotFound = this._isTokenNotFound(err);
2041
2047
  let newPath = path;
2042
- logger$a.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
2048
+ logger$c.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
2043
2049
 
2044
2050
  this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
2045
2051
 
2046
2052
  return this.refreshTokenPromise.then(() => {
2047
2053
  this.refreshTokenPromise = null;
2048
- logger$a.info('token refreshed', { isTokenNotFound });
2054
+ logger$c.info('token refreshed', { isTokenNotFound });
2049
2055
  if (isTokenNotFound) {
2050
2056
  const pathParts = path.split('/');
2051
2057
  pathParts.pop();
@@ -2506,6 +2512,65 @@ class ExternalApp {
2506
2512
  }
2507
2513
  }
2508
2514
 
2515
+ //
2516
+
2517
+
2518
+
2519
+
2520
+
2521
+
2522
+
2523
+
2524
+
2525
+
2526
+
2527
+ class Meeting {
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+
2538
+ static parse(plain ) {
2539
+ return new Meeting({
2540
+ guestSipAuthorization: plain.guest_sip_authorization,
2541
+ hostname: plain.hostname,
2542
+ name: plain.name,
2543
+ ownerUuids: plain.owner_uuids,
2544
+ port: plain.port,
2545
+ uuid: plain.uuid,
2546
+ number: plain.number,
2547
+ });
2548
+ }
2549
+
2550
+ static newFrom(meeting ) {
2551
+ return newFrom(meeting, Meeting);
2552
+ }
2553
+
2554
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2555
+ this.guestSipAuthorization = guestSipAuthorization;
2556
+ this.hostname = hostname;
2557
+ this.name = name;
2558
+ this.ownerUuids = ownerUuids;
2559
+ this.port = port;
2560
+ this.uuid = uuid;
2561
+ this.number = number;
2562
+
2563
+ // Useful to compare instead of instanceof with minified code
2564
+ this.type = 'Meeting';
2565
+ }
2566
+
2567
+ getGuestSipCredentials() {
2568
+ // eslint-disable-next-line no-undef
2569
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2570
+ return { username, secret };
2571
+ }
2572
+ }
2573
+
2509
2574
  /* */
2510
2575
 
2511
2576
  var confdMethods = (client , baseUrl ) => ({
@@ -2570,6 +2635,18 @@ var confdMethods = (client , baseUrl ) => ({
2570
2635
  return null;
2571
2636
  }
2572
2637
  },
2638
+
2639
+ createMyMeeting: (name ) =>
2640
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2641
+
2642
+ deleteMyMeeting: (meetingUuid ) =>
2643
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2644
+
2645
+ getMeeting: (meetingUuid ) =>
2646
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2647
+
2648
+ guestGetMeeting: (meetingUuid ) =>
2649
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2573
2650
  });
2574
2651
 
2575
2652
  //
@@ -3327,7 +3404,7 @@ class CallSession {
3327
3404
  return newFrom(callSession, CallSession);
3328
3405
  }
3329
3406
 
3330
- static parseCall(session , call ) {
3407
+ static parseCall(call ) {
3331
3408
  return new CallSession({
3332
3409
  callId: call.id,
3333
3410
  sipCallId: call.sipCallId,
@@ -3512,7 +3589,11 @@ class CallLog {
3512
3589
  answered: plain.answered,
3513
3590
  callDirection: plain.call_direction,
3514
3591
  destination: {
3515
- extension: plain.requested_extension || plain.destination_extension,
3592
+ // @TEMP: Temporarily assuming empty numbers are meetings
3593
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3594
+ extension: plain.requested_extension
3595
+ || plain.destination_extension
3596
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3516
3597
  name: plain.requested_name || plain.destination_name || '',
3517
3598
  },
3518
3599
  source: {
@@ -3528,27 +3609,11 @@ class CallLog {
3528
3609
  }
3529
3610
 
3530
3611
  static parseNew(plain , session ) {
3531
- return new CallLog({
3532
- answer: plain.answer ? moment(plain.answer).toDate() : null,
3533
- answered: plain.answered,
3534
- callDirection: plain.call_direction,
3535
- destination: {
3536
- extension: plain.requested_extension || plain.destination_extension,
3537
- name: plain.requested_name || plain.destination_name || '',
3538
- },
3539
- source: {
3540
- extension: plain.source_extension,
3541
- name: plain.source_name,
3542
- },
3543
- id: plain.id,
3544
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3545
- start: moment(plain.start).toDate(),
3546
- end: plain.end ? moment(plain.end).toDate() : null,
3547
- recordings: Recording.parseMany(plain.recordings),
3548
- // @TODO: FIXME add verification declined vs missed call
3549
- newMissedCall: session
3550
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3551
- });
3612
+ const callLog = CallLog.parse(plain);
3613
+ // @TODO: FIXME add verification declined vs missed call
3614
+ callLog.newMissedCall = session
3615
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3616
+ return callLog;
3552
3617
  }
3553
3618
 
3554
3619
  static newFrom(profile ) {
@@ -3708,29 +3773,432 @@ class IndirectTransfer {
3708
3773
  });
3709
3774
  }
3710
3775
 
3711
- destinationIs(callSession ) {
3712
- return callSession.isId(this.destinationId);
3776
+ destinationIs(callSession ) {
3777
+ return callSession.isId(this.destinationId);
3778
+ }
3779
+
3780
+ sourceIs(callSession ) {
3781
+ return callSession.isId(this.sourceId);
3782
+ }
3783
+
3784
+ updateFrom(indirectTransfer ) {
3785
+ updateFrom(this, indirectTransfer);
3786
+ }
3787
+
3788
+ static newFrom(indirectTransfer ) {
3789
+ return newFrom(indirectTransfer, IndirectTransfer);
3790
+ }
3791
+ }
3792
+
3793
+ //
3794
+
3795
+ class CallApi {
3796
+ static async fetchCallLogs(offset , limit ) {
3797
+ return getApiClient().callLogd.listCallLogs(offset, limit);
3798
+ }
3799
+
3800
+ static async fetchDistinctCallLogs(offset , limit , distinct = 'peer_exten') {
3801
+ return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
3802
+ }
3803
+
3804
+ static async fetchActiveCalls() {
3805
+ return getApiClient().calld.listCalls();
3806
+ }
3807
+
3808
+ static async fetchCallLogsFromDate(from , number ) {
3809
+ return getApiClient().callLogd.listCallLogsFromDate(from, number);
3810
+ }
3811
+
3812
+ static async search(query , limit ) {
3813
+ return getApiClient().callLogd.search(query, limit);
3814
+ }
3815
+
3816
+ static async searchBy(field , value , limit ) {
3817
+ return getApiClient().callLogd.searchBy(field, value, limit);
3818
+ }
3819
+
3820
+ static async fetchSIP(session , line ) {
3821
+ const lineToUse = line || session.primaryLine();
3822
+ return getApiClient().confd.getUserLineSip(session.uuid, lineToUse ? lineToUse.id : null);
3823
+ }
3824
+
3825
+ static async cancelCall(callSession ) {
3826
+ return getApiClient().calld.cancelCall(callSession.callId);
3827
+ }
3828
+
3829
+ static async makeCall(callFromLine , extension , isMobile = false,
3830
+ callbackAllLines = false) {
3831
+ const lineId = callFromLine ? callFromLine.id : null;
3832
+
3833
+ const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
3834
+ return Call.parse(response);
3835
+ }
3836
+
3837
+ static async relocateCall(callId , line , contactIdentifier ) {
3838
+ return getApiClient().calld.relocateCall(callId, 'line', line, contactIdentifier);
3839
+ }
3840
+
3841
+ static async hold(callId ) {
3842
+ return getApiClient().calld.hold(callId);
3843
+ }
3844
+
3845
+ static async resume(callId ) {
3846
+ return getApiClient().calld.resume(callId);
3847
+ }
3848
+
3849
+ static async mute(callId ) {
3850
+ return getApiClient().calld.mute(callId);
3851
+ }
3852
+
3853
+ static async sendDTMF(callId , digits ) {
3854
+ return getApiClient().calld.sendDTMF(callId, digits);
3855
+ }
3856
+
3857
+ static async unmute(callId ) {
3858
+ return getApiClient().calld.unmute(callId);
3859
+ }
3860
+
3861
+ static async transferCall(callId , number , flow ) {
3862
+ return getApiClient().calld.transferCall(callId, number, flow);
3863
+ }
3864
+
3865
+ static async cancelCallTransfer(transferId ) {
3866
+ return getApiClient().calld.cancelCallTransfer(transferId);
3867
+ }
3868
+
3869
+ static async confirmCallTransfer(transferId ) {
3870
+ return getApiClient().calld.confirmCallTransfer(transferId);
3871
+ }
3872
+ }
3873
+
3874
+ //
3875
+
3876
+ const TRANSFER_FLOW_ATTENDED = 'attended';
3877
+ const TRANSFER_FLOW_BLIND = 'blind';
3878
+
3879
+ // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
3880
+
3881
+ const logger$b = IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
3882
+
3883
+ class CTIPhone extends Emitter {
3884
+
3885
+
3886
+
3887
+
3888
+
3889
+
3890
+
3891
+
3892
+ constructor(session , isMobile = false, callbackAllLines = false) {
3893
+ super();
3894
+ logger$b.info('CTI Phone created');
3895
+ this.session = session;
3896
+ this.isMobile = isMobile;
3897
+ this.callbackAllLines = callbackAllLines;
3898
+ }
3899
+
3900
+ getOptions() {
3901
+ // @FIXME: temporarily disabling this option
3902
+ // const hold = this.session.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD);
3903
+
3904
+ return {
3905
+ accept: false,
3906
+ decline: true,
3907
+ mute: true,
3908
+ hold: false,
3909
+ transfer: true,
3910
+ sendKey: true,
3911
+ addParticipant: false,
3912
+ record: true,
3913
+ merge: false,
3914
+ };
3915
+ }
3916
+
3917
+ hasAnActiveCall() {
3918
+ return !!this.currentCall;
3919
+ }
3920
+
3921
+ callCount() {
3922
+ return this.currentCall ? 1 : 0;
3923
+ }
3924
+
3925
+ isWebRTC() {
3926
+ return false;
3927
+ }
3928
+
3929
+ getUserAgent() {
3930
+ return 'cti-phone';
3931
+ }
3932
+
3933
+ startHeartbeat() {
3934
+ }
3935
+
3936
+ setOnHeartbeatTimeout() {
3937
+ }
3938
+
3939
+ setOnHeartbeatCallback() {
3940
+ }
3941
+
3942
+ stopHeartbeat() {
3943
+ }
3944
+
3945
+ bindClientEvents() {
3946
+ }
3947
+
3948
+ onConnect() {
3949
+ }
3950
+
3951
+ onDisconnect() {
3952
+ }
3953
+
3954
+ async makeCall(number , line ) {
3955
+ logger$b.info('make CTI call', { number });
3956
+
3957
+ if (!number) {
3958
+ return null;
3959
+ }
3960
+ try {
3961
+ this.currentCall = await CallApi.makeCall(line, number, this.isMobile, this.callbackAllLines);
3962
+ } catch (_) {
3963
+ // We have to deal with error like `User has no mobile phone number` error in the UI.
3964
+ }
3965
+ if (!this.currentCall) {
3966
+ return null;
3967
+ }
3968
+ const callSession = CallSession.parseCall(this.currentCall);
3969
+ this.eventEmitter.emit('onCallOutgoing', callSession);
3970
+
3971
+ return callSession;
3972
+ }
3973
+
3974
+ accept(callSession ) {
3975
+ if (!callSession) {
3976
+ return Promise.resolve(null);
3977
+ }
3978
+ logger$b.info('accept CTI call', { callId: callSession.getId(), number: callSession.number });
3979
+
3980
+ if (!this.currentCall) {
3981
+ this.currentCall = callSession.call;
3982
+ }
3983
+
3984
+ return Promise.resolve(callSession.getId());
3985
+ }
3986
+
3987
+ endCurrentCall(callSession ) {
3988
+ if (!callSession) {
3989
+ return;
3990
+ }
3991
+ logger$b.info('end current CTI call', { callId: callSession.getId(), number: callSession.number });
3992
+
3993
+ this.currentCall = undefined;
3994
+ this.eventEmitter.emit('onCallEnded', callSession);
3995
+ }
3996
+
3997
+ async hangup(callSession ) {
3998
+ if (!callSession) {
3999
+ return Promise.resolve(false);
4000
+ }
4001
+ logger$b.info('hangup CTI call', { callId: callSession.getId(), number: callSession.number });
4002
+
4003
+ try {
4004
+ await CallApi.cancelCall(callSession);
4005
+ if (this.currentCall && callSession.callId === this.currentCall.id) {
4006
+ this.endCurrentCall(callSession);
4007
+ }
4008
+
4009
+ this.eventEmitter.emit('onCallEnded', callSession);
4010
+ return true;
4011
+ } catch (e) {
4012
+ logger$b.error('hangup CTI call, error', e);
4013
+
4014
+ this.eventEmitter.emit('onCallFailed', callSession);
4015
+ return false;
4016
+ }
4017
+ }
4018
+
4019
+ ignore() {}
4020
+
4021
+ async reject(callSession ) {
4022
+ if (!callSession) {
4023
+ return;
4024
+ }
4025
+ logger$b.info('reject CTI call', { callId: callSession.getId(), number: callSession.number });
4026
+
4027
+ await CallApi.cancelCall(callSession);
4028
+ this.eventEmitter.emit('onCallEnded', callSession);
4029
+ }
4030
+
4031
+ async transfer(callSession , number ) {
4032
+ if (!callSession) {
4033
+ return;
4034
+ }
4035
+ logger$b.info('transfer CTI call', { callId: callSession.getId(), number: callSession.number, to: number });
4036
+
4037
+ await CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_BLIND);
4038
+ }
4039
+
4040
+ indirectTransfer() {}
4041
+
4042
+ async initiateCTIIndirectTransfer(callSession , number ) {
4043
+ if (!callSession) {
4044
+ return;
4045
+ }
4046
+ logger$b.info('indirect CTI transfer', { callId: callSession.getId(), number: callSession.number, to: number });
4047
+
4048
+ return CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_ATTENDED);
4049
+ }
4050
+
4051
+ async cancelCTIIndirectTransfer(transferId ) {
4052
+ logger$b.info('cancel CTI transfer', { transferId });
4053
+
4054
+ return CallApi.cancelCallTransfer(transferId);
4055
+ }
4056
+
4057
+ async confirmCTIIndirectTransfer(transferId ) {
4058
+ logger$b.info('confirm CTI transfer', { transferId });
4059
+
4060
+ return CallApi.confirmCallTransfer(transferId);
4061
+ }
4062
+
4063
+ sendKey(callSession , digits ) {
4064
+ if (!callSession) {
4065
+ return;
4066
+ }
4067
+ logger$b.info('send CTI key', { callId: callSession.getId(), number: callSession.number, digits });
4068
+
4069
+ return CallApi.sendDTMF(callSession.callId, digits);
4070
+ }
4071
+
4072
+ onConnectionMade() {
4073
+ logger$b.info('on CTI connection made');
4074
+
4075
+ this.eventEmitter.emit('onCallAccepted');
4076
+ }
4077
+
4078
+ async close() {
4079
+ logger$b.info('CTI close');
4080
+
4081
+ return Promise.resolve();
4082
+ }
4083
+
4084
+ async hold(callSession ) {
4085
+ if (!callSession) {
4086
+ return;
4087
+ }
4088
+ logger$b.info('CTI hold', { callId: callSession.getId(), number: callSession.number });
4089
+
4090
+ return CallApi.hold(callSession.callId);
4091
+ }
4092
+
4093
+ async resume(callSession ) {
4094
+ if (!callSession) {
4095
+ return;
4096
+ }
4097
+ logger$b.info('CTI resume', { callId: callSession.getId(), number: callSession.number });
4098
+
4099
+ return CallApi.resume(callSession.callId);
4100
+ }
4101
+
4102
+ async mute(callSession ) {
4103
+ if (!callSession) {
4104
+ return;
4105
+ }
4106
+ logger$b.info('CTI mute', { callId: callSession.getId(), number: callSession.number });
4107
+
4108
+ return CallApi.mute(callSession.callId);
4109
+ }
4110
+
4111
+ async unmute(callSession ) {
4112
+ if (!callSession) {
4113
+ return;
4114
+ }
4115
+ logger$b.info('CTI unmute', { callId: callSession.getId(), number: callSession.number });
4116
+
4117
+ return CallApi.unmute(callSession.callId);
4118
+ }
4119
+
4120
+ putOnSpeaker() {}
4121
+
4122
+ putOffSpeaker() {}
4123
+
4124
+ turnCameraOff() {}
4125
+
4126
+ turnCameraOn() {}
4127
+
4128
+ changeAudioInputDevice() {}
4129
+
4130
+ changeVideoInputDevice() {}
4131
+
4132
+ changeAudioDevice() {}
4133
+
4134
+ changeRingDevice() {}
4135
+
4136
+ changeAudioVolume() {}
4137
+
4138
+ changeRingVolume() {}
4139
+
4140
+ hasVideo() {
4141
+ return false;
4142
+ }
4143
+
4144
+ getLocalStreamForCall() {
4145
+ return null;
4146
+ }
4147
+
4148
+ getRemoteStreamForCall() {
4149
+ return null;
4150
+ }
4151
+
4152
+ getLocalVideoStream() {
4153
+ return null;
4154
+ }
4155
+
4156
+ setActiveSipSession() {}
4157
+
4158
+ isRegistered() {
4159
+ return true;
4160
+ }
4161
+
4162
+ hasIncomingCallSession() {
4163
+ return true;
4164
+ }
4165
+
4166
+ hasActiveRemoteVideoStream() {
4167
+ return false;
4168
+ }
4169
+
4170
+ getCurrentCallSession() {
4171
+ return this.currentCall ? CallSession.parseCall(this.currentCall) : null;
4172
+ }
4173
+
4174
+ enableRinging() {}
4175
+
4176
+ sendMessage() {}
4177
+
4178
+ disableRinging() {}
4179
+
4180
+ getLocalStream() {
4181
+ return null;
3713
4182
  }
3714
4183
 
3715
- sourceIs(callSession ) {
3716
- return callSession.isId(this.sourceId);
4184
+ getRemoteStream() {
4185
+ return null;
3717
4186
  }
3718
4187
 
3719
- updateFrom(indirectTransfer ) {
3720
- updateFrom(this, indirectTransfer);
4188
+ getRemoteVideoStream() {
4189
+ return null;
3721
4190
  }
3722
4191
 
3723
- static newFrom(indirectTransfer ) {
3724
- return newFrom(indirectTransfer, IndirectTransfer);
4192
+ getRemoteAudioStream() {
4193
+ return null;
3725
4194
  }
3726
- }
3727
-
3728
- //
3729
- const TRANSFER_FLOW_BLIND = 'blind';
3730
4195
 
3731
- // const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
4196
+ hasLocalVideo() {
4197
+ return false;
4198
+ }
3732
4199
 
3733
- IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
4200
+ useLocalVideoElement() {}
4201
+ }
3734
4202
 
3735
4203
  /* */
3736
4204
 
@@ -4290,6 +4758,9 @@ var calldMethods = (client , baseUrl ) => ({
4290
4758
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4291
4759
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4292
4760
 
4761
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4762
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4763
+
4293
4764
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4294
4765
 
4295
4766
  mute: (callId ) =>
@@ -4643,7 +5114,7 @@ const AGENTD_VERSION = '1.0';
4643
5114
  const WEBHOOKD_VERSION = '1.0';
4644
5115
  const AMID_VERSION = '1.0';
4645
5116
 
4646
- const logger$9 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
5117
+ const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
4647
5118
 
4648
5119
  class ApiClient {
4649
5120
 
@@ -4695,12 +5166,12 @@ class ApiClient {
4695
5166
  }
4696
5167
 
4697
5168
  async forceRefreshToken() {
4698
- logger$9.info('forcing refresh token, calling callback');
5169
+ logger$a.info('forcing refresh token, calling callback');
4699
5170
  return this.refreshTokenCallback();
4700
5171
  }
4701
5172
 
4702
5173
  async refreshTokenCallback() {
4703
- logger$9.info('refresh token callback called', {
5174
+ logger$a.info('refresh token callback called', {
4704
5175
  refreshToken: this.refreshToken,
4705
5176
  refreshBackend: this.refreshBackend,
4706
5177
  refreshExpiration: this.refreshExpiration,
@@ -4718,7 +5189,7 @@ class ApiClient {
4718
5189
  this.isMobile,
4719
5190
  );
4720
5191
 
4721
- logger$9.info('token refreshed', { token: session.token });
5192
+ logger$a.info('token refreshed', { token: session.token });
4722
5193
 
4723
5194
  if (this.onRefreshToken) {
4724
5195
  this.onRefreshToken(session.token, session);
@@ -5191,7 +5662,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5191
5662
  .then(() => {
5192
5663
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5193
5664
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5194
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5665
+ if (this.peerConnection.addTransceiver) {
5666
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5667
+ }
5195
5668
  }
5196
5669
  })
5197
5670
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5218,12 +5691,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5218
5691
  };
5219
5692
  })
5220
5693
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5221
- .then((sessionDescription) => {
5222
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5223
- this.localMediaStreamConstraints = options.constraints;
5224
-
5225
- return sessionDescription;
5226
- })
5227
5694
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5228
5695
  .catch((error) => {
5229
5696
  wazoLogger.error('error when creating media', error);
@@ -5418,6 +5885,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5418
5885
 
5419
5886
  // set the transceiver direction to the answer direction
5420
5887
  this._peerConnection.getTransceivers().forEach((transceiver) => {
5888
+ if (transceiver.stopped) {
5889
+ return;
5890
+ }
5421
5891
  if (transceiver.direction /* guarding, but should always be true */) {
5422
5892
  const { receiver } = transceiver;
5423
5893
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5462,10 +5932,15 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5462
5932
  if (kind !== 'audio' && kind !== 'video') {
5463
5933
  throw new Error(`Unknown new track kind ${kind}.`);
5464
5934
  }
5465
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
5935
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
5936
+ otherSender.track && otherSender.track.kind === kind);
5466
5937
 
5467
5938
  // Do not reuse sender video tracks in SFU
5468
5939
  if (sender && (!sfu || newTrack.kind === 'audio')) {
5940
+ if (sender.track) {
5941
+ // eslint-disable-next-line no-param-reassign
5942
+ newTrack.enabled = sender.track.enabled;
5943
+ }
5469
5944
  trackUpdates.push(
5470
5945
  new Promise((resolve) => {
5471
5946
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5499,7 +5974,11 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5499
5974
  // Review: could make streamless tracks a configurable option?
5500
5975
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5501
5976
  try {
5502
- pc.addTrack(newTrack, localStream);
5977
+ if (pc.addTrack) {
5978
+ pc.addTrack(newTrack, localStream);
5979
+ } else {
5980
+ pc.addStream(localStream);
5981
+ }
5503
5982
  } catch (error) {
5504
5983
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5505
5984
  throw error;
@@ -5635,7 +6114,7 @@ const DEFAULT_ICE_TIMEOUT = 3000;
5635
6114
  const SEND_STATS_DELAY = 5000;
5636
6115
 
5637
6116
  const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
5638
- const logger$8 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
6117
+ const logger$9 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
5639
6118
  const statsLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-stats') : console;
5640
6119
 
5641
6120
  // events
@@ -5681,6 +6160,7 @@ const MAX_REGISTER_TRIES = 10;
5681
6160
 
5682
6161
 
5683
6162
 
6163
+
5684
6164
 
5685
6165
 
5686
6166
 
@@ -5707,6 +6187,7 @@ class WebRTCClient extends Emitter {
5707
6187
 
5708
6188
 
5709
6189
 
6190
+
5710
6191
 
5711
6192
  // sugar
5712
6193
 
@@ -5745,6 +6226,8 @@ class WebRTCClient extends Emitter {
5745
6226
  super();
5746
6227
  this.uaConfigOverrides = uaConfigOverrides;
5747
6228
  this.config = config;
6229
+ this.skipRegister = config.skipRegister;
6230
+
5748
6231
  this._buildConfig(config, session).then((newConfig ) => {
5749
6232
  this.config = newConfig;
5750
6233
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5800,13 +6283,13 @@ class WebRTCClient extends Emitter {
5800
6283
 
5801
6284
  createUserAgent(configOverrides ) {
5802
6285
  const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
5803
- logger$8.info('sdk webrtc, creating UA', { webRTCConfiguration });
6286
+ logger$9.info('sdk webrtc, creating UA', { webRTCConfiguration });
5804
6287
 
5805
6288
  webRTCConfiguration.delegate = {
5806
6289
  onConnect: this.onConnect.bind(this),
5807
6290
  onDisconnect: this.onDisconnect.bind(this),
5808
6291
  onInvite: (invitation ) => {
5809
- logger$8.info('sdk webrtc on invite', {
6292
+ logger$9.info('sdk webrtc on invite', {
5810
6293
  method: 'delegate.onInvite',
5811
6294
  id: invitation.id,
5812
6295
  remoteURI: invitation.remoteURI,
@@ -5849,7 +6332,7 @@ class WebRTCClient extends Emitter {
5849
6332
  }
5850
6333
 
5851
6334
  onConnect() {
5852
- logger$8.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6335
+ logger$9.info('sdk webrtc connected', { method: 'delegate.onConnect' });
5853
6336
  this.eventEmitter.emit(CONNECTED);
5854
6337
  if (!this.isRegistered() && this.registerer && this.registerer.waiting) {
5855
6338
  this.registerer.waitingToggle(false);
@@ -5858,7 +6341,7 @@ class WebRTCClient extends Emitter {
5858
6341
  }
5859
6342
 
5860
6343
  async onDisconnect(error ) {
5861
- logger$8.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6344
+ logger$9.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
5862
6345
  this.connectionPromise = null;
5863
6346
  // The UA will attempt to reconnect automatically when an error occurred
5864
6347
  this.eventEmitter.emit(DISCONNECTED, error);
@@ -5872,40 +6355,48 @@ class WebRTCClient extends Emitter {
5872
6355
  }
5873
6356
 
5874
6357
  register(tries = 0) {
5875
- logger$8.info('sdk webrtc registering...', {
6358
+ const logInfo = {
5876
6359
  userAgent: !!this.userAgent,
5877
6360
  registered: this.isRegistered(),
5878
6361
  connectionPromise: !!this.connectionPromise,
5879
6362
  registerer: !!this.registerer,
5880
6363
  waiting: this.registerer && this.registerer.waiting,
5881
6364
  tries,
5882
- });
6365
+ skipRegister: this.skipRegister,
6366
+ };
6367
+
6368
+ if (this.skipRegister) {
6369
+ logger$9.info('sdk webrtc skip register...', logInfo);
6370
+ return Promise.resolve();
6371
+ }
6372
+
6373
+ logger$9.info('sdk webrtc registering...', logInfo);
5883
6374
 
5884
6375
  if (!this.userAgent) {
5885
- logger$8.info('sdk webrtc recreating User Agent');
6376
+ logger$9.info('sdk webrtc recreating User Agent');
5886
6377
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
5887
6378
  }
5888
6379
  if (!this.userAgent || this.isRegistered()) {
5889
- logger$8.info('sdk webrtc registering aborted, already registered or no UA can be created');
6380
+ logger$9.info('sdk webrtc registering aborted, already registered or no UA can be created');
5890
6381
  return Promise.resolve();
5891
6382
  }
5892
6383
 
5893
6384
  if (this.connectionPromise || (this.registerer && this.registerer.waiting)) {
5894
- logger$8.info('sdk webrtc registering aborted due to a registration in progress.');
6385
+ logger$9.info('sdk webrtc registering aborted due to a registration in progress.');
5895
6386
  return Promise.resolve();
5896
6387
  }
5897
6388
 
5898
6389
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
5899
6390
 
5900
6391
  const onRegisterFailed = () => {
5901
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6392
+ logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
5902
6393
  this.connectionPromise = null;
5903
6394
  if (this.registerer && this.registerer.waiting) {
5904
6395
  this.registerer.waitingToggle(false);
5905
6396
  }
5906
6397
 
5907
6398
  if (tries <= MAX_REGISTER_TRIES) {
5908
- logger$8.info('sdk webrtc registering, retrying...', { tries });
6399
+ logger$9.info('sdk webrtc registering, retrying...', { tries });
5909
6400
  setTimeout(() => this.register(tries + 1), 300);
5910
6401
  }
5911
6402
  };
@@ -5914,18 +6405,18 @@ class WebRTCClient extends Emitter {
5914
6405
  // Avoid race condition with the close method called just before register and setting userAgent to null
5915
6406
  // during the resolution of the primise.
5916
6407
  if (!this.userAgent) {
5917
- logger$8.info('sdk webrtc recreating User Agent after connection');
6408
+ logger$9.info('sdk webrtc recreating User Agent after connection');
5918
6409
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
5919
6410
  }
5920
6411
 
5921
- logger$8.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6412
+ logger$9.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
5922
6413
  this.registerer = new Registerer(this.userAgent, registerOptions);
5923
6414
  this.connectionPromise = null;
5924
6415
  this._monkeyPatchRegisterer(this.registerer);
5925
6416
 
5926
6417
  // Bind registerer events
5927
6418
  this.registerer.stateChange.addListener(newState => {
5928
- logger$8.info('sdk webrtc registering, state changed', { newState });
6419
+ logger$9.info('sdk webrtc registering, state changed', { newState });
5929
6420
 
5930
6421
  if (newState === RegistererState.Registered && this.registerer
5931
6422
  && this.registerer.state === RegistererState.Registered) {
@@ -5938,7 +6429,7 @@ class WebRTCClient extends Emitter {
5938
6429
  const options = {
5939
6430
  requestDelegate: {
5940
6431
  onReject: response => {
5941
- logger$8.error('sdk webrtc registering, rejected', { response });
6432
+ logger$9.error('sdk webrtc registering, rejected', { response });
5942
6433
 
5943
6434
  onRegisterFailed();
5944
6435
  },
@@ -5946,13 +6437,13 @@ class WebRTCClient extends Emitter {
5946
6437
  };
5947
6438
 
5948
6439
  return this.registerer.register(options).catch((e) => {
5949
- logger$8.error('sdk webrtc registering, error', e);
6440
+ logger$9.error('sdk webrtc registering, error', e);
5950
6441
 
5951
6442
  this.eventEmitter.emit(REGISTRATION_FAILED);
5952
6443
  return e;
5953
6444
  });
5954
6445
  }).catch(error => {
5955
- logger$8.error('sdk webrtc registering, transport error', error);
6446
+ logger$9.error('sdk webrtc registering, transport error', error);
5956
6447
  onRegisterFailed();
5957
6448
  });
5958
6449
  }
@@ -5981,21 +6472,21 @@ class WebRTCClient extends Emitter {
5981
6472
  }
5982
6473
 
5983
6474
  unregister() {
5984
- logger$8.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6475
+ logger$9.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
5985
6476
  if (!this.registerer) {
5986
6477
  return Promise.resolve();
5987
6478
  }
5988
6479
 
5989
6480
  try {
5990
6481
  return this.registerer.unregister().then(() => {
5991
- logger$8.info('sdk webrtc unregistered');
6482
+ logger$9.info('sdk webrtc unregistered');
5992
6483
  this._cleanupRegister();
5993
6484
  }).catch(e => {
5994
- logger$8.error('sdk webrtc unregistering, promise error', e);
6485
+ logger$9.error('sdk webrtc unregistering, promise error', e);
5995
6486
  this._cleanupRegister();
5996
6487
  });
5997
6488
  } catch (e) {
5998
- logger$8.error('sdk webrtc unregistering, error', e);
6489
+ logger$9.error('sdk webrtc unregistering, error', e);
5999
6490
  // Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
6000
6491
  // error when the registerer is in a bad state
6001
6492
  this._cleanupRegister();
@@ -6003,7 +6494,7 @@ class WebRTCClient extends Emitter {
6003
6494
  }
6004
6495
 
6005
6496
  stop() {
6006
- logger$8.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6497
+ logger$9.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6007
6498
  if (!this.userAgent) {
6008
6499
  return Promise.resolve();
6009
6500
  }
@@ -6011,12 +6502,12 @@ class WebRTCClient extends Emitter {
6011
6502
  return this.userAgent.stop().then(() => {
6012
6503
  return this._cleanupRegister();
6013
6504
  }).catch(e => {
6014
- logger$8.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6505
+ logger$9.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6015
6506
  });
6016
6507
  }
6017
6508
 
6018
6509
  call(number , enableVideo , audioOnly = false, conference = false) {
6019
- logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6510
+ logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6020
6511
  const inviterOptions = {
6021
6512
  sessionDescriptionHandlerOptionsReInvite: {
6022
6513
  conference,
@@ -6045,7 +6536,7 @@ class WebRTCClient extends Emitter {
6045
6536
  this._onAccepted(session, response.session, true);
6046
6537
  },
6047
6538
  onReject: (response ) => {
6048
- logger$8.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6539
+ logger$9.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6049
6540
  this._stopSendingStats(session);
6050
6541
 
6051
6542
  this.eventEmitter.emit(REJECTED, session, response);
@@ -6067,11 +6558,11 @@ class WebRTCClient extends Emitter {
6067
6558
  }
6068
6559
 
6069
6560
  answer(session , enableVideo ) {
6070
- logger$8.info('sdk webrtc answer call', { id: session.id, enableVideo });
6561
+ logger$9.info('sdk webrtc answer call', { id: session.id, enableVideo });
6071
6562
 
6072
6563
  if (!session || !session.accept) {
6073
6564
  const error = 'No session to answer, or not an invitation';
6074
- logger$8.warn(error);
6565
+ logger$9.warn(error);
6075
6566
  return Promise.reject(new Error(error));
6076
6567
  }
6077
6568
  const options = {
@@ -6081,15 +6572,15 @@ class WebRTCClient extends Emitter {
6081
6572
  return session.accept(options).then(() => {
6082
6573
  if (session.isCanceled) {
6083
6574
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
6084
- logger$8.error(message, { id: session.id });
6575
+ logger$9.error(message, { id: session.id });
6085
6576
  this.onCallEnded(session);
6086
6577
 
6087
6578
  throw new CanceledCallError(message);
6088
6579
  }
6089
- logger$8.info('sdk webrtc answer, accepted.');
6580
+ logger$9.info('sdk webrtc answer, accepted.');
6090
6581
  this._onAccepted(session);
6091
6582
  }).catch(e => {
6092
- logger$8.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6583
+ logger$9.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6093
6584
 
6094
6585
  throw e;
6095
6586
  });
@@ -6097,7 +6588,7 @@ class WebRTCClient extends Emitter {
6097
6588
 
6098
6589
  hangup(session ) {
6099
6590
  const { state, id } = session;
6100
- logger$8.info('sdk webrtc hangup call', { id, state });
6591
+ logger$9.info('sdk webrtc hangup call', { id, state });
6101
6592
 
6102
6593
  try {
6103
6594
  this._stopSendingStats(session);
@@ -6126,24 +6617,24 @@ class WebRTCClient extends Emitter {
6126
6617
 
6127
6618
  return bye();
6128
6619
  } catch (error) {
6129
- logger$8.warn('sdk webrtc hangup, error', error);
6620
+ logger$9.warn('sdk webrtc hangup, error', error);
6130
6621
  }
6131
6622
 
6132
6623
  return null;
6133
6624
  }
6134
6625
 
6135
6626
  reject(session ) {
6136
- logger$8.info('sdk webrtc reject call', { id: session.id });
6627
+ logger$9.info('sdk webrtc reject call', { id: session.id });
6137
6628
 
6138
6629
  try {
6139
6630
  return session.reject ? session.reject() : session.cancel();
6140
6631
  } catch (e) {
6141
- logger$8.warn('Error when rejecting call', e.message, e.stack);
6632
+ logger$9.warn('Error when rejecting call', e.message, e.stack);
6142
6633
  }
6143
6634
  }
6144
6635
 
6145
6636
  async close() {
6146
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6637
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6147
6638
  this._cleanupMedia();
6148
6639
  this.connectionPromise = null;
6149
6640
 
@@ -6174,7 +6665,7 @@ class WebRTCClient extends Emitter {
6174
6665
  // eg: "INVITE not rejectable in state Completed"
6175
6666
  }
6176
6667
  this.userAgent = null;
6177
- logger$8.info('sdk webrtc client closed');
6668
+ logger$9.info('sdk webrtc client closed');
6178
6669
  }
6179
6670
 
6180
6671
  getNumber(session ) {
@@ -6187,13 +6678,13 @@ class WebRTCClient extends Emitter {
6187
6678
  }
6188
6679
 
6189
6680
  mute(session ) {
6190
- logger$8.info('sdk webrtc mute', { id: session.id });
6681
+ logger$9.info('sdk webrtc mute', { id: session.id });
6191
6682
 
6192
6683
  this._toggleAudio(session, true);
6193
6684
  }
6194
6685
 
6195
6686
  unmute(session ) {
6196
- logger$8.info('sdk webrtc unmute', { id: session.id });
6687
+ logger$9.info('sdk webrtc unmute', { id: session.id });
6197
6688
 
6198
6689
  this._toggleAudio(session, false);
6199
6690
  }
@@ -6210,12 +6701,18 @@ class WebRTCClient extends Emitter {
6210
6701
  }
6211
6702
 
6212
6703
  if (pc.getSenders) {
6704
+ if (!pc.getSenders().length) {
6705
+ return false;
6706
+ }
6213
6707
  pc.getSenders().forEach(sender => {
6214
6708
  if (sender && sender.track && sender.track.kind === 'audio') {
6215
6709
  muted = muted && !sender.track.enabled;
6216
6710
  }
6217
6711
  });
6218
6712
  } else {
6713
+ if (!pc.getLocalStreams().length) {
6714
+ return false;
6715
+ }
6219
6716
  pc.getLocalStreams().forEach(stream => {
6220
6717
  stream.getAudioTracks().forEach(track => {
6221
6718
  muted = muted && !track.enabled;
@@ -6227,20 +6724,20 @@ class WebRTCClient extends Emitter {
6227
6724
  }
6228
6725
 
6229
6726
  toggleCameraOn(session ) {
6230
- logger$8.info('sdk webrtc toggle camera on', { id: session.id });
6727
+ logger$9.info('sdk webrtc toggle camera on', { id: session.id });
6231
6728
 
6232
6729
  this._toggleVideo(session, false);
6233
6730
  }
6234
6731
 
6235
6732
  toggleCameraOff(session ) {
6236
- logger$8.info('sdk webrtc toggle camera off', { id: session.id });
6733
+ logger$9.info('sdk webrtc toggle camera off', { id: session.id });
6237
6734
 
6238
6735
  this._toggleVideo(session, true);
6239
6736
  }
6240
6737
 
6241
6738
  hold(session , isConference = false) {
6242
6739
  const sessionId = this.getSipSessionId(session);
6243
- logger$8.info('sdk webrtc hold', {
6740
+ logger$9.info('sdk webrtc hold', {
6244
6741
  sessionId,
6245
6742
  keys: Object.keys(this.heldSessions),
6246
6743
  pendingReinvite: !!session.pendingReinvite,
@@ -6272,6 +6769,9 @@ class WebRTCClient extends Emitter {
6272
6769
  if (!this._isWeb()) {
6273
6770
  options.sessionDescriptionHandlerModifiers = [holdModifier];
6274
6771
  }
6772
+ options.sessionDescriptionHandlerOptions = {
6773
+ constraints: options.constraints,
6774
+ };
6275
6775
 
6276
6776
  // Send re-INVITE
6277
6777
  return session.invite(options);
@@ -6280,7 +6780,7 @@ class WebRTCClient extends Emitter {
6280
6780
  unhold(session , isConference = false) {
6281
6781
  const sessionId = this.getSipSessionId(session);
6282
6782
 
6283
- logger$8.info('sdk webrtc unhold', {
6783
+ logger$9.info('sdk webrtc unhold', {
6284
6784
  sessionId,
6285
6785
  keys: Object.keys(this.heldSessions),
6286
6786
  pendingReinvite: !!session.pendingReinvite,
@@ -6311,6 +6811,9 @@ class WebRTCClient extends Emitter {
6311
6811
  // (eg: holdModifier)
6312
6812
  options.sessionDescriptionHandlerModifiers = [];
6313
6813
  }
6814
+ options.sessionDescriptionHandlerOptions = {
6815
+ constraints: options.constraints,
6816
+ };
6314
6817
 
6315
6818
  // Send re-INVITE
6316
6819
  return session.invite(options);
@@ -6368,7 +6871,7 @@ class WebRTCClient extends Emitter {
6368
6871
  return;
6369
6872
  }
6370
6873
 
6371
- logger$8.info('send WebRTC message', { sipId: sipSession.id, contentType });
6874
+ logger$9.info('send WebRTC message', { sipId: sipSession.id, contentType });
6372
6875
 
6373
6876
  try {
6374
6877
  sipSession.message({
@@ -6493,7 +6996,8 @@ class WebRTCClient extends Emitter {
6493
6996
  }
6494
6997
  const sdh = session.sessionDescriptionHandler;
6495
6998
  const pc = sdh.peerConnection;
6496
- const localStream = this.getLocalStream(this.getSipSessionId(session));
6999
+ const sessionId = this.getSipSessionId(session);
7000
+ const localStream = this.getLocalStream(sessionId);
6497
7001
 
6498
7002
  // Release old video stream
6499
7003
  if (localStream) {
@@ -6519,11 +7023,8 @@ class WebRTCClient extends Emitter {
6519
7023
 
6520
7024
  // let's update the local stream
6521
7025
  this.eventEmitter.emit('onVideoInputChange', stream);
6522
- try {
6523
- await sdh.setLocalMediaStream(stream);
6524
- } catch (_) {
6525
- // Nothing to do
6526
- }
7026
+ this.setLocalMediaStream(sessionId, stream);
7027
+
6527
7028
  return stream;
6528
7029
  });
6529
7030
  }
@@ -6735,7 +7236,7 @@ class WebRTCClient extends Emitter {
6735
7236
  }
6736
7237
 
6737
7238
  startHeartbeat() {
6738
- logger$8.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7239
+ logger$9.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
6739
7240
  if (!this.userAgent) {
6740
7241
  this.heartbeat.stop();
6741
7242
  return;
@@ -6748,7 +7249,7 @@ class WebRTCClient extends Emitter {
6748
7249
  }
6749
7250
 
6750
7251
  stopHeartbeat() {
6751
- logger$8.info('sdk webrtc stop heartbeat');
7252
+ logger$9.info('sdk webrtc stop heartbeat');
6752
7253
  this.heartbeat.stop();
6753
7254
  }
6754
7255
 
@@ -6768,7 +7269,7 @@ class WebRTCClient extends Emitter {
6768
7269
  }
6769
7270
 
6770
7271
  attemptReconnection() {
6771
- logger$8.info('attempt reconnection', { userAgent: !!this.userAgent });
7272
+ logger$9.info('attempt reconnection', { userAgent: !!this.userAgent });
6772
7273
  if (!this.userAgent) {
6773
7274
  return;
6774
7275
  }
@@ -6825,9 +7326,11 @@ class WebRTCClient extends Emitter {
6825
7326
  remoteStream.removeTrack(track);
6826
7327
  });
6827
7328
 
6828
- pc.getReceivers().forEach(receiver => {
6829
- remoteStream.addTrack(receiver.track);
6830
- });
7329
+ if (pc.getReceivers) {
7330
+ pc.getReceivers().forEach(receiver => {
7331
+ remoteStream.addTrack(receiver.track);
7332
+ });
7333
+ }
6831
7334
  }
6832
7335
 
6833
7336
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6862,6 +7365,25 @@ class WebRTCClient extends Emitter {
6862
7365
  return sessionId in this.conferences;
6863
7366
  }
6864
7367
 
7368
+ createAudioElementFor(sessionId ) {
7369
+ const audio = document.createElement('audio');
7370
+ audio.setAttribute('id', `audio-${sessionId}`);
7371
+
7372
+ if (audio.setSinkId && this.audioOutputDeviceId) {
7373
+ audio.setSinkId(this.audioOutputDeviceId);
7374
+ }
7375
+
7376
+ if (document.body) {
7377
+ document.body.appendChild(audio);
7378
+ }
7379
+ this.audioElements[sessionId] = audio;
7380
+
7381
+ audio.volume = this.audioOutputVolume;
7382
+ audio.autoplay = true;
7383
+
7384
+ return audio;
7385
+ }
7386
+
6865
7387
  _onTransportError() {
6866
7388
  this.eventEmitter.emit(TRANSPORT_ERROR);
6867
7389
  this.attemptReconnection();
@@ -6871,7 +7393,7 @@ class WebRTCClient extends Emitter {
6871
7393
  const body = message && typeof message === 'object' ? message.data : message;
6872
7394
  if (body && body.indexOf('200 OK') !== -1) {
6873
7395
  if (this.hasHeartbeat()) {
6874
- logger$8.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7396
+ logger$9.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
6875
7397
 
6876
7398
  this.heartbeat.onHeartbeat();
6877
7399
  if (this.heartbeatCb) {
@@ -6882,7 +7404,7 @@ class WebRTCClient extends Emitter {
6882
7404
  }
6883
7405
 
6884
7406
  async _onHeartbeatTimeout() {
6885
- logger$8.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7407
+ logger$9.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
6886
7408
 
6887
7409
  if (this.heartbeatTimeoutCb) {
6888
7410
  this.heartbeatTimeoutCb();
@@ -6894,7 +7416,7 @@ class WebRTCClient extends Emitter {
6894
7416
  try {
6895
7417
  await this.userAgent.transport.disconnect();
6896
7418
  } catch (e) {
6897
- logger$8.error('Transport disconnection after heartbeat timeout, error', e);
7419
+ logger$9.error('Transport disconnection after heartbeat timeout, error', e);
6898
7420
  }
6899
7421
  }
6900
7422
 
@@ -6927,31 +7449,31 @@ class WebRTCClient extends Emitter {
6927
7449
  }
6928
7450
 
6929
7451
  _connectIfNeeded() {
6930
- logger$8.info('connect if needed, checking', { connected: this.isConnected() });
7452
+ logger$9.info('connect if needed, checking', { connected: this.isConnected() });
6931
7453
  if (!this.userAgent) {
6932
- logger$8.info('need to recreate User Agent');
7454
+ logger$9.info('need to recreate User Agent');
6933
7455
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6934
7456
  }
6935
7457
 
6936
7458
  if (this.isConnected()) {
6937
- logger$8.info('webrtc sdk, already connected');
7459
+ logger$9.info('webrtc sdk, already connected');
6938
7460
  return Promise.resolve();
6939
7461
  }
6940
7462
 
6941
7463
  if (this.isConnecting()) {
6942
- logger$8.info('webrtc sdk, already connecting...');
7464
+ logger$9.info('webrtc sdk, already connecting...');
6943
7465
 
6944
7466
  this.connectionPromise = this.userAgent.transport.connectPromise;
6945
7467
  return this.connectionPromise;
6946
7468
  }
6947
7469
 
6948
7470
  if (this.connectionPromise) {
6949
- logger$8.info('webrtc sdk, connection promise connecting...');
7471
+ logger$9.info('webrtc sdk, connection promise connecting...');
6950
7472
  // $FlowFixMe
6951
7473
  return this.connectionPromise;
6952
7474
  }
6953
7475
 
6954
- logger$8.info('WebRTC UA needs to connect');
7476
+ logger$9.info('WebRTC UA needs to connect');
6955
7477
 
6956
7478
  // Force UA to reconnect
6957
7479
  if (this.userAgent && this.userAgent.state !== UserAgentState.Stopped) {
@@ -7076,7 +7598,7 @@ class WebRTCClient extends Emitter {
7076
7598
 
7077
7599
  sdh.peerConnectionDelegate = {
7078
7600
  onicecandidateerror: (error ) => {
7079
- logger$8.error('on icecandidate error', {
7601
+ logger$9.error('on icecandidate error', {
7080
7602
  address: error.address,
7081
7603
  port: error.port,
7082
7604
  errorCode: error.errorCode,
@@ -7091,7 +7613,7 @@ class WebRTCClient extends Emitter {
7091
7613
  let hadRemoteVideo = false;
7092
7614
 
7093
7615
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7094
- // Becase when `onInvite` is called we already got the video track
7616
+ // Because when `onInvite` is called we already got the video track
7095
7617
  session.onInviteRequest = (request) => {
7096
7618
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7097
7619
 
@@ -7105,7 +7627,7 @@ class WebRTCClient extends Emitter {
7105
7627
  updatedNumber = session.assertedIdentity.uri.normal.user;
7106
7628
  updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
7107
7629
  }
7108
- logger$8.info('re-invite received', { updatedCalleeName, updatedNumber });
7630
+ logger$9.info('re-invite received', { updatedCalleeName, updatedNumber });
7109
7631
 
7110
7632
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
7111
7633
 
@@ -7126,7 +7648,7 @@ class WebRTCClient extends Emitter {
7126
7648
  }
7127
7649
 
7128
7650
  _onAccepted(session , sessionDialog , withEvent = true) {
7129
- logger$8.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7651
+ logger$9.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7130
7652
 
7131
7653
  this.storeSipSession(session);
7132
7654
 
@@ -7166,20 +7688,10 @@ class WebRTCClient extends Emitter {
7166
7688
  const isConference = this.isConference(sessionId);
7167
7689
 
7168
7690
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7169
- const audio = document.createElement('audio');
7170
- audio.setAttribute('id', `audio-${sessionId}`);
7171
-
7172
- if (audio.setSinkId && this.audioOutputDeviceId) {
7173
- audio.setSinkId(this.audioOutputDeviceId);
7174
- }
7175
-
7176
- if (document.body) {
7177
- document.body.appendChild(audio);
7178
- }
7179
- this.audioElements[sessionId] = audio;
7691
+ this.createAudioElementFor(sessionId);
7180
7692
  }
7181
7693
 
7182
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7694
+ const audioElement = this.audioElements[sessionId];
7183
7695
  const stream = newStream || this.getRemoteStream(sessionId);
7184
7696
 
7185
7697
  if (!this._isWeb() || !stream) {
@@ -7326,10 +7838,10 @@ class WebRTCClient extends Emitter {
7326
7838
 
7327
7839
  _stopSendingStats(session ) {
7328
7840
  const sessionId = this.getSipSessionId(session);
7329
- logger$8.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7841
+ logger$9.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7330
7842
 
7331
7843
  if (sessionId in this.statsIntervals) {
7332
- logger$8.trace('Stop sending stats for call', { sessionId });
7844
+ logger$9.trace('Stop sending stats for call', { sessionId });
7333
7845
  this.statsIntervals[sessionId]();
7334
7846
  delete this.statsIntervals[sessionId];
7335
7847
  }
@@ -7345,7 +7857,7 @@ class WebRTCClient extends Emitter {
7345
7857
  try {
7346
7858
  await this.userAgent.transport.disconnect();
7347
7859
  } catch (e) {
7348
- logger$8.error('WebRTC transport disconnect, error', e);
7860
+ logger$9.error('WebRTC transport disconnect, error', e);
7349
7861
  }
7350
7862
  }
7351
7863
  }
@@ -7432,7 +7944,7 @@ const events = [
7432
7944
  ON_SIGNAL,
7433
7945
  ];
7434
7946
 
7435
- const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
7947
+ const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
7436
7948
 
7437
7949
  class WebRTCPhone extends Emitter {
7438
7950
 
@@ -7503,7 +8015,7 @@ class WebRTCPhone extends Emitter {
7503
8015
  }).catch(error => {
7504
8016
  // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
7505
8017
  console.error('register error', error, error.message, error.stack);
7506
- logger$7.error('WebRTC register error', { message: error.message, stack: error.stack });
8018
+ logger$8.error('WebRTC register error', { message: error.message, stack: error.stack });
7507
8019
  });
7508
8020
  }
7509
8021
 
@@ -7518,7 +8030,7 @@ class WebRTCPhone extends Emitter {
7518
8030
  if (!this.client) {
7519
8031
  return;
7520
8032
  }
7521
- logger$7.info('WebRTC phone stop');
8033
+ logger$8.info('WebRTC phone stop');
7522
8034
  this.client.stop();
7523
8035
  }
7524
8036
 
@@ -7533,14 +8045,14 @@ class WebRTCPhone extends Emitter {
7533
8045
  async sendReinvite(callSession , constraints = null, conference = false,
7534
8046
  audioOnly = false) {
7535
8047
  const sipSession = this.findSipSession(callSession);
7536
- logger$7.info('WebRTC phone - send reinvite', {
8048
+ logger$8.info('WebRTC phone - send reinvite', {
7537
8049
  sessionId: sipSession ? sipSession.id : null,
7538
8050
  constraints,
7539
8051
  audioOnly,
7540
8052
  });
7541
8053
 
7542
8054
  if (!sipSession) {
7543
- return null;
8055
+ return false;
7544
8056
  }
7545
8057
 
7546
8058
  // $FlowFixMe
@@ -7550,19 +8062,17 @@ class WebRTCPhone extends Emitter {
7550
8062
  // Downgrade
7551
8063
  if (constraints && !isUpgrade) {
7552
8064
  // No reinvite needed
7553
- return this._downgradeToAudio(callSession);
8065
+ this._downgradeToAudio(callSession);
8066
+ return false;
7554
8067
  }
7555
8068
 
7556
8069
  if (isUpgrade) {
7557
8070
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
7558
8071
  if (!shouldReinvite) {
7559
- return;
8072
+ return false;
7560
8073
  }
7561
8074
  }
7562
8075
 
7563
- // Force reinvite in SDH
7564
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
7565
-
7566
8076
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
7567
8077
  }
7568
8078
 
@@ -7571,7 +8081,7 @@ class WebRTCPhone extends Emitter {
7571
8081
  }
7572
8082
 
7573
8083
  startHeartbeat() {
7574
- logger$7.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
8084
+ logger$8.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
7575
8085
  if (!this.client || this.client.hasHeartbeat()) {
7576
8086
  return;
7577
8087
  }
@@ -7580,7 +8090,7 @@ class WebRTCPhone extends Emitter {
7580
8090
  }
7581
8091
 
7582
8092
  stopHeartbeat() {
7583
- logger$7.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
8093
+ logger$8.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
7584
8094
  if (!this.client) {
7585
8095
  return;
7586
8096
  }
@@ -7597,7 +8107,7 @@ class WebRTCPhone extends Emitter {
7597
8107
  }
7598
8108
 
7599
8109
  reconnect() {
7600
- logger$7.info('WebRTC phone - reconnect', { client: !!this.client });
8110
+ logger$8.info('WebRTC phone - reconnect', { client: !!this.client });
7601
8111
  if (!this.client) {
7602
8112
  return;
7603
8113
  }
@@ -7635,7 +8145,7 @@ class WebRTCPhone extends Emitter {
7635
8145
  _downgradeToAudio(callSession ) {
7636
8146
  const sipSession = this.findSipSession(callSession);
7637
8147
  if (!sipSession) {
7638
- return;
8148
+ return false;
7639
8149
  }
7640
8150
 
7641
8151
  // Release local video stream when downgrading to audio
@@ -7748,7 +8258,7 @@ class WebRTCPhone extends Emitter {
7748
8258
  // Monkey patch to know when canceled with the CANCEL message
7749
8259
  const onCancel = sipSession._onCancel.bind(sipSession);
7750
8260
  sipSession._onCancel = (message ) => {
7751
- logger$7.trace('on sip session canceled', { callId: message.callId });
8261
+ logger$8.trace('on sip session canceled', { callId: message.callId });
7752
8262
 
7753
8263
  onCancel(message);
7754
8264
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
@@ -7773,13 +8283,13 @@ class WebRTCPhone extends Emitter {
7773
8283
  this.audioOutputVolume,
7774
8284
  );
7775
8285
  case SessionState.Terminating:
7776
- logger$7.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8286
+ logger$8.info('WebRTC phone - call terminating', { sipId: sipSession.id });
7777
8287
 
7778
8288
  this.eventEmitter.emit(ON_CALL_ENDING, this._createCallSession(sipSession));
7779
8289
 
7780
8290
  break;
7781
8291
  case SessionState.Terminated:
7782
- logger$7.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8292
+ logger$8.info('WebRTC phone - call terminated', { sipId: sipSession.id });
7783
8293
 
7784
8294
  this._onCallTerminated(sipSession);
7785
8295
 
@@ -7815,7 +8325,7 @@ class WebRTCPhone extends Emitter {
7815
8325
  }
7816
8326
 
7817
8327
  async startScreenSharing(constraints , callSession ) {
7818
- logger$7.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8328
+ logger$8.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
7819
8329
 
7820
8330
  const screenShareStream = await this._getStreamFromConstraints(constraints);
7821
8331
  if (!screenShareStream) {
@@ -7837,6 +8347,10 @@ class WebRTCPhone extends Emitter {
7837
8347
  localStream.removeTrack(videoTrack);
7838
8348
  }
7839
8349
 
8350
+ if (localStream) {
8351
+ localStream.addTrack(screenTrack);
8352
+ }
8353
+
7840
8354
  if (sender) {
7841
8355
  sender.replaceTrack(screenTrack);
7842
8356
  }
@@ -7851,7 +8365,8 @@ class WebRTCPhone extends Emitter {
7851
8365
  return;
7852
8366
  }
7853
8367
 
7854
- logger$7.info('WebRTC phone - stop screen sharing');
8368
+ logger$8.info('WebRTC phone - stop screen sharing');
8369
+ let reinvited = false;
7855
8370
 
7856
8371
  try {
7857
8372
  if (this.currentScreenShare.stream) {
@@ -7866,7 +8381,8 @@ class WebRTCPhone extends Emitter {
7866
8381
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
7867
8382
  // We have to downgrade to audio.
7868
8383
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
7869
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
8384
+ const constraints = { audio: false, video: screenshareStopped };
8385
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
7870
8386
  }
7871
8387
  } catch (e) {
7872
8388
  console.warn(e);
@@ -7880,6 +8396,8 @@ class WebRTCPhone extends Emitter {
7880
8396
  );
7881
8397
 
7882
8398
  this.currentScreenShare = null;
8399
+
8400
+ return reinvited;
7883
8401
  }
7884
8402
 
7885
8403
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -7917,7 +8435,7 @@ class WebRTCPhone extends Emitter {
7917
8435
  }
7918
8436
 
7919
8437
  _onCallAccepted(sipSession , cameraEnabled ) {
7920
- logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8438
+ logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
7921
8439
 
7922
8440
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
7923
8441
  this.currentSipSession = sipSession;
@@ -7935,11 +8453,15 @@ class WebRTCPhone extends Emitter {
7935
8453
  }
7936
8454
 
7937
8455
  changeAudioDevice(id ) {
7938
- logger$7.info('WebRTC phone - change audio device', { deviceId: id });
8456
+ logger$8.info('WebRTC phone - change audio device', { deviceId: id });
7939
8457
  this.audioOutputDeviceId = id;
7940
8458
  this.client.changeAudioOutputDevice(id);
7941
8459
  }
7942
8460
 
8461
+ createAudioElementFor(sessionId ) {
8462
+ return this.client.createAudioElementFor(sessionId);
8463
+ }
8464
+
7943
8465
  changeRingDevice(id ) {
7944
8466
  this.audioRingDeviceId = id;
7945
8467
  }
@@ -7956,25 +8478,25 @@ class WebRTCPhone extends Emitter {
7956
8478
  }
7957
8479
 
7958
8480
  changeAudioInputDevice(id ) {
7959
- logger$7.info('WebRTC phone - changeAudio input device', { deviceId: id });
8481
+ logger$8.info('WebRTC phone - changeAudio input device', { deviceId: id });
7960
8482
 
7961
8483
  return this.client.changeAudioInputDevice(id, this.currentSipSession);
7962
8484
  }
7963
8485
 
7964
8486
  changeVideoInputDevice(id ) {
7965
- logger$7.info('WebRTC phone - change video input device', { deviceId: id });
8487
+ logger$8.info('WebRTC phone - change video input device', { deviceId: id });
7966
8488
 
7967
8489
  return this.client.changeVideoInputDevice(id, this.currentSipSession);
7968
8490
  }
7969
8491
 
7970
8492
  changeSessionVideoInputDevice(id ) {
7971
- logger$7.info('WebRTC phone - change session video input device', { deviceId: id });
8493
+ logger$8.info('WebRTC phone - change session video input device', { deviceId: id });
7972
8494
 
7973
8495
  return this.client.changeSessionVideoInputDevice(id, this.currentSipSession);
7974
8496
  }
7975
8497
 
7976
8498
  _onCallTerminated(sipSession ) {
7977
- logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8499
+ logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
7978
8500
 
7979
8501
  const callSession = this._createCallSession(sipSession);
7980
8502
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
@@ -8008,7 +8530,7 @@ class WebRTCPhone extends Emitter {
8008
8530
  const hasIncomingCallSession = this.hasIncomingCallSession();
8009
8531
 
8010
8532
  // Re-trigger incoming call event for remaining incoming calls
8011
- logger$7.info('WebRTC phone - check to re-trigger incoming call', {
8533
+ logger$8.info('WebRTC phone - check to re-trigger incoming call', {
8012
8534
  sipId: sipSession.id,
8013
8535
  shouldRetrigger,
8014
8536
  hasIncomingCallSession,
@@ -8097,37 +8619,37 @@ class WebRTCPhone extends Emitter {
8097
8619
 
8098
8620
  // Deprecated
8099
8621
  getLocalStreamForCall(callSession ) {
8100
- logger$7.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8622
+ logger$8.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8101
8623
 
8102
8624
  return this.getLocalStream(callSession);
8103
8625
  }
8104
8626
 
8105
8627
  // Deprecated
8106
8628
  getRemoteStreamForCall(callSession ) {
8107
- logger$7.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8629
+ logger$8.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8108
8630
 
8109
8631
  return this.getRemoteVideoStream(callSession);
8110
8632
  }
8111
8633
 
8112
8634
  getRemoteStreamsForCall(callSession ) {
8113
- logger$7.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8635
+ logger$8.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8114
8636
 
8115
8637
  return this.getRemoteStream(callSession);
8116
8638
  }
8117
8639
 
8118
8640
  accept(callSession , cameraEnabled ) {
8119
- logger$7.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8641
+ logger$8.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8120
8642
  if (this.currentSipSession) {
8121
8643
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
8122
8644
  }
8123
8645
 
8124
8646
  if (!callSession) {
8125
- logger$7.warn('no CallSession to accept.');
8647
+ logger$8.warn('no CallSession to accept.');
8126
8648
  return Promise.resolve(null);
8127
8649
  }
8128
8650
 
8129
8651
  if (callSession.getId() in this.acceptedSessions) {
8130
- logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8652
+ logger$8.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8131
8653
  return Promise.resolve(callSession.sipCallId);
8132
8654
  }
8133
8655
 
@@ -8139,24 +8661,24 @@ class WebRTCPhone extends Emitter {
8139
8661
  const sipSession = this.client.getSipSession(callSession.getId());
8140
8662
  if (sipSession) {
8141
8663
  if (sipSession.state === SessionState.Terminated || sipSession.state === SessionState.Terminating) {
8142
- logger$7.warn('Trying to answer a terminated sipSession.');
8664
+ logger$8.warn('Trying to answer a terminated sipSession.');
8143
8665
 
8144
8666
  return Promise.resolve(null);
8145
8667
  }
8146
8668
 
8147
- logger$7.info('accept call, session found', { sipId: sipSession.id });
8669
+ logger$8.info('accept call, session found', { sipId: sipSession.id });
8148
8670
 
8149
8671
  // $FlowFixMe
8150
8672
  return this.client.answer(sipSession, this.allowVideo ? cameraEnabled : false).then(() => {
8151
8673
  return callSession.sipCallId;
8152
8674
  }).catch(e => {
8153
- logger$7.error(e);
8675
+ logger$8.error(e);
8154
8676
  this.endCurrentCall(callSession);
8155
8677
  throw e;
8156
8678
  });
8157
8679
  }
8158
8680
 
8159
- logger$7.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8681
+ logger$8.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8160
8682
 
8161
8683
  return Promise.resolve(null);
8162
8684
  }
@@ -8166,7 +8688,7 @@ class WebRTCPhone extends Emitter {
8166
8688
  }
8167
8689
 
8168
8690
  async reject(callSession ) {
8169
- logger$7.info('reject WebRTC called', { id: callSession.getId() });
8691
+ logger$8.info('reject WebRTC called', { id: callSession.getId() });
8170
8692
 
8171
8693
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call rejected locally');
8172
8694
  if (!callSession || callSession.getId() in this.rejectedSessions) {
@@ -8178,14 +8700,14 @@ class WebRTCPhone extends Emitter {
8178
8700
 
8179
8701
  const sipSession = this.findSipSession(callSession);
8180
8702
  if (sipSession) {
8181
- logger$7.info('WebRTC rejecting', { sipId: sipSession.id });
8703
+ logger$8.info('WebRTC rejecting', { sipId: sipSession.id });
8182
8704
 
8183
8705
  this.client.hangup(sipSession);
8184
8706
  }
8185
8707
  }
8186
8708
 
8187
8709
  async ignore(callSession ) {
8188
- logger$7.info('WebRTC ignore', { id: callSession.getId() });
8710
+ logger$8.info('WebRTC ignore', { id: callSession.getId() });
8189
8711
 
8190
8712
  // kill the ring
8191
8713
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'ignoring call');
@@ -8194,7 +8716,7 @@ class WebRTCPhone extends Emitter {
8194
8716
  }
8195
8717
 
8196
8718
  hold(callSession , withEvent = true, isConference = false) {
8197
- logger$7.info('WebRTC hold', { id: callSession.getId() });
8719
+ logger$8.info('WebRTC hold', { id: callSession.getId() });
8198
8720
 
8199
8721
  const sipSession = this.findSipSession(callSession);
8200
8722
 
@@ -8205,7 +8727,7 @@ class WebRTCPhone extends Emitter {
8205
8727
 
8206
8728
  // @Deprecated
8207
8729
  unhold(callSession , withEvent = true, isConference = false) {
8208
- logger$7.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8730
+ logger$8.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8209
8731
 
8210
8732
  console.warn('Please note that `phone.unhold()` is being deprecated; `phone.resume()` is the preferred method');
8211
8733
 
@@ -8220,7 +8742,7 @@ class WebRTCPhone extends Emitter {
8220
8742
  const sipSession = this.findSipSession(callSession);
8221
8743
 
8222
8744
  if (sipSession) {
8223
- logger$7.info('WebRTC atxfer', { sipId: sipSession.id });
8745
+ logger$8.info('WebRTC atxfer', { sipId: sipSession.id });
8224
8746
 
8225
8747
  return this.client.atxfer(sipSession);
8226
8748
  }
@@ -8235,7 +8757,7 @@ class WebRTCPhone extends Emitter {
8235
8757
  if (!sipSession) {
8236
8758
  return new Promise((resolve, reject) => reject(new Error('No session to hold')));
8237
8759
  }
8238
- logger$7.info('WebRTC hold sip session', { sipId: sipSession.id });
8760
+ logger$8.info('WebRTC hold sip session', { sipId: sipSession.id });
8239
8761
 
8240
8762
  const promise = this.client.hold(sipSession, isConference);
8241
8763
  if (withEvent) {
@@ -8254,7 +8776,7 @@ class WebRTCPhone extends Emitter {
8254
8776
  if (!sipSession) {
8255
8777
  return new Promise((resolve, reject) => reject(new Error('No session to unhold')));
8256
8778
  }
8257
- logger$7.info('WebRTC unhold', { sipId: sipSession.id });
8779
+ logger$8.info('WebRTC unhold', { sipId: sipSession.id });
8258
8780
 
8259
8781
  const promise = this.client.unhold(sipSession, isConference);
8260
8782
  if (withEvent) {
@@ -8265,18 +8787,18 @@ class WebRTCPhone extends Emitter {
8265
8787
  }
8266
8788
 
8267
8789
  resume(callSession , isConference = false) {
8268
- logger$7.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8790
+ logger$8.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8269
8791
 
8270
8792
  const sipSession = this.findSipSession(callSession);
8271
8793
  if (!sipSession) {
8272
8794
  return new Promise((resolve, reject) => reject(new Error('No session to resume')));
8273
8795
  }
8274
8796
 
8275
- logger$7.info('WebRTC resuming', { sipId: sipSession.id });
8797
+ logger$8.info('WebRTC resuming', { sipId: sipSession.id });
8276
8798
 
8277
8799
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
8278
8800
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
8279
- logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8801
+ logger$8.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8280
8802
  this.holdSipSession(this.currentSipSession, callSession);
8281
8803
  }
8282
8804
 
@@ -8291,14 +8813,14 @@ class WebRTCPhone extends Emitter {
8291
8813
  }
8292
8814
 
8293
8815
  mute(callSession , withEvent = true) {
8294
- logger$7.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8816
+ logger$8.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8295
8817
 
8296
8818
  const sipSession = this.findSipSession(callSession);
8297
8819
  if (!sipSession) {
8298
8820
  return;
8299
8821
  }
8300
8822
 
8301
- logger$7.info('WebRTC muting', { sipId: sipSession.id });
8823
+ logger$8.info('WebRTC muting', { sipId: sipSession.id });
8302
8824
  this.client.mute(sipSession);
8303
8825
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: true });
8304
8826
 
@@ -8312,14 +8834,14 @@ class WebRTCPhone extends Emitter {
8312
8834
  }
8313
8835
 
8314
8836
  unmute(callSession , withEvent = true) {
8315
- logger$7.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8837
+ logger$8.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8316
8838
 
8317
8839
  const sipSession = this.findSipSession(callSession);
8318
8840
  if (!sipSession) {
8319
8841
  return;
8320
8842
  }
8321
8843
 
8322
- logger$7.info('WebRTC unmuting', { sipId: sipSession.id });
8844
+ logger$8.info('WebRTC unmuting', { sipId: sipSession.id });
8323
8845
  this.client.unmute(sipSession);
8324
8846
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: false });
8325
8847
 
@@ -8346,7 +8868,7 @@ class WebRTCPhone extends Emitter {
8346
8868
  if (!sipSession) {
8347
8869
  return;
8348
8870
  }
8349
- logger$7.info('WebRTC turn camera on', { sipId: sipSession.id });
8871
+ logger$8.info('WebRTC turn camera on', { sipId: sipSession.id });
8350
8872
 
8351
8873
  this.client.toggleCameraOn(sipSession);
8352
8874
 
@@ -8358,7 +8880,7 @@ class WebRTCPhone extends Emitter {
8358
8880
  if (!sipSession) {
8359
8881
  return;
8360
8882
  }
8361
- logger$7.info('WebRTC turn camera off', { sipId: sipSession.id });
8883
+ logger$8.info('WebRTC turn camera off', { sipId: sipSession.id });
8362
8884
 
8363
8885
  this.client.toggleCameraOff(sipSession);
8364
8886
  this.eventEmitter.emit(ON_CAMERA_DISABLED, this._createCameraDisabledCallSession(sipSession, callSession));
@@ -8370,7 +8892,7 @@ class WebRTCPhone extends Emitter {
8370
8892
  return;
8371
8893
  }
8372
8894
 
8373
- logger$7.info('WebRTC send key', { sipId: sipSession.id, tone });
8895
+ logger$8.info('WebRTC send key', { sipId: sipSession.id, tone });
8374
8896
  this.client.sendDTMF(sipSession, tone);
8375
8897
  }
8376
8898
 
@@ -8378,7 +8900,7 @@ class WebRTCPhone extends Emitter {
8378
8900
  // @TODO: line is not used here
8379
8901
  async makeCall(number , line , cameraEnabled ,
8380
8902
  audioOnly = false, conference = false) {
8381
- logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8903
+ logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8382
8904
  if (!number) {
8383
8905
  return Promise.resolve(null);
8384
8906
  }
@@ -8388,7 +8910,7 @@ class WebRTCPhone extends Emitter {
8388
8910
  }
8389
8911
  if (this.currentSipSession) {
8390
8912
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true).catch(e => {
8391
- logger$7.warn('Unable to hold current session when making another call', e);
8913
+ logger$8.warn('Unable to hold current session when making another call', e);
8392
8914
  });
8393
8915
  }
8394
8916
 
@@ -8398,7 +8920,7 @@ class WebRTCPhone extends Emitter {
8398
8920
  this._bindEvents(sipSession);
8399
8921
  } catch (error) {
8400
8922
  console.warn(error);
8401
- logger$7.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8923
+ logger$8.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8402
8924
  return Promise.resolve(null);
8403
8925
  }
8404
8926
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
@@ -8426,7 +8948,7 @@ class WebRTCPhone extends Emitter {
8426
8948
  return;
8427
8949
  }
8428
8950
 
8429
- logger$7.info('WebRTC transfer', { sipId: sipSession.id, target });
8951
+ logger$8.info('WebRTC transfer', { sipId: sipSession.id, target });
8430
8952
 
8431
8953
  this.client.transfer(sipSession, target);
8432
8954
  }
@@ -8435,7 +8957,7 @@ class WebRTCPhone extends Emitter {
8435
8957
  const sipSession = this.client.getSipSession(source.sipCallId);
8436
8958
  const sipSessionTarget = this.client.getSipSession(destination.sipCallId);
8437
8959
 
8438
- logger$7.info('WebRTC indirect transfer', {
8960
+ logger$8.info('WebRTC indirect transfer', {
8439
8961
  sipId: sipSession ? sipSession.id : null,
8440
8962
  target: sipSessionTarget ? sipSessionTarget.id : null,
8441
8963
  });
@@ -8463,7 +8985,7 @@ class WebRTCPhone extends Emitter {
8463
8985
  return false;
8464
8986
  }
8465
8987
 
8466
- logger$7.info('WebRTC hangup', { sipId: sipSession.id });
8988
+ logger$8.info('WebRTC hangup', { sipId: sipSession.id });
8467
8989
 
8468
8990
  const sipSessionId = this.getSipSessionId(sipSession);
8469
8991
 
@@ -8508,7 +9030,7 @@ class WebRTCPhone extends Emitter {
8508
9030
  }
8509
9031
 
8510
9032
  async close() {
8511
- logger$7.info('WebRTC close');
9033
+ logger$8.info('WebRTC close');
8512
9034
 
8513
9035
  try {
8514
9036
  await Promise.race([
@@ -8516,7 +9038,7 @@ class WebRTCPhone extends Emitter {
8516
9038
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Unregister, timed out')), 3000)),
8517
9039
  ]);
8518
9040
  } catch (e) {
8519
- logger$7.error('WebRTC close, unregister error', e);
9041
+ logger$8.error('WebRTC close, unregister error', e);
8520
9042
  }
8521
9043
 
8522
9044
  this.client.close();
@@ -8534,12 +9056,12 @@ class WebRTCPhone extends Emitter {
8534
9056
  }
8535
9057
 
8536
9058
  enableRinging() {
8537
- logger$7.info('WebRTC enable ringing');
9059
+ logger$8.info('WebRTC enable ringing');
8538
9060
  this.ringingEnabled = true;
8539
9061
  }
8540
9062
 
8541
9063
  disableRinging() {
8542
- logger$7.info('WebRTC disable ringing');
9064
+ logger$8.info('WebRTC disable ringing');
8543
9065
  this.ringingEnabled = false;
8544
9066
  }
8545
9067
 
@@ -8579,7 +9101,7 @@ class WebRTCPhone extends Emitter {
8579
9101
 
8580
9102
  // Deprecated
8581
9103
  getLocalMediaStream(callSession ) {
8582
- logger$7.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
9104
+ logger$8.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
8583
9105
  return this.getLocalStream(callSession);
8584
9106
  }
8585
9107
 
@@ -8587,6 +9109,10 @@ class WebRTCPhone extends Emitter {
8587
9109
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
8588
9110
  }
8589
9111
 
9112
+ hasALocalVideoTrack(callSession ) {
9113
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
9114
+ }
9115
+
8590
9116
  getRemoteStream(callSession ) {
8591
9117
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
8592
9118
  }
@@ -8609,7 +9135,7 @@ class WebRTCPhone extends Emitter {
8609
9135
  this.client.on(this.client.INVITE, (sipSession , wantsToDoVideo ) => {
8610
9136
  const autoAnswer = sipSession.request.getHeader('Answer-Mode') === 'Auto';
8611
9137
  const withVideo = this.allowVideo ? wantsToDoVideo : false;
8612
- logger$7.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
9138
+ logger$8.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
8613
9139
 
8614
9140
  const callSession = this._createIncomingCallSession(sipSession, withVideo, null, autoAnswer);
8615
9141
  this.incomingSessions.push(callSession.getId());
@@ -8632,7 +9158,7 @@ class WebRTCPhone extends Emitter {
8632
9158
  });
8633
9159
 
8634
9160
  this.client.on(this.client.ON_REINVITE, (...args) => {
8635
- logger$7.info('WebRTC on reinvite', {
9161
+ logger$8.info('WebRTC on reinvite', {
8636
9162
  sessionId: args[0].id,
8637
9163
  inviteId: args[1].id,
8638
9164
  updatedCalleeName: args[2],
@@ -8652,7 +9178,7 @@ class WebRTCPhone extends Emitter {
8652
9178
  });
8653
9179
 
8654
9180
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
8655
- logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
9181
+ logger$8.info('WebRTC call accepted', { sipId: sipSession.id });
8656
9182
 
8657
9183
  this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
8658
9184
 
@@ -8663,17 +9189,17 @@ class WebRTCPhone extends Emitter {
8663
9189
  this.client.on('ended', () => {});
8664
9190
 
8665
9191
  this.client.on(this.client.ON_ERROR, e => {
8666
- logger$7.error('WebRTC error', e);
9192
+ logger$8.error('WebRTC error', e);
8667
9193
  this.eventEmitter.emit(ON_CALL_ERROR, e);
8668
9194
  });
8669
9195
 
8670
9196
  this.client.on(this.client.UNREGISTERED, () => {
8671
- logger$7.info('WebRTC unregistered');
9197
+ logger$8.info('WebRTC unregistered');
8672
9198
  this.eventEmitter.emit(ON_UNREGISTERED);
8673
9199
  });
8674
9200
 
8675
9201
  this.client.on(this.client.REGISTERED, () => {
8676
- logger$7.info('WebRTC registered', {
9202
+ logger$8.info('WebRTC registered', {
8677
9203
  shouldSendReinvite: this.shouldSendReinvite,
8678
9204
  state: this.currentSipSession ? this.currentSipSession.state : null,
8679
9205
  currentSipSession: !!this.currentSipSession,
@@ -8689,19 +9215,19 @@ class WebRTCPhone extends Emitter {
8689
9215
  try {
8690
9216
  this.sendReinvite(this.currentCallSession);
8691
9217
  } catch (e) {
8692
- logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9218
+ logger$8.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
8693
9219
  }
8694
9220
  }
8695
9221
  });
8696
9222
 
8697
9223
  this.client.on(this.client.CONNECTED, () => {
8698
- logger$7.info('WebRTC client connected');
9224
+ logger$8.info('WebRTC client connected');
8699
9225
 
8700
9226
  this.stopHeartbeat();
8701
9227
  });
8702
9228
 
8703
9229
  this.client.on(this.client.DISCONNECTED, () => {
8704
- logger$7.info('WebRTC client disconnected');
9230
+ logger$8.info('WebRTC client disconnected');
8705
9231
 
8706
9232
  this.eventEmitter.emit(ON_UNREGISTERED);
8707
9233
 
@@ -8933,7 +9459,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
8933
9459
 
8934
9460
  //
8935
9461
 
8936
- const logger$6 = IssueReporter$1.loggerFor('simple-phone');
9462
+ const logger$7 = IssueReporter$1.loggerFor('simple-phone');
8937
9463
  const sipLogger = IssueReporter$1.loggerFor('sip.js');
8938
9464
  const protocolLogger = IssueReporter$1.loggerFor('sip');
8939
9465
 
@@ -9040,7 +9566,7 @@ class Phone extends Emitter {
9040
9566
  async disconnect() {
9041
9567
  if (this.phone) {
9042
9568
  if (this.phone.hasAnActiveCall()) {
9043
- logger$6.info('hangup call on disconnect');
9569
+ logger$7.info('hangup call on disconnect');
9044
9570
  // $FlowFixMe
9045
9571
  await this.phone.hangup();
9046
9572
  }
@@ -9063,13 +9589,13 @@ class Phone extends Emitter {
9063
9589
  }
9064
9590
 
9065
9591
  async hangup(callSession ) {
9066
- logger$6.info('hangup via simple phone', { callId: callSession.getId() });
9592
+ logger$7.info('hangup via simple phone', { callId: callSession.getId() });
9067
9593
 
9068
9594
  return this.phone && this.phone.hangup(callSession);
9069
9595
  }
9070
9596
 
9071
9597
  async accept(callSession , cameraEnabled ) {
9072
- logger$6.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9598
+ logger$7.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9073
9599
 
9074
9600
  return this.phone && this.phone.accept(callSession, cameraEnabled);
9075
9601
  }
@@ -9089,13 +9615,18 @@ class Phone extends Emitter {
9089
9615
  return adHocConference.start();
9090
9616
  }
9091
9617
 
9092
- mute(callSession ) {
9093
- this.muteViaAPI(callSession);
9618
+ mute(callSession , withApi = true) {
9619
+ if (withApi) {
9620
+ this.muteViaAPI(callSession);
9621
+ }
9622
+
9094
9623
  return this.phone && this.phone.mute(callSession);
9095
9624
  }
9096
9625
 
9097
- unmute(callSession ) {
9098
- this.unmuteViaAPI(callSession);
9626
+ unmute(callSession , withApi = true) {
9627
+ if (withApi) {
9628
+ this.unmuteViaAPI(callSession);
9629
+ }
9099
9630
 
9100
9631
  return this.phone && this.phone.unmute(callSession);
9101
9632
  }
@@ -9103,7 +9634,7 @@ class Phone extends Emitter {
9103
9634
  muteViaAPI(callSession ) {
9104
9635
  if (callSession && callSession.callId) {
9105
9636
  Wazo.getApiClient().calld.mute(callSession.callId).catch(e => {
9106
- logger$6.error('Mute via API, error', e);
9637
+ logger$7.error('Mute via API, error', e);
9107
9638
  });
9108
9639
  }
9109
9640
  }
@@ -9111,7 +9642,7 @@ class Phone extends Emitter {
9111
9642
  unmuteViaAPI(callSession ) {
9112
9643
  if (callSession && callSession.callId) {
9113
9644
  Wazo.getApiClient().calld.unmute(callSession.callId).catch(e => {
9114
- logger$6.error('Unmute via API, error', e);
9645
+ logger$7.error('Unmute via API, error', e);
9115
9646
  });
9116
9647
  }
9117
9648
  }
@@ -9201,9 +9732,13 @@ class Phone extends Emitter {
9201
9732
  return this.phone && this.phone.hasLocalVideo(callSession);
9202
9733
  }
9203
9734
 
9735
+ hasALocalVideoTrack(callSession ) {
9736
+ return this.phone && this.phone.hasALocalVideoTrack(callSession);
9737
+ }
9738
+
9204
9739
  // @Deprecated
9205
9740
  getLocalMediaStream(callSession ) {
9206
- logger$6.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9741
+ logger$7.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9207
9742
 
9208
9743
  return this.phone && this.phone.getLocalStream(callSession);
9209
9744
  }
@@ -9222,20 +9757,20 @@ class Phone extends Emitter {
9222
9757
 
9223
9758
  // @Deprecated
9224
9759
  getRemoteStreamForCall(callSession ) {
9225
- logger$6.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9760
+ logger$7.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9226
9761
  return this.getRemoteStream(callSession);
9227
9762
  }
9228
9763
 
9229
9764
  // Returns remote streams directly from the peerConnection
9230
9765
  // @Deprecated
9231
9766
  getRemoteStreamsForCall(callSession ) {
9232
- logger$6.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9767
+ logger$7.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9233
9768
  return this.getLocalStream(callSession);
9234
9769
  }
9235
9770
 
9236
9771
  // @Deprecated
9237
9772
  getRemoteVideoStreamForCall(callSession ) {
9238
- logger$6.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9773
+ logger$7.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9239
9774
 
9240
9775
  return this.getRemoteVideoStream(callSession);
9241
9776
  }
@@ -9365,6 +9900,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
9365
9900
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
9366
9901
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
9367
9902
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
9903
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
9904
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
9368
9905
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
9369
9906
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
9370
9907
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -9406,7 +9943,7 @@ const BLACKLIST_EVENTS = [
9406
9943
  ];
9407
9944
 
9408
9945
  const HEARTBEAT_ENGINE_VERSION = '20.09';
9409
- const logger$5 = IssueReporter$1.loggerFor('wazo-ws');
9946
+ const logger$6 = IssueReporter$1.loggerFor('wazo-ws');
9410
9947
  const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
9411
9948
 
9412
9949
  class WebSocketClient extends Emitter {
@@ -9455,19 +9992,19 @@ class WebSocketClient extends Emitter {
9455
9992
  }
9456
9993
 
9457
9994
  connect() {
9458
- logger$5.info('connect method started', { host: this.host, token: this.token });
9995
+ logger$6.info('connect method started', { host: this.host, token: this.token });
9459
9996
  this.socket = new ReconnectingWebSocket(this._getUrl.bind(this), [], this.options);
9460
9997
  if (this.options.binaryType) {
9461
9998
  this.socket.binaryType = this.options.binaryType;
9462
9999
  }
9463
10000
 
9464
10001
  this.socket.onopen = () => {
9465
- logger$5.info('on Wazo WS open', { method: 'connect', host: this.host });
10002
+ logger$6.info('on Wazo WS open', { method: 'connect', host: this.host });
9466
10003
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_OPEN);
9467
10004
  };
9468
10005
 
9469
10006
  this.socket.onerror = event => {
9470
- logger$5.error('on Wazo WS error', event.target);
10007
+ logger$6.error('on Wazo WS error', event.target);
9471
10008
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_ERROR, event);
9472
10009
  };
9473
10010
 
@@ -9497,7 +10034,7 @@ class WebSocketClient extends Emitter {
9497
10034
 
9498
10035
  this.socket.onclose = event => {
9499
10036
  // Can't be converted to JSON (circular structure)
9500
- logger$5.info('on Wazo WS close', {
10037
+ logger$6.info('on Wazo WS close', {
9501
10038
  reason: event.reason,
9502
10039
  code: event.code,
9503
10040
  readyState: event.target.readyState,
@@ -9515,12 +10052,12 @@ class WebSocketClient extends Emitter {
9515
10052
  };
9516
10053
 
9517
10054
  this.socket.onerror = event => {
9518
- logger$5.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
10055
+ logger$6.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
9519
10056
  };
9520
10057
  }
9521
10058
 
9522
10059
  close(force = false) {
9523
- logger$5.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
10060
+ logger$6.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
9524
10061
 
9525
10062
  if (!this.socket) {
9526
10063
  return;
@@ -9538,7 +10075,7 @@ class WebSocketClient extends Emitter {
9538
10075
 
9539
10076
  updateToken(token ) {
9540
10077
  this.token = token;
9541
- logger$5.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
10078
+ logger$6.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
9542
10079
 
9543
10080
  if (this.socket) {
9544
10081
  // If still connected, send the token to the WS
@@ -9556,7 +10093,7 @@ class WebSocketClient extends Emitter {
9556
10093
  }
9557
10094
 
9558
10095
  startHeartbeat() {
9559
- logger$5.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
10096
+ logger$6.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
9560
10097
 
9561
10098
  if (!this.socket) {
9562
10099
  this.heartbeat.stop();
@@ -9570,7 +10107,7 @@ class WebSocketClient extends Emitter {
9570
10107
  }
9571
10108
 
9572
10109
  stopHeartbeat() {
9573
- logger$5.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
10110
+ logger$6.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
9574
10111
 
9575
10112
  this.heartbeat.stop();
9576
10113
  }
@@ -9600,7 +10137,7 @@ class WebSocketClient extends Emitter {
9600
10137
  }
9601
10138
 
9602
10139
  reconnect(reason ) {
9603
- logger$5.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
10140
+ logger$6.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
9604
10141
  if (!this.socket) {
9605
10142
  return;
9606
10143
  }
@@ -9656,7 +10193,7 @@ class WebSocketClient extends Emitter {
9656
10193
  this.close();
9657
10194
  }
9658
10195
  const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
9659
- logger$5.log('Wazo WS url computed to reconnect', { url });
10196
+ logger$6.log('Wazo WS url computed to reconnect', { url });
9660
10197
 
9661
10198
  return url;
9662
10199
  }
@@ -9664,12 +10201,12 @@ class WebSocketClient extends Emitter {
9664
10201
  _onHeartbeat(message ) {
9665
10202
  if (message.payload === 'pong') {
9666
10203
  this.heartbeat.onHeartbeat();
9667
- logger$5.log('on heartbeat received from Wazo WS');
10204
+ logger$6.log('on heartbeat received from Wazo WS');
9668
10205
  }
9669
10206
  }
9670
10207
 
9671
10208
  async _onHeartbeatTimeout() {
9672
- logger$5.log('heartbeat timed out', { host: this.host, token: this.token });
10209
+ logger$6.log('heartbeat timed out', { host: this.host, token: this.token });
9673
10210
 
9674
10211
  this.close();
9675
10212
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_CLOSE, new Error('Websocket ping failure.'));
@@ -9711,6 +10248,8 @@ WebSocketClient.eventLists = [
9711
10248
  CHATD_USER_ROOM_CREATED,
9712
10249
  CONFERENCE_USER_PARTICIPANT_JOINED,
9713
10250
  CONFERENCE_USER_PARTICIPANT_LEFT,
10251
+ MEETING_USER_PARTICIPANT_JOINED,
10252
+ MEETING_USER_PARTICIPANT_LEFT,
9714
10253
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9715
10254
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
9716
10255
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -9781,6 +10320,8 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
9781
10320
  CONFERENCE_USER_PARTICIPANT_LEFT: CONFERENCE_USER_PARTICIPANT_LEFT,
9782
10321
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED: CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9783
10322
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED: CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
10323
+ MEETING_USER_PARTICIPANT_JOINED: MEETING_USER_PARTICIPANT_JOINED,
10324
+ MEETING_USER_PARTICIPANT_LEFT: MEETING_USER_PARTICIPANT_LEFT,
9784
10325
  SWITCHBOARD_QUEUED_CALLS_UPDATED: SWITCHBOARD_QUEUED_CALLS_UPDATED,
9785
10326
  SWITCHBOARD_QUEUED_CALL_ANSWERED: SWITCHBOARD_QUEUED_CALL_ANSWERED,
9786
10327
  SWITCHBOARD_HELD_CALLS_UPDATED: SWITCHBOARD_HELD_CALLS_UPDATED,
@@ -9822,7 +10363,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
9822
10363
  const { SOCKET_EVENTS, ...OTHER_EVENTS } = WebSocketClient$1;
9823
10364
  const ALL_EVENTS = [...Object.values(SOCKET_EVENTS), ...Object.values(OTHER_EVENTS)];
9824
10365
 
9825
- const logger$4 = IssueReporter$1.loggerFor('simple-ws-client');
10366
+ const logger$5 = IssueReporter$1.loggerFor('simple-ws-client');
9826
10367
 
9827
10368
  class Websocket extends Emitter {
9828
10369
 
@@ -9846,7 +10387,7 @@ class Websocket extends Emitter {
9846
10387
  }
9847
10388
 
9848
10389
  open(host , session ) {
9849
- logger$4.info('open simple WebSocket', { host, token: session.token });
10390
+ logger$5.info('open simple WebSocket', { host, token: session.token });
9850
10391
  this.ws = new WebSocketClient(
9851
10392
  {
9852
10393
  host,
@@ -9874,7 +10415,7 @@ class Websocket extends Emitter {
9874
10415
  }
9875
10416
 
9876
10417
  updateToken(token ) {
9877
- logger$4.info('update token via simple Websocket', { token, ws: !!this.ws });
10418
+ logger$5.info('update token via simple Websocket', { token, ws: !!this.ws });
9878
10419
 
9879
10420
  if (!this.ws) {
9880
10421
  return;
@@ -9902,7 +10443,7 @@ var Websocket$1 = global.wazoWebsocketInstance;
9902
10443
 
9903
10444
  //
9904
10445
 
9905
- const logger$3 = IssueReporter$1.loggerFor('room');
10446
+ const logger$4 = IssueReporter$1.loggerFor('room');
9906
10447
 
9907
10448
  class Participant extends Emitter {
9908
10449
 
@@ -9936,6 +10477,7 @@ class Participant extends Emitter {
9936
10477
 
9937
10478
 
9938
10479
  /**
10480
+ * @param room Room The room where the participant is
9939
10481
  * @param rawParticipant string Participant sent via the Wazo WS
9940
10482
  * @param extra Object extra status of the participant
9941
10483
  */
@@ -10023,7 +10565,7 @@ class Participant extends Emitter {
10023
10565
  }
10024
10566
 
10025
10567
  onTalking(isTalking ) {
10026
- logger$3.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10568
+ logger$4.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10027
10569
  this.isTalking = isTalking;
10028
10570
  // you may notice we're not broadcasting: since all participants are getting this info
10029
10571
  // directly from asterisk, there's no need to do so
@@ -10126,7 +10668,7 @@ class Participant extends Emitter {
10126
10668
  }
10127
10669
 
10128
10670
  updateStatus(status , broadcast = true) {
10129
- logger$3.info('updating participant status', { name: this.name, status });
10671
+ logger$4.info('updating participant status', { name: this.name, status });
10130
10672
 
10131
10673
  if (typeof status.audioMuted !== 'undefined' && status.audioMuted !== this.audioMuted) {
10132
10674
  if (status.audioMuted) {
@@ -10163,13 +10705,18 @@ class Participant extends Emitter {
10163
10705
  // Poor man's object comparison
10164
10706
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
10165
10707
  this.extra = { ...this.extra, ...status.extra };
10708
+
10709
+ if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
10710
+ this.extra.contact = new Contact(this.extra.contact);
10711
+ }
10712
+
10166
10713
  this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
10167
10714
  }
10168
10715
  }
10169
10716
 
10170
10717
  broadcastStatus(inboundStatus = null) {
10171
10718
  const status = inboundStatus || this.getStatus();
10172
- logger$3.info('broadcasting participant status', { callId: this.callId, status });
10719
+ logger$4.info('broadcasting participant status', { callId: this.callId, status });
10173
10720
 
10174
10721
  this.room.sendSignal({
10175
10722
  type: SIGNAL_TYPE_PARTICIPANT_UPDATE,
@@ -10190,18 +10737,24 @@ class RemoteParticipant extends Participant {
10190
10737
  }
10191
10738
  }
10192
10739
 
10193
- /* global document */
10740
+ //
10741
+
10742
+ class LocalParticipant extends Participant {
10743
+ }
10744
+
10745
+ //
10194
10746
 
10195
10747
  const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
10196
10748
  const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
10197
10749
 
10198
- const logger$2 = IssueReporter$1.loggerFor('sdk-room');
10750
+ const logger$3 = IssueReporter$1.loggerFor('sdk-room');
10199
10751
 
10200
10752
  class Room$1 extends Emitter {
10201
10753
 
10202
10754
 
10203
10755
 
10204
10756
 
10757
+
10205
10758
 
10206
10759
 
10207
10760
 
@@ -10223,6 +10776,8 @@ class Room$1 extends Emitter {
10223
10776
 
10224
10777
 
10225
10778
 
10779
+
10780
+
10226
10781
 
10227
10782
 
10228
10783
 
@@ -10240,6 +10795,7 @@ class Room$1 extends Emitter {
10240
10795
  * @param extension string
10241
10796
  * @param sourceId number
10242
10797
  * @param callId string
10798
+ * @param meetingUuid string
10243
10799
  * @param extra Object
10244
10800
  */
10245
10801
  constructor(
@@ -10247,15 +10803,17 @@ class Room$1 extends Emitter {
10247
10803
  extension ,
10248
10804
  sourceId ,
10249
10805
  callId ,
10806
+ meetingUuid ,
10250
10807
  extra = {},
10251
10808
  ) {
10252
10809
  super();
10253
- logger$2.info('room initialized', { callId, extension, sourceId });
10810
+ logger$3.info('room initialized', { callId, extension, sourceId, meetingUuid });
10254
10811
 
10255
10812
  // Represents the room callSession
10256
10813
  this.callSession = callSession;
10257
10814
  this.extension = extension;
10258
10815
  this.sourceId = sourceId;
10816
+ this.meetingUuid = meetingUuid;
10259
10817
  this.callId = callId;
10260
10818
  this.participants = [];
10261
10819
  this.connected = false;
@@ -10275,6 +10833,8 @@ class Room$1 extends Emitter {
10275
10833
  // Sugar syntax for `room.EVENT_NAME`
10276
10834
  this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
10277
10835
  this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
10836
+ this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
10837
+ this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
10278
10838
  this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
10279
10839
  this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
10280
10840
  this.ON_CHAT = Wazo.Phone.ON_CHAT;
@@ -10309,10 +10869,11 @@ class Room$1 extends Emitter {
10309
10869
  * @param audioOnly boolean
10310
10870
  * @param extra Object
10311
10871
  * @param room ?Room
10872
+ * @param meeting ?Meeting
10312
10873
  * @returns {Promise<Room>}
10313
10874
  */
10314
- static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
10315
- logger$2.info('connecting to room', { extension, audioOnly, room: !!room });
10875
+ static async connect({ extension, constraints, audioOnly = false, extra, room, meeting } ) {
10876
+ logger$3.info('connecting to room', { extension, audioOnly, room: !!room });
10316
10877
 
10317
10878
  if (!room) {
10318
10879
  await Wazo.Phone.connect();
@@ -10325,7 +10886,7 @@ class Room$1 extends Emitter {
10325
10886
 
10326
10887
  // Call_created is triggered before call_accepted, so we have to listen for it here.
10327
10888
  Wazo.Websocket.once(Wazo.Websocket.CALL_CREATED, ({ data }) => {
10328
- logger$2.info('room call received via WS', { callId: data.call_id });
10889
+ logger$3.info('room call received via WS', { callId: data.call_id });
10329
10890
  if (room) {
10330
10891
  room.setCallId(data.call_id);
10331
10892
  }
@@ -10346,34 +10907,44 @@ class Room$1 extends Emitter {
10346
10907
  room.setCallId(room.callSession.call.id);
10347
10908
  }
10348
10909
 
10349
- // Fetch conference source
10350
- const sources = await getApiClient().dird.fetchConferenceSource('default');
10351
- // Retrieve conference sources
10352
- const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
10353
- // Retrieve conference
10354
- const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
10910
+ if (!meeting) {
10911
+ // Fetch conference source
10912
+ const sources = await getApiClient().dird.fetchConferenceSource('default');
10913
+ // Retrieve conference sources
10914
+ const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
10915
+ // Retrieve conference
10916
+ const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
10355
10917
 
10356
- logger$2.info('connected to room', {
10357
- sourceId: conference ? conference.sourceId : null,
10358
- name: conference ? conference.name : null,
10359
- });
10918
+ logger$3.info('connected to room', {
10919
+ sourceId: conference ? conference.sourceId : null,
10920
+ name: conference ? conference.name : null,
10921
+ });
10360
10922
 
10361
- if (conference) {
10362
- room.setSourceId(conference.sourceId);
10363
- room.setName(conference.name);
10923
+ if (conference) {
10924
+ room.setSourceId(conference.sourceId);
10925
+ room.setName(conference.name);
10926
+ }
10927
+ } else if (meeting) {
10928
+ logger$3.info('Already connected to meeting', {
10929
+ uuid: meeting.uuid,
10930
+ name: meeting.name,
10931
+ });
10932
+
10933
+ room.setMeetingUuid(meeting.uuid);
10934
+ room.setName(meeting.name);
10364
10935
  }
10365
10936
 
10366
10937
  return room;
10367
10938
  }
10368
10939
 
10369
10940
  static disconnect() {
10370
- logger$2.info('static disconnection to room');
10941
+ logger$3.info('static disconnection to room');
10371
10942
 
10372
10943
  Wazo.Phone.disconnect();
10373
10944
  }
10374
10945
 
10375
10946
  async disconnect() {
10376
- logger$2.info('disconnection to room called');
10947
+ logger$3.info('disconnection to room called');
10377
10948
 
10378
10949
  await Wazo.Phone.hangup(this.callSession);
10379
10950
  this.callSession = null;
@@ -10388,20 +10959,24 @@ class Room$1 extends Emitter {
10388
10959
  Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10389
10960
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10390
10961
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10391
-
10392
- if (this.roomAudioElement && document.body) {
10393
- document.body.removeChild(this.roomAudioElement);
10394
- }
10962
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10963
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10395
10964
  }
10396
10965
 
10397
10966
  setSourceId(sourceId ) {
10398
- logger$2.info('set room source id', { sourceId });
10967
+ logger$3.info('set room source id', { sourceId });
10399
10968
 
10400
10969
  this.sourceId = sourceId;
10401
10970
  }
10402
10971
 
10972
+ setMeetingUuid(meetingUuid ) {
10973
+ logger$3.info('set meeting uuid', { meetingUuid });
10974
+
10975
+ this.meetingUuid = meetingUuid;
10976
+ }
10977
+
10403
10978
  setCallId(callId ) {
10404
- logger$2.info('set room call id', { callId });
10979
+ logger$3.info('set room call id', { callId });
10405
10980
 
10406
10981
  if (callId) {
10407
10982
  this.callId = callId;
@@ -10409,7 +10984,7 @@ class Room$1 extends Emitter {
10409
10984
  }
10410
10985
 
10411
10986
  setName(name ) {
10412
- logger$2.info('set room name', { name });
10987
+ logger$3.info('set room name', { name });
10413
10988
 
10414
10989
  this.name = name;
10415
10990
  }
@@ -10428,7 +11003,7 @@ class Room$1 extends Emitter {
10428
11003
  }
10429
11004
 
10430
11005
  async startScreenSharing(constraints ) {
10431
- logger$2.info('start room screen sharing', { constraints });
11006
+ logger$3.info('start room screen sharing', { constraints });
10432
11007
 
10433
11008
  const screensharingStream = await Wazo.Phone.startScreenSharing(constraints, this.callSession);
10434
11009
  if (!screensharingStream) {
@@ -10441,18 +11016,26 @@ class Room$1 extends Emitter {
10441
11016
  return screensharingStream;
10442
11017
  }
10443
11018
 
10444
- stopScreenSharing(restoreLocalStream = true) {
10445
- logger$2.info('stop room screen sharing');
11019
+ async stopScreenSharing(restoreLocalStream = true) {
11020
+ logger$3.info('stop room screen sharing');
10446
11021
 
10447
- Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
11022
+ const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
10448
11023
 
10449
11024
  if (this.localParticipant) {
10450
11025
  this.localParticipant.onStopScreensharing();
10451
11026
  }
11027
+
11028
+ if (!reinvited && this.localParticipant) {
11029
+ // When we had video and we made a screenshare we don't reinvite when stopping the screensahre
11030
+ // So not REINVITE even is fired, we have to restore the video stream manually
11031
+ const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
11032
+ // $FlowFixMe
11033
+ this._associateStreamTo(localVideoStream, this.localParticipant);
11034
+ }
10452
11035
  }
10453
11036
 
10454
11037
  turnCameraOff() {
10455
- logger$2.info('turn room camera off');
11038
+ logger$3.info('turn room camera off');
10456
11039
 
10457
11040
  Wazo.Phone.turnCameraOff(this.callSession);
10458
11041
 
@@ -10462,7 +11045,7 @@ class Room$1 extends Emitter {
10462
11045
  }
10463
11046
 
10464
11047
  turnCameraOn() {
10465
- logger$2.info('turn room camera on');
11048
+ logger$3.info('turn room camera on');
10466
11049
 
10467
11050
  Wazo.Phone.turnCameraOn(this.callSession);
10468
11051
 
@@ -10472,7 +11055,7 @@ class Room$1 extends Emitter {
10472
11055
  }
10473
11056
 
10474
11057
  mute() {
10475
- logger$2.info('mute room');
11058
+ logger$3.info('mute room');
10476
11059
 
10477
11060
  Wazo.Phone.mute(this.callSession);
10478
11061
 
@@ -10480,7 +11063,7 @@ class Room$1 extends Emitter {
10480
11063
  }
10481
11064
 
10482
11065
  unmute() {
10483
- logger$2.info('unmute room');
11066
+ logger$3.info('unmute room');
10484
11067
 
10485
11068
  Wazo.Phone.unmute(this.callSession);
10486
11069
 
@@ -10500,7 +11083,7 @@ class Room$1 extends Emitter {
10500
11083
  }
10501
11084
 
10502
11085
  hold() {
10503
- logger$2.info('hold room');
11086
+ logger$3.info('hold room');
10504
11087
 
10505
11088
  Wazo.Phone.hold(this.callSession, true);
10506
11089
 
@@ -10510,7 +11093,7 @@ class Room$1 extends Emitter {
10510
11093
  }
10511
11094
 
10512
11095
  resume() {
10513
- logger$2.info('resume room');
11096
+ logger$3.info('resume room');
10514
11097
 
10515
11098
  Wazo.Phone.resume(this.callSession, true);
10516
11099
 
@@ -10520,13 +11103,13 @@ class Room$1 extends Emitter {
10520
11103
  }
10521
11104
 
10522
11105
  sendDTMF(tone ) {
10523
- logger$2.info('send room DTMF', { tone });
11106
+ logger$3.info('send room DTMF', { tone });
10524
11107
 
10525
11108
  Wazo.Phone.sendDTMF(tone, this.callSession);
10526
11109
  }
10527
11110
 
10528
11111
  async sendReinvite(newConstraints = null) {
10529
- logger$2.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
11112
+ logger$3.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
10530
11113
  const wasScreensharing = this.localParticipant && this.localParticipant.screensharing;
10531
11114
 
10532
11115
  Wazo.Phone.on(Wazo.Phone.ON_SHARE_SCREEN_STARTED, () => {
@@ -10551,6 +11134,22 @@ class Room$1 extends Emitter {
10551
11134
  return response;
10552
11135
  }
10553
11136
 
11137
+ hasALocalVideoTrack() {
11138
+ return Wazo.Phone.hasALocalVideoTrack(this.callSession);
11139
+ }
11140
+
11141
+ getLocalStream() {
11142
+ return Wazo.Phone.getLocalStream(this.callSession);
11143
+ }
11144
+
11145
+ getRemoteStream() {
11146
+ return Wazo.Phone.getRemoteStream(this.callSession);
11147
+ }
11148
+
11149
+ getRemoteVideoStream() {
11150
+ return Wazo.Phone.getRemoteVideoStream(this.callSession);
11151
+ }
11152
+
10554
11153
  _bindEvents() {
10555
11154
  if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
10556
11155
  return;
@@ -10569,35 +11168,18 @@ class Room$1 extends Emitter {
10569
11168
  Wazo.Phone.phone.on(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10570
11169
 
10571
11170
  this.on(this.ON_AUDIO_STREAM, stream => {
10572
- logger$2.info('on room audio stream');
11171
+ logger$3.info('on room audio stream');
10573
11172
 
10574
11173
  this.audioStream = stream;
10575
- if (document.createElement) {
10576
- // $FlowFixMe
10577
- let roomAudioElement = document.getElementById('audio-room');
10578
- if (!this.roomAudioElement) {
10579
- roomAudioElement = document.createElement('audio');
10580
- // $FlowFixMe
10581
- document.body.appendChild(roomAudioElement);
10582
- }
10583
- if (!roomAudioElement) {
10584
- return;
10585
- }
10586
- this.roomAudioElement = roomAudioElement;
11174
+ if (!this.roomAudioElement) {
11175
+ const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11176
+ this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
10587
11177
  this.roomAudioElement.srcObject = stream;
10588
- this.roomAudioElement.autoplay = true;
10589
- this.roomAudioElement.id = 'audio-room';
10590
-
10591
- // $FlowFixMe
10592
- if (this.roomAudioElement.setSinkId) {
10593
- // $FlowFixMe
10594
- this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
10595
- }
10596
11178
  }
10597
11179
  });
10598
11180
 
10599
11181
  this.on(this.ON_VIDEO_STREAM, (stream, streamId, event, sipSession) => {
10600
- logger$2.info('on room video stream', { streamId });
11182
+ logger$3.info('on room video stream', { streamId });
10601
11183
 
10602
11184
  this._mapMsid(sipSession.body.body);
10603
11185
 
@@ -10612,7 +11194,7 @@ class Room$1 extends Emitter {
10612
11194
  });
10613
11195
 
10614
11196
  this.on(this.ON_REMOVE_STREAM, stream => {
10615
- logger$2.info('on room remove stream');
11197
+ logger$3.info('on room remove stream');
10616
11198
 
10617
11199
  const participant = this.participants.find(someParticipant =>
10618
11200
  someParticipant.streams.find(someStream => someStream && someStream.id === stream.id));
@@ -10667,6 +11249,9 @@ class Room$1 extends Emitter {
10667
11249
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10668
11250
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10669
11251
 
11252
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11253
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11254
+
10670
11255
  // Phone events
10671
11256
  Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
10672
11257
  Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
@@ -10677,15 +11262,15 @@ class Room$1 extends Emitter {
10677
11262
  Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
10678
11263
  }
10679
11264
 
10680
- _onMessage(message ) {
11265
+ _onMessage(message ) {
10681
11266
  if (message.method !== 'MESSAGE') {
10682
- return;
11267
+ return null;
10683
11268
  }
10684
11269
  let body;
10685
11270
  try {
10686
11271
  body = JSON.parse(message.body);
10687
11272
  } catch (e) {
10688
- return;
11273
+ return null;
10689
11274
  }
10690
11275
 
10691
11276
  switch (body.type) {
@@ -10704,6 +11289,8 @@ class Room$1 extends Emitter {
10704
11289
  }
10705
11290
 
10706
11291
  this.eventEmitter.emit(this.ON_MESSAGE, body);
11292
+
11293
+ return body;
10707
11294
  }
10708
11295
 
10709
11296
  _onChat(content ) {
@@ -10739,7 +11326,7 @@ class Room$1 extends Emitter {
10739
11326
  const requester = this._getParticipantFromCallId(origin.callId);
10740
11327
  if (requester) {
10741
11328
  // @FIXME?: when need to trigger an update on join-in; this is a bit of a hack
10742
- logger$2.info('trigger room requester status', { origin });
11329
+ logger$3.info('trigger room requester status', { origin });
10743
11330
  requester.triggerUpdate('REQUESTER_UPDATE');
10744
11331
  }
10745
11332
  break;
@@ -10768,25 +11355,26 @@ class Room$1 extends Emitter {
10768
11355
  const session = Wazo.Auth.getSession();
10769
11356
  let participants = [];
10770
11357
 
10771
- // @TODO: we could use a better function name here
10772
- const isJoining = part => {
10773
- this.__associateStreams(part);
10774
- // @VALIDATE: no need to publicize ourselves, no?
10775
- if (part instanceof RemoteParticipant) {
10776
- this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
10777
- }
10778
- };
10779
-
10780
11358
  // When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
10781
11359
  if (participant.user_uuid === session.uuid) {
10782
- logger$2.info('room current user joined');
11360
+ logger$3.info('room current user joined');
10783
11361
 
10784
11362
  // Retrieve participants via an API calls
10785
11363
  const conferenceId = this.sourceId || payload.data.conference_id;
10786
- const response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
10787
- logger$2.info('fetching conference participants', { conferenceId });
11364
+ let response;
11365
+ try {
11366
+ if (this.meetingUuid) {
11367
+ logger$3.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
11368
+ response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
11369
+ } else {
11370
+ logger$3.info('fetching conference participants', { conferenceId });
11371
+ response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
11372
+ }
11373
+ } catch (e) {
11374
+ logger$3.error('room participants fetching, error', e);
11375
+ }
10788
11376
  if (response) {
10789
- logger$2.info('conference participants fetched', { nb: response.items.length });
11377
+ logger$3.info('conference participants fetched', { nb: response.items.length });
10790
11378
  participants = response.items.map(item => {
10791
11379
  const isMe = item.call_id === this.callId;
10792
11380
 
@@ -10799,25 +11387,10 @@ class Room$1 extends Emitter {
10799
11387
 
10800
11388
  const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
10801
11389
  if (!this.localParticipant && localParticipant) {
10802
- this.localParticipant = localParticipant;
10803
-
10804
- const localVideoStream = this._getLocalVideoStream();
10805
- if (localVideoStream) {
10806
- this._saveLocalVideoStream(localVideoStream);
10807
- }
10808
-
10809
- this.connected = true;
10810
-
10811
- // we're in the room, now let's request everyone's status
10812
- if (this.localParticipant) {
10813
- this.sendSignal({
10814
- type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
10815
- origin: this.localParticipant.getStatus(),
10816
- });
10817
- }
11390
+ this._onLocalParticipantJoined(localParticipant);
10818
11391
  }
10819
11392
 
10820
- participants.forEach(someParticipant => isJoining(someParticipant));
11393
+ participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
10821
11394
  this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
10822
11395
  }
10823
11396
 
@@ -10828,16 +11401,45 @@ class Room$1 extends Emitter {
10828
11401
  ? new Wazo.RemoteParticipant(this, participant)
10829
11402
  : null;
10830
11403
 
10831
- logger$2.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
11404
+ logger$3.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
10832
11405
 
10833
11406
  if (remoteParticipant) {
10834
11407
  this.participants.push(remoteParticipant);
10835
- isJoining(remoteParticipant);
11408
+ this._isParticipantJoining(remoteParticipant);
10836
11409
  }
10837
11410
 
10838
11411
  return remoteParticipant;
10839
11412
  }
10840
11413
 
11414
+ _onLocalParticipantJoined(localParticipant ) {
11415
+ this.localParticipant = localParticipant;
11416
+
11417
+ const localVideoStream = this._getLocalVideoStream();
11418
+ if (localVideoStream) {
11419
+ this._saveLocalVideoStream(localVideoStream);
11420
+ }
11421
+
11422
+ this.connected = true;
11423
+
11424
+ localParticipant.broadcastStatus();
11425
+
11426
+ // we're in the room, now let's request everyone's status
11427
+ if (this.localParticipant) {
11428
+ this.sendSignal({
11429
+ type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
11430
+ origin: this.localParticipant.getStatus(),
11431
+ });
11432
+ }
11433
+ }
11434
+
11435
+ _isParticipantJoining(participant ) {
11436
+ this.__associateStreams(participant);
11437
+ // @VALIDATE: no need to publicize ourselves, no?
11438
+ if (participant instanceof RemoteParticipant) {
11439
+ this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
11440
+ }
11441
+ }
11442
+
10841
11443
  _saveLocalVideoStream(stream ) {
10842
11444
  const { localParticipant } = this;
10843
11445
 
@@ -10883,9 +11485,11 @@ class Room$1 extends Emitter {
10883
11485
  _onParticipantTrackUpdate(oldParticipant , update ) {
10884
11486
  const newParticipant = oldParticipant;
10885
11487
 
10886
- const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
11488
+ const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
10887
11489
  const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
10888
- const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
11490
+ // Can't use `getReceivers` here because on FF we make the mapping based on the streamId
11491
+ const stream = pc.getRemoteStreams().find(someStream =>
11492
+ someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
10889
11493
 
10890
11494
  if (update === 'downgrade') {
10891
11495
  newParticipant.streams = [];
@@ -10915,15 +11519,41 @@ class Room$1 extends Emitter {
10915
11519
  return;
10916
11520
  }
10917
11521
 
10918
- if (this._unassociatedVideoStreams[trackId]) {
11522
+ const streamId = this._getStreamIdFrTrackId(trackId);
11523
+ const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
11524
+ const stream = this._unassociatedVideoStreams[key];
11525
+
11526
+ if (stream) {
10919
11527
  // Try to associate stream
10920
- this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
11528
+ this._associateStreamTo(stream, participant);
10921
11529
 
10922
- delete this._unassociatedVideoStreams[trackId];
11530
+ delete this._unassociatedVideoStreams[key];
10923
11531
  delete this._unassociatedParticipants[participant.callId];
10924
11532
  }
10925
11533
  }
10926
11534
 
11535
+ _getUnassociatedMapIdFromTrackIdOrStreamId(trackId , streamId ) {
11536
+ // Find by trackId
11537
+ if (trackId in this._unassociatedVideoStreams) {
11538
+ return trackId;
11539
+ }
11540
+
11541
+ // Find by streamId
11542
+ if (streamId && streamId in this._unassociatedVideoStreams) {
11543
+ return streamId;
11544
+ }
11545
+
11546
+ // Find in all the streams by streamId (used on FF where we can't map by trackId)
11547
+ const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream ) => stream.id === streamId);
11548
+ return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
11549
+ }
11550
+
11551
+ _getStreamIdFrTrackId(trackId ) {
11552
+ const mapping = Object.values(this._callIdStreamIdMap).find((map ) => map.trackId === trackId);
11553
+
11554
+ return mapping ? mapping.streamId : null;
11555
+ }
11556
+
10927
11557
  _associateStreamTo(rawStream , participant ) {
10928
11558
  const stream = new Wazo.Stream(rawStream, participant);
10929
11559
  participant.streams.push(stream);
@@ -10947,7 +11577,141 @@ class Room$1 extends Emitter {
10947
11577
 
10948
11578
  //
10949
11579
 
10950
- class LocalParticipant extends Participant {
11580
+ const logger$2 = IssueReporter$1.loggerFor('sdk-sip-room');
11581
+
11582
+ class SipRoom extends Room$1 {
11583
+
11584
+ static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
11585
+ logger$2.info('connecting to sip room', { extension, audioOnly, room: !!room });
11586
+
11587
+ if (!room) {
11588
+ await Wazo.Phone.connect();
11589
+
11590
+ const withCamera = constraints && !!constraints.video;
11591
+
11592
+ const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
11593
+ // eslint-disable-next-line no-param-reassign
11594
+ room = new SipRoom(callSession, extension, null, null, extra);
11595
+ }
11596
+
11597
+ if (room && room.callSession && room.callSession.call) {
11598
+ room.setCallId(room.callSession.call.id);
11599
+ }
11600
+
11601
+ logger$2.info('connected to room', {
11602
+ extension: room.extension,
11603
+ });
11604
+
11605
+ return room;
11606
+ }
11607
+
11608
+ mute() {
11609
+ logger$2.info('mute sip room');
11610
+
11611
+ Wazo.Phone.mute(this.callSession, false);
11612
+
11613
+ this.sendMuteStatus();
11614
+ }
11615
+
11616
+ unmute() {
11617
+ logger$2.info('unmute sip room');
11618
+
11619
+ Wazo.Phone.unmute(this.callSession, false);
11620
+
11621
+ this.sendUnMuteStatus();
11622
+ }
11623
+
11624
+ getLocalGuestName() {
11625
+ return Wazo.Phone.phone.client.userAgent.options.displayName;
11626
+ }
11627
+
11628
+ // Overridden to not listen to websocket messages
11629
+ _transferEvents() {
11630
+ // Phone events
11631
+ Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
11632
+ Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
11633
+ Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
11634
+ Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
11635
+
11636
+ [this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
11637
+ Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
11638
+ }
11639
+
11640
+ _onMessage(message ) {
11641
+ // eslint-disable-next-line no-underscore-dangle
11642
+ const body = super._onMessage(message);
11643
+ if (!body) {
11644
+ return;
11645
+ }
11646
+
11647
+ const getChannel = () => body.channels[0];
11648
+
11649
+ switch (body.type) {
11650
+ case 'ConfbridgeWelcome':
11651
+ body.channels.forEach(channel => {
11652
+ this._onParticipantJoined(channel);
11653
+ });
11654
+
11655
+ break;
11656
+ case 'ConfbridgeJoin': {
11657
+ const channel = getChannel();
11658
+ this._onParticipantJoined(channel);
11659
+ break;
11660
+ }
11661
+ case 'ConfbridgeLeave': {
11662
+ const channel = getChannel();
11663
+ this._onParticipantLeft({
11664
+ data: {
11665
+ call_id: channel.id,
11666
+ },
11667
+ });
11668
+ break;
11669
+ }
11670
+ }
11671
+ }
11672
+
11673
+ async _onParticipantJoined(channel ) {
11674
+ const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
11675
+ const callId = channel.id;
11676
+ const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
11677
+ const name = channel.caller ? channel.caller.name : null;
11678
+ const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
11679
+ const participant = new ParticipantClass(this, {
11680
+ caller_id_name: name,
11681
+ call_id: callId,
11682
+ }, extra);
11683
+
11684
+ const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
11685
+ if (participantIdx !== -1 && name) {
11686
+ this.participants[participantIdx].name = name;
11687
+ return;
11688
+ }
11689
+
11690
+ if (isLocal) {
11691
+ // Should be updated by the Wazo WS but we don't have it for now
11692
+ if (this.callSession) {
11693
+ this.callSession.ringing = false;
11694
+ }
11695
+
11696
+ this._onLocalParticipantJoined(participant);
11697
+
11698
+ // Give some time for the stream to be updated
11699
+ setTimeout(() => {
11700
+ this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
11701
+ }, 1000);
11702
+ }
11703
+
11704
+ this.participants.push(participant);
11705
+
11706
+ this._isParticipantJoining(participant);
11707
+
11708
+ return participant;
11709
+ }
11710
+
11711
+ _getCurrentSipCallIs() {
11712
+ return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11713
+ }
11714
+
10951
11715
  }
10952
11716
 
10953
11717
  /* global document */
@@ -11000,9 +11764,7 @@ class Stream {
11000
11764
  return false;
11001
11765
  }
11002
11766
 
11003
- // With canvas track (used to fake upgrade in conference), we don't have a width
11004
- return this.htmlStream.getTracks().find(track => track.kind === 'video'
11005
- && track.readyState !== 'ended' && 'width' in track.getSettings());
11767
+ return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
11006
11768
  }
11007
11769
 
11008
11770
  get id() {
@@ -11903,6 +12665,7 @@ const Wazo = {
11903
12665
  Phone: Phone$1,
11904
12666
  Websocket: Websocket$1,
11905
12667
  Room: Room$1,
12668
+ SipRoom,
11906
12669
  RemoteParticipant,
11907
12670
  LocalParticipant,
11908
12671
  Stream,
@@ -11922,6 +12685,7 @@ const Wazo = {
11922
12685
  ServerError,
11923
12686
  Call,
11924
12687
  CallLog,
12688
+ CTIPhone,
11925
12689
  Recording,
11926
12690
  ChatMessage,
11927
12691
  ChatRoom,
@@ -11937,6 +12701,8 @@ const Wazo = {
11937
12701
  CallSession,
11938
12702
  IndirectTransfer,
11939
12703
  SwitchboardCall,
12704
+ WebRTCPhone,
12705
+ Meeting,
11940
12706
  },
11941
12707
 
11942
12708
  // Api