@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);
@@ -4859,7 +5330,7 @@ var getApiClient = (forServer ) => {
4859
5330
  class InvalidSubscription extends Error {}
4860
5331
  class InvalidAuthorization extends Error {}
4861
5332
 
4862
- const logger$8 = IssueReporter$1.loggerFor('simple-auth');
5333
+ const logger$9 = IssueReporter$1.loggerFor('simple-auth');
4863
5334
 
4864
5335
  class Auth {
4865
5336
 
@@ -4894,7 +5365,7 @@ class Auth {
4894
5365
  setApiClientId(this.clientId);
4895
5366
  setRefreshExpiration(this.expiration);
4896
5367
  setOnRefreshToken((token , session ) => {
4897
- logger$8.info('on refresh token done', { token });
5368
+ logger$9.info('on refresh token done', { token });
4898
5369
  setApiToken(token);
4899
5370
  Wazo.Websocket.updateToken(token);
4900
5371
 
@@ -5453,7 +5924,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5453
5924
  .then(() => {
5454
5925
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5455
5926
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5456
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5927
+ if (this.peerConnection.addTransceiver) {
5928
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5929
+ }
5457
5930
  }
5458
5931
  })
5459
5932
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5480,12 +5953,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5480
5953
  };
5481
5954
  })
5482
5955
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5483
- .then((sessionDescription) => {
5484
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5485
- this.localMediaStreamConstraints = options.constraints;
5486
-
5487
- return sessionDescription;
5488
- })
5489
5956
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5490
5957
  .catch((error) => {
5491
5958
  wazoLogger.error('error when creating media', error);
@@ -5680,6 +6147,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5680
6147
 
5681
6148
  // set the transceiver direction to the answer direction
5682
6149
  this._peerConnection.getTransceivers().forEach((transceiver) => {
6150
+ if (transceiver.stopped) {
6151
+ return;
6152
+ }
5683
6153
  if (transceiver.direction /* guarding, but should always be true */) {
5684
6154
  const { receiver } = transceiver;
5685
6155
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5724,10 +6194,15 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5724
6194
  if (kind !== 'audio' && kind !== 'video') {
5725
6195
  throw new Error(`Unknown new track kind ${kind}.`);
5726
6196
  }
5727
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
6197
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
6198
+ otherSender.track && otherSender.track.kind === kind);
5728
6199
 
5729
6200
  // Do not reuse sender video tracks in SFU
5730
6201
  if (sender && (!sfu || newTrack.kind === 'audio')) {
6202
+ if (sender.track) {
6203
+ // eslint-disable-next-line no-param-reassign
6204
+ newTrack.enabled = sender.track.enabled;
6205
+ }
5731
6206
  trackUpdates.push(
5732
6207
  new Promise((resolve) => {
5733
6208
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5761,7 +6236,11 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5761
6236
  // Review: could make streamless tracks a configurable option?
5762
6237
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5763
6238
  try {
5764
- pc.addTrack(newTrack, localStream);
6239
+ if (pc.addTrack) {
6240
+ pc.addTrack(newTrack, localStream);
6241
+ } else {
6242
+ pc.addStream(localStream);
6243
+ }
5765
6244
  } catch (error) {
5766
6245
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5767
6246
  throw error;
@@ -5897,7 +6376,7 @@ const DEFAULT_ICE_TIMEOUT = 3000;
5897
6376
  const SEND_STATS_DELAY = 5000;
5898
6377
 
5899
6378
  const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
5900
- const logger$7 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
6379
+ const logger$8 = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-client') : console;
5901
6380
  const statsLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-stats') : console;
5902
6381
 
5903
6382
  // events
@@ -5943,6 +6422,7 @@ const MAX_REGISTER_TRIES = 10;
5943
6422
 
5944
6423
 
5945
6424
 
6425
+
5946
6426
 
5947
6427
 
5948
6428
 
@@ -5969,6 +6449,7 @@ class WebRTCClient extends Emitter {
5969
6449
 
5970
6450
 
5971
6451
 
6452
+
5972
6453
 
5973
6454
  // sugar
5974
6455
 
@@ -6007,6 +6488,8 @@ class WebRTCClient extends Emitter {
6007
6488
  super();
6008
6489
  this.uaConfigOverrides = uaConfigOverrides;
6009
6490
  this.config = config;
6491
+ this.skipRegister = config.skipRegister;
6492
+
6010
6493
  this._buildConfig(config, session).then((newConfig ) => {
6011
6494
  this.config = newConfig;
6012
6495
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -6062,13 +6545,13 @@ class WebRTCClient extends Emitter {
6062
6545
 
6063
6546
  createUserAgent(configOverrides ) {
6064
6547
  const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
6065
- logger$7.info('sdk webrtc, creating UA', { webRTCConfiguration });
6548
+ logger$8.info('sdk webrtc, creating UA', { webRTCConfiguration });
6066
6549
 
6067
6550
  webRTCConfiguration.delegate = {
6068
6551
  onConnect: this.onConnect.bind(this),
6069
6552
  onDisconnect: this.onDisconnect.bind(this),
6070
6553
  onInvite: (invitation ) => {
6071
- logger$7.info('sdk webrtc on invite', {
6554
+ logger$8.info('sdk webrtc on invite', {
6072
6555
  method: 'delegate.onInvite',
6073
6556
  id: invitation.id,
6074
6557
  remoteURI: invitation.remoteURI,
@@ -6111,7 +6594,7 @@ class WebRTCClient extends Emitter {
6111
6594
  }
6112
6595
 
6113
6596
  onConnect() {
6114
- logger$7.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6597
+ logger$8.info('sdk webrtc connected', { method: 'delegate.onConnect' });
6115
6598
  this.eventEmitter.emit(CONNECTED);
6116
6599
  if (!this.isRegistered() && this.registerer && this.registerer.waiting) {
6117
6600
  this.registerer.waitingToggle(false);
@@ -6120,7 +6603,7 @@ class WebRTCClient extends Emitter {
6120
6603
  }
6121
6604
 
6122
6605
  async onDisconnect(error ) {
6123
- logger$7.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6606
+ logger$8.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
6124
6607
  this.connectionPromise = null;
6125
6608
  // The UA will attempt to reconnect automatically when an error occurred
6126
6609
  this.eventEmitter.emit(DISCONNECTED, error);
@@ -6134,40 +6617,48 @@ class WebRTCClient extends Emitter {
6134
6617
  }
6135
6618
 
6136
6619
  register(tries = 0) {
6137
- logger$7.info('sdk webrtc registering...', {
6620
+ const logInfo = {
6138
6621
  userAgent: !!this.userAgent,
6139
6622
  registered: this.isRegistered(),
6140
6623
  connectionPromise: !!this.connectionPromise,
6141
6624
  registerer: !!this.registerer,
6142
6625
  waiting: this.registerer && this.registerer.waiting,
6143
6626
  tries,
6144
- });
6627
+ skipRegister: this.skipRegister,
6628
+ };
6629
+
6630
+ if (this.skipRegister) {
6631
+ logger$8.info('sdk webrtc skip register...', logInfo);
6632
+ return Promise.resolve();
6633
+ }
6634
+
6635
+ logger$8.info('sdk webrtc registering...', logInfo);
6145
6636
 
6146
6637
  if (!this.userAgent) {
6147
- logger$7.info('sdk webrtc recreating User Agent');
6638
+ logger$8.info('sdk webrtc recreating User Agent');
6148
6639
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6149
6640
  }
6150
6641
  if (!this.userAgent || this.isRegistered()) {
6151
- logger$7.info('sdk webrtc registering aborted, already registered or no UA can be created');
6642
+ logger$8.info('sdk webrtc registering aborted, already registered or no UA can be created');
6152
6643
  return Promise.resolve();
6153
6644
  }
6154
6645
 
6155
6646
  if (this.connectionPromise || (this.registerer && this.registerer.waiting)) {
6156
- logger$7.info('sdk webrtc registering aborted due to a registration in progress.');
6647
+ logger$8.info('sdk webrtc registering aborted due to a registration in progress.');
6157
6648
  return Promise.resolve();
6158
6649
  }
6159
6650
 
6160
6651
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6161
6652
 
6162
6653
  const onRegisterFailed = () => {
6163
- logger$7.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6654
+ logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6164
6655
  this.connectionPromise = null;
6165
6656
  if (this.registerer && this.registerer.waiting) {
6166
6657
  this.registerer.waitingToggle(false);
6167
6658
  }
6168
6659
 
6169
6660
  if (tries <= MAX_REGISTER_TRIES) {
6170
- logger$7.info('sdk webrtc registering, retrying...', { tries });
6661
+ logger$8.info('sdk webrtc registering, retrying...', { tries });
6171
6662
  setTimeout(() => this.register(tries + 1), 300);
6172
6663
  }
6173
6664
  };
@@ -6176,18 +6667,18 @@ class WebRTCClient extends Emitter {
6176
6667
  // Avoid race condition with the close method called just before register and setting userAgent to null
6177
6668
  // during the resolution of the primise.
6178
6669
  if (!this.userAgent) {
6179
- logger$7.info('sdk webrtc recreating User Agent after connection');
6670
+ logger$8.info('sdk webrtc recreating User Agent after connection');
6180
6671
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
6181
6672
  }
6182
6673
 
6183
- logger$7.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6674
+ logger$8.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
6184
6675
  this.registerer = new Registerer(this.userAgent, registerOptions);
6185
6676
  this.connectionPromise = null;
6186
6677
  this._monkeyPatchRegisterer(this.registerer);
6187
6678
 
6188
6679
  // Bind registerer events
6189
6680
  this.registerer.stateChange.addListener(newState => {
6190
- logger$7.info('sdk webrtc registering, state changed', { newState });
6681
+ logger$8.info('sdk webrtc registering, state changed', { newState });
6191
6682
 
6192
6683
  if (newState === RegistererState.Registered && this.registerer
6193
6684
  && this.registerer.state === RegistererState.Registered) {
@@ -6200,7 +6691,7 @@ class WebRTCClient extends Emitter {
6200
6691
  const options = {
6201
6692
  requestDelegate: {
6202
6693
  onReject: response => {
6203
- logger$7.error('sdk webrtc registering, rejected', { response });
6694
+ logger$8.error('sdk webrtc registering, rejected', { response });
6204
6695
 
6205
6696
  onRegisterFailed();
6206
6697
  },
@@ -6208,13 +6699,13 @@ class WebRTCClient extends Emitter {
6208
6699
  };
6209
6700
 
6210
6701
  return this.registerer.register(options).catch((e) => {
6211
- logger$7.error('sdk webrtc registering, error', e);
6702
+ logger$8.error('sdk webrtc registering, error', e);
6212
6703
 
6213
6704
  this.eventEmitter.emit(REGISTRATION_FAILED);
6214
6705
  return e;
6215
6706
  });
6216
6707
  }).catch(error => {
6217
- logger$7.error('sdk webrtc registering, transport error', error);
6708
+ logger$8.error('sdk webrtc registering, transport error', error);
6218
6709
  onRegisterFailed();
6219
6710
  });
6220
6711
  }
@@ -6243,21 +6734,21 @@ class WebRTCClient extends Emitter {
6243
6734
  }
6244
6735
 
6245
6736
  unregister() {
6246
- logger$7.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6737
+ logger$8.info('sdk webrtc unregistering..', { userAgent: !!this.userAgent, registerer: !!this.registerer });
6247
6738
  if (!this.registerer) {
6248
6739
  return Promise.resolve();
6249
6740
  }
6250
6741
 
6251
6742
  try {
6252
6743
  return this.registerer.unregister().then(() => {
6253
- logger$7.info('sdk webrtc unregistered');
6744
+ logger$8.info('sdk webrtc unregistered');
6254
6745
  this._cleanupRegister();
6255
6746
  }).catch(e => {
6256
- logger$7.error('sdk webrtc unregistering, promise error', e);
6747
+ logger$8.error('sdk webrtc unregistering, promise error', e);
6257
6748
  this._cleanupRegister();
6258
6749
  });
6259
6750
  } catch (e) {
6260
- logger$7.error('sdk webrtc unregistering, error', e);
6751
+ logger$8.error('sdk webrtc unregistering, error', e);
6261
6752
  // Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
6262
6753
  // error when the registerer is in a bad state
6263
6754
  this._cleanupRegister();
@@ -6265,7 +6756,7 @@ class WebRTCClient extends Emitter {
6265
6756
  }
6266
6757
 
6267
6758
  stop() {
6268
- logger$7.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6759
+ logger$8.info('sdk webrtc stop', { userAgent: !!this.userAgent });
6269
6760
  if (!this.userAgent) {
6270
6761
  return Promise.resolve();
6271
6762
  }
@@ -6273,12 +6764,12 @@ class WebRTCClient extends Emitter {
6273
6764
  return this.userAgent.stop().then(() => {
6274
6765
  return this._cleanupRegister();
6275
6766
  }).catch(e => {
6276
- logger$7.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6767
+ logger$8.warn('sdk webrtc stop, error', { message: e.message, stack: e.stack });
6277
6768
  });
6278
6769
  }
6279
6770
 
6280
6771
  call(number , enableVideo , audioOnly = false, conference = false) {
6281
- logger$7.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6772
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6282
6773
  const inviterOptions = {
6283
6774
  sessionDescriptionHandlerOptionsReInvite: {
6284
6775
  conference,
@@ -6307,7 +6798,7 @@ class WebRTCClient extends Emitter {
6307
6798
  this._onAccepted(session, response.session, true);
6308
6799
  },
6309
6800
  onReject: (response ) => {
6310
- logger$7.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6801
+ logger$8.info('on call rejected', { id: session.id, fromTag: session.fromTag });
6311
6802
  this._stopSendingStats(session);
6312
6803
 
6313
6804
  this.eventEmitter.emit(REJECTED, session, response);
@@ -6329,11 +6820,11 @@ class WebRTCClient extends Emitter {
6329
6820
  }
6330
6821
 
6331
6822
  answer(session , enableVideo ) {
6332
- logger$7.info('sdk webrtc answer call', { id: session.id, enableVideo });
6823
+ logger$8.info('sdk webrtc answer call', { id: session.id, enableVideo });
6333
6824
 
6334
6825
  if (!session || !session.accept) {
6335
6826
  const error = 'No session to answer, or not an invitation';
6336
- logger$7.warn(error);
6827
+ logger$8.warn(error);
6337
6828
  return Promise.reject(new Error(error));
6338
6829
  }
6339
6830
  const options = {
@@ -6343,15 +6834,15 @@ class WebRTCClient extends Emitter {
6343
6834
  return session.accept(options).then(() => {
6344
6835
  if (session.isCanceled) {
6345
6836
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
6346
- logger$7.error(message, { id: session.id });
6837
+ logger$8.error(message, { id: session.id });
6347
6838
  this.onCallEnded(session);
6348
6839
 
6349
6840
  throw new CanceledCallError(message);
6350
6841
  }
6351
- logger$7.info('sdk webrtc answer, accepted.');
6842
+ logger$8.info('sdk webrtc answer, accepted.');
6352
6843
  this._onAccepted(session);
6353
6844
  }).catch(e => {
6354
- logger$7.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6845
+ logger$8.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
6355
6846
 
6356
6847
  throw e;
6357
6848
  });
@@ -6359,7 +6850,7 @@ class WebRTCClient extends Emitter {
6359
6850
 
6360
6851
  hangup(session ) {
6361
6852
  const { state, id } = session;
6362
- logger$7.info('sdk webrtc hangup call', { id, state });
6853
+ logger$8.info('sdk webrtc hangup call', { id, state });
6363
6854
 
6364
6855
  try {
6365
6856
  this._stopSendingStats(session);
@@ -6388,24 +6879,24 @@ class WebRTCClient extends Emitter {
6388
6879
 
6389
6880
  return bye();
6390
6881
  } catch (error) {
6391
- logger$7.warn('sdk webrtc hangup, error', error);
6882
+ logger$8.warn('sdk webrtc hangup, error', error);
6392
6883
  }
6393
6884
 
6394
6885
  return null;
6395
6886
  }
6396
6887
 
6397
6888
  reject(session ) {
6398
- logger$7.info('sdk webrtc reject call', { id: session.id });
6889
+ logger$8.info('sdk webrtc reject call', { id: session.id });
6399
6890
 
6400
6891
  try {
6401
6892
  return session.reject ? session.reject() : session.cancel();
6402
6893
  } catch (e) {
6403
- logger$7.warn('Error when rejecting call', e.message, e.stack);
6894
+ logger$8.warn('Error when rejecting call', e.message, e.stack);
6404
6895
  }
6405
6896
  }
6406
6897
 
6407
6898
  async close() {
6408
- logger$7.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6899
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6409
6900
  this._cleanupMedia();
6410
6901
  this.connectionPromise = null;
6411
6902
 
@@ -6436,7 +6927,7 @@ class WebRTCClient extends Emitter {
6436
6927
  // eg: "INVITE not rejectable in state Completed"
6437
6928
  }
6438
6929
  this.userAgent = null;
6439
- logger$7.info('sdk webrtc client closed');
6930
+ logger$8.info('sdk webrtc client closed');
6440
6931
  }
6441
6932
 
6442
6933
  getNumber(session ) {
@@ -6449,13 +6940,13 @@ class WebRTCClient extends Emitter {
6449
6940
  }
6450
6941
 
6451
6942
  mute(session ) {
6452
- logger$7.info('sdk webrtc mute', { id: session.id });
6943
+ logger$8.info('sdk webrtc mute', { id: session.id });
6453
6944
 
6454
6945
  this._toggleAudio(session, true);
6455
6946
  }
6456
6947
 
6457
6948
  unmute(session ) {
6458
- logger$7.info('sdk webrtc unmute', { id: session.id });
6949
+ logger$8.info('sdk webrtc unmute', { id: session.id });
6459
6950
 
6460
6951
  this._toggleAudio(session, false);
6461
6952
  }
@@ -6472,12 +6963,18 @@ class WebRTCClient extends Emitter {
6472
6963
  }
6473
6964
 
6474
6965
  if (pc.getSenders) {
6966
+ if (!pc.getSenders().length) {
6967
+ return false;
6968
+ }
6475
6969
  pc.getSenders().forEach(sender => {
6476
6970
  if (sender && sender.track && sender.track.kind === 'audio') {
6477
6971
  muted = muted && !sender.track.enabled;
6478
6972
  }
6479
6973
  });
6480
6974
  } else {
6975
+ if (!pc.getLocalStreams().length) {
6976
+ return false;
6977
+ }
6481
6978
  pc.getLocalStreams().forEach(stream => {
6482
6979
  stream.getAudioTracks().forEach(track => {
6483
6980
  muted = muted && !track.enabled;
@@ -6489,20 +6986,20 @@ class WebRTCClient extends Emitter {
6489
6986
  }
6490
6987
 
6491
6988
  toggleCameraOn(session ) {
6492
- logger$7.info('sdk webrtc toggle camera on', { id: session.id });
6989
+ logger$8.info('sdk webrtc toggle camera on', { id: session.id });
6493
6990
 
6494
6991
  this._toggleVideo(session, false);
6495
6992
  }
6496
6993
 
6497
6994
  toggleCameraOff(session ) {
6498
- logger$7.info('sdk webrtc toggle camera off', { id: session.id });
6995
+ logger$8.info('sdk webrtc toggle camera off', { id: session.id });
6499
6996
 
6500
6997
  this._toggleVideo(session, true);
6501
6998
  }
6502
6999
 
6503
7000
  hold(session , isConference = false) {
6504
7001
  const sessionId = this.getSipSessionId(session);
6505
- logger$7.info('sdk webrtc hold', {
7002
+ logger$8.info('sdk webrtc hold', {
6506
7003
  sessionId,
6507
7004
  keys: Object.keys(this.heldSessions),
6508
7005
  pendingReinvite: !!session.pendingReinvite,
@@ -6534,6 +7031,9 @@ class WebRTCClient extends Emitter {
6534
7031
  if (!this._isWeb()) {
6535
7032
  options.sessionDescriptionHandlerModifiers = [holdModifier];
6536
7033
  }
7034
+ options.sessionDescriptionHandlerOptions = {
7035
+ constraints: options.constraints,
7036
+ };
6537
7037
 
6538
7038
  // Send re-INVITE
6539
7039
  return session.invite(options);
@@ -6542,7 +7042,7 @@ class WebRTCClient extends Emitter {
6542
7042
  unhold(session , isConference = false) {
6543
7043
  const sessionId = this.getSipSessionId(session);
6544
7044
 
6545
- logger$7.info('sdk webrtc unhold', {
7045
+ logger$8.info('sdk webrtc unhold', {
6546
7046
  sessionId,
6547
7047
  keys: Object.keys(this.heldSessions),
6548
7048
  pendingReinvite: !!session.pendingReinvite,
@@ -6573,6 +7073,9 @@ class WebRTCClient extends Emitter {
6573
7073
  // (eg: holdModifier)
6574
7074
  options.sessionDescriptionHandlerModifiers = [];
6575
7075
  }
7076
+ options.sessionDescriptionHandlerOptions = {
7077
+ constraints: options.constraints,
7078
+ };
6576
7079
 
6577
7080
  // Send re-INVITE
6578
7081
  return session.invite(options);
@@ -6630,7 +7133,7 @@ class WebRTCClient extends Emitter {
6630
7133
  return;
6631
7134
  }
6632
7135
 
6633
- logger$7.info('send WebRTC message', { sipId: sipSession.id, contentType });
7136
+ logger$8.info('send WebRTC message', { sipId: sipSession.id, contentType });
6634
7137
 
6635
7138
  try {
6636
7139
  sipSession.message({
@@ -6755,7 +7258,8 @@ class WebRTCClient extends Emitter {
6755
7258
  }
6756
7259
  const sdh = session.sessionDescriptionHandler;
6757
7260
  const pc = sdh.peerConnection;
6758
- const localStream = this.getLocalStream(this.getSipSessionId(session));
7261
+ const sessionId = this.getSipSessionId(session);
7262
+ const localStream = this.getLocalStream(sessionId);
6759
7263
 
6760
7264
  // Release old video stream
6761
7265
  if (localStream) {
@@ -6781,11 +7285,8 @@ class WebRTCClient extends Emitter {
6781
7285
 
6782
7286
  // let's update the local stream
6783
7287
  this.eventEmitter.emit('onVideoInputChange', stream);
6784
- try {
6785
- await sdh.setLocalMediaStream(stream);
6786
- } catch (_) {
6787
- // Nothing to do
6788
- }
7288
+ this.setLocalMediaStream(sessionId, stream);
7289
+
6789
7290
  return stream;
6790
7291
  });
6791
7292
  }
@@ -6997,7 +7498,7 @@ class WebRTCClient extends Emitter {
6997
7498
  }
6998
7499
 
6999
7500
  startHeartbeat() {
7000
- logger$7.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7501
+ logger$8.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
7001
7502
  if (!this.userAgent) {
7002
7503
  this.heartbeat.stop();
7003
7504
  return;
@@ -7010,7 +7511,7 @@ class WebRTCClient extends Emitter {
7010
7511
  }
7011
7512
 
7012
7513
  stopHeartbeat() {
7013
- logger$7.info('sdk webrtc stop heartbeat');
7514
+ logger$8.info('sdk webrtc stop heartbeat');
7014
7515
  this.heartbeat.stop();
7015
7516
  }
7016
7517
 
@@ -7030,7 +7531,7 @@ class WebRTCClient extends Emitter {
7030
7531
  }
7031
7532
 
7032
7533
  attemptReconnection() {
7033
- logger$7.info('attempt reconnection', { userAgent: !!this.userAgent });
7534
+ logger$8.info('attempt reconnection', { userAgent: !!this.userAgent });
7034
7535
  if (!this.userAgent) {
7035
7536
  return;
7036
7537
  }
@@ -7087,9 +7588,11 @@ class WebRTCClient extends Emitter {
7087
7588
  remoteStream.removeTrack(track);
7088
7589
  });
7089
7590
 
7090
- pc.getReceivers().forEach(receiver => {
7091
- remoteStream.addTrack(receiver.track);
7092
- });
7591
+ if (pc.getReceivers) {
7592
+ pc.getReceivers().forEach(receiver => {
7593
+ remoteStream.addTrack(receiver.track);
7594
+ });
7595
+ }
7093
7596
  }
7094
7597
 
7095
7598
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -7124,6 +7627,25 @@ class WebRTCClient extends Emitter {
7124
7627
  return sessionId in this.conferences;
7125
7628
  }
7126
7629
 
7630
+ createAudioElementFor(sessionId ) {
7631
+ const audio = document.createElement('audio');
7632
+ audio.setAttribute('id', `audio-${sessionId}`);
7633
+
7634
+ if (audio.setSinkId && this.audioOutputDeviceId) {
7635
+ audio.setSinkId(this.audioOutputDeviceId);
7636
+ }
7637
+
7638
+ if (document.body) {
7639
+ document.body.appendChild(audio);
7640
+ }
7641
+ this.audioElements[sessionId] = audio;
7642
+
7643
+ audio.volume = this.audioOutputVolume;
7644
+ audio.autoplay = true;
7645
+
7646
+ return audio;
7647
+ }
7648
+
7127
7649
  _onTransportError() {
7128
7650
  this.eventEmitter.emit(TRANSPORT_ERROR);
7129
7651
  this.attemptReconnection();
@@ -7133,7 +7655,7 @@ class WebRTCClient extends Emitter {
7133
7655
  const body = message && typeof message === 'object' ? message.data : message;
7134
7656
  if (body && body.indexOf('200 OK') !== -1) {
7135
7657
  if (this.hasHeartbeat()) {
7136
- logger$7.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7658
+ logger$8.info('on heartbeat received from Asterisk', { hasHeartbeat: this.hasHeartbeat() });
7137
7659
 
7138
7660
  this.heartbeat.onHeartbeat();
7139
7661
  if (this.heartbeatCb) {
@@ -7144,7 +7666,7 @@ class WebRTCClient extends Emitter {
7144
7666
  }
7145
7667
 
7146
7668
  async _onHeartbeatTimeout() {
7147
- logger$7.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7669
+ logger$8.info('sdk webrtc heartbeat timed out', { userAgent: !!this.userAgent, cb: !!this.heartbeatTimeoutCb });
7148
7670
 
7149
7671
  if (this.heartbeatTimeoutCb) {
7150
7672
  this.heartbeatTimeoutCb();
@@ -7156,7 +7678,7 @@ class WebRTCClient extends Emitter {
7156
7678
  try {
7157
7679
  await this.userAgent.transport.disconnect();
7158
7680
  } catch (e) {
7159
- logger$7.error('Transport disconnection after heartbeat timeout, error', e);
7681
+ logger$8.error('Transport disconnection after heartbeat timeout, error', e);
7160
7682
  }
7161
7683
  }
7162
7684
 
@@ -7189,31 +7711,31 @@ class WebRTCClient extends Emitter {
7189
7711
  }
7190
7712
 
7191
7713
  _connectIfNeeded() {
7192
- logger$7.info('connect if needed, checking', { connected: this.isConnected() });
7714
+ logger$8.info('connect if needed, checking', { connected: this.isConnected() });
7193
7715
  if (!this.userAgent) {
7194
- logger$7.info('need to recreate User Agent');
7716
+ logger$8.info('need to recreate User Agent');
7195
7717
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
7196
7718
  }
7197
7719
 
7198
7720
  if (this.isConnected()) {
7199
- logger$7.info('webrtc sdk, already connected');
7721
+ logger$8.info('webrtc sdk, already connected');
7200
7722
  return Promise.resolve();
7201
7723
  }
7202
7724
 
7203
7725
  if (this.isConnecting()) {
7204
- logger$7.info('webrtc sdk, already connecting...');
7726
+ logger$8.info('webrtc sdk, already connecting...');
7205
7727
 
7206
7728
  this.connectionPromise = this.userAgent.transport.connectPromise;
7207
7729
  return this.connectionPromise;
7208
7730
  }
7209
7731
 
7210
7732
  if (this.connectionPromise) {
7211
- logger$7.info('webrtc sdk, connection promise connecting...');
7733
+ logger$8.info('webrtc sdk, connection promise connecting...');
7212
7734
  // $FlowFixMe
7213
7735
  return this.connectionPromise;
7214
7736
  }
7215
7737
 
7216
- logger$7.info('WebRTC UA needs to connect');
7738
+ logger$8.info('WebRTC UA needs to connect');
7217
7739
 
7218
7740
  // Force UA to reconnect
7219
7741
  if (this.userAgent && this.userAgent.state !== UserAgentState.Stopped) {
@@ -7338,7 +7860,7 @@ class WebRTCClient extends Emitter {
7338
7860
 
7339
7861
  sdh.peerConnectionDelegate = {
7340
7862
  onicecandidateerror: (error ) => {
7341
- logger$7.error('on icecandidate error', {
7863
+ logger$8.error('on icecandidate error', {
7342
7864
  address: error.address,
7343
7865
  port: error.port,
7344
7866
  errorCode: error.errorCode,
@@ -7353,7 +7875,7 @@ class WebRTCClient extends Emitter {
7353
7875
  let hadRemoteVideo = false;
7354
7876
 
7355
7877
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7356
- // Becase when `onInvite` is called we already got the video track
7878
+ // Because when `onInvite` is called we already got the video track
7357
7879
  session.onInviteRequest = (request) => {
7358
7880
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7359
7881
 
@@ -7367,7 +7889,7 @@ class WebRTCClient extends Emitter {
7367
7889
  updatedNumber = session.assertedIdentity.uri.normal.user;
7368
7890
  updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
7369
7891
  }
7370
- logger$7.info('re-invite received', { updatedCalleeName, updatedNumber });
7892
+ logger$8.info('re-invite received', { updatedCalleeName, updatedNumber });
7371
7893
 
7372
7894
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
7373
7895
 
@@ -7388,7 +7910,7 @@ class WebRTCClient extends Emitter {
7388
7910
  }
7389
7911
 
7390
7912
  _onAccepted(session , sessionDialog , withEvent = true) {
7391
- logger$7.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7913
+ logger$8.info('on call accepted', { id: session.id, remoteTag: session.remoteTag });
7392
7914
 
7393
7915
  this.storeSipSession(session);
7394
7916
 
@@ -7428,20 +7950,10 @@ class WebRTCClient extends Emitter {
7428
7950
  const isConference = this.isConference(sessionId);
7429
7951
 
7430
7952
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7431
- const audio = document.createElement('audio');
7432
- audio.setAttribute('id', `audio-${sessionId}`);
7433
-
7434
- if (audio.setSinkId && this.audioOutputDeviceId) {
7435
- audio.setSinkId(this.audioOutputDeviceId);
7436
- }
7437
-
7438
- if (document.body) {
7439
- document.body.appendChild(audio);
7440
- }
7441
- this.audioElements[sessionId] = audio;
7953
+ this.createAudioElementFor(sessionId);
7442
7954
  }
7443
7955
 
7444
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7956
+ const audioElement = this.audioElements[sessionId];
7445
7957
  const stream = newStream || this.getRemoteStream(sessionId);
7446
7958
 
7447
7959
  if (!this._isWeb() || !stream) {
@@ -7588,10 +8100,10 @@ class WebRTCClient extends Emitter {
7588
8100
 
7589
8101
  _stopSendingStats(session ) {
7590
8102
  const sessionId = this.getSipSessionId(session);
7591
- logger$7.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
8103
+ logger$8.trace('Check for stopping stats', { sessionId, ids: Object.keys(this.statsIntervals) });
7592
8104
 
7593
8105
  if (sessionId in this.statsIntervals) {
7594
- logger$7.trace('Stop sending stats for call', { sessionId });
8106
+ logger$8.trace('Stop sending stats for call', { sessionId });
7595
8107
  this.statsIntervals[sessionId]();
7596
8108
  delete this.statsIntervals[sessionId];
7597
8109
  }
@@ -7607,7 +8119,7 @@ class WebRTCClient extends Emitter {
7607
8119
  try {
7608
8120
  await this.userAgent.transport.disconnect();
7609
8121
  } catch (e) {
7610
- logger$7.error('WebRTC transport disconnect, error', e);
8122
+ logger$8.error('WebRTC transport disconnect, error', e);
7611
8123
  }
7612
8124
  }
7613
8125
  }
@@ -7694,7 +8206,7 @@ const events = [
7694
8206
  ON_SIGNAL,
7695
8207
  ];
7696
8208
 
7697
- const logger$6 = IssueReporter$1.loggerFor('webrtc-phone');
8209
+ const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
7698
8210
 
7699
8211
  class WebRTCPhone extends Emitter {
7700
8212
 
@@ -7765,7 +8277,7 @@ class WebRTCPhone extends Emitter {
7765
8277
  }).catch(error => {
7766
8278
  // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
7767
8279
  console.error('register error', error, error.message, error.stack);
7768
- logger$6.error('WebRTC register error', { message: error.message, stack: error.stack });
8280
+ logger$7.error('WebRTC register error', { message: error.message, stack: error.stack });
7769
8281
  });
7770
8282
  }
7771
8283
 
@@ -7780,7 +8292,7 @@ class WebRTCPhone extends Emitter {
7780
8292
  if (!this.client) {
7781
8293
  return;
7782
8294
  }
7783
- logger$6.info('WebRTC phone stop');
8295
+ logger$7.info('WebRTC phone stop');
7784
8296
  this.client.stop();
7785
8297
  }
7786
8298
 
@@ -7795,14 +8307,14 @@ class WebRTCPhone extends Emitter {
7795
8307
  async sendReinvite(callSession , constraints = null, conference = false,
7796
8308
  audioOnly = false) {
7797
8309
  const sipSession = this.findSipSession(callSession);
7798
- logger$6.info('WebRTC phone - send reinvite', {
8310
+ logger$7.info('WebRTC phone - send reinvite', {
7799
8311
  sessionId: sipSession ? sipSession.id : null,
7800
8312
  constraints,
7801
8313
  audioOnly,
7802
8314
  });
7803
8315
 
7804
8316
  if (!sipSession) {
7805
- return null;
8317
+ return false;
7806
8318
  }
7807
8319
 
7808
8320
  // $FlowFixMe
@@ -7812,19 +8324,17 @@ class WebRTCPhone extends Emitter {
7812
8324
  // Downgrade
7813
8325
  if (constraints && !isUpgrade) {
7814
8326
  // No reinvite needed
7815
- return this._downgradeToAudio(callSession);
8327
+ this._downgradeToAudio(callSession);
8328
+ return false;
7816
8329
  }
7817
8330
 
7818
8331
  if (isUpgrade) {
7819
8332
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
7820
8333
  if (!shouldReinvite) {
7821
- return;
8334
+ return false;
7822
8335
  }
7823
8336
  }
7824
8337
 
7825
- // Force reinvite in SDH
7826
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
7827
-
7828
8338
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
7829
8339
  }
7830
8340
 
@@ -7833,7 +8343,7 @@ class WebRTCPhone extends Emitter {
7833
8343
  }
7834
8344
 
7835
8345
  startHeartbeat() {
7836
- logger$6.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
8346
+ logger$7.info('WebRTC phone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
7837
8347
  if (!this.client || this.client.hasHeartbeat()) {
7838
8348
  return;
7839
8349
  }
@@ -7842,7 +8352,7 @@ class WebRTCPhone extends Emitter {
7842
8352
  }
7843
8353
 
7844
8354
  stopHeartbeat() {
7845
- logger$6.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
8355
+ logger$7.info('WebRTC phone - stopHeartbeat', { client: !!this.client });
7846
8356
  if (!this.client) {
7847
8357
  return;
7848
8358
  }
@@ -7859,7 +8369,7 @@ class WebRTCPhone extends Emitter {
7859
8369
  }
7860
8370
 
7861
8371
  reconnect() {
7862
- logger$6.info('WebRTC phone - reconnect', { client: !!this.client });
8372
+ logger$7.info('WebRTC phone - reconnect', { client: !!this.client });
7863
8373
  if (!this.client) {
7864
8374
  return;
7865
8375
  }
@@ -7897,7 +8407,7 @@ class WebRTCPhone extends Emitter {
7897
8407
  _downgradeToAudio(callSession ) {
7898
8408
  const sipSession = this.findSipSession(callSession);
7899
8409
  if (!sipSession) {
7900
- return;
8410
+ return false;
7901
8411
  }
7902
8412
 
7903
8413
  // Release local video stream when downgrading to audio
@@ -8010,7 +8520,7 @@ class WebRTCPhone extends Emitter {
8010
8520
  // Monkey patch to know when canceled with the CANCEL message
8011
8521
  const onCancel = sipSession._onCancel.bind(sipSession);
8012
8522
  sipSession._onCancel = (message ) => {
8013
- logger$6.trace('on sip session canceled', { callId: message.callId });
8523
+ logger$7.trace('on sip session canceled', { callId: message.callId });
8014
8524
 
8015
8525
  onCancel(message);
8016
8526
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
@@ -8035,13 +8545,13 @@ class WebRTCPhone extends Emitter {
8035
8545
  this.audioOutputVolume,
8036
8546
  );
8037
8547
  case SessionState.Terminating:
8038
- logger$6.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8548
+ logger$7.info('WebRTC phone - call terminating', { sipId: sipSession.id });
8039
8549
 
8040
8550
  this.eventEmitter.emit(ON_CALL_ENDING, this._createCallSession(sipSession));
8041
8551
 
8042
8552
  break;
8043
8553
  case SessionState.Terminated:
8044
- logger$6.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8554
+ logger$7.info('WebRTC phone - call terminated', { sipId: sipSession.id });
8045
8555
 
8046
8556
  this._onCallTerminated(sipSession);
8047
8557
 
@@ -8077,7 +8587,7 @@ class WebRTCPhone extends Emitter {
8077
8587
  }
8078
8588
 
8079
8589
  async startScreenSharing(constraints , callSession ) {
8080
- logger$6.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8590
+ logger$7.info('WebRTC - start screen sharing', { constraints, id: callSession ? callSession.getId() : null });
8081
8591
 
8082
8592
  const screenShareStream = await this._getStreamFromConstraints(constraints);
8083
8593
  if (!screenShareStream) {
@@ -8099,6 +8609,10 @@ class WebRTCPhone extends Emitter {
8099
8609
  localStream.removeTrack(videoTrack);
8100
8610
  }
8101
8611
 
8612
+ if (localStream) {
8613
+ localStream.addTrack(screenTrack);
8614
+ }
8615
+
8102
8616
  if (sender) {
8103
8617
  sender.replaceTrack(screenTrack);
8104
8618
  }
@@ -8113,7 +8627,8 @@ class WebRTCPhone extends Emitter {
8113
8627
  return;
8114
8628
  }
8115
8629
 
8116
- logger$6.info('WebRTC phone - stop screen sharing');
8630
+ logger$7.info('WebRTC phone - stop screen sharing');
8631
+ let reinvited = false;
8117
8632
 
8118
8633
  try {
8119
8634
  if (this.currentScreenShare.stream) {
@@ -8128,7 +8643,8 @@ class WebRTCPhone extends Emitter {
8128
8643
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
8129
8644
  // We have to downgrade to audio.
8130
8645
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
8131
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
8646
+ const constraints = { audio: false, video: screenshareStopped };
8647
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
8132
8648
  }
8133
8649
  } catch (e) {
8134
8650
  console.warn(e);
@@ -8142,6 +8658,8 @@ class WebRTCPhone extends Emitter {
8142
8658
  );
8143
8659
 
8144
8660
  this.currentScreenShare = null;
8661
+
8662
+ return reinvited;
8145
8663
  }
8146
8664
 
8147
8665
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -8179,7 +8697,7 @@ class WebRTCPhone extends Emitter {
8179
8697
  }
8180
8698
 
8181
8699
  _onCallAccepted(sipSession , cameraEnabled ) {
8182
- logger$6.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8700
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
8183
8701
 
8184
8702
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
8185
8703
  this.currentSipSession = sipSession;
@@ -8197,11 +8715,15 @@ class WebRTCPhone extends Emitter {
8197
8715
  }
8198
8716
 
8199
8717
  changeAudioDevice(id ) {
8200
- logger$6.info('WebRTC phone - change audio device', { deviceId: id });
8718
+ logger$7.info('WebRTC phone - change audio device', { deviceId: id });
8201
8719
  this.audioOutputDeviceId = id;
8202
8720
  this.client.changeAudioOutputDevice(id);
8203
8721
  }
8204
8722
 
8723
+ createAudioElementFor(sessionId ) {
8724
+ return this.client.createAudioElementFor(sessionId);
8725
+ }
8726
+
8205
8727
  changeRingDevice(id ) {
8206
8728
  this.audioRingDeviceId = id;
8207
8729
  }
@@ -8218,25 +8740,25 @@ class WebRTCPhone extends Emitter {
8218
8740
  }
8219
8741
 
8220
8742
  changeAudioInputDevice(id ) {
8221
- logger$6.info('WebRTC phone - changeAudio input device', { deviceId: id });
8743
+ logger$7.info('WebRTC phone - changeAudio input device', { deviceId: id });
8222
8744
 
8223
8745
  return this.client.changeAudioInputDevice(id, this.currentSipSession);
8224
8746
  }
8225
8747
 
8226
8748
  changeVideoInputDevice(id ) {
8227
- logger$6.info('WebRTC phone - change video input device', { deviceId: id });
8749
+ logger$7.info('WebRTC phone - change video input device', { deviceId: id });
8228
8750
 
8229
8751
  return this.client.changeVideoInputDevice(id, this.currentSipSession);
8230
8752
  }
8231
8753
 
8232
8754
  changeSessionVideoInputDevice(id ) {
8233
- logger$6.info('WebRTC phone - change session video input device', { deviceId: id });
8755
+ logger$7.info('WebRTC phone - change session video input device', { deviceId: id });
8234
8756
 
8235
8757
  return this.client.changeSessionVideoInputDevice(id, this.currentSipSession);
8236
8758
  }
8237
8759
 
8238
8760
  _onCallTerminated(sipSession ) {
8239
- logger$6.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8761
+ logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
8240
8762
 
8241
8763
  const callSession = this._createCallSession(sipSession);
8242
8764
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
@@ -8270,7 +8792,7 @@ class WebRTCPhone extends Emitter {
8270
8792
  const hasIncomingCallSession = this.hasIncomingCallSession();
8271
8793
 
8272
8794
  // Re-trigger incoming call event for remaining incoming calls
8273
- logger$6.info('WebRTC phone - check to re-trigger incoming call', {
8795
+ logger$7.info('WebRTC phone - check to re-trigger incoming call', {
8274
8796
  sipId: sipSession.id,
8275
8797
  shouldRetrigger,
8276
8798
  hasIncomingCallSession,
@@ -8359,37 +8881,37 @@ class WebRTCPhone extends Emitter {
8359
8881
 
8360
8882
  // Deprecated
8361
8883
  getLocalStreamForCall(callSession ) {
8362
- logger$6.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8884
+ logger$7.warn('WebRTCPhone.getLocalStreamForCall is deprecated, use WebRTCPhone.getLocalStream instead');
8363
8885
 
8364
8886
  return this.getLocalStream(callSession);
8365
8887
  }
8366
8888
 
8367
8889
  // Deprecated
8368
8890
  getRemoteStreamForCall(callSession ) {
8369
- logger$6.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8891
+ logger$7.warn('WebRTCPhone.getRemoteStreamForCall is deprecated, use WebRTCPhone.getRemoteStream instead');
8370
8892
 
8371
8893
  return this.getRemoteVideoStream(callSession);
8372
8894
  }
8373
8895
 
8374
8896
  getRemoteStreamsForCall(callSession ) {
8375
- logger$6.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8897
+ logger$7.warn('WebRTCPhone.getRemoteStreamsForCall is deprecated, use WebRTCPhone.getRemoteStreams instead');
8376
8898
 
8377
8899
  return this.getRemoteStream(callSession);
8378
8900
  }
8379
8901
 
8380
8902
  accept(callSession , cameraEnabled ) {
8381
- logger$6.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8903
+ logger$7.info('WebRTC phone - accept call', { id: callSession ? callSession.getId() : 'n/a', cameraEnabled });
8382
8904
  if (this.currentSipSession) {
8383
8905
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
8384
8906
  }
8385
8907
 
8386
8908
  if (!callSession) {
8387
- logger$6.warn('no CallSession to accept.');
8909
+ logger$7.warn('no CallSession to accept.');
8388
8910
  return Promise.resolve(null);
8389
8911
  }
8390
8912
 
8391
8913
  if (callSession.getId() in this.acceptedSessions) {
8392
- logger$6.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8914
+ logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
8393
8915
  return Promise.resolve(callSession.sipCallId);
8394
8916
  }
8395
8917
 
@@ -8401,24 +8923,24 @@ class WebRTCPhone extends Emitter {
8401
8923
  const sipSession = this.client.getSipSession(callSession.getId());
8402
8924
  if (sipSession) {
8403
8925
  if (sipSession.state === SessionState.Terminated || sipSession.state === SessionState.Terminating) {
8404
- logger$6.warn('Trying to answer a terminated sipSession.');
8926
+ logger$7.warn('Trying to answer a terminated sipSession.');
8405
8927
 
8406
8928
  return Promise.resolve(null);
8407
8929
  }
8408
8930
 
8409
- logger$6.info('accept call, session found', { sipId: sipSession.id });
8931
+ logger$7.info('accept call, session found', { sipId: sipSession.id });
8410
8932
 
8411
8933
  // $FlowFixMe
8412
8934
  return this.client.answer(sipSession, this.allowVideo ? cameraEnabled : false).then(() => {
8413
8935
  return callSession.sipCallId;
8414
8936
  }).catch(e => {
8415
- logger$6.error(e);
8937
+ logger$7.error(e);
8416
8938
  this.endCurrentCall(callSession);
8417
8939
  throw e;
8418
8940
  });
8419
8941
  }
8420
8942
 
8421
- logger$6.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8943
+ logger$7.warn('no CallSession found to accept.', { id: callSession ? callSession.getId() : 'n/a' });
8422
8944
 
8423
8945
  return Promise.resolve(null);
8424
8946
  }
@@ -8428,7 +8950,7 @@ class WebRTCPhone extends Emitter {
8428
8950
  }
8429
8951
 
8430
8952
  async reject(callSession ) {
8431
- logger$6.info('reject WebRTC called', { id: callSession.getId() });
8953
+ logger$7.info('reject WebRTC called', { id: callSession.getId() });
8432
8954
 
8433
8955
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call rejected locally');
8434
8956
  if (!callSession || callSession.getId() in this.rejectedSessions) {
@@ -8440,14 +8962,14 @@ class WebRTCPhone extends Emitter {
8440
8962
 
8441
8963
  const sipSession = this.findSipSession(callSession);
8442
8964
  if (sipSession) {
8443
- logger$6.info('WebRTC rejecting', { sipId: sipSession.id });
8965
+ logger$7.info('WebRTC rejecting', { sipId: sipSession.id });
8444
8966
 
8445
8967
  this.client.hangup(sipSession);
8446
8968
  }
8447
8969
  }
8448
8970
 
8449
8971
  async ignore(callSession ) {
8450
- logger$6.info('WebRTC ignore', { id: callSession.getId() });
8972
+ logger$7.info('WebRTC ignore', { id: callSession.getId() });
8451
8973
 
8452
8974
  // kill the ring
8453
8975
  this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'ignoring call');
@@ -8456,7 +8978,7 @@ class WebRTCPhone extends Emitter {
8456
8978
  }
8457
8979
 
8458
8980
  hold(callSession , withEvent = true, isConference = false) {
8459
- logger$6.info('WebRTC hold', { id: callSession.getId() });
8981
+ logger$7.info('WebRTC hold', { id: callSession.getId() });
8460
8982
 
8461
8983
  const sipSession = this.findSipSession(callSession);
8462
8984
 
@@ -8467,7 +8989,7 @@ class WebRTCPhone extends Emitter {
8467
8989
 
8468
8990
  // @Deprecated
8469
8991
  unhold(callSession , withEvent = true, isConference = false) {
8470
- logger$6.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8992
+ logger$7.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
8471
8993
 
8472
8994
  console.warn('Please note that `phone.unhold()` is being deprecated; `phone.resume()` is the preferred method');
8473
8995
 
@@ -8482,7 +9004,7 @@ class WebRTCPhone extends Emitter {
8482
9004
  const sipSession = this.findSipSession(callSession);
8483
9005
 
8484
9006
  if (sipSession) {
8485
- logger$6.info('WebRTC atxfer', { sipId: sipSession.id });
9007
+ logger$7.info('WebRTC atxfer', { sipId: sipSession.id });
8486
9008
 
8487
9009
  return this.client.atxfer(sipSession);
8488
9010
  }
@@ -8497,7 +9019,7 @@ class WebRTCPhone extends Emitter {
8497
9019
  if (!sipSession) {
8498
9020
  return new Promise((resolve, reject) => reject(new Error('No session to hold')));
8499
9021
  }
8500
- logger$6.info('WebRTC hold sip session', { sipId: sipSession.id });
9022
+ logger$7.info('WebRTC hold sip session', { sipId: sipSession.id });
8501
9023
 
8502
9024
  const promise = this.client.hold(sipSession, isConference);
8503
9025
  if (withEvent) {
@@ -8516,7 +9038,7 @@ class WebRTCPhone extends Emitter {
8516
9038
  if (!sipSession) {
8517
9039
  return new Promise((resolve, reject) => reject(new Error('No session to unhold')));
8518
9040
  }
8519
- logger$6.info('WebRTC unhold', { sipId: sipSession.id });
9041
+ logger$7.info('WebRTC unhold', { sipId: sipSession.id });
8520
9042
 
8521
9043
  const promise = this.client.unhold(sipSession, isConference);
8522
9044
  if (withEvent) {
@@ -8527,18 +9049,18 @@ class WebRTCPhone extends Emitter {
8527
9049
  }
8528
9050
 
8529
9051
  resume(callSession , isConference = false) {
8530
- logger$6.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
9052
+ logger$7.info('WebRTC resume called', { id: callSession ? callSession.getId() : null });
8531
9053
 
8532
9054
  const sipSession = this.findSipSession(callSession);
8533
9055
  if (!sipSession) {
8534
9056
  return new Promise((resolve, reject) => reject(new Error('No session to resume')));
8535
9057
  }
8536
9058
 
8537
- logger$6.info('WebRTC resuming', { sipId: sipSession.id });
9059
+ logger$7.info('WebRTC resuming', { sipId: sipSession.id });
8538
9060
 
8539
9061
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
8540
9062
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
8541
- logger$6.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9063
+ logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
8542
9064
  this.holdSipSession(this.currentSipSession, callSession);
8543
9065
  }
8544
9066
 
@@ -8553,14 +9075,14 @@ class WebRTCPhone extends Emitter {
8553
9075
  }
8554
9076
 
8555
9077
  mute(callSession , withEvent = true) {
8556
- logger$6.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
9078
+ logger$7.info('WebRTC mute called', { id: callSession ? callSession.getId() : null });
8557
9079
 
8558
9080
  const sipSession = this.findSipSession(callSession);
8559
9081
  if (!sipSession) {
8560
9082
  return;
8561
9083
  }
8562
9084
 
8563
- logger$6.info('WebRTC muting', { sipId: sipSession.id });
9085
+ logger$7.info('WebRTC muting', { sipId: sipSession.id });
8564
9086
  this.client.mute(sipSession);
8565
9087
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: true });
8566
9088
 
@@ -8574,14 +9096,14 @@ class WebRTCPhone extends Emitter {
8574
9096
  }
8575
9097
 
8576
9098
  unmute(callSession , withEvent = true) {
8577
- logger$6.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
9099
+ logger$7.info('WebRTC unmute called', { id: callSession ? callSession.getId() : null });
8578
9100
 
8579
9101
  const sipSession = this.findSipSession(callSession);
8580
9102
  if (!sipSession) {
8581
9103
  return;
8582
9104
  }
8583
9105
 
8584
- logger$6.info('WebRTC unmuting', { sipId: sipSession.id });
9106
+ logger$7.info('WebRTC unmuting', { sipId: sipSession.id });
8585
9107
  this.client.unmute(sipSession);
8586
9108
  const newCallSession = this._createCallSession(sipSession, callSession, { muted: false });
8587
9109
 
@@ -8608,7 +9130,7 @@ class WebRTCPhone extends Emitter {
8608
9130
  if (!sipSession) {
8609
9131
  return;
8610
9132
  }
8611
- logger$6.info('WebRTC turn camera on', { sipId: sipSession.id });
9133
+ logger$7.info('WebRTC turn camera on', { sipId: sipSession.id });
8612
9134
 
8613
9135
  this.client.toggleCameraOn(sipSession);
8614
9136
 
@@ -8620,7 +9142,7 @@ class WebRTCPhone extends Emitter {
8620
9142
  if (!sipSession) {
8621
9143
  return;
8622
9144
  }
8623
- logger$6.info('WebRTC turn camera off', { sipId: sipSession.id });
9145
+ logger$7.info('WebRTC turn camera off', { sipId: sipSession.id });
8624
9146
 
8625
9147
  this.client.toggleCameraOff(sipSession);
8626
9148
  this.eventEmitter.emit(ON_CAMERA_DISABLED, this._createCameraDisabledCallSession(sipSession, callSession));
@@ -8632,7 +9154,7 @@ class WebRTCPhone extends Emitter {
8632
9154
  return;
8633
9155
  }
8634
9156
 
8635
- logger$6.info('WebRTC send key', { sipId: sipSession.id, tone });
9157
+ logger$7.info('WebRTC send key', { sipId: sipSession.id, tone });
8636
9158
  this.client.sendDTMF(sipSession, tone);
8637
9159
  }
8638
9160
 
@@ -8640,7 +9162,7 @@ class WebRTCPhone extends Emitter {
8640
9162
  // @TODO: line is not used here
8641
9163
  async makeCall(number , line , cameraEnabled ,
8642
9164
  audioOnly = false, conference = false) {
8643
- logger$6.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9165
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
8644
9166
  if (!number) {
8645
9167
  return Promise.resolve(null);
8646
9168
  }
@@ -8650,7 +9172,7 @@ class WebRTCPhone extends Emitter {
8650
9172
  }
8651
9173
  if (this.currentSipSession) {
8652
9174
  this.holdSipSession(this.currentSipSession, this.currentCallSession, true).catch(e => {
8653
- logger$6.warn('Unable to hold current session when making another call', e);
9175
+ logger$7.warn('Unable to hold current session when making another call', e);
8654
9176
  });
8655
9177
  }
8656
9178
 
@@ -8660,7 +9182,7 @@ class WebRTCPhone extends Emitter {
8660
9182
  this._bindEvents(sipSession);
8661
9183
  } catch (error) {
8662
9184
  console.warn(error);
8663
- logger$6.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
9185
+ logger$7.warn('make WebRTC call, error', { message: error.message, stack: error.stack });
8664
9186
  return Promise.resolve(null);
8665
9187
  }
8666
9188
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
@@ -8688,7 +9210,7 @@ class WebRTCPhone extends Emitter {
8688
9210
  return;
8689
9211
  }
8690
9212
 
8691
- logger$6.info('WebRTC transfer', { sipId: sipSession.id, target });
9213
+ logger$7.info('WebRTC transfer', { sipId: sipSession.id, target });
8692
9214
 
8693
9215
  this.client.transfer(sipSession, target);
8694
9216
  }
@@ -8697,7 +9219,7 @@ class WebRTCPhone extends Emitter {
8697
9219
  const sipSession = this.client.getSipSession(source.sipCallId);
8698
9220
  const sipSessionTarget = this.client.getSipSession(destination.sipCallId);
8699
9221
 
8700
- logger$6.info('WebRTC indirect transfer', {
9222
+ logger$7.info('WebRTC indirect transfer', {
8701
9223
  sipId: sipSession ? sipSession.id : null,
8702
9224
  target: sipSessionTarget ? sipSessionTarget.id : null,
8703
9225
  });
@@ -8725,7 +9247,7 @@ class WebRTCPhone extends Emitter {
8725
9247
  return false;
8726
9248
  }
8727
9249
 
8728
- logger$6.info('WebRTC hangup', { sipId: sipSession.id });
9250
+ logger$7.info('WebRTC hangup', { sipId: sipSession.id });
8729
9251
 
8730
9252
  const sipSessionId = this.getSipSessionId(sipSession);
8731
9253
 
@@ -8770,7 +9292,7 @@ class WebRTCPhone extends Emitter {
8770
9292
  }
8771
9293
 
8772
9294
  async close() {
8773
- logger$6.info('WebRTC close');
9295
+ logger$7.info('WebRTC close');
8774
9296
 
8775
9297
  try {
8776
9298
  await Promise.race([
@@ -8778,7 +9300,7 @@ class WebRTCPhone extends Emitter {
8778
9300
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Unregister, timed out')), 3000)),
8779
9301
  ]);
8780
9302
  } catch (e) {
8781
- logger$6.error('WebRTC close, unregister error', e);
9303
+ logger$7.error('WebRTC close, unregister error', e);
8782
9304
  }
8783
9305
 
8784
9306
  this.client.close();
@@ -8796,12 +9318,12 @@ class WebRTCPhone extends Emitter {
8796
9318
  }
8797
9319
 
8798
9320
  enableRinging() {
8799
- logger$6.info('WebRTC enable ringing');
9321
+ logger$7.info('WebRTC enable ringing');
8800
9322
  this.ringingEnabled = true;
8801
9323
  }
8802
9324
 
8803
9325
  disableRinging() {
8804
- logger$6.info('WebRTC disable ringing');
9326
+ logger$7.info('WebRTC disable ringing');
8805
9327
  this.ringingEnabled = false;
8806
9328
  }
8807
9329
 
@@ -8841,7 +9363,7 @@ class WebRTCPhone extends Emitter {
8841
9363
 
8842
9364
  // Deprecated
8843
9365
  getLocalMediaStream(callSession ) {
8844
- logger$6.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
9366
+ logger$7.warn('WebRTCPhone.getLocalMediaStream is deprecated, use WebRTCPhone.getLocalStream instead');
8845
9367
  return this.getLocalStream(callSession);
8846
9368
  }
8847
9369
 
@@ -8849,6 +9371,10 @@ class WebRTCPhone extends Emitter {
8849
9371
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
8850
9372
  }
8851
9373
 
9374
+ hasALocalVideoTrack(callSession ) {
9375
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
9376
+ }
9377
+
8852
9378
  getRemoteStream(callSession ) {
8853
9379
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
8854
9380
  }
@@ -8871,7 +9397,7 @@ class WebRTCPhone extends Emitter {
8871
9397
  this.client.on(this.client.INVITE, (sipSession , wantsToDoVideo ) => {
8872
9398
  const autoAnswer = sipSession.request.getHeader('Answer-Mode') === 'Auto';
8873
9399
  const withVideo = this.allowVideo ? wantsToDoVideo : false;
8874
- logger$6.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
9400
+ logger$7.info('WebRTC invite received', { sipId: sipSession.id, withVideo, autoAnswer });
8875
9401
 
8876
9402
  const callSession = this._createIncomingCallSession(sipSession, withVideo, null, autoAnswer);
8877
9403
  this.incomingSessions.push(callSession.getId());
@@ -8894,7 +9420,7 @@ class WebRTCPhone extends Emitter {
8894
9420
  });
8895
9421
 
8896
9422
  this.client.on(this.client.ON_REINVITE, (...args) => {
8897
- logger$6.info('WebRTC on reinvite', {
9423
+ logger$7.info('WebRTC on reinvite', {
8898
9424
  sessionId: args[0].id,
8899
9425
  inviteId: args[1].id,
8900
9426
  updatedCalleeName: args[2],
@@ -8914,7 +9440,7 @@ class WebRTCPhone extends Emitter {
8914
9440
  });
8915
9441
 
8916
9442
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
8917
- logger$6.info('WebRTC call accepted', { sipId: sipSession.id });
9443
+ logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
8918
9444
 
8919
9445
  this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
8920
9446
 
@@ -8925,17 +9451,17 @@ class WebRTCPhone extends Emitter {
8925
9451
  this.client.on('ended', () => {});
8926
9452
 
8927
9453
  this.client.on(this.client.ON_ERROR, e => {
8928
- logger$6.error('WebRTC error', e);
9454
+ logger$7.error('WebRTC error', e);
8929
9455
  this.eventEmitter.emit(ON_CALL_ERROR, e);
8930
9456
  });
8931
9457
 
8932
9458
  this.client.on(this.client.UNREGISTERED, () => {
8933
- logger$6.info('WebRTC unregistered');
9459
+ logger$7.info('WebRTC unregistered');
8934
9460
  this.eventEmitter.emit(ON_UNREGISTERED);
8935
9461
  });
8936
9462
 
8937
9463
  this.client.on(this.client.REGISTERED, () => {
8938
- logger$6.info('WebRTC registered', {
9464
+ logger$7.info('WebRTC registered', {
8939
9465
  shouldSendReinvite: this.shouldSendReinvite,
8940
9466
  state: this.currentSipSession ? this.currentSipSession.state : null,
8941
9467
  currentSipSession: !!this.currentSipSession,
@@ -8951,19 +9477,19 @@ class WebRTCPhone extends Emitter {
8951
9477
  try {
8952
9478
  this.sendReinvite(this.currentCallSession);
8953
9479
  } catch (e) {
8954
- logger$6.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9480
+ logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
8955
9481
  }
8956
9482
  }
8957
9483
  });
8958
9484
 
8959
9485
  this.client.on(this.client.CONNECTED, () => {
8960
- logger$6.info('WebRTC client connected');
9486
+ logger$7.info('WebRTC client connected');
8961
9487
 
8962
9488
  this.stopHeartbeat();
8963
9489
  });
8964
9490
 
8965
9491
  this.client.on(this.client.DISCONNECTED, () => {
8966
- logger$6.info('WebRTC client disconnected');
9492
+ logger$7.info('WebRTC client disconnected');
8967
9493
 
8968
9494
  this.eventEmitter.emit(ON_UNREGISTERED);
8969
9495
 
@@ -9195,7 +9721,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9195
9721
 
9196
9722
  //
9197
9723
 
9198
- const logger$5 = IssueReporter$1.loggerFor('simple-phone');
9724
+ const logger$6 = IssueReporter$1.loggerFor('simple-phone');
9199
9725
  const sipLogger = IssueReporter$1.loggerFor('sip.js');
9200
9726
  const protocolLogger = IssueReporter$1.loggerFor('sip');
9201
9727
 
@@ -9302,7 +9828,7 @@ class Phone extends Emitter {
9302
9828
  async disconnect() {
9303
9829
  if (this.phone) {
9304
9830
  if (this.phone.hasAnActiveCall()) {
9305
- logger$5.info('hangup call on disconnect');
9831
+ logger$6.info('hangup call on disconnect');
9306
9832
  // $FlowFixMe
9307
9833
  await this.phone.hangup();
9308
9834
  }
@@ -9325,13 +9851,13 @@ class Phone extends Emitter {
9325
9851
  }
9326
9852
 
9327
9853
  async hangup(callSession ) {
9328
- logger$5.info('hangup via simple phone', { callId: callSession.getId() });
9854
+ logger$6.info('hangup via simple phone', { callId: callSession.getId() });
9329
9855
 
9330
9856
  return this.phone && this.phone.hangup(callSession);
9331
9857
  }
9332
9858
 
9333
9859
  async accept(callSession , cameraEnabled ) {
9334
- logger$5.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9860
+ logger$6.info('accept via simple phone', { callId: callSession.getId(), cameraEnabled });
9335
9861
 
9336
9862
  return this.phone && this.phone.accept(callSession, cameraEnabled);
9337
9863
  }
@@ -9351,13 +9877,18 @@ class Phone extends Emitter {
9351
9877
  return adHocConference.start();
9352
9878
  }
9353
9879
 
9354
- mute(callSession ) {
9355
- this.muteViaAPI(callSession);
9880
+ mute(callSession , withApi = true) {
9881
+ if (withApi) {
9882
+ this.muteViaAPI(callSession);
9883
+ }
9884
+
9356
9885
  return this.phone && this.phone.mute(callSession);
9357
9886
  }
9358
9887
 
9359
- unmute(callSession ) {
9360
- this.unmuteViaAPI(callSession);
9888
+ unmute(callSession , withApi = true) {
9889
+ if (withApi) {
9890
+ this.unmuteViaAPI(callSession);
9891
+ }
9361
9892
 
9362
9893
  return this.phone && this.phone.unmute(callSession);
9363
9894
  }
@@ -9365,7 +9896,7 @@ class Phone extends Emitter {
9365
9896
  muteViaAPI(callSession ) {
9366
9897
  if (callSession && callSession.callId) {
9367
9898
  Wazo.getApiClient().calld.mute(callSession.callId).catch(e => {
9368
- logger$5.error('Mute via API, error', e);
9899
+ logger$6.error('Mute via API, error', e);
9369
9900
  });
9370
9901
  }
9371
9902
  }
@@ -9373,7 +9904,7 @@ class Phone extends Emitter {
9373
9904
  unmuteViaAPI(callSession ) {
9374
9905
  if (callSession && callSession.callId) {
9375
9906
  Wazo.getApiClient().calld.unmute(callSession.callId).catch(e => {
9376
- logger$5.error('Unmute via API, error', e);
9907
+ logger$6.error('Unmute via API, error', e);
9377
9908
  });
9378
9909
  }
9379
9910
  }
@@ -9463,9 +9994,13 @@ class Phone extends Emitter {
9463
9994
  return this.phone && this.phone.hasLocalVideo(callSession);
9464
9995
  }
9465
9996
 
9997
+ hasALocalVideoTrack(callSession ) {
9998
+ return this.phone && this.phone.hasALocalVideoTrack(callSession);
9999
+ }
10000
+
9466
10001
  // @Deprecated
9467
10002
  getLocalMediaStream(callSession ) {
9468
- logger$5.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
10003
+ logger$6.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
9469
10004
 
9470
10005
  return this.phone && this.phone.getLocalStream(callSession);
9471
10006
  }
@@ -9484,20 +10019,20 @@ class Phone extends Emitter {
9484
10019
 
9485
10020
  // @Deprecated
9486
10021
  getRemoteStreamForCall(callSession ) {
9487
- logger$5.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
10022
+ logger$6.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
9488
10023
  return this.getRemoteStream(callSession);
9489
10024
  }
9490
10025
 
9491
10026
  // Returns remote streams directly from the peerConnection
9492
10027
  // @Deprecated
9493
10028
  getRemoteStreamsForCall(callSession ) {
9494
- logger$5.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
10029
+ logger$6.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
9495
10030
  return this.getLocalStream(callSession);
9496
10031
  }
9497
10032
 
9498
10033
  // @Deprecated
9499
10034
  getRemoteVideoStreamForCall(callSession ) {
9500
- logger$5.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
10035
+ logger$6.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
9501
10036
 
9502
10037
  return this.getRemoteVideoStream(callSession);
9503
10038
  }
@@ -9627,6 +10162,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
9627
10162
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
9628
10163
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
9629
10164
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
10165
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
10166
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
9630
10167
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
9631
10168
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
9632
10169
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -9668,7 +10205,7 @@ const BLACKLIST_EVENTS = [
9668
10205
  ];
9669
10206
 
9670
10207
  const HEARTBEAT_ENGINE_VERSION = '20.09';
9671
- const logger$4 = IssueReporter$1.loggerFor('wazo-ws');
10208
+ const logger$5 = IssueReporter$1.loggerFor('wazo-ws');
9672
10209
  const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
9673
10210
 
9674
10211
  class WebSocketClient extends Emitter {
@@ -9717,19 +10254,19 @@ class WebSocketClient extends Emitter {
9717
10254
  }
9718
10255
 
9719
10256
  connect() {
9720
- logger$4.info('connect method started', { host: this.host, token: this.token });
10257
+ logger$5.info('connect method started', { host: this.host, token: this.token });
9721
10258
  this.socket = new ReconnectingWebSocket(this._getUrl.bind(this), [], this.options);
9722
10259
  if (this.options.binaryType) {
9723
10260
  this.socket.binaryType = this.options.binaryType;
9724
10261
  }
9725
10262
 
9726
10263
  this.socket.onopen = () => {
9727
- logger$4.info('on Wazo WS open', { method: 'connect', host: this.host });
10264
+ logger$5.info('on Wazo WS open', { method: 'connect', host: this.host });
9728
10265
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_OPEN);
9729
10266
  };
9730
10267
 
9731
10268
  this.socket.onerror = event => {
9732
- logger$4.error('on Wazo WS error', event.target);
10269
+ logger$5.error('on Wazo WS error', event.target);
9733
10270
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_ERROR, event);
9734
10271
  };
9735
10272
 
@@ -9759,7 +10296,7 @@ class WebSocketClient extends Emitter {
9759
10296
 
9760
10297
  this.socket.onclose = event => {
9761
10298
  // Can't be converted to JSON (circular structure)
9762
- logger$4.info('on Wazo WS close', {
10299
+ logger$5.info('on Wazo WS close', {
9763
10300
  reason: event.reason,
9764
10301
  code: event.code,
9765
10302
  readyState: event.target.readyState,
@@ -9777,12 +10314,12 @@ class WebSocketClient extends Emitter {
9777
10314
  };
9778
10315
 
9779
10316
  this.socket.onerror = event => {
9780
- logger$4.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
10317
+ logger$5.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
9781
10318
  };
9782
10319
  }
9783
10320
 
9784
10321
  close(force = false) {
9785
- logger$4.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
10322
+ logger$5.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
9786
10323
 
9787
10324
  if (!this.socket) {
9788
10325
  return;
@@ -9800,7 +10337,7 @@ class WebSocketClient extends Emitter {
9800
10337
 
9801
10338
  updateToken(token ) {
9802
10339
  this.token = token;
9803
- logger$4.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
10340
+ logger$5.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
9804
10341
 
9805
10342
  if (this.socket) {
9806
10343
  // If still connected, send the token to the WS
@@ -9818,7 +10355,7 @@ class WebSocketClient extends Emitter {
9818
10355
  }
9819
10356
 
9820
10357
  startHeartbeat() {
9821
- logger$4.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
10358
+ logger$5.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
9822
10359
 
9823
10360
  if (!this.socket) {
9824
10361
  this.heartbeat.stop();
@@ -9832,7 +10369,7 @@ class WebSocketClient extends Emitter {
9832
10369
  }
9833
10370
 
9834
10371
  stopHeartbeat() {
9835
- logger$4.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
10372
+ logger$5.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
9836
10373
 
9837
10374
  this.heartbeat.stop();
9838
10375
  }
@@ -9862,7 +10399,7 @@ class WebSocketClient extends Emitter {
9862
10399
  }
9863
10400
 
9864
10401
  reconnect(reason ) {
9865
- logger$4.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
10402
+ logger$5.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
9866
10403
  if (!this.socket) {
9867
10404
  return;
9868
10405
  }
@@ -9918,7 +10455,7 @@ class WebSocketClient extends Emitter {
9918
10455
  this.close();
9919
10456
  }
9920
10457
  const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
9921
- logger$4.log('Wazo WS url computed to reconnect', { url });
10458
+ logger$5.log('Wazo WS url computed to reconnect', { url });
9922
10459
 
9923
10460
  return url;
9924
10461
  }
@@ -9926,12 +10463,12 @@ class WebSocketClient extends Emitter {
9926
10463
  _onHeartbeat(message ) {
9927
10464
  if (message.payload === 'pong') {
9928
10465
  this.heartbeat.onHeartbeat();
9929
- logger$4.log('on heartbeat received from Wazo WS');
10466
+ logger$5.log('on heartbeat received from Wazo WS');
9930
10467
  }
9931
10468
  }
9932
10469
 
9933
10470
  async _onHeartbeatTimeout() {
9934
- logger$4.log('heartbeat timed out', { host: this.host, token: this.token });
10471
+ logger$5.log('heartbeat timed out', { host: this.host, token: this.token });
9935
10472
 
9936
10473
  this.close();
9937
10474
  this.eventEmitter.emit(SOCKET_EVENTS$1.ON_CLOSE, new Error('Websocket ping failure.'));
@@ -9973,6 +10510,8 @@ WebSocketClient.eventLists = [
9973
10510
  CHATD_USER_ROOM_CREATED,
9974
10511
  CONFERENCE_USER_PARTICIPANT_JOINED,
9975
10512
  CONFERENCE_USER_PARTICIPANT_LEFT,
10513
+ MEETING_USER_PARTICIPANT_JOINED,
10514
+ MEETING_USER_PARTICIPANT_LEFT,
9976
10515
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
9977
10516
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
9978
10517
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -10043,6 +10582,8 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10043
10582
  CONFERENCE_USER_PARTICIPANT_LEFT: CONFERENCE_USER_PARTICIPANT_LEFT,
10044
10583
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED: CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
10045
10584
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED: CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
10585
+ MEETING_USER_PARTICIPANT_JOINED: MEETING_USER_PARTICIPANT_JOINED,
10586
+ MEETING_USER_PARTICIPANT_LEFT: MEETING_USER_PARTICIPANT_LEFT,
10046
10587
  SWITCHBOARD_QUEUED_CALLS_UPDATED: SWITCHBOARD_QUEUED_CALLS_UPDATED,
10047
10588
  SWITCHBOARD_QUEUED_CALL_ANSWERED: SWITCHBOARD_QUEUED_CALL_ANSWERED,
10048
10589
  SWITCHBOARD_HELD_CALLS_UPDATED: SWITCHBOARD_HELD_CALLS_UPDATED,
@@ -10084,7 +10625,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
10084
10625
  const { SOCKET_EVENTS, ...OTHER_EVENTS } = WebSocketClient$1;
10085
10626
  const ALL_EVENTS = [...Object.values(SOCKET_EVENTS), ...Object.values(OTHER_EVENTS)];
10086
10627
 
10087
- const logger$3 = IssueReporter$1.loggerFor('simple-ws-client');
10628
+ const logger$4 = IssueReporter$1.loggerFor('simple-ws-client');
10088
10629
 
10089
10630
  class Websocket extends Emitter {
10090
10631
 
@@ -10108,7 +10649,7 @@ class Websocket extends Emitter {
10108
10649
  }
10109
10650
 
10110
10651
  open(host , session ) {
10111
- logger$3.info('open simple WebSocket', { host, token: session.token });
10652
+ logger$4.info('open simple WebSocket', { host, token: session.token });
10112
10653
  this.ws = new WebSocketClient(
10113
10654
  {
10114
10655
  host,
@@ -10136,7 +10677,7 @@ class Websocket extends Emitter {
10136
10677
  }
10137
10678
 
10138
10679
  updateToken(token ) {
10139
- logger$3.info('update token via simple Websocket', { token, ws: !!this.ws });
10680
+ logger$4.info('update token via simple Websocket', { token, ws: !!this.ws });
10140
10681
 
10141
10682
  if (!this.ws) {
10142
10683
  return;
@@ -10164,7 +10705,7 @@ var Websocket$1 = global.wazoWebsocketInstance;
10164
10705
 
10165
10706
  //
10166
10707
 
10167
- const logger$2 = IssueReporter$1.loggerFor('room');
10708
+ const logger$3 = IssueReporter$1.loggerFor('room');
10168
10709
 
10169
10710
  class Participant extends Emitter {
10170
10711
 
@@ -10198,6 +10739,7 @@ class Participant extends Emitter {
10198
10739
 
10199
10740
 
10200
10741
  /**
10742
+ * @param room Room The room where the participant is
10201
10743
  * @param rawParticipant string Participant sent via the Wazo WS
10202
10744
  * @param extra Object extra status of the participant
10203
10745
  */
@@ -10285,7 +10827,7 @@ class Participant extends Emitter {
10285
10827
  }
10286
10828
 
10287
10829
  onTalking(isTalking ) {
10288
- logger$2.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10830
+ logger$3.info('on participant talking', { name: this.name, isTalking, callId: this.callId });
10289
10831
  this.isTalking = isTalking;
10290
10832
  // you may notice we're not broadcasting: since all participants are getting this info
10291
10833
  // directly from asterisk, there's no need to do so
@@ -10388,7 +10930,7 @@ class Participant extends Emitter {
10388
10930
  }
10389
10931
 
10390
10932
  updateStatus(status , broadcast = true) {
10391
- logger$2.info('updating participant status', { name: this.name, status });
10933
+ logger$3.info('updating participant status', { name: this.name, status });
10392
10934
 
10393
10935
  if (typeof status.audioMuted !== 'undefined' && status.audioMuted !== this.audioMuted) {
10394
10936
  if (status.audioMuted) {
@@ -10425,13 +10967,18 @@ class Participant extends Emitter {
10425
10967
  // Poor man's object comparison
10426
10968
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
10427
10969
  this.extra = { ...this.extra, ...status.extra };
10970
+
10971
+ if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
10972
+ this.extra.contact = new Contact(this.extra.contact);
10973
+ }
10974
+
10428
10975
  this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
10429
10976
  }
10430
10977
  }
10431
10978
 
10432
10979
  broadcastStatus(inboundStatus = null) {
10433
10980
  const status = inboundStatus || this.getStatus();
10434
- logger$2.info('broadcasting participant status', { callId: this.callId, status });
10981
+ logger$3.info('broadcasting participant status', { callId: this.callId, status });
10435
10982
 
10436
10983
  this.room.sendSignal({
10437
10984
  type: SIGNAL_TYPE_PARTICIPANT_UPDATE,
@@ -10452,18 +10999,24 @@ class RemoteParticipant extends Participant {
10452
10999
  }
10453
11000
  }
10454
11001
 
10455
- /* global document */
11002
+ //
11003
+
11004
+ class LocalParticipant extends Participant {
11005
+ }
11006
+
11007
+ //
10456
11008
 
10457
11009
  const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
10458
11010
  const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
10459
11011
 
10460
- const logger$1 = IssueReporter$1.loggerFor('sdk-room');
11012
+ const logger$2 = IssueReporter$1.loggerFor('sdk-room');
10461
11013
 
10462
11014
  class Room$1 extends Emitter {
10463
11015
 
10464
11016
 
10465
11017
 
10466
11018
 
11019
+
10467
11020
 
10468
11021
 
10469
11022
 
@@ -10485,6 +11038,8 @@ class Room$1 extends Emitter {
10485
11038
 
10486
11039
 
10487
11040
 
11041
+
11042
+
10488
11043
 
10489
11044
 
10490
11045
 
@@ -10502,6 +11057,7 @@ class Room$1 extends Emitter {
10502
11057
  * @param extension string
10503
11058
  * @param sourceId number
10504
11059
  * @param callId string
11060
+ * @param meetingUuid string
10505
11061
  * @param extra Object
10506
11062
  */
10507
11063
  constructor(
@@ -10509,15 +11065,17 @@ class Room$1 extends Emitter {
10509
11065
  extension ,
10510
11066
  sourceId ,
10511
11067
  callId ,
11068
+ meetingUuid ,
10512
11069
  extra = {},
10513
11070
  ) {
10514
11071
  super();
10515
- logger$1.info('room initialized', { callId, extension, sourceId });
11072
+ logger$2.info('room initialized', { callId, extension, sourceId, meetingUuid });
10516
11073
 
10517
11074
  // Represents the room callSession
10518
11075
  this.callSession = callSession;
10519
11076
  this.extension = extension;
10520
11077
  this.sourceId = sourceId;
11078
+ this.meetingUuid = meetingUuid;
10521
11079
  this.callId = callId;
10522
11080
  this.participants = [];
10523
11081
  this.connected = false;
@@ -10537,6 +11095,8 @@ class Room$1 extends Emitter {
10537
11095
  // Sugar syntax for `room.EVENT_NAME`
10538
11096
  this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
10539
11097
  this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
11098
+ this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
11099
+ this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
10540
11100
  this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
10541
11101
  this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
10542
11102
  this.ON_CHAT = Wazo.Phone.ON_CHAT;
@@ -10571,10 +11131,11 @@ class Room$1 extends Emitter {
10571
11131
  * @param audioOnly boolean
10572
11132
  * @param extra Object
10573
11133
  * @param room ?Room
11134
+ * @param meeting ?Meeting
10574
11135
  * @returns {Promise<Room>}
10575
11136
  */
10576
- static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
10577
- logger$1.info('connecting to room', { extension, audioOnly, room: !!room });
11137
+ static async connect({ extension, constraints, audioOnly = false, extra, room, meeting } ) {
11138
+ logger$2.info('connecting to room', { extension, audioOnly, room: !!room });
10578
11139
 
10579
11140
  if (!room) {
10580
11141
  await Wazo.Phone.connect();
@@ -10587,7 +11148,7 @@ class Room$1 extends Emitter {
10587
11148
 
10588
11149
  // Call_created is triggered before call_accepted, so we have to listen for it here.
10589
11150
  Wazo.Websocket.once(Wazo.Websocket.CALL_CREATED, ({ data }) => {
10590
- logger$1.info('room call received via WS', { callId: data.call_id });
11151
+ logger$2.info('room call received via WS', { callId: data.call_id });
10591
11152
  if (room) {
10592
11153
  room.setCallId(data.call_id);
10593
11154
  }
@@ -10608,34 +11169,44 @@ class Room$1 extends Emitter {
10608
11169
  room.setCallId(room.callSession.call.id);
10609
11170
  }
10610
11171
 
10611
- // Fetch conference source
10612
- const sources = await getApiClient().dird.fetchConferenceSource('default');
10613
- // Retrieve conference sources
10614
- const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
10615
- // Retrieve conference
10616
- const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
11172
+ if (!meeting) {
11173
+ // Fetch conference source
11174
+ const sources = await getApiClient().dird.fetchConferenceSource('default');
11175
+ // Retrieve conference sources
11176
+ const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
11177
+ // Retrieve conference
11178
+ const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
10617
11179
 
10618
- logger$1.info('connected to room', {
10619
- sourceId: conference ? conference.sourceId : null,
10620
- name: conference ? conference.name : null,
10621
- });
11180
+ logger$2.info('connected to room', {
11181
+ sourceId: conference ? conference.sourceId : null,
11182
+ name: conference ? conference.name : null,
11183
+ });
10622
11184
 
10623
- if (conference) {
10624
- room.setSourceId(conference.sourceId);
10625
- room.setName(conference.name);
11185
+ if (conference) {
11186
+ room.setSourceId(conference.sourceId);
11187
+ room.setName(conference.name);
11188
+ }
11189
+ } else if (meeting) {
11190
+ logger$2.info('Already connected to meeting', {
11191
+ uuid: meeting.uuid,
11192
+ name: meeting.name,
11193
+ });
11194
+
11195
+ room.setMeetingUuid(meeting.uuid);
11196
+ room.setName(meeting.name);
10626
11197
  }
10627
11198
 
10628
11199
  return room;
10629
11200
  }
10630
11201
 
10631
11202
  static disconnect() {
10632
- logger$1.info('static disconnection to room');
11203
+ logger$2.info('static disconnection to room');
10633
11204
 
10634
11205
  Wazo.Phone.disconnect();
10635
11206
  }
10636
11207
 
10637
11208
  async disconnect() {
10638
- logger$1.info('disconnection to room called');
11209
+ logger$2.info('disconnection to room called');
10639
11210
 
10640
11211
  await Wazo.Phone.hangup(this.callSession);
10641
11212
  this.callSession = null;
@@ -10650,20 +11221,24 @@ class Room$1 extends Emitter {
10650
11221
  Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10651
11222
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10652
11223
  Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10653
-
10654
- if (this.roomAudioElement && document.body) {
10655
- document.body.removeChild(this.roomAudioElement);
10656
- }
11224
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11225
+ Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10657
11226
  }
10658
11227
 
10659
11228
  setSourceId(sourceId ) {
10660
- logger$1.info('set room source id', { sourceId });
11229
+ logger$2.info('set room source id', { sourceId });
10661
11230
 
10662
11231
  this.sourceId = sourceId;
10663
11232
  }
10664
11233
 
11234
+ setMeetingUuid(meetingUuid ) {
11235
+ logger$2.info('set meeting uuid', { meetingUuid });
11236
+
11237
+ this.meetingUuid = meetingUuid;
11238
+ }
11239
+
10665
11240
  setCallId(callId ) {
10666
- logger$1.info('set room call id', { callId });
11241
+ logger$2.info('set room call id', { callId });
10667
11242
 
10668
11243
  if (callId) {
10669
11244
  this.callId = callId;
@@ -10671,7 +11246,7 @@ class Room$1 extends Emitter {
10671
11246
  }
10672
11247
 
10673
11248
  setName(name ) {
10674
- logger$1.info('set room name', { name });
11249
+ logger$2.info('set room name', { name });
10675
11250
 
10676
11251
  this.name = name;
10677
11252
  }
@@ -10690,7 +11265,7 @@ class Room$1 extends Emitter {
10690
11265
  }
10691
11266
 
10692
11267
  async startScreenSharing(constraints ) {
10693
- logger$1.info('start room screen sharing', { constraints });
11268
+ logger$2.info('start room screen sharing', { constraints });
10694
11269
 
10695
11270
  const screensharingStream = await Wazo.Phone.startScreenSharing(constraints, this.callSession);
10696
11271
  if (!screensharingStream) {
@@ -10703,18 +11278,26 @@ class Room$1 extends Emitter {
10703
11278
  return screensharingStream;
10704
11279
  }
10705
11280
 
10706
- stopScreenSharing(restoreLocalStream = true) {
10707
- logger$1.info('stop room screen sharing');
11281
+ async stopScreenSharing(restoreLocalStream = true) {
11282
+ logger$2.info('stop room screen sharing');
10708
11283
 
10709
- Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
11284
+ const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
10710
11285
 
10711
11286
  if (this.localParticipant) {
10712
11287
  this.localParticipant.onStopScreensharing();
10713
11288
  }
11289
+
11290
+ if (!reinvited && this.localParticipant) {
11291
+ // When we had video and we made a screenshare we don't reinvite when stopping the screensahre
11292
+ // So not REINVITE even is fired, we have to restore the video stream manually
11293
+ const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
11294
+ // $FlowFixMe
11295
+ this._associateStreamTo(localVideoStream, this.localParticipant);
11296
+ }
10714
11297
  }
10715
11298
 
10716
11299
  turnCameraOff() {
10717
- logger$1.info('turn room camera off');
11300
+ logger$2.info('turn room camera off');
10718
11301
 
10719
11302
  Wazo.Phone.turnCameraOff(this.callSession);
10720
11303
 
@@ -10724,7 +11307,7 @@ class Room$1 extends Emitter {
10724
11307
  }
10725
11308
 
10726
11309
  turnCameraOn() {
10727
- logger$1.info('turn room camera on');
11310
+ logger$2.info('turn room camera on');
10728
11311
 
10729
11312
  Wazo.Phone.turnCameraOn(this.callSession);
10730
11313
 
@@ -10734,7 +11317,7 @@ class Room$1 extends Emitter {
10734
11317
  }
10735
11318
 
10736
11319
  mute() {
10737
- logger$1.info('mute room');
11320
+ logger$2.info('mute room');
10738
11321
 
10739
11322
  Wazo.Phone.mute(this.callSession);
10740
11323
 
@@ -10742,7 +11325,7 @@ class Room$1 extends Emitter {
10742
11325
  }
10743
11326
 
10744
11327
  unmute() {
10745
- logger$1.info('unmute room');
11328
+ logger$2.info('unmute room');
10746
11329
 
10747
11330
  Wazo.Phone.unmute(this.callSession);
10748
11331
 
@@ -10762,7 +11345,7 @@ class Room$1 extends Emitter {
10762
11345
  }
10763
11346
 
10764
11347
  hold() {
10765
- logger$1.info('hold room');
11348
+ logger$2.info('hold room');
10766
11349
 
10767
11350
  Wazo.Phone.hold(this.callSession, true);
10768
11351
 
@@ -10772,7 +11355,7 @@ class Room$1 extends Emitter {
10772
11355
  }
10773
11356
 
10774
11357
  resume() {
10775
- logger$1.info('resume room');
11358
+ logger$2.info('resume room');
10776
11359
 
10777
11360
  Wazo.Phone.resume(this.callSession, true);
10778
11361
 
@@ -10782,13 +11365,13 @@ class Room$1 extends Emitter {
10782
11365
  }
10783
11366
 
10784
11367
  sendDTMF(tone ) {
10785
- logger$1.info('send room DTMF', { tone });
11368
+ logger$2.info('send room DTMF', { tone });
10786
11369
 
10787
11370
  Wazo.Phone.sendDTMF(tone, this.callSession);
10788
11371
  }
10789
11372
 
10790
11373
  async sendReinvite(newConstraints = null) {
10791
- logger$1.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
11374
+ logger$2.info('send room reinvite', { callId: this.callSession ? this.callSession.getId() : null, newConstraints });
10792
11375
  const wasScreensharing = this.localParticipant && this.localParticipant.screensharing;
10793
11376
 
10794
11377
  Wazo.Phone.on(Wazo.Phone.ON_SHARE_SCREEN_STARTED, () => {
@@ -10813,6 +11396,22 @@ class Room$1 extends Emitter {
10813
11396
  return response;
10814
11397
  }
10815
11398
 
11399
+ hasALocalVideoTrack() {
11400
+ return Wazo.Phone.hasALocalVideoTrack(this.callSession);
11401
+ }
11402
+
11403
+ getLocalStream() {
11404
+ return Wazo.Phone.getLocalStream(this.callSession);
11405
+ }
11406
+
11407
+ getRemoteStream() {
11408
+ return Wazo.Phone.getRemoteStream(this.callSession);
11409
+ }
11410
+
11411
+ getRemoteVideoStream() {
11412
+ return Wazo.Phone.getRemoteVideoStream(this.callSession);
11413
+ }
11414
+
10816
11415
  _bindEvents() {
10817
11416
  if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
10818
11417
  return;
@@ -10831,35 +11430,18 @@ class Room$1 extends Emitter {
10831
11430
  Wazo.Phone.phone.on(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
10832
11431
 
10833
11432
  this.on(this.ON_AUDIO_STREAM, stream => {
10834
- logger$1.info('on room audio stream');
11433
+ logger$2.info('on room audio stream');
10835
11434
 
10836
11435
  this.audioStream = stream;
10837
- if (document.createElement) {
10838
- // $FlowFixMe
10839
- let roomAudioElement = document.getElementById('audio-room');
10840
- if (!this.roomAudioElement) {
10841
- roomAudioElement = document.createElement('audio');
10842
- // $FlowFixMe
10843
- document.body.appendChild(roomAudioElement);
10844
- }
10845
- if (!roomAudioElement) {
10846
- return;
10847
- }
10848
- this.roomAudioElement = roomAudioElement;
11436
+ if (!this.roomAudioElement) {
11437
+ const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11438
+ this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
10849
11439
  this.roomAudioElement.srcObject = stream;
10850
- this.roomAudioElement.autoplay = true;
10851
- this.roomAudioElement.id = 'audio-room';
10852
-
10853
- // $FlowFixMe
10854
- if (this.roomAudioElement.setSinkId) {
10855
- // $FlowFixMe
10856
- this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
10857
- }
10858
11440
  }
10859
11441
  });
10860
11442
 
10861
11443
  this.on(this.ON_VIDEO_STREAM, (stream, streamId, event, sipSession) => {
10862
- logger$1.info('on room video stream', { streamId });
11444
+ logger$2.info('on room video stream', { streamId });
10863
11445
 
10864
11446
  this._mapMsid(sipSession.body.body);
10865
11447
 
@@ -10874,7 +11456,7 @@ class Room$1 extends Emitter {
10874
11456
  });
10875
11457
 
10876
11458
  this.on(this.ON_REMOVE_STREAM, stream => {
10877
- logger$1.info('on room remove stream');
11459
+ logger$2.info('on room remove stream');
10878
11460
 
10879
11461
  const participant = this.participants.find(someParticipant =>
10880
11462
  someParticipant.streams.find(someStream => someStream && someStream.id === stream.id));
@@ -10929,6 +11511,9 @@ class Room$1 extends Emitter {
10929
11511
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
10930
11512
  Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
10931
11513
 
11514
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
11515
+ Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
11516
+
10932
11517
  // Phone events
10933
11518
  Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
10934
11519
  Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
@@ -10939,15 +11524,15 @@ class Room$1 extends Emitter {
10939
11524
  Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
10940
11525
  }
10941
11526
 
10942
- _onMessage(message ) {
11527
+ _onMessage(message ) {
10943
11528
  if (message.method !== 'MESSAGE') {
10944
- return;
11529
+ return null;
10945
11530
  }
10946
11531
  let body;
10947
11532
  try {
10948
11533
  body = JSON.parse(message.body);
10949
11534
  } catch (e) {
10950
- return;
11535
+ return null;
10951
11536
  }
10952
11537
 
10953
11538
  switch (body.type) {
@@ -10966,6 +11551,8 @@ class Room$1 extends Emitter {
10966
11551
  }
10967
11552
 
10968
11553
  this.eventEmitter.emit(this.ON_MESSAGE, body);
11554
+
11555
+ return body;
10969
11556
  }
10970
11557
 
10971
11558
  _onChat(content ) {
@@ -11001,7 +11588,7 @@ class Room$1 extends Emitter {
11001
11588
  const requester = this._getParticipantFromCallId(origin.callId);
11002
11589
  if (requester) {
11003
11590
  // @FIXME?: when need to trigger an update on join-in; this is a bit of a hack
11004
- logger$1.info('trigger room requester status', { origin });
11591
+ logger$2.info('trigger room requester status', { origin });
11005
11592
  requester.triggerUpdate('REQUESTER_UPDATE');
11006
11593
  }
11007
11594
  break;
@@ -11030,25 +11617,26 @@ class Room$1 extends Emitter {
11030
11617
  const session = Wazo.Auth.getSession();
11031
11618
  let participants = [];
11032
11619
 
11033
- // @TODO: we could use a better function name here
11034
- const isJoining = part => {
11035
- this.__associateStreams(part);
11036
- // @VALIDATE: no need to publicize ourselves, no?
11037
- if (part instanceof RemoteParticipant) {
11038
- this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
11039
- }
11040
- };
11041
-
11042
11620
  // When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
11043
11621
  if (participant.user_uuid === session.uuid) {
11044
- logger$1.info('room current user joined');
11622
+ logger$2.info('room current user joined');
11045
11623
 
11046
11624
  // Retrieve participants via an API calls
11047
11625
  const conferenceId = this.sourceId || payload.data.conference_id;
11048
- const response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
11049
- logger$1.info('fetching conference participants', { conferenceId });
11626
+ let response;
11627
+ try {
11628
+ if (this.meetingUuid) {
11629
+ logger$2.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
11630
+ response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
11631
+ } else {
11632
+ logger$2.info('fetching conference participants', { conferenceId });
11633
+ response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
11634
+ }
11635
+ } catch (e) {
11636
+ logger$2.error('room participants fetching, error', e);
11637
+ }
11050
11638
  if (response) {
11051
- logger$1.info('conference participants fetched', { nb: response.items.length });
11639
+ logger$2.info('conference participants fetched', { nb: response.items.length });
11052
11640
  participants = response.items.map(item => {
11053
11641
  const isMe = item.call_id === this.callId;
11054
11642
 
@@ -11061,25 +11649,10 @@ class Room$1 extends Emitter {
11061
11649
 
11062
11650
  const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
11063
11651
  if (!this.localParticipant && localParticipant) {
11064
- this.localParticipant = localParticipant;
11065
-
11066
- const localVideoStream = this._getLocalVideoStream();
11067
- if (localVideoStream) {
11068
- this._saveLocalVideoStream(localVideoStream);
11069
- }
11070
-
11071
- this.connected = true;
11072
-
11073
- // we're in the room, now let's request everyone's status
11074
- if (this.localParticipant) {
11075
- this.sendSignal({
11076
- type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
11077
- origin: this.localParticipant.getStatus(),
11078
- });
11079
- }
11652
+ this._onLocalParticipantJoined(localParticipant);
11080
11653
  }
11081
11654
 
11082
- participants.forEach(someParticipant => isJoining(someParticipant));
11655
+ participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
11083
11656
  this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
11084
11657
  }
11085
11658
 
@@ -11090,16 +11663,45 @@ class Room$1 extends Emitter {
11090
11663
  ? new Wazo.RemoteParticipant(this, participant)
11091
11664
  : null;
11092
11665
 
11093
- logger$1.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
11666
+ logger$2.info('other room user joined', { callId: participant.call_id, remoteParticipant: !!remoteParticipant });
11094
11667
 
11095
11668
  if (remoteParticipant) {
11096
11669
  this.participants.push(remoteParticipant);
11097
- isJoining(remoteParticipant);
11670
+ this._isParticipantJoining(remoteParticipant);
11098
11671
  }
11099
11672
 
11100
11673
  return remoteParticipant;
11101
11674
  }
11102
11675
 
11676
+ _onLocalParticipantJoined(localParticipant ) {
11677
+ this.localParticipant = localParticipant;
11678
+
11679
+ const localVideoStream = this._getLocalVideoStream();
11680
+ if (localVideoStream) {
11681
+ this._saveLocalVideoStream(localVideoStream);
11682
+ }
11683
+
11684
+ this.connected = true;
11685
+
11686
+ localParticipant.broadcastStatus();
11687
+
11688
+ // we're in the room, now let's request everyone's status
11689
+ if (this.localParticipant) {
11690
+ this.sendSignal({
11691
+ type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
11692
+ origin: this.localParticipant.getStatus(),
11693
+ });
11694
+ }
11695
+ }
11696
+
11697
+ _isParticipantJoining(participant ) {
11698
+ this.__associateStreams(participant);
11699
+ // @VALIDATE: no need to publicize ourselves, no?
11700
+ if (participant instanceof RemoteParticipant) {
11701
+ this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
11702
+ }
11703
+ }
11704
+
11103
11705
  _saveLocalVideoStream(stream ) {
11104
11706
  const { localParticipant } = this;
11105
11707
 
@@ -11145,9 +11747,11 @@ class Room$1 extends Emitter {
11145
11747
  _onParticipantTrackUpdate(oldParticipant , update ) {
11146
11748
  const newParticipant = oldParticipant;
11147
11749
 
11148
- const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
11750
+ const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
11149
11751
  const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
11150
- const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
11752
+ // Can't use `getReceivers` here because on FF we make the mapping based on the streamId
11753
+ const stream = pc.getRemoteStreams().find(someStream =>
11754
+ someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
11151
11755
 
11152
11756
  if (update === 'downgrade') {
11153
11757
  newParticipant.streams = [];
@@ -11177,15 +11781,41 @@ class Room$1 extends Emitter {
11177
11781
  return;
11178
11782
  }
11179
11783
 
11180
- if (this._unassociatedVideoStreams[trackId]) {
11784
+ const streamId = this._getStreamIdFrTrackId(trackId);
11785
+ const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
11786
+ const stream = this._unassociatedVideoStreams[key];
11787
+
11788
+ if (stream) {
11181
11789
  // Try to associate stream
11182
- this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
11790
+ this._associateStreamTo(stream, participant);
11183
11791
 
11184
- delete this._unassociatedVideoStreams[trackId];
11792
+ delete this._unassociatedVideoStreams[key];
11185
11793
  delete this._unassociatedParticipants[participant.callId];
11186
11794
  }
11187
11795
  }
11188
11796
 
11797
+ _getUnassociatedMapIdFromTrackIdOrStreamId(trackId , streamId ) {
11798
+ // Find by trackId
11799
+ if (trackId in this._unassociatedVideoStreams) {
11800
+ return trackId;
11801
+ }
11802
+
11803
+ // Find by streamId
11804
+ if (streamId && streamId in this._unassociatedVideoStreams) {
11805
+ return streamId;
11806
+ }
11807
+
11808
+ // Find in all the streams by streamId (used on FF where we can't map by trackId)
11809
+ const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream ) => stream.id === streamId);
11810
+ return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
11811
+ }
11812
+
11813
+ _getStreamIdFrTrackId(trackId ) {
11814
+ const mapping = Object.values(this._callIdStreamIdMap).find((map ) => map.trackId === trackId);
11815
+
11816
+ return mapping ? mapping.streamId : null;
11817
+ }
11818
+
11189
11819
  _associateStreamTo(rawStream , participant ) {
11190
11820
  const stream = new Wazo.Stream(rawStream, participant);
11191
11821
  participant.streams.push(stream);
@@ -11209,7 +11839,141 @@ class Room$1 extends Emitter {
11209
11839
 
11210
11840
  //
11211
11841
 
11212
- class LocalParticipant extends Participant {
11842
+ const logger$1 = IssueReporter$1.loggerFor('sdk-sip-room');
11843
+
11844
+ class SipRoom extends Room$1 {
11845
+
11846
+ static async connect({ extension, constraints, audioOnly = false, extra, room } ) {
11847
+ logger$1.info('connecting to sip room', { extension, audioOnly, room: !!room });
11848
+
11849
+ if (!room) {
11850
+ await Wazo.Phone.connect();
11851
+
11852
+ const withCamera = constraints && !!constraints.video;
11853
+
11854
+ const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
11855
+ // eslint-disable-next-line no-param-reassign
11856
+ room = new SipRoom(callSession, extension, null, null, extra);
11857
+ }
11858
+
11859
+ if (room && room.callSession && room.callSession.call) {
11860
+ room.setCallId(room.callSession.call.id);
11861
+ }
11862
+
11863
+ logger$1.info('connected to room', {
11864
+ extension: room.extension,
11865
+ });
11866
+
11867
+ return room;
11868
+ }
11869
+
11870
+ mute() {
11871
+ logger$1.info('mute sip room');
11872
+
11873
+ Wazo.Phone.mute(this.callSession, false);
11874
+
11875
+ this.sendMuteStatus();
11876
+ }
11877
+
11878
+ unmute() {
11879
+ logger$1.info('unmute sip room');
11880
+
11881
+ Wazo.Phone.unmute(this.callSession, false);
11882
+
11883
+ this.sendUnMuteStatus();
11884
+ }
11885
+
11886
+ getLocalGuestName() {
11887
+ return Wazo.Phone.phone.client.userAgent.options.displayName;
11888
+ }
11889
+
11890
+ // Overridden to not listen to websocket messages
11891
+ _transferEvents() {
11892
+ // Phone events
11893
+ Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
11894
+ Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
11895
+ Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
11896
+ Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
11897
+
11898
+ [this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
11899
+ Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
11900
+ }
11901
+
11902
+ _onMessage(message ) {
11903
+ // eslint-disable-next-line no-underscore-dangle
11904
+ const body = super._onMessage(message);
11905
+ if (!body) {
11906
+ return;
11907
+ }
11908
+
11909
+ const getChannel = () => body.channels[0];
11910
+
11911
+ switch (body.type) {
11912
+ case 'ConfbridgeWelcome':
11913
+ body.channels.forEach(channel => {
11914
+ this._onParticipantJoined(channel);
11915
+ });
11916
+
11917
+ break;
11918
+ case 'ConfbridgeJoin': {
11919
+ const channel = getChannel();
11920
+ this._onParticipantJoined(channel);
11921
+ break;
11922
+ }
11923
+ case 'ConfbridgeLeave': {
11924
+ const channel = getChannel();
11925
+ this._onParticipantLeft({
11926
+ data: {
11927
+ call_id: channel.id,
11928
+ },
11929
+ });
11930
+ break;
11931
+ }
11932
+ }
11933
+ }
11934
+
11935
+ async _onParticipantJoined(channel ) {
11936
+ const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
11937
+ const callId = channel.id;
11938
+ const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
11939
+ const name = channel.caller ? channel.caller.name : null;
11940
+ const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
11941
+ const participant = new ParticipantClass(this, {
11942
+ caller_id_name: name,
11943
+ call_id: callId,
11944
+ }, extra);
11945
+
11946
+ const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
11947
+ if (participantIdx !== -1 && name) {
11948
+ this.participants[participantIdx].name = name;
11949
+ return;
11950
+ }
11951
+
11952
+ if (isLocal) {
11953
+ // Should be updated by the Wazo WS but we don't have it for now
11954
+ if (this.callSession) {
11955
+ this.callSession.ringing = false;
11956
+ }
11957
+
11958
+ this._onLocalParticipantJoined(participant);
11959
+
11960
+ // Give some time for the stream to be updated
11961
+ setTimeout(() => {
11962
+ this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
11963
+ }, 1000);
11964
+ }
11965
+
11966
+ this.participants.push(participant);
11967
+
11968
+ this._isParticipantJoining(participant);
11969
+
11970
+ return participant;
11971
+ }
11972
+
11973
+ _getCurrentSipCallIs() {
11974
+ return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
11975
+ }
11976
+
11213
11977
  }
11214
11978
 
11215
11979
  //
@@ -12105,6 +12869,7 @@ const Wazo = {
12105
12869
  Phone: Phone$1,
12106
12870
  Websocket: Websocket$1,
12107
12871
  Room: Room$1,
12872
+ SipRoom,
12108
12873
  RemoteParticipant,
12109
12874
  LocalParticipant,
12110
12875
  Stream,
@@ -12124,6 +12889,7 @@ const Wazo = {
12124
12889
  ServerError,
12125
12890
  Call,
12126
12891
  CallLog,
12892
+ CTIPhone,
12127
12893
  Recording,
12128
12894
  ChatMessage,
12129
12895
  ChatRoom,
@@ -12139,6 +12905,8 @@ const Wazo = {
12139
12905
  CallSession,
12140
12906
  IndirectTransfer,
12141
12907
  SwitchboardCall,
12908
+ WebRTCPhone,
12909
+ Meeting,
12142
12910
  },
12143
12911
 
12144
12912
  // Api
@@ -12217,9 +12985,7 @@ class Stream {
12217
12985
  return false;
12218
12986
  }
12219
12987
 
12220
- // With canvas track (used to fake upgrade in conference), we don't have a width
12221
- return this.htmlStream.getTracks().find(track => track.kind === 'video'
12222
- && track.readyState !== 'ended' && 'width' in track.getSettings());
12988
+ return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
12223
12989
  }
12224
12990
 
12225
12991
  get id() {