@wazo/sdk 1.0.0-alpha.0 → 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.
- package/README.md +16 -7
- package/dist/wazo-sdk.js +6 -6
- package/esm/__tests__/__voice__/call.test.js +57 -2
- package/esm/__tests__/api-client.test.js +20 -1
- package/esm/api/auth.js +16 -2
- package/esm/checker/checks/webrtc.js +2 -2
- package/esm/domain/CallLog.js +2 -3
- package/esm/domain/Phone/CTIPhone.js +2 -2
- package/esm/domain/Phone/WebRTCPhone.js +64 -63
- package/esm/index.js +5 -1
- package/esm/service/CallApi.js +4 -4
- package/esm/simple/Auth.js +19 -15
- package/esm/simple/Phone.js +6 -5
- package/esm/simple/__tests__/Auth.test.js +8 -64
- package/esm/simple/index.js +2 -1
- package/esm/simple/room/Room.js +2 -2
- package/esm/simple/room/SipRoom.js +2 -2
- package/esm/state-machine/call-state-machine.js +2 -2
- package/esm/state-machine/softphone-state-machine.js +1 -2
- package/esm/state-machine/utils.js +8 -3
- package/esm/types/api/auth.d.ts +3 -0
- package/esm/types/api/auth.d.ts.map +1 -1
- package/esm/types/checker/checks/index.d.ts +1 -1
- package/esm/types/checker/checks/webrtc-transport.d.ts +2 -2
- package/esm/types/checker/checks/webrtc-transport.d.ts.map +1 -1
- package/esm/types/domain/CallLog.d.ts.map +1 -1
- package/esm/types/domain/CallSession.d.ts +3 -3
- package/esm/types/domain/CallSession.d.ts.map +1 -1
- package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/esm/types/domain/Phone/WebRTCPhone.d.ts +22 -22
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/esm/types/domain/types.d.ts +0 -4
- package/esm/types/domain/types.d.ts.map +1 -1
- package/esm/types/index.d.ts +5 -1
- package/esm/types/index.d.ts.map +1 -1
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
- package/esm/types/service/CallApi.d.ts +5 -5
- package/esm/types/service/CallApi.d.ts.map +1 -1
- package/esm/types/simple/Auth.d.ts +6 -1
- package/esm/types/simple/Auth.d.ts.map +1 -1
- package/esm/types/simple/Phone.d.ts +8 -8
- package/esm/types/simple/Phone.d.ts.map +1 -1
- package/esm/types/simple/index.d.ts +3 -1
- package/esm/types/simple/index.d.ts.map +1 -1
- package/esm/types/state-machine/softphone-state-machine.d.ts +1 -2
- package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -1
- package/esm/types/state-machine/utils.d.ts +2 -2
- package/esm/types/state-machine/utils.d.ts.map +1 -1
- package/esm/types/utils/api-requester.d.ts.map +1 -1
- package/esm/types/utils/sdp.d.ts +3 -2
- package/esm/types/utils/sdp.d.ts.map +1 -1
- package/esm/types/utils/webrtc.d.ts +1 -0
- package/esm/types/utils/webrtc.d.ts.map +1 -1
- package/esm/types/voice/call.d.ts +30 -12
- package/esm/types/voice/call.d.ts.map +1 -1
- package/esm/types/voice/softphone.d.ts +25 -13
- package/esm/types/voice/softphone.d.ts.map +1 -1
- package/esm/types/web-rtc-client.d.ts +39 -38
- package/esm/types/web-rtc-client.d.ts.map +1 -1
- package/esm/utils/__tests__/api-requester.test.js +17 -0
- package/esm/utils/api-requester.js +9 -1
- package/esm/utils/sdp.js +22 -9
- package/esm/utils/webrtc.js +24 -4
- package/esm/voice/call.js +130 -38
- package/esm/voice/softphone.js +145 -35
- package/esm/web-rtc-client.js +61 -58
- package/lib/__tests__/__voice__/call.test.js +56 -1
- package/lib/__tests__/api-client.test.js +20 -1
- package/lib/api/auth.js +16 -2
- package/lib/checker/checks/webrtc.js +1 -1
- package/lib/domain/CallLog.js +2 -3
- package/lib/domain/Phone/CTIPhone.js +2 -2
- package/lib/domain/Phone/WebRTCPhone.js +63 -62
- package/lib/index.js +11 -3
- package/lib/service/CallApi.js +2 -2
- package/lib/simple/Auth.js +21 -15
- package/lib/simple/Phone.js +3 -2
- package/lib/simple/__tests__/Auth.test.js +11 -64
- package/lib/simple/index.js +2 -1
- package/lib/simple/room/Room.js +1 -1
- package/lib/simple/room/SipRoom.js +1 -1
- package/lib/state-machine/call-state-machine.js +2 -2
- package/lib/state-machine/softphone-state-machine.js +1 -2
- package/lib/state-machine/utils.js +8 -3
- package/lib/types/api/auth.d.ts +3 -0
- package/lib/types/api/auth.d.ts.map +1 -1
- package/lib/types/checker/checks/index.d.ts +1 -1
- package/lib/types/checker/checks/webrtc-transport.d.ts +2 -2
- package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -1
- package/lib/types/domain/CallLog.d.ts.map +1 -1
- package/lib/types/domain/CallSession.d.ts +3 -3
- package/lib/types/domain/CallSession.d.ts.map +1 -1
- package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/lib/types/domain/Phone/WebRTCPhone.d.ts +22 -22
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/lib/types/domain/types.d.ts +0 -4
- package/lib/types/domain/types.d.ts.map +1 -1
- package/lib/types/index.d.ts +5 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
- package/lib/types/service/CallApi.d.ts +5 -5
- package/lib/types/service/CallApi.d.ts.map +1 -1
- package/lib/types/simple/Auth.d.ts +6 -1
- package/lib/types/simple/Auth.d.ts.map +1 -1
- package/lib/types/simple/Phone.d.ts +8 -8
- package/lib/types/simple/Phone.d.ts.map +1 -1
- package/lib/types/simple/index.d.ts +3 -1
- package/lib/types/simple/index.d.ts.map +1 -1
- package/lib/types/state-machine/softphone-state-machine.d.ts +1 -2
- package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -1
- package/lib/types/state-machine/utils.d.ts +2 -2
- package/lib/types/state-machine/utils.d.ts.map +1 -1
- package/lib/types/utils/api-requester.d.ts.map +1 -1
- package/lib/types/utils/sdp.d.ts +3 -2
- package/lib/types/utils/sdp.d.ts.map +1 -1
- package/lib/types/utils/webrtc.d.ts +1 -0
- package/lib/types/utils/webrtc.d.ts.map +1 -1
- package/lib/types/voice/call.d.ts +30 -12
- package/lib/types/voice/call.d.ts.map +1 -1
- package/lib/types/voice/softphone.d.ts +25 -13
- package/lib/types/voice/softphone.d.ts.map +1 -1
- package/lib/types/web-rtc-client.d.ts +39 -38
- package/lib/types/web-rtc-client.d.ts.map +1 -1
- package/lib/utils/__tests__/api-requester.test.js +17 -0
- package/lib/utils/api-requester.js +9 -1
- package/lib/utils/sdp.js +25 -10
- package/lib/utils/webrtc.js +25 -4
- package/lib/voice/call.js +131 -36
- package/lib/voice/softphone.js +150 -35
- package/lib/web-rtc-client.js +59 -57
- package/package.json +1 -1
- package/src/__tests__/__voice__/call.test.ts +63 -2
- package/src/__tests__/api-client.test.ts +22 -1
- package/src/api/auth.ts +30 -3
- package/src/checker/checks/webrtc-transport.ts +2 -2
- package/src/checker/checks/webrtc.ts +2 -2
- package/src/domain/CallLog.ts +2 -3
- package/src/domain/CallSession.ts +3 -3
- package/src/domain/Phone/CTIPhone.ts +3 -2
- package/src/domain/Phone/WebRTCPhone.ts +95 -93
- package/src/domain/types.ts +0 -5
- package/src/index.ts +6 -1
- package/src/lib/WazoSessionDescriptionHandler.ts +3 -3
- package/src/service/CallApi.ts +7 -7
- package/src/simple/Auth.ts +21 -16
- package/src/simple/Phone.ts +12 -11
- package/src/simple/__tests__/Auth.test.ts +9 -87
- package/src/simple/index.ts +2 -1
- package/src/simple/room/Room.ts +3 -3
- package/src/simple/room/SipRoom.ts +3 -3
- package/src/state-machine/call-state-machine.ts +2 -2
- package/src/state-machine/softphone-state-machine.ts +1 -2
- package/src/state-machine/utils.ts +12 -5
- package/src/utils/__tests__/api-requester.test.ts +20 -0
- package/src/utils/api-requester.ts +9 -1
- package/src/utils/sdp.ts +26 -11
- package/src/utils/webrtc.ts +27 -5
- package/src/voice/call.ts +169 -50
- package/src/voice/softphone.ts +180 -41
- package/src/web-rtc-client.ts +106 -99
package/src/voice/call.ts
CHANGED
|
@@ -8,13 +8,16 @@ import { SessionDescriptionHandler } from 'sip.js/lib/platform/web';
|
|
|
8
8
|
import { SessionDescriptionHandlerOptions } from 'sip.js/lib/api';
|
|
9
9
|
import type { IncomingRequestMessage } from 'sip.js/lib/core/messages/incoming-request-message';
|
|
10
10
|
|
|
11
|
-
import callStateMachine, { type ActionTypes, Actions, type EstablishedActionTypes, EstablishedActions, States, EstablishedStates, type CallActorRef } from '../state-machine/call-state-machine';
|
|
11
|
+
import callStateMachine, { type ActionTypes, Actions, type EstablishedActionTypes, EstablishedActions, States, type StateTypes, EstablishedStates, type EstablishedStateTypes, type CallActorRef } from '../state-machine/call-state-machine';
|
|
12
12
|
import { SipCall, PeerConnection } from '../domain/types';
|
|
13
|
+
import ApiCall from '../domain/Call';
|
|
14
|
+
import newFrom from '../utils/new-from';
|
|
15
|
+
import updateFrom from '../utils/update-from';
|
|
13
16
|
import IssueReporter from '../service/IssueReporter';
|
|
14
|
-
import { Softphone } from './softphone';
|
|
15
|
-
import {
|
|
17
|
+
import softphone, { Softphone } from './softphone';
|
|
18
|
+
import { getCallDisplayName, getCallNumber, getSipCallId } from '../utils/sdp';
|
|
16
19
|
import { assertCan, assertState, getState } from '../state-machine/utils';
|
|
17
|
-
import { downgradeToAudio, getLocalStream, getLocalVideoStream, getPeerConnection, getRemoteStream, getRemoteVideoStream, getStreamFromConstraints, getWebRtcStats, hasALocalVideoTrack, hasLocalVideo, hasRemoteVideo, isVideoRemotelyHeld, setLocalMediaStream, toggleVideo, upgradeToVideo } from '../utils/webrtc';
|
|
20
|
+
import { downgradeToAudio, getLocalStream, getLocalVideoStream, getPeerConnection, getRemoteStream, getRemoteVideoStream, getStreamFromConstraints, getWebRtcStats, hasALocalVideoTrack, hasLocalVideo, hasRemoteVideo, isVideoMuted, isVideoRemotelyHeld, setLocalMediaStream, toggleVideo, upgradeToVideo } from '../utils/webrtc';
|
|
18
21
|
|
|
19
22
|
const logger = IssueReporter.loggerFor('call');
|
|
20
23
|
|
|
@@ -30,7 +33,8 @@ export type ReinviteOptions = {
|
|
|
30
33
|
};
|
|
31
34
|
|
|
32
35
|
// Events
|
|
33
|
-
export const
|
|
36
|
+
export const EVENT_CALL_REMOTLY_ACCEPTED = 'remotelyAccepted';
|
|
37
|
+
export const EVENT_CALL_LOCALLY_ACCEPTED = 'locallyAccepted';
|
|
34
38
|
export const EVENT_CALL_CANCELED = 'canceled';
|
|
35
39
|
export const EVENT_PROGRESS = 'progress';
|
|
36
40
|
export const EVENT_EARLY_MEDIA = 'earlyMedia';
|
|
@@ -53,15 +57,12 @@ export const EVENT_SHARE_SCREEN_ENDED = 'onScreenShareEnded';
|
|
|
53
57
|
export const EVENT_WEB_RTC_STATS = 'webRtcStats';
|
|
54
58
|
export const EVENT_CAMERA_RESUMED = 'onCameraResumed';
|
|
55
59
|
export const EVENT_CAMERA_DISABLED = 'onCameraDisabled';
|
|
56
|
-
export const EVENT_TERMINATE_SOUND = 'terminateSound';
|
|
57
60
|
|
|
58
61
|
export const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
|
|
59
62
|
export const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
|
|
60
63
|
export const MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
|
|
61
64
|
|
|
62
65
|
class Call extends EventEmitter {
|
|
63
|
-
eventEmitter: EventEmitter;
|
|
64
|
-
|
|
65
66
|
callActor: CallActorRef;
|
|
66
67
|
|
|
67
68
|
// Wazo call id, used in Wazo Websocket and API
|
|
@@ -81,8 +82,68 @@ class Call extends EventEmitter {
|
|
|
81
82
|
|
|
82
83
|
shouldSendReinvite = false;
|
|
83
84
|
|
|
85
|
+
recording = false;
|
|
86
|
+
|
|
87
|
+
displayName: string | null;
|
|
88
|
+
|
|
89
|
+
number: string | null;
|
|
90
|
+
|
|
84
91
|
currentScreenShare: Record<string, any> | null;
|
|
85
92
|
|
|
93
|
+
static newFrom(call: Call) {
|
|
94
|
+
return newFrom(call, Call);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static parseCall(apiCall: ApiCall): Call {
|
|
98
|
+
const sipCall = {
|
|
99
|
+
id: apiCall.sipCallId,
|
|
100
|
+
stateChange: {
|
|
101
|
+
addListener: () => {},
|
|
102
|
+
},
|
|
103
|
+
remoteIdentity: {
|
|
104
|
+
uri: {
|
|
105
|
+
_normal: {
|
|
106
|
+
user: apiCall.calleeNumber,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
// Mock sdk so `hasLocalVideo` will return true.
|
|
111
|
+
sessionDescriptionHandler: {
|
|
112
|
+
localMediaStream: {
|
|
113
|
+
getTracks: () => (apiCall.isVideo ? [{ kind: 'video', readyState: 'live' }] : []),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
} as any;
|
|
117
|
+
|
|
118
|
+
const call = new Call(sipCall, softphone);
|
|
119
|
+
call.apiId = apiCall.id;
|
|
120
|
+
call.answerTime = new Date(+apiCall.startingTime);
|
|
121
|
+
|
|
122
|
+
// Update call state
|
|
123
|
+
const snapshot = call.callActor.getSnapshot();
|
|
124
|
+
|
|
125
|
+
if (apiCall.isUp()) {
|
|
126
|
+
snapshot.value = { [States.ESTABLISHED]: EstablishedStates.ONGOING };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (apiCall.muted) {
|
|
130
|
+
snapshot.value = { [States.ESTABLISHED]: EstablishedStates.MUTED };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (apiCall.isRinging()) {
|
|
134
|
+
snapshot.value = States.RINGING;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (apiCall.isRecording()) {
|
|
138
|
+
call.recording = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// @ts-ignore
|
|
142
|
+
call.callActor.update(snapshot);
|
|
143
|
+
|
|
144
|
+
return call;
|
|
145
|
+
}
|
|
146
|
+
|
|
86
147
|
constructor(sipCall: SipCall, phone: Softphone) {
|
|
87
148
|
super();
|
|
88
149
|
|
|
@@ -94,7 +155,8 @@ class Call extends EventEmitter {
|
|
|
94
155
|
this.phone = phone;
|
|
95
156
|
this.sipCall = sipCall;
|
|
96
157
|
|
|
97
|
-
this.
|
|
158
|
+
this.number = getCallNumber(sipCall);
|
|
159
|
+
this.displayName = getCallDisplayName(sipCall);
|
|
98
160
|
}
|
|
99
161
|
|
|
100
162
|
async accept(options: AcceptOptions = {}): Promise<string | null> {
|
|
@@ -111,6 +173,8 @@ class Call extends EventEmitter {
|
|
|
111
173
|
return this.phone.client.answer(this.sipCall as Invitation, options.withCamera).then(() => {
|
|
112
174
|
logger.info('call - accepted', { id: this.id, ...options });
|
|
113
175
|
|
|
176
|
+
this.emit(EVENT_CALL_LOCALLY_ACCEPTED, this);
|
|
177
|
+
|
|
114
178
|
return this.id;
|
|
115
179
|
}).catch(e => {
|
|
116
180
|
logger.error(e);
|
|
@@ -123,21 +187,23 @@ class Call extends EventEmitter {
|
|
|
123
187
|
assertCan(this.callActor, Actions.REJECT);
|
|
124
188
|
logger.info('call - reject', { id: this.id });
|
|
125
189
|
|
|
126
|
-
this.
|
|
127
|
-
|
|
128
|
-
this.shouldSendReinvite = false;
|
|
129
|
-
|
|
130
|
-
return this.hangup();
|
|
190
|
+
return this._terminate();
|
|
131
191
|
}
|
|
132
192
|
|
|
133
193
|
async hangup(): Promise<boolean> {
|
|
134
194
|
assertCan(this.callActor, Actions.HANGUP);
|
|
135
195
|
logger.info('call - hangup', { id: this.id });
|
|
136
196
|
|
|
197
|
+
return this._terminate();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async _terminate(): Promise<boolean> {
|
|
137
201
|
await this.phone.client.hangup(this.sipCall);
|
|
138
202
|
|
|
203
|
+
this.shouldSendReinvite = false;
|
|
204
|
+
|
|
139
205
|
// Remove this call from softphone's calls
|
|
140
|
-
this.phone.
|
|
206
|
+
this.phone.onCallTerminated(this);
|
|
141
207
|
|
|
142
208
|
return true;
|
|
143
209
|
}
|
|
@@ -151,7 +217,7 @@ class Call extends EventEmitter {
|
|
|
151
217
|
}
|
|
152
218
|
}
|
|
153
219
|
|
|
154
|
-
startConference(withCalls: Call[]) {
|
|
220
|
+
startConference(/* withCalls: Call[] */) {
|
|
155
221
|
// @TODO
|
|
156
222
|
// const participants = [this, ...withCalls].reduce((acc: Record<string, any>, call: Call) => {
|
|
157
223
|
// acc[call.talkingToIds[0]] = call;
|
|
@@ -174,7 +240,7 @@ class Call extends EventEmitter {
|
|
|
174
240
|
|
|
175
241
|
this.phone.client.mute(this.sipCall);
|
|
176
242
|
|
|
177
|
-
this.
|
|
243
|
+
this.emit(EVENT_CALL_MUTED);
|
|
178
244
|
}
|
|
179
245
|
|
|
180
246
|
unMute() {
|
|
@@ -185,7 +251,7 @@ class Call extends EventEmitter {
|
|
|
185
251
|
|
|
186
252
|
this.phone.client.unmute(this.sipCall);
|
|
187
253
|
|
|
188
|
-
this.
|
|
254
|
+
this.emit(EVENT_CALL_UN_MUTED);
|
|
189
255
|
}
|
|
190
256
|
|
|
191
257
|
async hold() {
|
|
@@ -208,7 +274,7 @@ class Call extends EventEmitter {
|
|
|
208
274
|
|
|
209
275
|
const promise = this.phone.client.hold(this.sipCall, this.isConference(), hasVideo);
|
|
210
276
|
|
|
211
|
-
this.
|
|
277
|
+
this.emit(EVENT_CALL_HELD);
|
|
212
278
|
|
|
213
279
|
return promise;
|
|
214
280
|
}
|
|
@@ -244,7 +310,7 @@ class Call extends EventEmitter {
|
|
|
244
310
|
}
|
|
245
311
|
};
|
|
246
312
|
|
|
247
|
-
this.
|
|
313
|
+
this.emit(EVENT_CALL_RESUMED);
|
|
248
314
|
|
|
249
315
|
return promise.then(() => {
|
|
250
316
|
const stream = this.getLocalVideoStream();
|
|
@@ -261,7 +327,7 @@ class Call extends EventEmitter {
|
|
|
261
327
|
logger.info('call - turn camera on', { id: this.id });
|
|
262
328
|
toggleVideo(this.sipCall, true);
|
|
263
329
|
|
|
264
|
-
this.
|
|
330
|
+
this.emit(EVENT_CAMERA_RESUMED);
|
|
265
331
|
}
|
|
266
332
|
|
|
267
333
|
turnCameraOff(): void {
|
|
@@ -269,15 +335,39 @@ class Call extends EventEmitter {
|
|
|
269
335
|
logger.info('call - turn camera off', { id: this.id });
|
|
270
336
|
toggleVideo(this.sipCall, false);
|
|
271
337
|
|
|
272
|
-
this.
|
|
338
|
+
this.emit(EVENT_CAMERA_DISABLED);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
isMuted() {
|
|
342
|
+
return this._hasEstablishedState(EstablishedStates.MUTED);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
isCameraMuted() {
|
|
346
|
+
return isVideoMuted(this.sipCall);
|
|
273
347
|
}
|
|
274
348
|
|
|
275
349
|
isHeld() {
|
|
276
|
-
return
|
|
350
|
+
return this._hasEstablishedState(EstablishedStates.HELD);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
isEstablishing() {
|
|
354
|
+
return this.sipCall.state === SessionState.Establishing;
|
|
277
355
|
}
|
|
278
356
|
|
|
279
357
|
isEstablished() {
|
|
280
|
-
return
|
|
358
|
+
return typeof this.state === 'object' && States.ESTABLISHED in (this.state as Record<StateTypes, EstablishedStateTypes>);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
isRinging() {
|
|
362
|
+
return this.state === States.RINGING;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
isOutgoing() {
|
|
366
|
+
return this.sipCall instanceof Invitation;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
isIncoming() {
|
|
370
|
+
return !this.isOutgoing();
|
|
281
371
|
}
|
|
282
372
|
|
|
283
373
|
isConference(): boolean {
|
|
@@ -288,7 +378,7 @@ class Call extends EventEmitter {
|
|
|
288
378
|
assertState(this.callActor, States.ESTABLISHED);
|
|
289
379
|
logger.info('call - transfer', { id: this.id, target });
|
|
290
380
|
|
|
291
|
-
this.phone.client.transfer(this.sipCall, target);
|
|
381
|
+
return this.phone.client.transfer(this.sipCall, target);
|
|
292
382
|
}
|
|
293
383
|
|
|
294
384
|
atxfer(): Record<string, any> | null | undefined {
|
|
@@ -446,7 +536,7 @@ class Call extends EventEmitter {
|
|
|
446
536
|
console.warn(e);
|
|
447
537
|
}
|
|
448
538
|
|
|
449
|
-
this.
|
|
539
|
+
this.emit(EVENT_SHARE_SCREEN_ENDED);
|
|
450
540
|
this.currentScreenShare = null;
|
|
451
541
|
|
|
452
542
|
return reinvited;
|
|
@@ -459,9 +549,15 @@ class Call extends EventEmitter {
|
|
|
459
549
|
this._onScreenSharing(localStream as MediaStream, false, desktop);
|
|
460
550
|
}
|
|
461
551
|
|
|
552
|
+
onMakeCall() {
|
|
553
|
+
this._bindEvents();
|
|
554
|
+
|
|
555
|
+
this._sendAction(Actions.MAKE_CALL);
|
|
556
|
+
}
|
|
557
|
+
|
|
462
558
|
onAccepted() {
|
|
463
559
|
this._sendAction(Actions.REMOTLY_ACCEPTED);
|
|
464
|
-
this.emit(
|
|
560
|
+
this.emit(EVENT_CALL_REMOTLY_ACCEPTED);
|
|
465
561
|
}
|
|
466
562
|
|
|
467
563
|
onProgress() {
|
|
@@ -480,12 +576,18 @@ class Call extends EventEmitter {
|
|
|
480
576
|
this.emit(EVENT_CALL_ERROR, error);
|
|
481
577
|
}
|
|
482
578
|
|
|
579
|
+
onCallIncoming() {
|
|
580
|
+
this._bindEvents();
|
|
581
|
+
|
|
582
|
+
this._sendAction(Actions.INCOMING_CALL);
|
|
583
|
+
}
|
|
584
|
+
|
|
483
585
|
onRejected() {
|
|
484
586
|
this.endTime = new Date();
|
|
485
587
|
|
|
486
588
|
this.emit(EVENT_CALL_REJECTED);
|
|
487
589
|
|
|
488
|
-
this.phone.
|
|
590
|
+
this.phone.onCallTerminated(this);
|
|
489
591
|
}
|
|
490
592
|
|
|
491
593
|
onNetworkStats(stats: Record<string, any>, previousStats: Record<string, any>) {
|
|
@@ -528,17 +630,32 @@ class Call extends EventEmitter {
|
|
|
528
630
|
this.emit(EVENT_REINVITE, request, updatedCalleeName, updatedNumber, hadRemoteVideo);
|
|
529
631
|
}
|
|
530
632
|
|
|
633
|
+
updateFrom(call: Call) {
|
|
634
|
+
updateFrom(this, call);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
is(otherCall: Call) {
|
|
638
|
+
return otherCall && this.id && this.id === otherCall.id;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
shouldAutoAnswer() {
|
|
642
|
+
return !!this.sipCall.request?.getHeader('alert-info');
|
|
643
|
+
}
|
|
644
|
+
|
|
531
645
|
get id() {
|
|
532
|
-
return
|
|
646
|
+
return getSipCallId(this.sipCall);
|
|
533
647
|
}
|
|
534
648
|
|
|
535
|
-
get
|
|
536
|
-
|
|
537
|
-
// @ts-ignore: private
|
|
538
|
-
return identity ? identity.uri._normal.user : null;
|
|
649
|
+
get state(): StateTypes | Record<StateTypes, EstablishedStateTypes> {
|
|
650
|
+
return getState(this.callActor) as StateTypes | Record<StateTypes, EstablishedStateTypes>;
|
|
539
651
|
}
|
|
540
652
|
|
|
541
|
-
|
|
653
|
+
private _hasEstablishedState(establishedState: EstablishedStateTypes) {
|
|
654
|
+
const state = this.state as Record<StateTypes, EstablishedStateTypes>;
|
|
655
|
+
return typeof state === 'object' && States.ESTABLISHED in state && state[States.ESTABLISHED] === establishedState;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
private _bindEvents() {
|
|
542
659
|
if (this.sipCall instanceof Invitation) {
|
|
543
660
|
// Monkey patch to know when canceled with the CANCEL message
|
|
544
661
|
const onCancel = (this.sipCall as Invitation)._onCancel.bind(this.sipCall);
|
|
@@ -548,15 +665,15 @@ class Call extends EventEmitter {
|
|
|
548
665
|
onCancel(message);
|
|
549
666
|
const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
|
|
550
667
|
|
|
551
|
-
this.
|
|
668
|
+
this.emit(EVENT_CALL_CANCELED, elsewhere);
|
|
552
669
|
};
|
|
553
670
|
}
|
|
554
671
|
|
|
555
|
-
this.sipCall
|
|
672
|
+
this.sipCall?.stateChange?.addListener((newState: SessionState) => {
|
|
556
673
|
switch (newState) {
|
|
557
674
|
case SessionState.Terminating:
|
|
558
675
|
logger.info('call - terminating', { id: this.id });
|
|
559
|
-
this.
|
|
676
|
+
this.emit(EVENT_CALL_TERMINATING);
|
|
560
677
|
break;
|
|
561
678
|
|
|
562
679
|
case SessionState.Terminated:
|
|
@@ -566,7 +683,9 @@ class Call extends EventEmitter {
|
|
|
566
683
|
// Should be called before `_onCallTerminated` or the callCount will not decrement...
|
|
567
684
|
this.endTime = new Date();
|
|
568
685
|
|
|
569
|
-
|
|
686
|
+
this.emit(EVENT_CALL_ENDED);
|
|
687
|
+
|
|
688
|
+
return this.phone.onCallTerminated(this);
|
|
570
689
|
}
|
|
571
690
|
|
|
572
691
|
default:
|
|
@@ -599,10 +718,10 @@ class Call extends EventEmitter {
|
|
|
599
718
|
});
|
|
600
719
|
|
|
601
720
|
if (kind === 'audio') {
|
|
602
|
-
return this.
|
|
721
|
+
return this.emit(EVENT_AUDIO_STREAM, stream);
|
|
603
722
|
}
|
|
604
723
|
|
|
605
|
-
return this.
|
|
724
|
+
return this.emit(EVENT_VIDEO_STREAM, stream, event.track.id, event);
|
|
606
725
|
};
|
|
607
726
|
|
|
608
727
|
peerConnection.onremovestream = (event: any) => {
|
|
@@ -610,13 +729,11 @@ class Call extends EventEmitter {
|
|
|
610
729
|
id: event.stream.id,
|
|
611
730
|
tracks: event.stream.getTracks(),
|
|
612
731
|
});
|
|
613
|
-
this.
|
|
732
|
+
this.emit(EVENT_REMOVE_STREAM, event.stream);
|
|
614
733
|
};
|
|
615
|
-
|
|
616
|
-
// Client events
|
|
617
734
|
}
|
|
618
735
|
|
|
619
|
-
_downgradeToAudio(withMessage = true) {
|
|
736
|
+
private _downgradeToAudio(withMessage = true) {
|
|
620
737
|
assertState(this.callActor, States.ESTABLISHED);
|
|
621
738
|
logger.info('call - downgrade to audio', { id: this.id, withMessage });
|
|
622
739
|
|
|
@@ -630,7 +747,7 @@ class Call extends EventEmitter {
|
|
|
630
747
|
}
|
|
631
748
|
|
|
632
749
|
// Returns true if we need to send a re-INVITE request
|
|
633
|
-
async _upgradeToVideo(options: ReinviteOptions = {}): Promise<boolean> {
|
|
750
|
+
private async _upgradeToVideo(options: ReinviteOptions = {}): Promise<boolean> {
|
|
634
751
|
assertState(this.callActor, States.ESTABLISHED);
|
|
635
752
|
logger.info('call - upgrade to video', { id: this.id, ...options });
|
|
636
753
|
|
|
@@ -660,7 +777,7 @@ class Call extends EventEmitter {
|
|
|
660
777
|
return false;
|
|
661
778
|
}
|
|
662
779
|
|
|
663
|
-
_sendReinviteMessage(isUpgrade: boolean) {
|
|
780
|
+
private _sendReinviteMessage(isUpgrade: boolean) {
|
|
664
781
|
assertState(this.callActor, States.ESTABLISHED);
|
|
665
782
|
logger.info('call - sending reinvite message', { id: this.id, isUpgrade });
|
|
666
783
|
|
|
@@ -679,7 +796,7 @@ class Call extends EventEmitter {
|
|
|
679
796
|
}, 2500);
|
|
680
797
|
}
|
|
681
798
|
|
|
682
|
-
_onScreenSharing(screenStream: MediaStream, hadVideo: boolean, desktop?: boolean | null | undefined) {
|
|
799
|
+
private _onScreenSharing(screenStream: MediaStream, hadVideo: boolean, desktop?: boolean | null | undefined) {
|
|
683
800
|
const screenTrack = screenStream.getVideoTracks()[0];
|
|
684
801
|
const pc = this.phone.client.getPeerConnection(this.id);
|
|
685
802
|
const sender = pc && pc.getSenders && pc.getSenders().find((s) => s && s.track && s.track.kind === 'video');
|
|
@@ -690,7 +807,7 @@ class Call extends EventEmitter {
|
|
|
690
807
|
screenTrack.onended = () => {
|
|
691
808
|
logger.info('call - on screenshare ended', { hadVideo, id: this.id, screenTrack });
|
|
692
809
|
|
|
693
|
-
this.
|
|
810
|
+
this.emit(EVENT_SHARE_SCREEN_ENDING);
|
|
694
811
|
};
|
|
695
812
|
}
|
|
696
813
|
|
|
@@ -702,11 +819,13 @@ class Call extends EventEmitter {
|
|
|
702
819
|
};
|
|
703
820
|
|
|
704
821
|
setLocalMediaStream(this.sipCall, screenStream);
|
|
705
|
-
this.
|
|
822
|
+
this.emit(EVENT_SHARE_SCREEN_STARTED, screenStream);
|
|
706
823
|
}
|
|
707
824
|
|
|
708
|
-
_sendAction(action: ActionTypes | EstablishedActionTypes) {
|
|
825
|
+
private _sendAction(action: ActionTypes | EstablishedActionTypes) {
|
|
826
|
+
const was = this.state;
|
|
709
827
|
this.callActor.send({ type: action });
|
|
828
|
+
logger.trace('call - send action', { action, was, state: this.state });
|
|
710
829
|
}
|
|
711
830
|
}
|
|
712
831
|
|