@wazo/sdk 0.37.0-rc.5 → 0.37.2
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 +5 -5
- package/esm/__tests__/api-client.test.js +93 -16
- package/esm/__tests__/web-rtc-client.test.js +153 -54
- package/esm/api/agentd.js +24 -3
- package/esm/api/amid.js +7 -1
- package/esm/api/application.js +24 -3
- package/esm/api/auth.js +24 -3
- package/esm/api/call-logd.js +78 -20
- package/esm/api/calld.js +24 -20
- package/esm/api/chatd.js +24 -3
- package/esm/api/confd.js +24 -3
- package/esm/api/ctid-ng.js +24 -3
- package/esm/api/dird.js +27 -6
- package/esm/api/webhookd.js +7 -1
- package/esm/api-client.js +93 -16
- package/esm/checker/Checker.js +156 -54
- package/esm/checker/checks/aor.js +95 -16
- package/esm/checker/checks/api.js +94 -16
- package/esm/checker/checks/index.js +156 -54
- package/esm/checker/checks/wazo-websocket.js +7 -1
- package/esm/checker/checks/webrtc-transport.js +153 -54
- package/esm/checker/checks/webrtc.js +153 -54
- package/esm/domain/AdHocAPIConference.js +1717 -1640
- package/esm/domain/CallLog.js +71 -19
- package/esm/domain/CallSession.js +1 -18
- package/esm/domain/Contact.js +3 -3
- package/esm/domain/Features.js +93 -16
- package/esm/domain/IndirectTransfer.js +0 -17
- package/esm/domain/Phone/CTIPhone.js +100 -19
- package/esm/domain/Phone/Phone.js +0 -17
- package/esm/domain/Phone/WebRTCPhone.js +51 -36
- package/esm/domain/Recording.js +51 -0
- package/esm/domain/Room.js +0 -17
- package/esm/domain/SwitchboardCall.js +0 -17
- package/esm/domain/__tests__/CallLog.test.js +89 -19
- package/esm/domain/__tests__/CallSession.test.js +1 -18
- package/esm/domain/__tests__/Contact.test.js +3 -3
- package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/esm/domain/__tests__/Room.test.js +1 -18
- package/esm/domain/__tests__/Session.test.js +7 -0
- package/esm/index.js +3436 -2911
- package/esm/lib/WazoSessionDescriptionHandler.js +28 -10
- package/esm/service/CallApi.js +93 -16
- package/esm/service/IssueReporter.js +7 -1
- package/esm/service/__tests__/IssueReporter.test.js +26 -2
- package/esm/service/getApiClient.js +93 -16
- package/esm/simple/Auth.js +619 -97
- package/esm/simple/Configuration.js +619 -97
- package/esm/simple/Directory.js +93 -16
- package/esm/simple/Phone.js +3261 -2739
- package/esm/simple/Websocket.js +7 -1
- package/esm/simple/index.js +619 -97
- package/esm/simple/room/LocalParticipant.js +619 -97
- package/esm/simple/room/Participant.js +619 -97
- package/esm/simple/room/RemoteParticipant.js +619 -97
- package/esm/simple/room/Room.js +619 -97
- package/esm/simple/room/Stream.js +619 -97
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +619 -97
- package/esm/simple/utils.js +619 -97
- package/esm/utils/__tests__/api-requester.test.js +32 -6
- package/esm/utils/api-requester.js +24 -3
- package/esm/web-rtc-client.js +153 -54
- package/esm/websocket-client.js +7 -1
- package/lib/__tests__/api-client.test.js +93 -16
- package/lib/__tests__/web-rtc-client.test.js +154 -55
- package/lib/api/agentd.js +24 -3
- package/lib/api/amid.js +7 -1
- package/lib/api/application.js +24 -3
- package/lib/api/auth.js +24 -3
- package/lib/api/call-logd.js +78 -20
- package/lib/api/calld.js +24 -20
- package/lib/api/chatd.js +24 -3
- package/lib/api/confd.js +24 -3
- package/lib/api/ctid-ng.js +24 -3
- package/lib/api/dird.js +27 -6
- package/lib/api/webhookd.js +7 -1
- package/lib/api-client.js +93 -16
- package/lib/checker/Checker.js +157 -55
- package/lib/checker/checks/aor.js +95 -16
- package/lib/checker/checks/api.js +94 -16
- package/lib/checker/checks/index.js +157 -55
- package/lib/checker/checks/wazo-websocket.js +7 -1
- package/lib/checker/checks/webrtc-transport.js +154 -55
- package/lib/checker/checks/webrtc.js +154 -55
- package/lib/domain/AdHocAPIConference.js +1717 -1640
- package/lib/domain/CallLog.js +71 -19
- package/lib/domain/CallSession.js +1 -18
- package/lib/domain/Contact.js +3 -3
- package/lib/domain/Features.js +93 -16
- package/lib/domain/IndirectTransfer.js +0 -17
- package/lib/domain/Phone/CTIPhone.js +100 -19
- package/lib/domain/Phone/Phone.js +0 -16
- package/lib/domain/Phone/WebRTCPhone.js +51 -36
- package/lib/domain/Recording.js +57 -0
- package/lib/domain/Room.js +0 -17
- package/lib/domain/SwitchboardCall.js +0 -17
- package/lib/domain/__tests__/CallLog.test.js +89 -19
- package/lib/domain/__tests__/CallSession.test.js +1 -18
- package/lib/domain/__tests__/Contact.test.js +3 -3
- package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/lib/domain/__tests__/Room.test.js +1 -18
- package/lib/domain/__tests__/Session.test.js +7 -0
- package/lib/index.js +3437 -2912
- package/lib/lib/WazoSessionDescriptionHandler.js +28 -10
- package/lib/service/CallApi.js +93 -16
- package/lib/service/IssueReporter.js +7 -1
- package/lib/service/__tests__/IssueReporter.test.js +26 -2
- package/lib/service/getApiClient.js +93 -16
- package/lib/simple/Auth.js +620 -98
- package/lib/simple/Configuration.js +620 -98
- package/lib/simple/Directory.js +93 -16
- package/lib/simple/Phone.js +3262 -2740
- package/lib/simple/Websocket.js +7 -1
- package/lib/simple/index.js +620 -98
- package/lib/simple/room/LocalParticipant.js +620 -98
- package/lib/simple/room/Participant.js +620 -98
- package/lib/simple/room/RemoteParticipant.js +620 -98
- package/lib/simple/room/Room.js +620 -98
- package/lib/simple/room/Stream.js +620 -98
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +620 -98
- package/lib/simple/utils.js +620 -98
- package/lib/utils/__tests__/api-requester.test.js +32 -6
- package/lib/utils/api-requester.js +24 -3
- package/lib/web-rtc-client.js +154 -55
- package/lib/websocket-client.js +7 -1
- package/package.json +1 -1
- package/src/api-client.js +4 -0
- package/src/checker/checks/aor.js +2 -0
- package/src/checker/checks/api.js +1 -0
- package/src/domain/CallLog.js +18 -11
- package/src/domain/CallSession.js +1 -2
- package/src/domain/Contact.js +3 -3
- package/src/domain/Phone/CTIPhone.js +6 -2
- package/src/domain/Phone/Phone.js +2 -0
- package/src/domain/Phone/WebRTCPhone.js +26 -16
- package/src/domain/Recording.js +48 -0
- package/src/domain/__tests__/CallLog.test.js +19 -0
- package/src/domain/__tests__/Session.test.js +7 -0
- package/src/index.js +6 -0
- package/src/lib/WazoSessionDescriptionHandler.js +21 -9
- package/src/service/IssueReporter.js +7 -1
- package/src/service/__tests__/IssueReporter.test.js +20 -1
- package/src/simple/Phone.js +5 -1
- package/src/simple/index.js +6 -0
- package/src/simple/room/Room.js +18 -15
- package/src/simple/room/Stream.js +1 -4
- package/src/utils/__tests__/api-requester.test.js +9 -4
- package/src/utils/api-requester.js +17 -2
- package/src/web-rtc-client.js +40 -13
|
@@ -10,7 +10,6 @@ var jsonToGraphQLQuery = require('json-to-graphql-query/lib/jsonToGraphQLQuery')
|
|
|
10
10
|
var invitation = require('sip.js/lib/api/invitation');
|
|
11
11
|
require('webrtc-adapter');
|
|
12
12
|
var userAgentState = require('sip.js/lib/api/user-agent-state');
|
|
13
|
-
require('sip.js/lib/api/message');
|
|
14
13
|
var parser = require('sip.js/lib/core/messages/parser');
|
|
15
14
|
var constants = require('sip.js/lib/core/messages/methods/constants');
|
|
16
15
|
var uri = require('sip.js/lib/grammar/uri');
|
|
@@ -139,7 +138,7 @@ const isMobile = () => typeof navigator !== 'undefined' && navigator.product ===
|
|
|
139
138
|
|
|
140
139
|
const methods = ['head', 'get', 'post', 'put', 'delete'];
|
|
141
140
|
|
|
142
|
-
const logger$
|
|
141
|
+
const logger$b = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
143
142
|
|
|
144
143
|
// Use a function here to be able to mock it in tests
|
|
145
144
|
const realFetch = () => {
|
|
@@ -174,6 +173,7 @@ class ApiRequester {
|
|
|
174
173
|
|
|
175
174
|
|
|
176
175
|
|
|
176
|
+
|
|
177
177
|
|
|
178
178
|
|
|
179
179
|
|
|
@@ -213,6 +213,8 @@ class ApiRequester {
|
|
|
213
213
|
this.token = token;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
this.shouldLogErrors = true;
|
|
217
|
+
|
|
216
218
|
methods.forEach(method => {
|
|
217
219
|
// $FlowFixMe
|
|
218
220
|
ApiRequester.prototype[method] = function sugar(...args) {
|
|
@@ -236,6 +238,14 @@ class ApiRequester {
|
|
|
236
238
|
this.fetchOptions = options;
|
|
237
239
|
}
|
|
238
240
|
|
|
241
|
+
disableErrorLogging() {
|
|
242
|
+
this.shouldLogErrors = false;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
enableErrorLogging() {
|
|
246
|
+
this.shouldLogErrors = true;
|
|
247
|
+
}
|
|
248
|
+
|
|
239
249
|
async call(
|
|
240
250
|
path ,
|
|
241
251
|
method = 'get',
|
|
@@ -267,7 +277,7 @@ class ApiRequester {
|
|
|
267
277
|
};
|
|
268
278
|
|
|
269
279
|
if (this.refreshTokenPromise) {
|
|
270
|
-
logger$
|
|
280
|
+
logger$b.info('A token is already refreshing, waiting ...', { url });
|
|
271
281
|
await this.refreshTokenPromise;
|
|
272
282
|
}
|
|
273
283
|
|
|
@@ -287,7 +297,7 @@ class ApiRequester {
|
|
|
287
297
|
return promise.then(async (err ) => {
|
|
288
298
|
// Check if the token is still valid
|
|
289
299
|
if (firstCall && this._checkTokenExpired(response, err)) {
|
|
290
|
-
logger$
|
|
300
|
+
logger$b.warn('token expired', { error: err.reason });
|
|
291
301
|
// Replay the call after refreshing the token
|
|
292
302
|
return this._replayWithNewToken(err, path, method, body, headers, parse);
|
|
293
303
|
}
|
|
@@ -296,7 +306,9 @@ class ApiRequester {
|
|
|
296
306
|
? exceptionClass.fromText(err, response.status)
|
|
297
307
|
: exceptionClass.fromResponse(err, response.status);
|
|
298
308
|
|
|
299
|
-
|
|
309
|
+
if (this.shouldLogErrors) {
|
|
310
|
+
logger$b.error('API error', error);
|
|
311
|
+
}
|
|
300
312
|
|
|
301
313
|
throw error;
|
|
302
314
|
});
|
|
@@ -304,7 +316,9 @@ class ApiRequester {
|
|
|
304
316
|
|
|
305
317
|
return newParse(response, isJson);
|
|
306
318
|
}).catch(error => {
|
|
307
|
-
|
|
319
|
+
if (this.shouldLogErrors) {
|
|
320
|
+
logger$b.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
|
|
321
|
+
}
|
|
308
322
|
|
|
309
323
|
throw error;
|
|
310
324
|
});
|
|
@@ -331,13 +345,13 @@ class ApiRequester {
|
|
|
331
345
|
) {
|
|
332
346
|
const isTokenNotFound = this._isTokenNotFound(err);
|
|
333
347
|
let newPath = path;
|
|
334
|
-
logger$
|
|
348
|
+
logger$b.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
|
|
335
349
|
|
|
336
350
|
this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
|
|
337
351
|
|
|
338
352
|
return this.refreshTokenPromise.then(() => {
|
|
339
353
|
this.refreshTokenPromise = null;
|
|
340
|
-
logger$
|
|
354
|
+
logger$b.info('token refreshed', { isTokenNotFound });
|
|
341
355
|
if (isTokenNotFound) {
|
|
342
356
|
const pathParts = path.split('/');
|
|
343
357
|
pathParts.pop();
|
|
@@ -615,7 +629,13 @@ class IssueReporter {
|
|
|
615
629
|
}
|
|
616
630
|
|
|
617
631
|
_isLevelAbove(level1 , level2 ) {
|
|
618
|
-
|
|
632
|
+
const index1 = LOG_LEVELS.indexOf(level1);
|
|
633
|
+
const index2 = LOG_LEVELS.indexOf(level2);
|
|
634
|
+
if (index1 === -1 || index2 === -1) {
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return index1 > index2;
|
|
619
639
|
}
|
|
620
640
|
|
|
621
641
|
_makeCategory(category ) {
|
|
@@ -1603,7 +1623,7 @@ class Contact {
|
|
|
1603
1623
|
|
|
1604
1624
|
return new Contact({
|
|
1605
1625
|
sourceId: single.id || '',
|
|
1606
|
-
name: single.displayName,
|
|
1626
|
+
name: single.displayName || '',
|
|
1607
1627
|
number: numbers.length ? numbers[0].number : '',
|
|
1608
1628
|
numbers,
|
|
1609
1629
|
emails,
|
|
@@ -1634,7 +1654,7 @@ class Contact {
|
|
|
1634
1654
|
|
|
1635
1655
|
return new Contact({
|
|
1636
1656
|
sourceId: single.id || '',
|
|
1637
|
-
name: single.name,
|
|
1657
|
+
name: single.name || '',
|
|
1638
1658
|
number: numbers.length ? numbers[0].number : '',
|
|
1639
1659
|
numbers,
|
|
1640
1660
|
emails,
|
|
@@ -1735,7 +1755,7 @@ class Contact {
|
|
|
1735
1755
|
} = {}) {
|
|
1736
1756
|
this.id = id;
|
|
1737
1757
|
this.uuid = uuid;
|
|
1738
|
-
this.name = name;
|
|
1758
|
+
this.name = name || '';
|
|
1739
1759
|
this.number = number;
|
|
1740
1760
|
this.numbers = numbers;
|
|
1741
1761
|
this.email = email;
|
|
@@ -3349,7 +3369,7 @@ class CallSession {
|
|
|
3349
3369
|
return newFrom(callSession, CallSession);
|
|
3350
3370
|
}
|
|
3351
3371
|
|
|
3352
|
-
static parseCall(
|
|
3372
|
+
static parseCall(call ) {
|
|
3353
3373
|
return new CallSession({
|
|
3354
3374
|
callId: call.id,
|
|
3355
3375
|
sipCallId: call.sipCallId,
|
|
@@ -3376,17 +3396,66 @@ class CallSession {
|
|
|
3376
3396
|
|
|
3377
3397
|
//
|
|
3378
3398
|
|
|
3399
|
+
|
|
3400
|
+
|
|
3401
|
+
|
|
3402
|
+
|
|
3403
|
+
|
|
3404
|
+
|
|
3405
|
+
|
|
3406
|
+
|
|
3407
|
+
|
|
3408
|
+
|
|
3409
|
+
|
|
3410
|
+
|
|
3411
|
+
|
|
3412
|
+
|
|
3413
|
+
|
|
3414
|
+
|
|
3415
|
+
class Recording {
|
|
3416
|
+
|
|
3417
|
+
|
|
3418
|
+
|
|
3419
|
+
|
|
3420
|
+
|
|
3421
|
+
|
|
3422
|
+
static parseMany(recordings ) {
|
|
3423
|
+
return recordings.map(item => Recording.parse(item));
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
static parse(plain ) {
|
|
3427
|
+
return new Recording({
|
|
3428
|
+
deleted: plain.deleted,
|
|
3429
|
+
fileName: plain.filename,
|
|
3430
|
+
end: plain.end_time ? moment__default['default'](plain.end_time).toDate() : null,
|
|
3431
|
+
start: moment__default['default'](plain.start_time).toDate(),
|
|
3432
|
+
uuid: plain.uuid,
|
|
3433
|
+
});
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3436
|
+
constructor({ deleted, end, fileName, start, uuid } ) {
|
|
3437
|
+
this.deleted = deleted;
|
|
3438
|
+
this.end = end;
|
|
3439
|
+
this.fileName = fileName;
|
|
3440
|
+
this.start = start;
|
|
3441
|
+
this.uuid = uuid;
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3445
|
+
//
|
|
3446
|
+
|
|
3379
3447
|
|
|
3380
|
-
|
|
3448
|
+
|
|
3381
3449
|
|
|
3382
3450
|
|
|
3383
3451
|
|
|
3384
3452
|
|
|
3385
3453
|
|
|
3386
|
-
|
|
3454
|
+
|
|
3387
3455
|
|
|
3388
3456
|
|
|
3389
3457
|
|
|
3458
|
+
|
|
3390
3459
|
|
|
3391
3460
|
|
|
3392
3461
|
|
|
@@ -3399,7 +3468,7 @@ class CallSession {
|
|
|
3399
3468
|
|
|
3400
3469
|
|
|
3401
3470
|
|
|
3402
|
-
|
|
3471
|
+
|
|
3403
3472
|
|
|
3404
3473
|
|
|
3405
3474
|
|
|
@@ -3414,13 +3483,14 @@ class CallSession {
|
|
|
3414
3483
|
|
|
3415
3484
|
|
|
3416
3485
|
|
|
3417
|
-
|
|
3486
|
+
|
|
3487
|
+
|
|
3418
3488
|
|
|
3419
3489
|
|
|
3420
3490
|
class CallLog {
|
|
3421
3491
|
|
|
3422
3492
|
|
|
3423
|
-
|
|
3493
|
+
|
|
3424
3494
|
|
|
3425
3495
|
|
|
3426
3496
|
|
|
@@ -3437,7 +3507,7 @@ class CallLog {
|
|
|
3437
3507
|
|
|
3438
3508
|
|
|
3439
3509
|
|
|
3440
|
-
|
|
3510
|
+
|
|
3441
3511
|
|
|
3442
3512
|
static merge(current , toMerge ) {
|
|
3443
3513
|
const onlyUnique = (value, index, self) => self.indexOf(value) === index;
|
|
@@ -3454,7 +3524,7 @@ class CallLog {
|
|
|
3454
3524
|
|
|
3455
3525
|
static parse(plain ) {
|
|
3456
3526
|
return new CallLog({
|
|
3457
|
-
answer: moment__default['default'](plain.answer).toDate(),
|
|
3527
|
+
answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
|
|
3458
3528
|
answered: plain.answered,
|
|
3459
3529
|
callDirection: plain.call_direction,
|
|
3460
3530
|
destination: {
|
|
@@ -3468,13 +3538,14 @@ class CallLog {
|
|
|
3468
3538
|
id: plain.id,
|
|
3469
3539
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3470
3540
|
start: moment__default['default'](plain.start).toDate(),
|
|
3471
|
-
end: moment__default['default'](plain.end).toDate(),
|
|
3541
|
+
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3542
|
+
recordings: Recording.parseMany(plain.recordings),
|
|
3472
3543
|
});
|
|
3473
3544
|
}
|
|
3474
3545
|
|
|
3475
3546
|
static parseNew(plain , session ) {
|
|
3476
3547
|
return new CallLog({
|
|
3477
|
-
answer: moment__default['default'](plain.answer).toDate(),
|
|
3548
|
+
answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
|
|
3478
3549
|
answered: plain.answered,
|
|
3479
3550
|
callDirection: plain.call_direction,
|
|
3480
3551
|
destination: {
|
|
@@ -3488,7 +3559,8 @@ class CallLog {
|
|
|
3488
3559
|
id: plain.id,
|
|
3489
3560
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3490
3561
|
start: moment__default['default'](plain.start).toDate(),
|
|
3491
|
-
end: moment__default['default'](plain.end).toDate(),
|
|
3562
|
+
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3563
|
+
recordings: Recording.parseMany(plain.recordings),
|
|
3492
3564
|
// @TODO: FIXME add verification declined vs missed call
|
|
3493
3565
|
newMissedCall: session
|
|
3494
3566
|
&& session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
|
|
@@ -3670,11 +3742,414 @@ class IndirectTransfer {
|
|
|
3670
3742
|
}
|
|
3671
3743
|
|
|
3672
3744
|
//
|
|
3745
|
+
|
|
3746
|
+
class CallApi {
|
|
3747
|
+
static async fetchCallLogs(offset , limit ) {
|
|
3748
|
+
return getApiClient().callLogd.listCallLogs(offset, limit);
|
|
3749
|
+
}
|
|
3750
|
+
|
|
3751
|
+
static async fetchDistinctCallLogs(offset , limit , distinct = 'peer_exten') {
|
|
3752
|
+
return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
|
|
3753
|
+
}
|
|
3754
|
+
|
|
3755
|
+
static async fetchActiveCalls() {
|
|
3756
|
+
return getApiClient().calld.listCalls();
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
static async fetchCallLogsFromDate(from , number ) {
|
|
3760
|
+
return getApiClient().callLogd.listCallLogsFromDate(from, number);
|
|
3761
|
+
}
|
|
3762
|
+
|
|
3763
|
+
static async search(query , limit ) {
|
|
3764
|
+
return getApiClient().callLogd.search(query, limit);
|
|
3765
|
+
}
|
|
3766
|
+
|
|
3767
|
+
static async searchBy(field , value , limit ) {
|
|
3768
|
+
return getApiClient().callLogd.searchBy(field, value, limit);
|
|
3769
|
+
}
|
|
3770
|
+
|
|
3771
|
+
static async fetchSIP(session , line ) {
|
|
3772
|
+
const lineToUse = line || session.primaryLine();
|
|
3773
|
+
return getApiClient().confd.getUserLineSip(session.uuid, lineToUse ? lineToUse.id : null);
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
static async cancelCall(callSession ) {
|
|
3777
|
+
return getApiClient().calld.cancelCall(callSession.callId);
|
|
3778
|
+
}
|
|
3779
|
+
|
|
3780
|
+
static async makeCall(callFromLine , extension , isMobile = false,
|
|
3781
|
+
callbackAllLines = false) {
|
|
3782
|
+
const lineId = callFromLine ? callFromLine.id : null;
|
|
3783
|
+
|
|
3784
|
+
const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
|
|
3785
|
+
return Call.parse(response);
|
|
3786
|
+
}
|
|
3787
|
+
|
|
3788
|
+
static async relocateCall(callId , line , contactIdentifier ) {
|
|
3789
|
+
return getApiClient().calld.relocateCall(callId, 'line', line, contactIdentifier);
|
|
3790
|
+
}
|
|
3791
|
+
|
|
3792
|
+
static async hold(callId ) {
|
|
3793
|
+
return getApiClient().calld.hold(callId);
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
static async resume(callId ) {
|
|
3797
|
+
return getApiClient().calld.resume(callId);
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
static async mute(callId ) {
|
|
3801
|
+
return getApiClient().calld.mute(callId);
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3804
|
+
static async sendDTMF(callId , digits ) {
|
|
3805
|
+
return getApiClient().calld.sendDTMF(callId, digits);
|
|
3806
|
+
}
|
|
3807
|
+
|
|
3808
|
+
static async unmute(callId ) {
|
|
3809
|
+
return getApiClient().calld.unmute(callId);
|
|
3810
|
+
}
|
|
3811
|
+
|
|
3812
|
+
static async transferCall(callId , number , flow ) {
|
|
3813
|
+
return getApiClient().calld.transferCall(callId, number, flow);
|
|
3814
|
+
}
|
|
3815
|
+
|
|
3816
|
+
static async cancelCallTransfer(transferId ) {
|
|
3817
|
+
return getApiClient().calld.cancelCallTransfer(transferId);
|
|
3818
|
+
}
|
|
3819
|
+
|
|
3820
|
+
static async confirmCallTransfer(transferId ) {
|
|
3821
|
+
return getApiClient().calld.confirmCallTransfer(transferId);
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
|
|
3825
|
+
//
|
|
3826
|
+
|
|
3827
|
+
const TRANSFER_FLOW_ATTENDED = 'attended';
|
|
3673
3828
|
const TRANSFER_FLOW_BLIND = 'blind';
|
|
3674
3829
|
|
|
3675
3830
|
// const MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD = '20.11';
|
|
3676
3831
|
|
|
3677
|
-
IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
|
|
3832
|
+
const logger$a = IssueReporter$1 ? IssueReporter$1.loggerFor('cti-phone') : console;
|
|
3833
|
+
|
|
3834
|
+
class CTIPhone extends Emitter {
|
|
3835
|
+
|
|
3836
|
+
|
|
3837
|
+
|
|
3838
|
+
|
|
3839
|
+
|
|
3840
|
+
|
|
3841
|
+
|
|
3842
|
+
|
|
3843
|
+
constructor(session , isMobile = false, callbackAllLines = false) {
|
|
3844
|
+
super();
|
|
3845
|
+
logger$a.info('CTI Phone created');
|
|
3846
|
+
this.session = session;
|
|
3847
|
+
this.isMobile = isMobile;
|
|
3848
|
+
this.callbackAllLines = callbackAllLines;
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
getOptions() {
|
|
3852
|
+
// @FIXME: temporarily disabling this option
|
|
3853
|
+
// const hold = this.session.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_CTI_HOLD);
|
|
3854
|
+
|
|
3855
|
+
return {
|
|
3856
|
+
accept: false,
|
|
3857
|
+
decline: true,
|
|
3858
|
+
mute: true,
|
|
3859
|
+
hold: false,
|
|
3860
|
+
transfer: true,
|
|
3861
|
+
sendKey: true,
|
|
3862
|
+
addParticipant: false,
|
|
3863
|
+
record: true,
|
|
3864
|
+
merge: false,
|
|
3865
|
+
};
|
|
3866
|
+
}
|
|
3867
|
+
|
|
3868
|
+
hasAnActiveCall() {
|
|
3869
|
+
return !!this.currentCall;
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3872
|
+
callCount() {
|
|
3873
|
+
return this.currentCall ? 1 : 0;
|
|
3874
|
+
}
|
|
3875
|
+
|
|
3876
|
+
isWebRTC() {
|
|
3877
|
+
return false;
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
getUserAgent() {
|
|
3881
|
+
return 'cti-phone';
|
|
3882
|
+
}
|
|
3883
|
+
|
|
3884
|
+
startHeartbeat() {
|
|
3885
|
+
}
|
|
3886
|
+
|
|
3887
|
+
setOnHeartbeatTimeout() {
|
|
3888
|
+
}
|
|
3889
|
+
|
|
3890
|
+
setOnHeartbeatCallback() {
|
|
3891
|
+
}
|
|
3892
|
+
|
|
3893
|
+
stopHeartbeat() {
|
|
3894
|
+
}
|
|
3895
|
+
|
|
3896
|
+
bindClientEvents() {
|
|
3897
|
+
}
|
|
3898
|
+
|
|
3899
|
+
onConnect() {
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3902
|
+
onDisconnect() {
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3905
|
+
async makeCall(number , line ) {
|
|
3906
|
+
logger$a.info('make CTI call', { number });
|
|
3907
|
+
|
|
3908
|
+
if (!number) {
|
|
3909
|
+
return null;
|
|
3910
|
+
}
|
|
3911
|
+
try {
|
|
3912
|
+
this.currentCall = await CallApi.makeCall(line, number, this.isMobile, this.callbackAllLines);
|
|
3913
|
+
} catch (_) {
|
|
3914
|
+
// We have to deal with error like `User has no mobile phone number` error in the UI.
|
|
3915
|
+
}
|
|
3916
|
+
if (!this.currentCall) {
|
|
3917
|
+
return null;
|
|
3918
|
+
}
|
|
3919
|
+
const callSession = CallSession.parseCall(this.currentCall);
|
|
3920
|
+
this.eventEmitter.emit('onCallOutgoing', callSession);
|
|
3921
|
+
|
|
3922
|
+
return callSession;
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3925
|
+
accept(callSession ) {
|
|
3926
|
+
if (!callSession) {
|
|
3927
|
+
return Promise.resolve(null);
|
|
3928
|
+
}
|
|
3929
|
+
logger$a.info('accept CTI call', { callId: callSession.getId(), number: callSession.number });
|
|
3930
|
+
|
|
3931
|
+
if (!this.currentCall) {
|
|
3932
|
+
this.currentCall = callSession.call;
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
return Promise.resolve(callSession.getId());
|
|
3936
|
+
}
|
|
3937
|
+
|
|
3938
|
+
endCurrentCall(callSession ) {
|
|
3939
|
+
if (!callSession) {
|
|
3940
|
+
return;
|
|
3941
|
+
}
|
|
3942
|
+
logger$a.info('end current CTI call', { callId: callSession.getId(), number: callSession.number });
|
|
3943
|
+
|
|
3944
|
+
this.currentCall = undefined;
|
|
3945
|
+
this.eventEmitter.emit('onCallEnded', callSession);
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3948
|
+
async hangup(callSession ) {
|
|
3949
|
+
if (!callSession) {
|
|
3950
|
+
return Promise.resolve(false);
|
|
3951
|
+
}
|
|
3952
|
+
logger$a.info('hangup CTI call', { callId: callSession.getId(), number: callSession.number });
|
|
3953
|
+
|
|
3954
|
+
try {
|
|
3955
|
+
await CallApi.cancelCall(callSession);
|
|
3956
|
+
if (this.currentCall && callSession.callId === this.currentCall.id) {
|
|
3957
|
+
this.endCurrentCall(callSession);
|
|
3958
|
+
}
|
|
3959
|
+
|
|
3960
|
+
this.eventEmitter.emit('onCallEnded', callSession);
|
|
3961
|
+
return true;
|
|
3962
|
+
} catch (e) {
|
|
3963
|
+
logger$a.error('hangup CTI call, error', e);
|
|
3964
|
+
|
|
3965
|
+
this.eventEmitter.emit('onCallFailed', callSession);
|
|
3966
|
+
return false;
|
|
3967
|
+
}
|
|
3968
|
+
}
|
|
3969
|
+
|
|
3970
|
+
ignore() {}
|
|
3971
|
+
|
|
3972
|
+
async reject(callSession ) {
|
|
3973
|
+
if (!callSession) {
|
|
3974
|
+
return;
|
|
3975
|
+
}
|
|
3976
|
+
logger$a.info('reject CTI call', { callId: callSession.getId(), number: callSession.number });
|
|
3977
|
+
|
|
3978
|
+
await CallApi.cancelCall(callSession);
|
|
3979
|
+
this.eventEmitter.emit('onCallEnded', callSession);
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
async transfer(callSession , number ) {
|
|
3983
|
+
if (!callSession) {
|
|
3984
|
+
return;
|
|
3985
|
+
}
|
|
3986
|
+
logger$a.info('transfer CTI call', { callId: callSession.getId(), number: callSession.number, to: number });
|
|
3987
|
+
|
|
3988
|
+
await CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_BLIND);
|
|
3989
|
+
}
|
|
3990
|
+
|
|
3991
|
+
indirectTransfer() {}
|
|
3992
|
+
|
|
3993
|
+
async initiateCTIIndirectTransfer(callSession , number ) {
|
|
3994
|
+
if (!callSession) {
|
|
3995
|
+
return;
|
|
3996
|
+
}
|
|
3997
|
+
logger$a.info('indirect CTI transfer', { callId: callSession.getId(), number: callSession.number, to: number });
|
|
3998
|
+
|
|
3999
|
+
return CallApi.transferCall(callSession.callId, number, TRANSFER_FLOW_ATTENDED);
|
|
4000
|
+
}
|
|
4001
|
+
|
|
4002
|
+
async cancelCTIIndirectTransfer(transferId ) {
|
|
4003
|
+
logger$a.info('cancel CTI transfer', { transferId });
|
|
4004
|
+
|
|
4005
|
+
return CallApi.cancelCallTransfer(transferId);
|
|
4006
|
+
}
|
|
4007
|
+
|
|
4008
|
+
async confirmCTIIndirectTransfer(transferId ) {
|
|
4009
|
+
logger$a.info('confirm CTI transfer', { transferId });
|
|
4010
|
+
|
|
4011
|
+
return CallApi.confirmCallTransfer(transferId);
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
sendKey(callSession , digits ) {
|
|
4015
|
+
if (!callSession) {
|
|
4016
|
+
return;
|
|
4017
|
+
}
|
|
4018
|
+
logger$a.info('send CTI key', { callId: callSession.getId(), number: callSession.number, digits });
|
|
4019
|
+
|
|
4020
|
+
return CallApi.sendDTMF(callSession.callId, digits);
|
|
4021
|
+
}
|
|
4022
|
+
|
|
4023
|
+
onConnectionMade() {
|
|
4024
|
+
logger$a.info('on CTI connection made');
|
|
4025
|
+
|
|
4026
|
+
this.eventEmitter.emit('onCallAccepted');
|
|
4027
|
+
}
|
|
4028
|
+
|
|
4029
|
+
async close() {
|
|
4030
|
+
logger$a.info('CTI close');
|
|
4031
|
+
|
|
4032
|
+
return Promise.resolve();
|
|
4033
|
+
}
|
|
4034
|
+
|
|
4035
|
+
async hold(callSession ) {
|
|
4036
|
+
if (!callSession) {
|
|
4037
|
+
return;
|
|
4038
|
+
}
|
|
4039
|
+
logger$a.info('CTI hold', { callId: callSession.getId(), number: callSession.number });
|
|
4040
|
+
|
|
4041
|
+
return CallApi.hold(callSession.callId);
|
|
4042
|
+
}
|
|
4043
|
+
|
|
4044
|
+
async resume(callSession ) {
|
|
4045
|
+
if (!callSession) {
|
|
4046
|
+
return;
|
|
4047
|
+
}
|
|
4048
|
+
logger$a.info('CTI resume', { callId: callSession.getId(), number: callSession.number });
|
|
4049
|
+
|
|
4050
|
+
return CallApi.resume(callSession.callId);
|
|
4051
|
+
}
|
|
4052
|
+
|
|
4053
|
+
async mute(callSession ) {
|
|
4054
|
+
if (!callSession) {
|
|
4055
|
+
return;
|
|
4056
|
+
}
|
|
4057
|
+
logger$a.info('CTI mute', { callId: callSession.getId(), number: callSession.number });
|
|
4058
|
+
|
|
4059
|
+
return CallApi.mute(callSession.callId);
|
|
4060
|
+
}
|
|
4061
|
+
|
|
4062
|
+
async unmute(callSession ) {
|
|
4063
|
+
if (!callSession) {
|
|
4064
|
+
return;
|
|
4065
|
+
}
|
|
4066
|
+
logger$a.info('CTI unmute', { callId: callSession.getId(), number: callSession.number });
|
|
4067
|
+
|
|
4068
|
+
return CallApi.unmute(callSession.callId);
|
|
4069
|
+
}
|
|
4070
|
+
|
|
4071
|
+
putOnSpeaker() {}
|
|
4072
|
+
|
|
4073
|
+
putOffSpeaker() {}
|
|
4074
|
+
|
|
4075
|
+
turnCameraOff() {}
|
|
4076
|
+
|
|
4077
|
+
turnCameraOn() {}
|
|
4078
|
+
|
|
4079
|
+
changeAudioInputDevice() {}
|
|
4080
|
+
|
|
4081
|
+
changeVideoInputDevice() {}
|
|
4082
|
+
|
|
4083
|
+
changeAudioDevice() {}
|
|
4084
|
+
|
|
4085
|
+
changeRingDevice() {}
|
|
4086
|
+
|
|
4087
|
+
changeAudioVolume() {}
|
|
4088
|
+
|
|
4089
|
+
changeRingVolume() {}
|
|
4090
|
+
|
|
4091
|
+
hasVideo() {
|
|
4092
|
+
return false;
|
|
4093
|
+
}
|
|
4094
|
+
|
|
4095
|
+
getLocalStreamForCall() {
|
|
4096
|
+
return null;
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
getRemoteStreamForCall() {
|
|
4100
|
+
return null;
|
|
4101
|
+
}
|
|
4102
|
+
|
|
4103
|
+
getLocalVideoStream() {
|
|
4104
|
+
return null;
|
|
4105
|
+
}
|
|
4106
|
+
|
|
4107
|
+
setActiveSipSession() {}
|
|
4108
|
+
|
|
4109
|
+
isRegistered() {
|
|
4110
|
+
return true;
|
|
4111
|
+
}
|
|
4112
|
+
|
|
4113
|
+
hasIncomingCallSession() {
|
|
4114
|
+
return true;
|
|
4115
|
+
}
|
|
4116
|
+
|
|
4117
|
+
hasActiveRemoteVideoStream() {
|
|
4118
|
+
return false;
|
|
4119
|
+
}
|
|
4120
|
+
|
|
4121
|
+
getCurrentCallSession() {
|
|
4122
|
+
return this.currentCall ? CallSession.parseCall(this.currentCall) : null;
|
|
4123
|
+
}
|
|
4124
|
+
|
|
4125
|
+
enableRinging() {}
|
|
4126
|
+
|
|
4127
|
+
sendMessage() {}
|
|
4128
|
+
|
|
4129
|
+
disableRinging() {}
|
|
4130
|
+
|
|
4131
|
+
getLocalStream() {
|
|
4132
|
+
return null;
|
|
4133
|
+
}
|
|
4134
|
+
|
|
4135
|
+
getRemoteStream() {
|
|
4136
|
+
return null;
|
|
4137
|
+
}
|
|
4138
|
+
|
|
4139
|
+
getRemoteVideoStream() {
|
|
4140
|
+
return null;
|
|
4141
|
+
}
|
|
4142
|
+
|
|
4143
|
+
getRemoteAudioStream() {
|
|
4144
|
+
return null;
|
|
4145
|
+
}
|
|
4146
|
+
|
|
4147
|
+
hasLocalVideo() {
|
|
4148
|
+
return false;
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
useLocalVideoElement() {}
|
|
4152
|
+
}
|
|
3678
4153
|
|
|
3679
4154
|
/* */
|
|
3680
4155
|
|
|
@@ -4709,6 +5184,10 @@ class ApiClient {
|
|
|
4709
5184
|
this.fetchOptions = fetchOptions;
|
|
4710
5185
|
this.client.setFetchOptions(fetchOptions);
|
|
4711
5186
|
}
|
|
5187
|
+
|
|
5188
|
+
disableErrorLogging() {
|
|
5189
|
+
this.client.disableErrorLogging();
|
|
5190
|
+
}
|
|
4712
5191
|
}
|
|
4713
5192
|
|
|
4714
5193
|
/* eslint-disable dot-notation */
|
|
@@ -5250,23 +5729,6 @@ const areCandidateValid = (candidates ) =>
|
|
|
5250
5729
|
getSrflxOrRelay(candidates)
|
|
5251
5730
|
.length > 0;
|
|
5252
5731
|
|
|
5253
|
-
const toggleVideoDirection = (sdp , direction ) => {
|
|
5254
|
-
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
5255
|
-
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
5256
|
-
...media,
|
|
5257
|
-
...(media.type === 'video' ? { direction } : {}),
|
|
5258
|
-
}));
|
|
5259
|
-
|
|
5260
|
-
return sdpParser__default['default'].write(parsedSdp);
|
|
5261
|
-
};
|
|
5262
|
-
|
|
5263
|
-
const deactivateVideoModifier = (rawDescription ) => {
|
|
5264
|
-
const description = rawDescription;
|
|
5265
|
-
description.sdp = toggleVideoDirection(description.sdp, 'inactive');
|
|
5266
|
-
|
|
5267
|
-
return Promise.resolve(description);
|
|
5268
|
-
};
|
|
5269
|
-
|
|
5270
5732
|
const hasAnActiveVideo = (sdp ) => {
|
|
5271
5733
|
if (!sdp) {
|
|
5272
5734
|
return false;
|
|
@@ -5378,6 +5840,7 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5378
5840
|
const iceRestart = options.offerOptions ? options.offerOptions.iceRestart : false;
|
|
5379
5841
|
|
|
5380
5842
|
const isConference = options ? !!options.conference : false;
|
|
5843
|
+
const audioOnly = options ? !!options.audioOnly : false;
|
|
5381
5844
|
|
|
5382
5845
|
// We should wait for ice when iceRestart (reinvite) or for the first invite
|
|
5383
5846
|
// We shouldn't wait for ice when holding or resuming the call
|
|
@@ -5404,16 +5867,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5404
5867
|
};
|
|
5405
5868
|
|
|
5406
5869
|
return this.getLocalMediaStream(options)
|
|
5407
|
-
.then(() => this.updateDirection(options, isConference))
|
|
5870
|
+
.then(() => this.updateDirection(options, isConference, audioOnly))
|
|
5408
5871
|
.then(() => this.createDataChannel(options))
|
|
5409
5872
|
.then(() => {
|
|
5410
|
-
if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options)) {
|
|
5873
|
+
if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
|
|
5411
5874
|
// Add a video an empty bundle to be able to replaceTrack when joining a conference without video
|
|
5412
5875
|
this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
|
|
5413
5876
|
}
|
|
5414
5877
|
})
|
|
5415
5878
|
.then(() => this.createLocalOfferOrAnswer(options))
|
|
5416
|
-
.then(
|
|
5879
|
+
.then(sessionDescription => this.setLocalSessionDescription(sessionDescription))
|
|
5417
5880
|
.then(() => this.waitForIceGatheringComplete(iceRestart, iceTimeout))
|
|
5418
5881
|
.then(() => this.getLocalSessionDescription())
|
|
5419
5882
|
.then(description => {
|
|
@@ -5536,7 +5999,8 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5536
5999
|
}
|
|
5537
6000
|
|
|
5538
6001
|
// Overridden to send `inactive` in conference
|
|
5539
|
-
updateDirection(options , isConference = false
|
|
6002
|
+
updateDirection(options , isConference = false,
|
|
6003
|
+
audioOnly = false) {
|
|
5540
6004
|
if (this._peerConnection === undefined) {
|
|
5541
6005
|
return Promise.reject(new Error('Peer connection closed.'));
|
|
5542
6006
|
}
|
|
@@ -5551,14 +6015,17 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5551
6015
|
// if we are stable, assume we are creating a local offer
|
|
5552
6016
|
this.logger.debug('SessionDescriptionHandler.updateDirection - setting offer direction');
|
|
5553
6017
|
// determine the direction to offer given the current direction and hold state
|
|
5554
|
-
const directionToOffer = (currentDirection ) => {
|
|
6018
|
+
const directionToOffer = (currentDirection , transceiver /* RTCRtpTransceiver */) => {
|
|
5555
6019
|
if (isConference) {
|
|
6020
|
+
if (audioOnly && transceiver.receiver.track && transceiver.receiver.track.kind === 'video') {
|
|
6021
|
+
return 'sendonly';
|
|
6022
|
+
}
|
|
5556
6023
|
return options && options.hold ? 'sendonly' : 'sendrecv';
|
|
5557
6024
|
}
|
|
5558
6025
|
|
|
5559
6026
|
switch (currentDirection) {
|
|
5560
6027
|
case 'inactive':
|
|
5561
|
-
return options && options.hold ? 'inactive' : 'recvonly';
|
|
6028
|
+
return options && options.hold ? 'inactive' : (isConference && !audioOnly ? 'sendrecv' : 'recvonly');
|
|
5562
6029
|
case 'recvonly':
|
|
5563
6030
|
return options && options.hold ? 'inactive' : 'recvonly';
|
|
5564
6031
|
case 'sendonly':
|
|
@@ -5574,7 +6041,7 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5574
6041
|
// set the transceiver direction to the offer direction
|
|
5575
6042
|
this._peerConnection.getTransceivers().forEach((transceiver) => {
|
|
5576
6043
|
if (transceiver.direction /* guarding, but should always be true */) {
|
|
5577
|
-
const offerDirection = directionToOffer(transceiver.direction);
|
|
6044
|
+
const offerDirection = directionToOffer(transceiver.direction, transceiver);
|
|
5578
6045
|
if (transceiver.direction !== offerDirection) {
|
|
5579
6046
|
// eslint-disable-next-line no-param-reassign
|
|
5580
6047
|
transceiver.direction = offerDirection;
|
|
@@ -5633,6 +6100,13 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5633
6100
|
// set the transceiver direction to the answer direction
|
|
5634
6101
|
this._peerConnection.getTransceivers().forEach((transceiver) => {
|
|
5635
6102
|
if (transceiver.direction /* guarding, but should always be true */) {
|
|
6103
|
+
const { receiver } = transceiver;
|
|
6104
|
+
if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
|
|
6105
|
+
// eslint-disable-next-line no-param-reassign
|
|
6106
|
+
transceiver.direction = 'inactive';
|
|
6107
|
+
return;
|
|
6108
|
+
}
|
|
6109
|
+
|
|
5636
6110
|
if (transceiver.direction !== 'stopped' && transceiver.direction !== answerDirection) {
|
|
5637
6111
|
// eslint-disable-next-line no-param-reassign
|
|
5638
6112
|
transceiver.direction = answerDirection;
|
|
@@ -5671,8 +6145,8 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5671
6145
|
}
|
|
5672
6146
|
const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
|
|
5673
6147
|
|
|
5674
|
-
// Do not reuse sender tracks in SFU
|
|
5675
|
-
if (sender && !sfu) {
|
|
6148
|
+
// Do not reuse sender video tracks in SFU
|
|
6149
|
+
if (sender && (!sfu || newTrack.kind === 'audio')) {
|
|
5676
6150
|
trackUpdates.push(
|
|
5677
6151
|
new Promise((resolve) => {
|
|
5678
6152
|
this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
|
|
@@ -6224,9 +6698,15 @@ class WebRTCClient extends Emitter {
|
|
|
6224
6698
|
|
|
6225
6699
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
6226
6700
|
logger$7.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
6227
|
-
const inviterOptions
|
|
6701
|
+
const inviterOptions = {
|
|
6702
|
+
sessionDescriptionHandlerOptionsReInvite: {
|
|
6703
|
+
conference,
|
|
6704
|
+
audioOnly,
|
|
6705
|
+
},
|
|
6706
|
+
};
|
|
6707
|
+
|
|
6228
6708
|
if (audioOnly) {
|
|
6229
|
-
inviterOptions.sessionDescriptionHandlerModifiersReInvite = [
|
|
6709
|
+
inviterOptions.sessionDescriptionHandlerModifiersReInvite = [modifiers.stripVideo];
|
|
6230
6710
|
}
|
|
6231
6711
|
|
|
6232
6712
|
const session = new inviter.Inviter(this.userAgent, this._makeURI(number), inviterOptions);
|
|
@@ -6255,10 +6735,11 @@ class WebRTCClient extends Emitter {
|
|
|
6255
6735
|
sessionDescriptionHandlerOptions: this.getMediaConfiguration(enableVideo || false, conference),
|
|
6256
6736
|
};
|
|
6257
6737
|
|
|
6258
|
-
inviteOptions.
|
|
6738
|
+
inviteOptions.sessionDescriptionHandlerOptions.audioOnly = audioOnly;
|
|
6259
6739
|
|
|
6740
|
+
inviteOptions.sessionDescriptionHandlerModifiers = [replaceLocalIpModifier];
|
|
6260
6741
|
if (audioOnly) {
|
|
6261
|
-
inviteOptions.sessionDescriptionHandlerModifiers.push(
|
|
6742
|
+
inviteOptions.sessionDescriptionHandlerModifiers.push(modifiers.stripVideo);
|
|
6262
6743
|
}
|
|
6263
6744
|
|
|
6264
6745
|
// Do not await invite here or we'll miss the Establishing state transition
|
|
@@ -6472,6 +6953,9 @@ class WebRTCClient extends Emitter {
|
|
|
6472
6953
|
if (!this._isWeb()) {
|
|
6473
6954
|
options.sessionDescriptionHandlerModifiers = [modifiers.holdModifier];
|
|
6474
6955
|
}
|
|
6956
|
+
options.sessionDescriptionHandlerOptions = {
|
|
6957
|
+
constraints: options.constraints,
|
|
6958
|
+
};
|
|
6475
6959
|
|
|
6476
6960
|
// Send re-INVITE
|
|
6477
6961
|
return session.invite(options);
|
|
@@ -6511,6 +6995,9 @@ class WebRTCClient extends Emitter {
|
|
|
6511
6995
|
// (eg: holdModifier)
|
|
6512
6996
|
options.sessionDescriptionHandlerModifiers = [];
|
|
6513
6997
|
}
|
|
6998
|
+
options.sessionDescriptionHandlerOptions = {
|
|
6999
|
+
constraints: options.constraints,
|
|
7000
|
+
};
|
|
6514
7001
|
|
|
6515
7002
|
// Send re-INVITE
|
|
6516
7003
|
return session.invite(options);
|
|
@@ -6740,7 +7227,8 @@ class WebRTCClient extends Emitter {
|
|
|
6740
7227
|
? this.video.deviceId.exact : undefined;
|
|
6741
7228
|
}
|
|
6742
7229
|
|
|
6743
|
-
reinvite(sipSession , newConstraints = null, conference = false
|
|
7230
|
+
reinvite(sipSession , newConstraints = null, conference = false,
|
|
7231
|
+
audioOnly = false) {
|
|
6744
7232
|
if (!sipSession) {
|
|
6745
7233
|
return false;
|
|
6746
7234
|
}
|
|
@@ -6750,16 +7238,17 @@ class WebRTCClient extends Emitter {
|
|
|
6750
7238
|
}
|
|
6751
7239
|
|
|
6752
7240
|
const wasMuted = this.isAudioMuted(sipSession);
|
|
6753
|
-
// When upgrading to video, remove the `
|
|
7241
|
+
// When upgrading to video, remove the `stripVideo` modifiers
|
|
6754
7242
|
if (newConstraints && newConstraints.video) {
|
|
6755
|
-
const modifiers = sipSession.sessionDescriptionHandlerModifiersReInvite;
|
|
6756
|
-
sipSession.sessionDescriptionHandlerModifiersReInvite = modifiers.filter(modifier =>
|
|
6757
|
-
modifier !==
|
|
7243
|
+
const modifiers$1 = sipSession.sessionDescriptionHandlerModifiersReInvite;
|
|
7244
|
+
sipSession.sessionDescriptionHandlerModifiersReInvite = modifiers$1.filter(modifier =>
|
|
7245
|
+
modifier !== modifiers.stripVideo);
|
|
6758
7246
|
}
|
|
6759
7247
|
|
|
6760
7248
|
sipSession.sessionDescriptionHandlerOptionsReInvite = {
|
|
6761
7249
|
...sipSession.sessionDescriptionHandlerOptionsReInvite,
|
|
6762
7250
|
conference,
|
|
7251
|
+
audioOnly,
|
|
6763
7252
|
};
|
|
6764
7253
|
|
|
6765
7254
|
const shouldDoVideo = newConstraints ? newConstraints.video : this.sessionWantsToDoVideo(sipSession);
|
|
@@ -6799,6 +7288,8 @@ class WebRTCClient extends Emitter {
|
|
|
6799
7288
|
},
|
|
6800
7289
|
sessionDescriptionHandlerOptions: {
|
|
6801
7290
|
constraints,
|
|
7291
|
+
conference,
|
|
7292
|
+
audioOnly,
|
|
6802
7293
|
offerOptions: {
|
|
6803
7294
|
iceRestart: false,
|
|
6804
7295
|
},
|
|
@@ -7258,6 +7749,8 @@ class WebRTCClient extends Emitter {
|
|
|
7258
7749
|
|
|
7259
7750
|
// Invitation and Inviter extends Session
|
|
7260
7751
|
_setupSession(session ) {
|
|
7752
|
+
const sipSessionId = this.getSipSessionId(session);
|
|
7753
|
+
|
|
7261
7754
|
// When receiving an Invitation, the delegate is not defined.
|
|
7262
7755
|
if (!session.delegate) {
|
|
7263
7756
|
session.delegate = {};
|
|
@@ -7281,8 +7774,18 @@ class WebRTCClient extends Emitter {
|
|
|
7281
7774
|
};
|
|
7282
7775
|
};
|
|
7283
7776
|
|
|
7777
|
+
const oldInviteRequest = session.onInviteRequest.bind(session);
|
|
7778
|
+
let hadRemoteVideo = false;
|
|
7779
|
+
|
|
7780
|
+
// Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
|
|
7781
|
+
// Becase when `onInvite` is called we already got the video track
|
|
7782
|
+
session.onInviteRequest = (request) => {
|
|
7783
|
+
hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
|
|
7784
|
+
|
|
7785
|
+
oldInviteRequest(request);
|
|
7786
|
+
};
|
|
7787
|
+
|
|
7284
7788
|
session.delegate.onInvite = (request ) => {
|
|
7285
|
-
const sipSessionId = this.getSipSessionId(session);
|
|
7286
7789
|
let updatedCalleeName = null;
|
|
7287
7790
|
let updatedNumber = null;
|
|
7288
7791
|
if (session.assertedIdentity) {
|
|
@@ -7292,7 +7795,6 @@ class WebRTCClient extends Emitter {
|
|
|
7292
7795
|
logger$7.info('re-invite received', { updatedCalleeName, updatedNumber });
|
|
7293
7796
|
|
|
7294
7797
|
// Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
|
|
7295
|
-
const hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
|
|
7296
7798
|
|
|
7297
7799
|
// Update SDP
|
|
7298
7800
|
// Remote video is handled by the `track` event. Here we're dealing with video stream removal.
|
|
@@ -7342,7 +7844,7 @@ class WebRTCClient extends Emitter {
|
|
|
7342
7844
|
}
|
|
7343
7845
|
|
|
7344
7846
|
_isAudioOnly(session ) {
|
|
7345
|
-
return session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier ===
|
|
7847
|
+
return session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier === modifiers.stripVideo);
|
|
7346
7848
|
}
|
|
7347
7849
|
|
|
7348
7850
|
_setupMedias(session , newStream ) {
|
|
@@ -7715,9 +8217,14 @@ class WebRTCPhone extends Emitter {
|
|
|
7715
8217
|
return true;
|
|
7716
8218
|
}
|
|
7717
8219
|
|
|
7718
|
-
async sendReinvite(callSession , constraints = null, conference = false
|
|
8220
|
+
async sendReinvite(callSession , constraints = null, conference = false,
|
|
8221
|
+
audioOnly = false) {
|
|
7719
8222
|
const sipSession = this.findSipSession(callSession);
|
|
7720
|
-
logger$6.info('WebRTC phone - send reinvite', {
|
|
8223
|
+
logger$6.info('WebRTC phone - send reinvite', {
|
|
8224
|
+
sessionId: sipSession ? sipSession.id : null,
|
|
8225
|
+
constraints,
|
|
8226
|
+
audioOnly,
|
|
8227
|
+
});
|
|
7721
8228
|
|
|
7722
8229
|
if (!sipSession) {
|
|
7723
8230
|
return null;
|
|
@@ -7743,7 +8250,7 @@ class WebRTCPhone extends Emitter {
|
|
|
7743
8250
|
// Force reinvite in SDH
|
|
7744
8251
|
sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
|
|
7745
8252
|
|
|
7746
|
-
return this.client.reinvite(sipSession, constraints, conference);
|
|
8253
|
+
return this.client.reinvite(sipSession, constraints, conference, audioOnly);
|
|
7747
8254
|
}
|
|
7748
8255
|
|
|
7749
8256
|
getUserAgent() {
|
|
@@ -7819,9 +8326,9 @@ class WebRTCPhone extends Emitter {
|
|
|
7819
8326
|
}
|
|
7820
8327
|
|
|
7821
8328
|
// Release local video stream when downgrading to audio
|
|
7822
|
-
const
|
|
8329
|
+
const localStream = sipSession.sessionDescriptionHandler.localMediaStream;
|
|
7823
8330
|
const pc = sipSession.sessionDescriptionHandler.peerConnection;
|
|
7824
|
-
const videoTracks =
|
|
8331
|
+
const videoTracks = localStream.getVideoTracks();
|
|
7825
8332
|
|
|
7826
8333
|
// Remove video senders
|
|
7827
8334
|
pc.getSenders().filter(sender => sender.track && sender.track.kind === 'video').forEach(videoSender => {
|
|
@@ -7836,7 +8343,7 @@ class WebRTCPhone extends Emitter {
|
|
|
7836
8343
|
videoTracks.forEach(videoTrack => {
|
|
7837
8344
|
videoTrack.enabled = false;
|
|
7838
8345
|
videoTrack.stop();
|
|
7839
|
-
|
|
8346
|
+
localStream.removeTrack(videoTrack);
|
|
7840
8347
|
});
|
|
7841
8348
|
|
|
7842
8349
|
this._sendReinviteMessage(callSession, false);
|
|
@@ -7853,12 +8360,14 @@ class WebRTCPhone extends Emitter {
|
|
|
7853
8360
|
|
|
7854
8361
|
const pc = sipSession.sessionDescriptionHandler.peerConnection;
|
|
7855
8362
|
const shouldScreenShare = constraints && constraints.screen;
|
|
8363
|
+
const options = sipSession.sessionDescriptionHandlerOptionsReInvite;
|
|
8364
|
+
const wasAudioOnly = options && options.audioOnly;
|
|
7856
8365
|
|
|
7857
8366
|
// Check if a video sender already exists
|
|
7858
8367
|
let videoSender;
|
|
7859
8368
|
if (isConference) {
|
|
7860
8369
|
const trans = pc.getTransceivers().find(transceiver => transceiver.mid === '1');
|
|
7861
|
-
videoSender = trans.sender;
|
|
8370
|
+
videoSender = trans ? trans.sender : null;
|
|
7862
8371
|
} else {
|
|
7863
8372
|
videoSender = pc.getSenders().find(sender => sender.track === null);
|
|
7864
8373
|
}
|
|
@@ -7895,6 +8404,11 @@ class WebRTCPhone extends Emitter {
|
|
|
7895
8404
|
this._onScreenSharing(newStream, sipSession, callSession, false);
|
|
7896
8405
|
}
|
|
7897
8406
|
|
|
8407
|
+
// We have to reinvite to change the direction on the bundle when upgrading from an audioOnly conference
|
|
8408
|
+
if (isConference && wasAudioOnly) {
|
|
8409
|
+
return true;
|
|
8410
|
+
}
|
|
8411
|
+
|
|
7898
8412
|
// No reinvite needed here
|
|
7899
8413
|
return false;
|
|
7900
8414
|
}
|
|
@@ -7979,7 +8493,7 @@ class WebRTCPhone extends Emitter {
|
|
|
7979
8493
|
event.track.enabled = false;
|
|
7980
8494
|
}
|
|
7981
8495
|
|
|
7982
|
-
return this.eventEmitter.emit(ON_VIDEO_STREAM, stream, event.track.id, event);
|
|
8496
|
+
return this.eventEmitter.emit(ON_VIDEO_STREAM, stream, event.track.id, event, sipSession);
|
|
7983
8497
|
};
|
|
7984
8498
|
|
|
7985
8499
|
peerConnection.onremovestream = event => {
|
|
@@ -8035,14 +8549,11 @@ class WebRTCPhone extends Emitter {
|
|
|
8035
8549
|
const targetCallSession = callSession || this.currentCallSession;
|
|
8036
8550
|
const conference = this.isConference(targetCallSession);
|
|
8037
8551
|
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
// We have to downgrade to audio.
|
|
8044
|
-
await this.sendReinvite(targetCallSession, { audio: false, video: false }, conference);
|
|
8045
|
-
}
|
|
8552
|
+
// When stopping screenshare and we had video before that, we have to re-upgrade
|
|
8553
|
+
// When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
|
|
8554
|
+
// We have to downgrade to audio.
|
|
8555
|
+
const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
|
|
8556
|
+
await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
|
|
8046
8557
|
}
|
|
8047
8558
|
} catch (e) {
|
|
8048
8559
|
console.warn(e);
|
|
@@ -8379,6 +8890,7 @@ class WebRTCPhone extends Emitter {
|
|
|
8379
8890
|
}
|
|
8380
8891
|
}
|
|
8381
8892
|
|
|
8893
|
+
// @Deprecated
|
|
8382
8894
|
unhold(callSession , withEvent = true, isConference = false) {
|
|
8383
8895
|
logger$6.info('WebRTC unhold', { id: callSession ? callSession.getId() : null });
|
|
8384
8896
|
|
|
@@ -9376,6 +9888,7 @@ class Phone extends Emitter {
|
|
|
9376
9888
|
return this.phone && this.phone.hasLocalVideo(callSession);
|
|
9377
9889
|
}
|
|
9378
9890
|
|
|
9891
|
+
// @Deprecated
|
|
9379
9892
|
getLocalMediaStream(callSession ) {
|
|
9380
9893
|
logger$5.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
|
|
9381
9894
|
|
|
@@ -9394,17 +9907,20 @@ class Phone extends Emitter {
|
|
|
9394
9907
|
return this.phone ? this.phone.getRemoteVideoStream(callSession) : null;
|
|
9395
9908
|
}
|
|
9396
9909
|
|
|
9910
|
+
// @Deprecated
|
|
9397
9911
|
getRemoteStreamForCall(callSession ) {
|
|
9398
9912
|
logger$5.warn('Phone.getRemoteStreamForCall is deprecated, use Phone.getRemoteStream instead');
|
|
9399
9913
|
return this.getRemoteStream(callSession);
|
|
9400
9914
|
}
|
|
9401
9915
|
|
|
9402
9916
|
// Returns remote streams directly from the peerConnection
|
|
9917
|
+
// @Deprecated
|
|
9403
9918
|
getRemoteStreamsForCall(callSession ) {
|
|
9404
|
-
logger$5.warn('Phone.
|
|
9919
|
+
logger$5.warn('Phone.getRemoteStreamsForCall is deprecated, use Phone.getLocalStream instead');
|
|
9405
9920
|
return this.getLocalStream(callSession);
|
|
9406
9921
|
}
|
|
9407
9922
|
|
|
9923
|
+
// @Deprecated
|
|
9408
9924
|
getRemoteVideoStreamForCall(callSession ) {
|
|
9409
9925
|
logger$5.warn('Phone.getRemoteVideoStreamForCall is deprecated, use Phone.getRemoteVideoStream instead');
|
|
9410
9926
|
|
|
@@ -10119,10 +10635,7 @@ class Stream {
|
|
|
10119
10635
|
element.onloadedmetadata = () => {
|
|
10120
10636
|
const tracks = this.htmlStream ? this.htmlStream.getVideoTracks() : [];
|
|
10121
10637
|
tracks.forEach(track => {
|
|
10122
|
-
|
|
10123
|
-
if (!track.loaded) {
|
|
10124
|
-
track.enabled = true;
|
|
10125
|
-
}
|
|
10638
|
+
track.enabled = true;
|
|
10126
10639
|
// $FlowFixMe
|
|
10127
10640
|
track.loaded = true;
|
|
10128
10641
|
});
|
|
@@ -10563,6 +11076,7 @@ var api = {
|
|
|
10563
11076
|
check: async (server, session) => {
|
|
10564
11077
|
const client = new ApiClient({ server });
|
|
10565
11078
|
client.setToken(session.token);
|
|
11079
|
+
client.disableErrorLogging();
|
|
10566
11080
|
|
|
10567
11081
|
const handleApiError = (apiName, error) => {
|
|
10568
11082
|
const statusText = error instanceof ServerError ? 'server error' : 'api error';
|
|
@@ -10637,6 +11151,8 @@ var aor = {
|
|
|
10637
11151
|
check: async (server, session) => {
|
|
10638
11152
|
const apiClient = new ApiClient({ server });
|
|
10639
11153
|
apiClient.setToken(session.token);
|
|
11154
|
+
apiClient.disableErrorLogging();
|
|
11155
|
+
|
|
10640
11156
|
const line = session.primaryWebRtcLine();
|
|
10641
11157
|
if (!line) {
|
|
10642
11158
|
return 'No WebRTC line for this user';
|
|
@@ -11059,6 +11575,8 @@ const Wazo = {
|
|
|
11059
11575
|
ServerError,
|
|
11060
11576
|
Call,
|
|
11061
11577
|
CallLog,
|
|
11578
|
+
CTIPhone,
|
|
11579
|
+
Recording,
|
|
11062
11580
|
ChatMessage,
|
|
11063
11581
|
ChatRoom,
|
|
11064
11582
|
Contact,
|
|
@@ -11073,6 +11591,7 @@ const Wazo = {
|
|
|
11073
11591
|
CallSession,
|
|
11074
11592
|
IndirectTransfer,
|
|
11075
11593
|
SwitchboardCall,
|
|
11594
|
+
WebRTCPhone,
|
|
11076
11595
|
},
|
|
11077
11596
|
|
|
11078
11597
|
// Api
|
|
@@ -11507,13 +12026,15 @@ class Room extends Emitter {
|
|
|
11507
12026
|
}
|
|
11508
12027
|
});
|
|
11509
12028
|
|
|
11510
|
-
this.on(this.ON_VIDEO_STREAM, (stream, streamId) => {
|
|
12029
|
+
this.on(this.ON_VIDEO_STREAM, (stream, streamId, event, sipSession) => {
|
|
11511
12030
|
logger$1.info('on room video stream', { streamId });
|
|
11512
12031
|
|
|
12032
|
+
this._mapMsid(sipSession.body.body);
|
|
12033
|
+
|
|
11513
12034
|
// ON_VIDEO_STREAM is called before PARTICIPANT_JOINED, so we have to keep stream in `_unassociatedVideoStreams`.
|
|
11514
12035
|
this._unassociatedVideoStreams[streamId] = stream;
|
|
11515
12036
|
|
|
11516
|
-
const callId = this.
|
|
12037
|
+
const callId = this._getCallIdFromTrackId(streamId);
|
|
11517
12038
|
const participant = callId ? this._getParticipantFromCallId(callId) : null;
|
|
11518
12039
|
if (participant) {
|
|
11519
12040
|
this.__associateStreams(participant);
|
|
@@ -11557,11 +12078,12 @@ class Room extends Emitter {
|
|
|
11557
12078
|
const sdp = sdpParser__default['default'].parse(rawSdp);
|
|
11558
12079
|
const labelMsidArray = sdp.media.filter(media => !!media.label).map(({ label, msid }) => ({
|
|
11559
12080
|
label: String(label),
|
|
11560
|
-
|
|
12081
|
+
streamId: msid.split(' ')[0],
|
|
12082
|
+
trackId: msid.split(' ')[1],
|
|
11561
12083
|
}));
|
|
11562
12084
|
|
|
11563
|
-
labelMsidArray.forEach(({ label,
|
|
11564
|
-
this._callIdStreamIdMap[String(label)] =
|
|
12085
|
+
labelMsidArray.forEach(({ label, streamId, trackId }) => {
|
|
12086
|
+
this._callIdStreamIdMap[String(label)] = { streamId, trackId };
|
|
11565
12087
|
|
|
11566
12088
|
const callId = String(label);
|
|
11567
12089
|
const participant = this._unassociatedParticipants[callId] || this._getParticipantFromCallId(callId);
|
|
@@ -11791,9 +12313,9 @@ class Room extends Emitter {
|
|
|
11791
12313
|
_onParticipantTrackUpdate(oldParticipant , update ) {
|
|
11792
12314
|
const newParticipant = oldParticipant;
|
|
11793
12315
|
|
|
11794
|
-
const
|
|
12316
|
+
const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
|
|
11795
12317
|
const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
11796
|
-
const stream = pc.getRemoteStreams().find(
|
|
12318
|
+
const stream = pc.getRemoteStreams().find(someStream => someStream.getTracks().some(track => track.id === trackId));
|
|
11797
12319
|
|
|
11798
12320
|
if (update === 'downgrade') {
|
|
11799
12321
|
newParticipant.streams = [];
|
|
@@ -11813,21 +12335,21 @@ class Room extends Emitter {
|
|
|
11813
12335
|
|
|
11814
12336
|
// Associate audio/video streams to the participant and triggers events on it
|
|
11815
12337
|
__associateStreams(participant ) {
|
|
11816
|
-
const
|
|
11817
|
-
if (!
|
|
12338
|
+
const { trackId } = this._callIdStreamIdMap[participant.callId] || {};
|
|
12339
|
+
if (!trackId) {
|
|
11818
12340
|
this._unassociatedParticipants[participant.callId] = participant;
|
|
11819
12341
|
|
|
11820
12342
|
return;
|
|
11821
12343
|
}
|
|
11822
|
-
if (!
|
|
12344
|
+
if (!trackId || !participant || !this.localParticipant || participant.callId === this.localParticipant.callId) {
|
|
11823
12345
|
return;
|
|
11824
12346
|
}
|
|
11825
12347
|
|
|
11826
|
-
if (this._unassociatedVideoStreams[
|
|
12348
|
+
if (this._unassociatedVideoStreams[trackId]) {
|
|
11827
12349
|
// Try to associate stream
|
|
11828
|
-
this._associateStreamTo(this._unassociatedVideoStreams[
|
|
12350
|
+
this._associateStreamTo(this._unassociatedVideoStreams[trackId], participant);
|
|
11829
12351
|
|
|
11830
|
-
delete this._unassociatedVideoStreams[
|
|
12352
|
+
delete this._unassociatedVideoStreams[trackId];
|
|
11831
12353
|
delete this._unassociatedParticipants[participant.callId];
|
|
11832
12354
|
}
|
|
11833
12355
|
}
|
|
@@ -11840,8 +12362,8 @@ class Room extends Emitter {
|
|
|
11840
12362
|
participant.onStreamSubscribed(stream);
|
|
11841
12363
|
}
|
|
11842
12364
|
|
|
11843
|
-
|
|
11844
|
-
return Object.keys(this._callIdStreamIdMap).find(key => this._callIdStreamIdMap[key] ===
|
|
12365
|
+
_getCallIdFromTrackId(trackId ) {
|
|
12366
|
+
return Object.keys(this._callIdStreamIdMap).find(key => this._callIdStreamIdMap[key].trackId === trackId);
|
|
11845
12367
|
}
|
|
11846
12368
|
|
|
11847
12369
|
_getParticipantFromCallId(callId ) {
|