@wazo/sdk 1.0.0-alpha.1 → 1.0.0-alpha.3
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/dist/wazo-sdk.js +6 -6
- package/esm/__tests__/__voice__/call.test.js +45 -2
- package/esm/domain/Phone/CTIPhone.js +2 -2
- package/esm/domain/Phone/WebRTCPhone.js +6 -7
- package/esm/index.js +1 -1
- package/esm/service/CallApi.js +4 -4
- package/esm/simple/Phone.js +1 -0
- package/esm/state-machine/call-state-machine.js +1 -1
- package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/esm/types/index.d.ts +1 -1
- package/esm/types/index.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/Phone.d.ts.map +1 -1
- package/esm/types/state-machine/softphone-state-machine.d.ts +1 -1
- package/esm/types/state-machine/utils.d.ts +1 -1
- package/esm/types/state-machine/utils.d.ts.map +1 -1
- package/esm/types/utils/sdp.d.ts +2 -0
- 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 +27 -12
- package/esm/types/voice/call.d.ts.map +1 -1
- package/esm/types/voice/softphone.d.ts +22 -13
- package/esm/types/voice/softphone.d.ts.map +1 -1
- package/esm/utils/sdp.js +13 -0
- package/esm/utils/webrtc.js +20 -0
- package/esm/voice/call.js +115 -33
- package/esm/voice/softphone.js +105 -25
- package/lib/__tests__/__voice__/call.test.js +44 -1
- package/lib/domain/Phone/CTIPhone.js +2 -2
- package/lib/domain/Phone/WebRTCPhone.js +5 -6
- package/lib/index.js +2 -2
- package/lib/service/CallApi.js +2 -2
- package/lib/simple/Phone.js +1 -0
- package/lib/state-machine/call-state-machine.js +1 -1
- package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.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/Phone.d.ts.map +1 -1
- package/lib/types/state-machine/softphone-state-machine.d.ts +1 -1
- package/lib/types/state-machine/utils.d.ts +1 -1
- package/lib/types/state-machine/utils.d.ts.map +1 -1
- package/lib/types/utils/sdp.d.ts +2 -0
- 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 +27 -12
- package/lib/types/voice/call.d.ts.map +1 -1
- package/lib/types/voice/softphone.d.ts +22 -13
- package/lib/types/voice/softphone.d.ts.map +1 -1
- package/lib/utils/sdp.js +16 -1
- package/lib/utils/webrtc.js +22 -1
- package/lib/voice/call.js +112 -31
- package/lib/voice/softphone.js +109 -25
- package/package.json +1 -1
- package/src/__tests__/__voice__/call.test.ts +48 -2
- package/src/domain/Phone/CTIPhone.ts +3 -2
- package/src/domain/Phone/WebRTCPhone.ts +9 -9
- package/src/index.ts +1 -1
- package/src/service/CallApi.ts +7 -7
- package/src/simple/Phone.ts +1 -0
- package/src/state-machine/call-state-machine.ts +1 -1
- package/src/state-machine/utils.ts +2 -2
- package/src/utils/sdp.ts +16 -0
- package/src/utils/webrtc.ts +23 -1
- package/src/voice/call.ts +149 -43
- package/src/voice/softphone.ts +130 -31
- package/src/web-rtc-client.ts +1 -1
package/src/voice/softphone.ts
CHANGED
|
@@ -10,7 +10,6 @@ import InvalidState from '../domain/InvalidState';
|
|
|
10
10
|
|
|
11
11
|
import Wazo from '..';
|
|
12
12
|
import softphoneStateMachine, { type SoftphoneActorRef, Actions, type StateTypes, States, ActionTypes } from '../state-machine/softphone-state-machine';
|
|
13
|
-
import { Actions as CallActions } from '../state-machine/call-state-machine';
|
|
14
13
|
import { WebRtcConfig, SipCall } from '../domain/types';
|
|
15
14
|
import WazoWebRTCClient from '../web-rtc-client';
|
|
16
15
|
import IssueReporter from '../service/IssueReporter';
|
|
@@ -19,12 +18,17 @@ import Call from './call';
|
|
|
19
18
|
import { assertCan, can, getState, waitUntilState } from '../state-machine/utils';
|
|
20
19
|
|
|
21
20
|
export const EVENT_INCOMING = 'incoming';
|
|
21
|
+
export const EVENT_OUTGOING = 'outgoing';
|
|
22
22
|
export const EVENT_HEARTBEAT = 'heartbeat';
|
|
23
23
|
export const EVENT_HEARTBEAT_TIMEOUT = 'heartbeatTimeout';
|
|
24
24
|
export const EVENT_REGISTERED = 'registered';
|
|
25
25
|
export const EVENT_UNREGISTERED = 'unregistered';
|
|
26
26
|
export const EVENT_DISCONNECTED = 'disconnected';
|
|
27
27
|
export const EVENT_VIDEO_INPUT_CHANGE = 'videoInputChange';
|
|
28
|
+
export const EVENT_TERMINATE_SOUND = 'terminateSound';
|
|
29
|
+
export const EVENT_PLAY_HANGUP_SOUND = 'playHangupSound';
|
|
30
|
+
export const EVENT_PLAY_RING_SOUND = 'playRingSound';
|
|
31
|
+
export const EVENT_PLAY_INBOUND_CALL_SOUND = 'playInboundCallSound';
|
|
28
32
|
export const EVENT_ON_MESSAGE = 'message';
|
|
29
33
|
export const EVENT_ON_CHAT = 'phone/ON_CHAT';
|
|
30
34
|
export const EVENT_ON_SIGNAL = 'phone/ON_SIGNAL';
|
|
@@ -40,6 +44,7 @@ export type CallOptions = {
|
|
|
40
44
|
// If audioOnly is set to true, all video stream will be deactivated, even remotes ones.
|
|
41
45
|
audioOnly?: boolean,
|
|
42
46
|
conference?: boolean,
|
|
47
|
+
extraHeaders?: Record<string, any>,
|
|
43
48
|
};
|
|
44
49
|
|
|
45
50
|
const logger = IssueReporter.loggerFor('softphone');
|
|
@@ -53,8 +58,6 @@ export class Softphone extends EventEmitter {
|
|
|
53
58
|
|
|
54
59
|
audioRingVolume: number;
|
|
55
60
|
|
|
56
|
-
eventEmitter: EventEmitter;
|
|
57
|
-
|
|
58
61
|
calls: Call[];
|
|
59
62
|
|
|
60
63
|
client: WazoWebRTCClient;
|
|
@@ -69,6 +72,8 @@ export class Softphone extends EventEmitter {
|
|
|
69
72
|
|
|
70
73
|
shouldSendReinvite: boolean;
|
|
71
74
|
|
|
75
|
+
ringingEnabled = true;
|
|
76
|
+
|
|
72
77
|
constructor() {
|
|
73
78
|
super();
|
|
74
79
|
|
|
@@ -103,6 +108,10 @@ export class Softphone extends EventEmitter {
|
|
|
103
108
|
return this.connectWithCredentials(server, this.sipLine, session.displayName(), options);
|
|
104
109
|
}
|
|
105
110
|
|
|
111
|
+
async hangupAllCalls() {
|
|
112
|
+
return Promise.all(this.calls.map(call => call.hangup()));
|
|
113
|
+
}
|
|
114
|
+
|
|
106
115
|
async disconnect() {
|
|
107
116
|
assertCan(this.softphoneActor, Actions.UNREGISTER);
|
|
108
117
|
if (!this.client) {
|
|
@@ -110,7 +119,7 @@ export class Softphone extends EventEmitter {
|
|
|
110
119
|
}
|
|
111
120
|
|
|
112
121
|
// Terminate all calls
|
|
113
|
-
await
|
|
122
|
+
await this.hangupAllCalls();
|
|
114
123
|
|
|
115
124
|
return this.client.unregister();
|
|
116
125
|
}
|
|
@@ -179,16 +188,16 @@ export class Softphone extends EventEmitter {
|
|
|
179
188
|
return Promise.resolve(null);
|
|
180
189
|
}
|
|
181
190
|
|
|
182
|
-
if (this.
|
|
183
|
-
throw new InvalidState(`Invalid state ${States.UNREGISTERED}`, States.UNREGISTERED);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (this.getState() !== States.REGISTERING) {
|
|
191
|
+
if (this.state === States.REGISTERING) {
|
|
187
192
|
logger.info('softphone - calling when registering, waiting for Softphone to be registered ...');
|
|
188
193
|
|
|
189
194
|
await waitUntilState(this.softphoneActor, States.REGISTERED);
|
|
190
195
|
}
|
|
191
196
|
|
|
197
|
+
if (this.state !== States.UNREGISTERED) {
|
|
198
|
+
throw new InvalidState(`Invalid state ${States.UNREGISTERED}`, States.UNREGISTERED);
|
|
199
|
+
}
|
|
200
|
+
|
|
192
201
|
// Hold other calls
|
|
193
202
|
this.holdAllCalls();
|
|
194
203
|
|
|
@@ -198,6 +207,8 @@ export class Softphone extends EventEmitter {
|
|
|
198
207
|
sipCall = this.client.call(options.params.To, options.withCamera, options.audioOnly, options.conference, options) as SipCall;
|
|
199
208
|
const call = new Call(sipCall, this);
|
|
200
209
|
|
|
210
|
+
this.emit(EVENT_OUTGOING, call);
|
|
211
|
+
|
|
201
212
|
return call;
|
|
202
213
|
} catch (error: any) {
|
|
203
214
|
logger.warn('softphone - call, error', { message: error.message, stack: error.stack });
|
|
@@ -209,6 +220,69 @@ export class Softphone extends EventEmitter {
|
|
|
209
220
|
this.calls = this.calls.filter((call: Call) => call.id !== callToRemove.id);
|
|
210
221
|
}
|
|
211
222
|
|
|
223
|
+
onCallTerminated(call: Call) {
|
|
224
|
+
logger.info('softphone - on call terminated', { id: call.id });
|
|
225
|
+
|
|
226
|
+
const currentCall = this.getCurrentCall();
|
|
227
|
+
const isCurrentCall = currentCall?.id === call.id;
|
|
228
|
+
const isRinging = call.isRinging();
|
|
229
|
+
const isCurrentIncomingCall = isCurrentCall && isRinging;
|
|
230
|
+
const incomingCalls = this.getIncomingCalls();
|
|
231
|
+
const nbIncomingCalls = incomingCalls.length;
|
|
232
|
+
|
|
233
|
+
// Send an event to terminate ringing sound
|
|
234
|
+
if (isCurrentIncomingCall) {
|
|
235
|
+
setTimeout(() => {
|
|
236
|
+
// Avoid race condition when the other is calling and hanging up immediately
|
|
237
|
+
this.emit(EVENT_TERMINATE_SOUND, call, 'call terminated');
|
|
238
|
+
}, 5);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// If the terminated call was an incoming call, we have to re-trigger if it's was the first incoming call
|
|
242
|
+
// Otherwise, we have to re-trigger an incoming call event if another call is incoming
|
|
243
|
+
const shouldRetrigger = isCurrentCall ? nbIncomingCalls : isCurrentIncomingCall;
|
|
244
|
+
|
|
245
|
+
// Re-trigger incoming call event for remaining incoming calls
|
|
246
|
+
logger.info('Softphone - check to re-trigger incoming call', { shouldRetrigger, nbIncomingCalls });
|
|
247
|
+
|
|
248
|
+
if (shouldRetrigger && nbIncomingCalls > 1) {
|
|
249
|
+
const nextCall = incomingCalls.find(c => c.id !== call.id);
|
|
250
|
+
// Avoid race condition
|
|
251
|
+
setTimeout(() => {
|
|
252
|
+
if (this.ringingEnabled) {
|
|
253
|
+
if (currentCall) {
|
|
254
|
+
this.emit(EVENT_PLAY_RING_SOUND, this.audioRingDeviceId, this.audioRingVolume, nextCall);
|
|
255
|
+
} else {
|
|
256
|
+
this.emit(EVENT_PLAY_INBOUND_CALL_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, nextCall);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
this.emit(EVENT_INCOMING, nextCall);
|
|
261
|
+
}, 100);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// @ts-ignore: does not exist
|
|
265
|
+
if (!call.sipCall.isCanceled) {
|
|
266
|
+
setTimeout(() => {
|
|
267
|
+
this.emit(EVENT_PLAY_HANGUP_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, call);
|
|
268
|
+
}, 10);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
this.client.onCallEnded(call.sipCall);
|
|
272
|
+
|
|
273
|
+
this.removeCall(call);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
enableRinging(): Promise<void> | void {
|
|
277
|
+
logger.info('softphone - enable ringing');
|
|
278
|
+
this.ringingEnabled = true;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
disableRinging(): Promise<void> | void {
|
|
282
|
+
logger.info('softphone - disable ringing');
|
|
283
|
+
this.ringingEnabled = false;
|
|
284
|
+
}
|
|
285
|
+
|
|
212
286
|
holdAllCalls(exceptCall: Call | null = null) {
|
|
213
287
|
this.calls.filter(call => !call.isHeld() && call.id === exceptCall?.id).forEach(call => call.hold());
|
|
214
288
|
}
|
|
@@ -278,29 +352,51 @@ export class Softphone extends EventEmitter {
|
|
|
278
352
|
this.audioRingVolume = volume;
|
|
279
353
|
}
|
|
280
354
|
|
|
281
|
-
|
|
282
|
-
return this.
|
|
355
|
+
getCurrentCall(): Call | undefined {
|
|
356
|
+
return this.getActiveCalls()[0];
|
|
283
357
|
}
|
|
284
358
|
|
|
285
|
-
|
|
286
|
-
return this.calls.
|
|
359
|
+
getActiveCalls(): Call[] {
|
|
360
|
+
return this.calls.filter(call => call.isEstablished());
|
|
287
361
|
}
|
|
288
362
|
|
|
289
|
-
|
|
290
|
-
return this.
|
|
363
|
+
getIncomingCalls(): Call[] {
|
|
364
|
+
return this.calls.filter(call => call.isRinging());
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
get state(): StateTypes {
|
|
368
|
+
return getState(this.softphoneActor) as StateTypes;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
get user() {
|
|
372
|
+
return this.client?.userAgent?.contact?.uri?.user;
|
|
291
373
|
}
|
|
292
374
|
|
|
293
375
|
getUserAgent() {
|
|
294
376
|
return this.client?.config?.userAgentString || 'softphone';
|
|
295
377
|
}
|
|
296
378
|
|
|
379
|
+
isRegistered() {
|
|
380
|
+
return this.state === States.REGISTERED;
|
|
381
|
+
}
|
|
382
|
+
|
|
297
383
|
_bindEvents(): void {
|
|
298
384
|
this.client.on(this.client.INVITE, (sipSession: SipCall) => {
|
|
299
385
|
const call = new Call(sipSession, this);
|
|
300
|
-
|
|
386
|
+
logger.info('softphone - on invite', { callId: call.id, number: call.number });
|
|
387
|
+
|
|
388
|
+
call.onCallIncoming();
|
|
301
389
|
this.calls.push(call);
|
|
302
390
|
|
|
303
|
-
this.
|
|
391
|
+
this.emit(EVENT_INCOMING, call);
|
|
392
|
+
|
|
393
|
+
if (!this.getCurrentCall()) {
|
|
394
|
+
if (this.ringingEnabled) {
|
|
395
|
+
this.emit(EVENT_PLAY_RING_SOUND, this.audioRingDeviceId, this.audioRingVolume, call);
|
|
396
|
+
}
|
|
397
|
+
} else {
|
|
398
|
+
this.emit(EVENT_PLAY_INBOUND_CALL_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, call);
|
|
399
|
+
}
|
|
304
400
|
});
|
|
305
401
|
|
|
306
402
|
this.client.on(this.client.ON_REINVITE, (sipCall: SipCall, request: IncomingRequestMessage, updatedCalleeName: string, updatedNumber: string, hadRemoteVideo: boolean) => {
|
|
@@ -316,6 +412,9 @@ export class Softphone extends EventEmitter {
|
|
|
316
412
|
});
|
|
317
413
|
|
|
318
414
|
this.client.on(this.client.ACCEPTED, async (sipCall: SipCall) => {
|
|
415
|
+
const call = this._getCall(sipCall);
|
|
416
|
+
this.emit(EVENT_TERMINATE_SOUND, call, 'call accepted');
|
|
417
|
+
|
|
319
418
|
this._onCallEvent(sipCall, 'onAccepted');
|
|
320
419
|
|
|
321
420
|
if (this.audioOutputDeviceId) {
|
|
@@ -354,14 +453,14 @@ export class Softphone extends EventEmitter {
|
|
|
354
453
|
|
|
355
454
|
this.client.on(this.client.UNREGISTERED, () => {
|
|
356
455
|
logger.info('softphone - unregistered');
|
|
357
|
-
this.
|
|
456
|
+
this.emit(EVENT_UNREGISTERED);
|
|
358
457
|
|
|
359
458
|
this._sendAction(Actions.UNREGISTERED);
|
|
360
459
|
});
|
|
361
460
|
|
|
362
461
|
this.client.on(this.client.ON_DISCONNECTED, () => {
|
|
363
462
|
logger.info('softphone - disconnected');
|
|
364
|
-
this.
|
|
463
|
+
this.emit(EVENT_DISCONNECTED);
|
|
365
464
|
|
|
366
465
|
this._sendAction(Actions.TRANSPORT_CLOSED);
|
|
367
466
|
});
|
|
@@ -376,7 +475,7 @@ export class Softphone extends EventEmitter {
|
|
|
376
475
|
this.stopHeartbeat();
|
|
377
476
|
this._sendAction(Actions.REGISTER_DONE);
|
|
378
477
|
|
|
379
|
-
this.
|
|
478
|
+
this.emit(EVENT_REGISTERED);
|
|
380
479
|
|
|
381
480
|
// If the phone registered with a current callSession (eg: when switching network):
|
|
382
481
|
// send a reinvite to renegociate ICE with new IP
|
|
@@ -396,7 +495,7 @@ export class Softphone extends EventEmitter {
|
|
|
396
495
|
|
|
397
496
|
this.client.on(this.client.DISCONNECTED, () => {
|
|
398
497
|
logger.info('softphone - disconnected');
|
|
399
|
-
this.
|
|
498
|
+
this.emit(EVENT_DISCONNECTED);
|
|
400
499
|
|
|
401
500
|
// Do not trigger heartbeat if already running
|
|
402
501
|
if (!this.client.hasHeartbeat()) {
|
|
@@ -408,33 +507,33 @@ export class Softphone extends EventEmitter {
|
|
|
408
507
|
});
|
|
409
508
|
|
|
410
509
|
this.client.on('onVideoInputChange', stream => {
|
|
411
|
-
this.
|
|
510
|
+
this.emit(EVENT_VIDEO_INPUT_CHANGE, stream);
|
|
412
511
|
});
|
|
413
512
|
|
|
414
513
|
this.client.on(this.client.MESSAGE, (message: Message) => {
|
|
415
514
|
this._onMessage(message);
|
|
416
515
|
|
|
417
|
-
this.
|
|
516
|
+
this.emit(EVENT_ON_MESSAGE, message);
|
|
418
517
|
});
|
|
419
518
|
|
|
420
519
|
this.client.setOnHeartbeatTimeout(() => {
|
|
421
|
-
this.
|
|
520
|
+
this.emit(EVENT_HEARTBEAT_TIMEOUT);
|
|
422
521
|
});
|
|
423
522
|
|
|
424
523
|
this.client.setOnHeartbeatCallback(() => {
|
|
425
|
-
this.
|
|
524
|
+
this.emit(EVENT_HEARTBEAT);
|
|
426
525
|
});
|
|
427
526
|
}
|
|
428
527
|
|
|
429
|
-
_sendAction(action: ActionTypes) {
|
|
528
|
+
private _sendAction(action: ActionTypes) {
|
|
430
529
|
this.softphoneActor.send({ type: action });
|
|
431
530
|
}
|
|
432
531
|
|
|
433
|
-
_getCall(sipCall: SipCall): Call | undefined {
|
|
532
|
+
private _getCall(sipCall: SipCall): Call | undefined {
|
|
434
533
|
return this.calls.find(call => call.id === sipCall.id);
|
|
435
534
|
}
|
|
436
535
|
|
|
437
|
-
_onCallEvent(sipCall: SipCall, eventName: string, ...args: any[]) {
|
|
536
|
+
private _onCallEvent(sipCall: SipCall, eventName: string, ...args: any[]) {
|
|
438
537
|
logger.warn('softphone - received call event', { eventName, sipId: sipCall.id });
|
|
439
538
|
|
|
440
539
|
const call = this._getCall(sipCall);
|
|
@@ -447,7 +546,7 @@ export class Softphone extends EventEmitter {
|
|
|
447
546
|
call[eventName](...args);
|
|
448
547
|
}
|
|
449
548
|
|
|
450
|
-
_onMessage(message: Message & { method?: string, body?: string }): void {
|
|
549
|
+
private _onMessage(message: Message & { method?: string, body?: string }): void {
|
|
451
550
|
if (!message || message.method !== 'MESSAGE') {
|
|
452
551
|
return;
|
|
453
552
|
}
|
|
@@ -467,12 +566,12 @@ export class Softphone extends EventEmitter {
|
|
|
467
566
|
|
|
468
567
|
switch (type) {
|
|
469
568
|
case MESSAGE_TYPE_CHAT:
|
|
470
|
-
this.
|
|
569
|
+
this.emit(EVENT_ON_CHAT, content);
|
|
471
570
|
break;
|
|
472
571
|
|
|
473
572
|
case MESSAGE_TYPE_SIGNAL:
|
|
474
573
|
{
|
|
475
|
-
this.
|
|
574
|
+
this.emit(EVENT_ON_SIGNAL, content);
|
|
476
575
|
break;
|
|
477
576
|
}
|
|
478
577
|
|
package/src/web-rtc-client.ts
CHANGED
|
@@ -31,7 +31,7 @@ import IssueReporter from './service/IssueReporter';
|
|
|
31
31
|
import Heartbeat from './utils/Heartbeat';
|
|
32
32
|
import { getSipSessionId, makeURI, replaceLocalIpModifier, SIP_ID_LENGTH } from './utils/sdp';
|
|
33
33
|
import type { MediaConfig, UserAgentConfigOverrides, WebRtcConfig, IncomingResponse, PeerConnection, WazoSession, WazoTransport } from './domain/types';
|
|
34
|
-
import { cleanupStream, createUaOptions, fetchNetworkStats, getAudioConstraints, getLocalStream, getLocalTracks, getLocalVideoStream, getMediaConfiguration, getPeerConnection, getRemoteStream, getRemoteTracks, getRemoteVideoStream, getRemoteVideoStreamFromPc,
|
|
34
|
+
import { cleanupStream, createUaOptions, fetchNetworkStats, getAudioConstraints, getLocalStream, getLocalTracks, getLocalVideoStream, getMediaConfiguration, getPeerConnection, getRemoteStream, getRemoteTracks, getRemoteVideoStream, getRemoteVideoStreamFromPc, getVideoConstraints, hasALocalVideoTrack, hasARemoteVideoTrack, hasAVideoTrack, hasLocalVideo, hasRemoteVideo, hasVideoTrack, isAudioOnly, isVideoRemotelyHeld, isWeb, sessionWantsToDoVideo, setLocalMediaStream, toggleAudio, toggleVideo, updateRemoteStream } from './utils/webrtc';
|
|
35
35
|
|
|
36
36
|
const SEND_STATS_DELAY = 5000;
|
|
37
37
|
const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
|