@wazo/sdk 1.0.0-alpha.1 → 1.0.0-alpha.10

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 (148) hide show
  1. package/README.md +16 -7
  2. package/dist/wazo-sdk.js +6 -6
  3. package/esm/__tests__/__voice__/call.test.js +57 -2
  4. package/esm/api/auth.js +3 -0
  5. package/esm/checker/checks/webrtc.js +2 -2
  6. package/esm/domain/CallLog.js +2 -3
  7. package/esm/domain/Phone/CTIPhone.js +2 -2
  8. package/esm/domain/Phone/WebRTCPhone.js +64 -63
  9. package/esm/index.js +3 -1
  10. package/esm/service/CallApi.js +4 -4
  11. package/esm/simple/Auth.js +13 -3
  12. package/esm/simple/Phone.js +6 -5
  13. package/esm/simple/index.js +2 -1
  14. package/esm/simple/room/Room.js +2 -2
  15. package/esm/simple/room/SipRoom.js +2 -2
  16. package/esm/state-machine/call-state-machine.js +2 -2
  17. package/esm/state-machine/softphone-state-machine.js +1 -2
  18. package/esm/state-machine/utils.js +8 -3
  19. package/esm/types/api/auth.d.ts +3 -0
  20. package/esm/types/api/auth.d.ts.map +1 -1
  21. package/esm/types/checker/checks/index.d.ts +1 -1
  22. package/esm/types/checker/checks/webrtc-transport.d.ts +2 -2
  23. package/esm/types/checker/checks/webrtc-transport.d.ts.map +1 -1
  24. package/esm/types/domain/CallLog.d.ts.map +1 -1
  25. package/esm/types/domain/CallSession.d.ts +3 -3
  26. package/esm/types/domain/CallSession.d.ts.map +1 -1
  27. package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  28. package/esm/types/domain/Phone/WebRTCPhone.d.ts +22 -22
  29. package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  30. package/esm/types/domain/types.d.ts +0 -4
  31. package/esm/types/domain/types.d.ts.map +1 -1
  32. package/esm/types/index.d.ts +3 -1
  33. package/esm/types/index.d.ts.map +1 -1
  34. package/esm/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
  35. package/esm/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
  36. package/esm/types/service/CallApi.d.ts +5 -5
  37. package/esm/types/service/CallApi.d.ts.map +1 -1
  38. package/esm/types/simple/Auth.d.ts +6 -1
  39. package/esm/types/simple/Auth.d.ts.map +1 -1
  40. package/esm/types/simple/Phone.d.ts +8 -8
  41. package/esm/types/simple/Phone.d.ts.map +1 -1
  42. package/esm/types/simple/index.d.ts +3 -1
  43. package/esm/types/simple/index.d.ts.map +1 -1
  44. package/esm/types/state-machine/softphone-state-machine.d.ts +1 -2
  45. package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  46. package/esm/types/state-machine/utils.d.ts +2 -2
  47. package/esm/types/state-machine/utils.d.ts.map +1 -1
  48. package/esm/types/utils/sdp.d.ts +3 -2
  49. package/esm/types/utils/sdp.d.ts.map +1 -1
  50. package/esm/types/utils/webrtc.d.ts +1 -0
  51. package/esm/types/utils/webrtc.d.ts.map +1 -1
  52. package/esm/types/voice/call.d.ts +30 -12
  53. package/esm/types/voice/call.d.ts.map +1 -1
  54. package/esm/types/voice/softphone.d.ts +25 -13
  55. package/esm/types/voice/softphone.d.ts.map +1 -1
  56. package/esm/types/web-rtc-client.d.ts +39 -38
  57. package/esm/types/web-rtc-client.d.ts.map +1 -1
  58. package/esm/utils/sdp.js +22 -9
  59. package/esm/utils/webrtc.js +23 -3
  60. package/esm/voice/call.js +130 -38
  61. package/esm/voice/softphone.js +145 -35
  62. package/esm/web-rtc-client.js +61 -58
  63. package/lib/__tests__/__voice__/call.test.js +56 -1
  64. package/lib/api/auth.js +3 -0
  65. package/lib/checker/checks/webrtc.js +1 -1
  66. package/lib/domain/CallLog.js +2 -3
  67. package/lib/domain/Phone/CTIPhone.js +2 -2
  68. package/lib/domain/Phone/WebRTCPhone.js +63 -62
  69. package/lib/index.js +7 -3
  70. package/lib/service/CallApi.js +2 -2
  71. package/lib/simple/Auth.js +15 -3
  72. package/lib/simple/Phone.js +3 -2
  73. package/lib/simple/index.js +2 -1
  74. package/lib/simple/room/Room.js +1 -1
  75. package/lib/simple/room/SipRoom.js +1 -1
  76. package/lib/state-machine/call-state-machine.js +2 -2
  77. package/lib/state-machine/softphone-state-machine.js +1 -2
  78. package/lib/state-machine/utils.js +8 -3
  79. package/lib/types/api/auth.d.ts +3 -0
  80. package/lib/types/api/auth.d.ts.map +1 -1
  81. package/lib/types/checker/checks/index.d.ts +1 -1
  82. package/lib/types/checker/checks/webrtc-transport.d.ts +2 -2
  83. package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -1
  84. package/lib/types/domain/CallLog.d.ts.map +1 -1
  85. package/lib/types/domain/CallSession.d.ts +3 -3
  86. package/lib/types/domain/CallSession.d.ts.map +1 -1
  87. package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  88. package/lib/types/domain/Phone/WebRTCPhone.d.ts +22 -22
  89. package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  90. package/lib/types/domain/types.d.ts +0 -4
  91. package/lib/types/domain/types.d.ts.map +1 -1
  92. package/lib/types/index.d.ts +3 -1
  93. package/lib/types/index.d.ts.map +1 -1
  94. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
  95. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
  96. package/lib/types/service/CallApi.d.ts +5 -5
  97. package/lib/types/service/CallApi.d.ts.map +1 -1
  98. package/lib/types/simple/Auth.d.ts +6 -1
  99. package/lib/types/simple/Auth.d.ts.map +1 -1
  100. package/lib/types/simple/Phone.d.ts +8 -8
  101. package/lib/types/simple/Phone.d.ts.map +1 -1
  102. package/lib/types/simple/index.d.ts +3 -1
  103. package/lib/types/simple/index.d.ts.map +1 -1
  104. package/lib/types/state-machine/softphone-state-machine.d.ts +1 -2
  105. package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  106. package/lib/types/state-machine/utils.d.ts +2 -2
  107. package/lib/types/state-machine/utils.d.ts.map +1 -1
  108. package/lib/types/utils/sdp.d.ts +3 -2
  109. package/lib/types/utils/sdp.d.ts.map +1 -1
  110. package/lib/types/utils/webrtc.d.ts +1 -0
  111. package/lib/types/utils/webrtc.d.ts.map +1 -1
  112. package/lib/types/voice/call.d.ts +30 -12
  113. package/lib/types/voice/call.d.ts.map +1 -1
  114. package/lib/types/voice/softphone.d.ts +25 -13
  115. package/lib/types/voice/softphone.d.ts.map +1 -1
  116. package/lib/types/web-rtc-client.d.ts +39 -38
  117. package/lib/types/web-rtc-client.d.ts.map +1 -1
  118. package/lib/utils/sdp.js +25 -10
  119. package/lib/utils/webrtc.js +24 -3
  120. package/lib/voice/call.js +131 -36
  121. package/lib/voice/softphone.js +150 -35
  122. package/lib/web-rtc-client.js +59 -57
  123. package/package.json +1 -1
  124. package/src/__tests__/__voice__/call.test.ts +63 -2
  125. package/src/api/auth.ts +5 -0
  126. package/src/checker/checks/webrtc-transport.ts +2 -2
  127. package/src/checker/checks/webrtc.ts +2 -2
  128. package/src/domain/CallLog.ts +2 -3
  129. package/src/domain/CallSession.ts +3 -3
  130. package/src/domain/Phone/CTIPhone.ts +3 -2
  131. package/src/domain/Phone/WebRTCPhone.ts +95 -93
  132. package/src/domain/types.ts +0 -5
  133. package/src/index.ts +4 -1
  134. package/src/lib/WazoSessionDescriptionHandler.ts +3 -3
  135. package/src/service/CallApi.ts +7 -7
  136. package/src/simple/Auth.ts +15 -3
  137. package/src/simple/Phone.ts +12 -11
  138. package/src/simple/index.ts +2 -1
  139. package/src/simple/room/Room.ts +3 -3
  140. package/src/simple/room/SipRoom.ts +3 -3
  141. package/src/state-machine/call-state-machine.ts +2 -2
  142. package/src/state-machine/softphone-state-machine.ts +1 -2
  143. package/src/state-machine/utils.ts +12 -5
  144. package/src/utils/sdp.ts +26 -11
  145. package/src/utils/webrtc.ts +26 -4
  146. package/src/voice/call.ts +169 -50
  147. package/src/voice/softphone.ts +180 -41
  148. package/src/web-rtc-client.ts +106 -99
@@ -35,26 +35,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.Softphone = exports.MESSAGE_TYPE_SIGNAL = exports.MESSAGE_TYPE_CHAT = exports.EVENT_ON_SIGNAL = exports.EVENT_ON_CHAT = exports.EVENT_ON_MESSAGE = exports.EVENT_VIDEO_INPUT_CHANGE = exports.EVENT_DISCONNECTED = exports.EVENT_UNREGISTERED = exports.EVENT_REGISTERED = exports.EVENT_HEARTBEAT_TIMEOUT = exports.EVENT_HEARTBEAT = exports.EVENT_INCOMING = void 0;
38
+ exports.Softphone = exports.MESSAGE_TYPE_SIGNAL = exports.MESSAGE_TYPE_CHAT = exports.EVENT_ON_SIGNAL = exports.EVENT_ON_CHAT = exports.EVENT_ON_MESSAGE = exports.EVENT_PLAY_INBOUND_CALL_SOUND = exports.EVENT_PLAY_RING_SOUND = exports.EVENT_PLAY_HANGUP_SOUND = exports.EVENT_TERMINATE_SOUND = exports.EVENT_VIDEO_INPUT_CHANGE = exports.EVENT_DISCONNECTED = exports.EVENT_UNREGISTERED = exports.EVENT_REGISTERED = exports.EVENT_HEARTBEAT_TIMEOUT = exports.EVENT_HEARTBEAT = exports.EVENT_OUTGOING = exports.EVENT_INCOMING = void 0;
39
39
  /* eslint-disable no-underscore-dangle */
40
40
  const events_1 = require("events");
41
41
  const xstate_1 = require("xstate");
42
42
  const InvalidState_1 = __importDefault(require("../domain/InvalidState"));
43
43
  const __1 = __importDefault(require(".."));
44
44
  const softphone_state_machine_1 = __importStar(require("../state-machine/softphone-state-machine"));
45
- const call_state_machine_1 = require("../state-machine/call-state-machine");
46
45
  const web_rtc_client_1 = __importDefault(require("../web-rtc-client"));
47
46
  const IssueReporter_1 = __importDefault(require("../service/IssueReporter"));
48
47
  const sip_logger_1 = __importDefault(require("../utils/sip-logger"));
49
48
  const call_1 = __importDefault(require("./call"));
50
49
  const utils_1 = require("../state-machine/utils");
50
+ const sdp_1 = require("../utils/sdp");
51
51
  exports.EVENT_INCOMING = 'incoming';
52
+ exports.EVENT_OUTGOING = 'outgoing';
52
53
  exports.EVENT_HEARTBEAT = 'heartbeat';
53
54
  exports.EVENT_HEARTBEAT_TIMEOUT = 'heartbeatTimeout';
54
55
  exports.EVENT_REGISTERED = 'registered';
55
56
  exports.EVENT_UNREGISTERED = 'unregistered';
56
57
  exports.EVENT_DISCONNECTED = 'disconnected';
57
58
  exports.EVENT_VIDEO_INPUT_CHANGE = 'videoInputChange';
59
+ exports.EVENT_TERMINATE_SOUND = 'terminateSound';
60
+ exports.EVENT_PLAY_HANGUP_SOUND = 'playHangupSound';
61
+ exports.EVENT_PLAY_RING_SOUND = 'playRingSound';
62
+ exports.EVENT_PLAY_INBOUND_CALL_SOUND = 'playInboundCallSound';
58
63
  exports.EVENT_ON_MESSAGE = 'message';
59
64
  exports.EVENT_ON_CHAT = 'phone/ON_CHAT';
60
65
  exports.EVENT_ON_SIGNAL = 'phone/ON_SIGNAL';
@@ -64,6 +69,7 @@ const logger = IssueReporter_1.default.loggerFor('softphone');
64
69
  class Softphone extends events_1.EventEmitter {
65
70
  constructor() {
66
71
  super();
72
+ this.ringingEnabled = true;
67
73
  this.calls = [];
68
74
  this.softphoneActor = (0, xstate_1.createActor)(softphone_state_machine_1.default);
69
75
  this.softphoneActor.start();
@@ -75,6 +81,7 @@ class Softphone extends events_1.EventEmitter {
75
81
  this.audioRingVolume = 1;
76
82
  const server = __1.default.Auth.getHost();
77
83
  const session = __1.default.Auth.getSession();
84
+ logger.info('softphone - connect', { server, session: !!session });
78
85
  if (!server || !session) {
79
86
  throw new Error('Please connect to the server using `Wazo.Auth.logIn` or `Wazo.Auth.authenticate` before using Room.connect().');
80
87
  }
@@ -86,14 +93,20 @@ class Softphone extends events_1.EventEmitter {
86
93
  this.options.userUuid = session.uuid || '';
87
94
  return this.connectWithCredentials(server, this.sipLine, session.displayName(), options);
88
95
  }
96
+ hangupAllCalls() {
97
+ return __awaiter(this, void 0, void 0, function* () {
98
+ return Promise.all(this.calls.map(call => call.hangup()));
99
+ });
100
+ }
89
101
  disconnect() {
90
102
  return __awaiter(this, void 0, void 0, function* () {
91
103
  (0, utils_1.assertCan)(this.softphoneActor, softphone_state_machine_1.Actions.UNREGISTER);
92
104
  if (!this.client) {
105
+ logger.info('softphone - disconnect, not client to disconnect, bailing');
93
106
  return null;
94
107
  }
95
108
  // Terminate all calls
96
- yield Promise.all(this.calls.map(call => call.hangup()));
109
+ yield this.hangupAllCalls();
97
110
  return this.client.unregister();
98
111
  });
99
112
  }
@@ -104,7 +117,8 @@ class Softphone extends events_1.EventEmitter {
104
117
  connectWithCredentials(server_1, sipLine_1, displayName_1) {
105
118
  return __awaiter(this, arguments, void 0, function* (server, sipLine, displayName, rawOptions = {}) {
106
119
  (0, utils_1.assertCan)(this.softphoneActor, softphone_state_machine_1.Actions.REGISTER);
107
- this.softphoneActor.send({ type: softphone_state_machine_1.Actions.REGISTER });
120
+ logger.info('softphone - connect with credentials', { server, username: sipLine.username, displayName, options: rawOptions });
121
+ this._sendAction(softphone_state_machine_1.Actions.REGISTER);
108
122
  const [host, port = 443] = server.split(':');
109
123
  let options = Object.assign({}, rawOptions);
110
124
  options.media = options.media || {
@@ -138,19 +152,22 @@ class Softphone extends events_1.EventEmitter {
138
152
  logger.warn('softphone - calling with empty number, bailing.');
139
153
  return Promise.resolve(null);
140
154
  }
141
- if (this.getState() !== softphone_state_machine_1.States.UNREGISTERED) {
142
- throw new InvalidState_1.default(`Invalid state ${softphone_state_machine_1.States.UNREGISTERED}`, softphone_state_machine_1.States.UNREGISTERED);
143
- }
144
- if (this.getState() !== softphone_state_machine_1.States.REGISTERING) {
155
+ if (this.state === softphone_state_machine_1.States.REGISTERING) {
145
156
  logger.info('softphone - calling when registering, waiting for Softphone to be registered ...');
146
157
  yield (0, utils_1.waitUntilState)(this.softphoneActor, softphone_state_machine_1.States.REGISTERED);
147
158
  }
159
+ if (this.state !== softphone_state_machine_1.States.REGISTERED) {
160
+ throw new InvalidState_1.default(`Invalid state ${softphone_state_machine_1.States.UNREGISTERED}`, softphone_state_machine_1.States.UNREGISTERED);
161
+ }
148
162
  // Hold other calls
149
163
  this.holdAllCalls();
150
164
  let sipCall;
151
165
  try {
152
166
  sipCall = this.client.call(options.params.To, options.withCamera, options.audioOnly, options.conference, options);
153
167
  const call = new call_1.default(sipCall, this);
168
+ call.onMakeCall();
169
+ this.calls.push(call);
170
+ this.emit(exports.EVENT_OUTGOING, call);
154
171
  return call;
155
172
  }
156
173
  catch (error) {
@@ -162,11 +179,65 @@ class Softphone extends events_1.EventEmitter {
162
179
  removeCall(callToRemove) {
163
180
  this.calls = this.calls.filter((call) => call.id !== callToRemove.id);
164
181
  }
182
+ onCallTerminated(call) {
183
+ logger.info('softphone - on call terminated', { id: call.id });
184
+ const currentCall = this.getCurrentCall();
185
+ const isCurrentCall = (currentCall === null || currentCall === void 0 ? void 0 : currentCall.id) === call.id;
186
+ const isRinging = call.isRinging();
187
+ const isCurrentIncomingCall = isCurrentCall && isRinging;
188
+ const incomingCalls = this.getIncomingCalls();
189
+ const nbIncomingCalls = incomingCalls.length;
190
+ // Send an event to terminate ringing sound
191
+ if (isCurrentIncomingCall) {
192
+ setTimeout(() => {
193
+ // Avoid race condition when the other is calling and hanging up immediately
194
+ this.emit(exports.EVENT_TERMINATE_SOUND, call, 'call terminated');
195
+ }, 5);
196
+ }
197
+ // If the terminated call was an incoming call, we have to re-trigger if it's was the first incoming call
198
+ // Otherwise, we have to re-trigger an incoming call event if another call is incoming
199
+ const shouldRetrigger = isCurrentCall ? nbIncomingCalls : isCurrentIncomingCall;
200
+ // Re-trigger incoming call event for remaining incoming calls
201
+ logger.info('Softphone - check to re-trigger incoming call', { shouldRetrigger, nbIncomingCalls });
202
+ if (shouldRetrigger && nbIncomingCalls > 1) {
203
+ const nextCall = incomingCalls.find(c => c.id !== call.id);
204
+ // Avoid race condition
205
+ setTimeout(() => {
206
+ if (this.ringingEnabled) {
207
+ if (currentCall) {
208
+ this.emit(exports.EVENT_PLAY_RING_SOUND, this.audioRingDeviceId, this.audioRingVolume, nextCall);
209
+ }
210
+ else {
211
+ this.emit(exports.EVENT_PLAY_INBOUND_CALL_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, nextCall);
212
+ }
213
+ }
214
+ this.emit(exports.EVENT_INCOMING, nextCall);
215
+ }, 100);
216
+ }
217
+ // @ts-ignore: does not exist
218
+ if (!call.sipCall.isCanceled) {
219
+ setTimeout(() => {
220
+ this.emit(exports.EVENT_PLAY_HANGUP_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, call);
221
+ }, 10);
222
+ }
223
+ this.client.onCallEnded(call.sipCall);
224
+ this.removeCall(call);
225
+ }
226
+ enableRinging() {
227
+ logger.info('softphone - enable ringing');
228
+ this.ringingEnabled = true;
229
+ }
230
+ disableRinging() {
231
+ logger.info('softphone - disable ringing');
232
+ this.ringingEnabled = false;
233
+ }
165
234
  holdAllCalls(exceptCall = null) {
166
- this.calls.filter(call => !call.isHeld() && call.id === (exceptCall === null || exceptCall === void 0 ? void 0 : exceptCall.id)).forEach(call => call.hold());
235
+ logger.info('softphone - hold all calls', { exceptId: exceptCall === null || exceptCall === void 0 ? void 0 : exceptCall.id, ids: this.calls.map(call => call.id) });
236
+ this.calls.filter(call => !call.isHeld() && call.id !== (exceptCall === null || exceptCall === void 0 ? void 0 : exceptCall.id)).forEach(call => call.hold());
167
237
  }
168
238
  startHeartbeat() {
169
- logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
239
+ var _a;
240
+ logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: (_a = this.client) === null || _a === void 0 ? void 0 : _a.hasHeartbeat() });
170
241
  if (!this.client || this.client.hasHeartbeat()) {
171
242
  return;
172
243
  }
@@ -216,29 +287,54 @@ class Softphone extends events_1.EventEmitter {
216
287
  logger.info('softphone - changing ring volume', { volume });
217
288
  this.audioRingVolume = volume;
218
289
  }
219
- getCalls() {
220
- return this.calls;
221
- }
222
290
  getCurrentCall() {
223
- return this.calls.find(call => call.isEstablished());
291
+ return this.getActiveCalls()[0];
292
+ }
293
+ getActiveCalls() {
294
+ return this.calls.filter(call => call.isEstablished());
295
+ }
296
+ getIncomingCalls() {
297
+ return this.calls.filter(call => call.isRinging());
298
+ }
299
+ get state() {
300
+ return (0, utils_1.getState)(this.softphoneActor);
224
301
  }
225
- getState() {
226
- return this.softphoneActor.getSnapshot().value;
302
+ get user() {
303
+ var _a, _b, _c, _d;
304
+ return (_d = (_c = (_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.userAgent) === null || _b === void 0 ? void 0 : _b.contact) === null || _c === void 0 ? void 0 : _c.uri) === null || _d === void 0 ? void 0 : _d.user;
227
305
  }
228
306
  getUserAgent() {
229
307
  var _a, _b;
230
308
  return ((_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.userAgentString) || 'softphone';
231
309
  }
310
+ isRegistering() {
311
+ return this.state === softphone_state_machine_1.States.REGISTERING;
312
+ }
313
+ isRegistered() {
314
+ return this.state === softphone_state_machine_1.States.REGISTERED;
315
+ }
316
+ isUnRegistered() {
317
+ return this.state === softphone_state_machine_1.States.UNREGISTERED;
318
+ }
232
319
  _bindEvents() {
233
320
  this.client.on(this.client.INVITE, (sipSession) => {
234
321
  const call = new call_1.default(sipSession, this);
235
- call._sendAction(call_state_machine_1.Actions.INCOMING_CALL);
322
+ logger.info('softphone - on invite', { callId: call.id, number: call.number });
323
+ call.onCallIncoming();
236
324
  this.calls.push(call);
237
- this.eventEmitter.emit(exports.EVENT_INCOMING, call);
325
+ this.emit(exports.EVENT_INCOMING, call);
326
+ if (!this.getCurrentCall()) {
327
+ if (this.ringingEnabled) {
328
+ this.emit(exports.EVENT_PLAY_RING_SOUND, this.audioRingDeviceId, this.audioRingVolume, call);
329
+ }
330
+ }
331
+ else {
332
+ this.emit(exports.EVENT_PLAY_INBOUND_CALL_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, call);
333
+ }
238
334
  });
239
335
  this.client.on(this.client.ON_REINVITE, (sipCall, request, updatedCalleeName, updatedNumber, hadRemoteVideo) => {
240
336
  logger.info('softphone - on reinvite', {
241
- callId: sipCall.id,
337
+ callId: (0, sdp_1.getSipCallId)(sipCall),
242
338
  inviteId: request.callId,
243
339
  updatedCalleeName,
244
340
  updatedNumber,
@@ -247,6 +343,8 @@ class Softphone extends events_1.EventEmitter {
247
343
  this._onCallEvent(sipCall, 'onReinvite', request, updatedCalleeName, updatedNumber, hadRemoteVideo);
248
344
  });
249
345
  this.client.on(this.client.ACCEPTED, (sipCall) => __awaiter(this, void 0, void 0, function* () {
346
+ const call = this._getCall(sipCall);
347
+ this.emit(exports.EVENT_TERMINATE_SOUND, call, 'call accepted');
250
348
  this._onCallEvent(sipCall, 'onAccepted');
251
349
  if (this.audioOutputDeviceId) {
252
350
  yield this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
@@ -276,23 +374,31 @@ class Softphone extends events_1.EventEmitter {
276
374
  });
277
375
  this.client.on(this.client.UNREGISTERED, () => {
278
376
  logger.info('softphone - unregistered');
279
- this.eventEmitter.emit(exports.EVENT_UNREGISTERED);
280
- this._sendAction(softphone_state_machine_1.Actions.UNREGISTERED);
377
+ if (!(0, utils_1.can)(this.softphoneActor, softphone_state_machine_1.Actions.UNREGISTER)) {
378
+ logger.warn('softphone - cannot unregister', { state: this.state });
379
+ return;
380
+ }
381
+ this._sendAction(softphone_state_machine_1.Actions.UNREGISTER);
382
+ this.emit(exports.EVENT_UNREGISTERED);
281
383
  });
282
384
  this.client.on(this.client.ON_DISCONNECTED, () => {
283
385
  logger.info('softphone - disconnected');
284
- this.eventEmitter.emit(exports.EVENT_DISCONNECTED);
386
+ if (!(0, utils_1.can)(this.softphoneActor, softphone_state_machine_1.Actions.TRANSPORT_CLOSED)) {
387
+ logger.warn('softphone - cannot disconnected', { state: this.state });
388
+ return;
389
+ }
285
390
  this._sendAction(softphone_state_machine_1.Actions.TRANSPORT_CLOSED);
391
+ this.emit(exports.EVENT_DISCONNECTED);
286
392
  });
287
393
  this.client.on(this.client.REGISTERED, () => {
288
394
  logger.info('softphone - registered', { state: (0, utils_1.getState)(this.softphoneActor) });
289
395
  if (!(0, utils_1.can)(this.softphoneActor, softphone_state_machine_1.Actions.REGISTER_DONE)) {
290
- logger.warn('softphone - registered but not in REGISTERING state', { state: (0, utils_1.getState)(this.softphoneActor) });
396
+ logger.warn('softphone - registered but not in REGISTERING state', { state: this.state });
291
397
  return;
292
398
  }
293
399
  this.stopHeartbeat();
294
400
  this._sendAction(softphone_state_machine_1.Actions.REGISTER_DONE);
295
- this.eventEmitter.emit(exports.EVENT_REGISTERED);
401
+ this.emit(exports.EVENT_REGISTERED);
296
402
  // If the phone registered with a current callSession (eg: when switching network):
297
403
  // send a reinvite to renegociate ICE with new IP
298
404
  if (this.shouldSendReinvite) {
@@ -303,12 +409,16 @@ class Softphone extends events_1.EventEmitter {
303
409
  }
304
410
  });
305
411
  this.client.on(this.client.CONNECTED, () => {
306
- logger.info('softphone - connected');
412
+ logger.info('softphone - connected', { state: this.state });
307
413
  this.stopHeartbeat();
308
414
  });
415
+ this.client.on(this.client.REGISTERING, () => {
416
+ logger.info('softphone - registering', { state: this.state });
417
+ this._sendAction(softphone_state_machine_1.Actions.REGISTER);
418
+ });
309
419
  this.client.on(this.client.DISCONNECTED, () => {
310
420
  logger.info('softphone - disconnected');
311
- this.eventEmitter.emit(exports.EVENT_DISCONNECTED);
421
+ this.emit(exports.EVENT_DISCONNECTED);
312
422
  // Do not trigger heartbeat if already running
313
423
  if (!this.client.hasHeartbeat()) {
314
424
  this.startHeartbeat();
@@ -317,30 +427,35 @@ class Softphone extends events_1.EventEmitter {
317
427
  this.shouldSendReinvite = this.calls.length > 0;
318
428
  });
319
429
  this.client.on('onVideoInputChange', stream => {
320
- this.eventEmitter.emit(exports.EVENT_VIDEO_INPUT_CHANGE, stream);
430
+ this.emit(exports.EVENT_VIDEO_INPUT_CHANGE, stream);
321
431
  });
322
432
  this.client.on(this.client.MESSAGE, (message) => {
323
433
  this._onMessage(message);
324
- this.eventEmitter.emit(exports.EVENT_ON_MESSAGE, message);
434
+ this.emit(exports.EVENT_ON_MESSAGE, message);
325
435
  });
326
436
  this.client.setOnHeartbeatTimeout(() => {
327
- this.eventEmitter.emit(exports.EVENT_HEARTBEAT_TIMEOUT);
437
+ this.emit(exports.EVENT_HEARTBEAT_TIMEOUT);
328
438
  });
329
439
  this.client.setOnHeartbeatCallback(() => {
330
- this.eventEmitter.emit(exports.EVENT_HEARTBEAT);
440
+ this.emit(exports.EVENT_HEARTBEAT);
331
441
  });
332
442
  }
333
443
  _sendAction(action) {
444
+ const was = this.state;
334
445
  this.softphoneActor.send({ type: action });
446
+ logger.trace('softphone - send action', { action, was, state: this.state });
335
447
  }
336
448
  _getCall(sipCall) {
337
- return this.calls.find(call => call.id === sipCall.id);
449
+ return this.calls.find(call => call.id === (0, sdp_1.getSipCallId)(sipCall));
450
+ }
451
+ _getCallIds() {
452
+ return this.calls.map(call => call.id);
338
453
  }
339
454
  _onCallEvent(sipCall, eventName, ...args) {
340
- logger.warn('softphone - received call event', { eventName, sipId: sipCall.id });
455
+ logger.info('softphone - received call event', { eventName, sipId: (0, sdp_1.getSipCallId)(sipCall) });
341
456
  const call = this._getCall(sipCall);
342
457
  if (!call) {
343
- logger.warn('softphone - no call found to send the event', { eventName, sipId: sipCall.id });
458
+ logger.warn('softphone - no call found to send the event', { eventName, sipId: (0, sdp_1.getSipCallId)(sipCall), ids: this._getCallIds() });
344
459
  return;
345
460
  }
346
461
  // @ts-ignore
@@ -360,11 +475,11 @@ class Softphone extends events_1.EventEmitter {
360
475
  const { type, content, } = body;
361
476
  switch (type) {
362
477
  case exports.MESSAGE_TYPE_CHAT:
363
- this.eventEmitter.emit(exports.EVENT_ON_CHAT, content);
478
+ this.emit(exports.EVENT_ON_CHAT, content);
364
479
  break;
365
480
  case exports.MESSAGE_TYPE_SIGNAL:
366
481
  {
367
- this.eventEmitter.emit(exports.EVENT_ON_SIGNAL, content);
482
+ this.emit(exports.EVENT_ON_SIGNAL, content);
368
483
  break;
369
484
  }
370
485
  default: