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