@signalwire/js 1.4.2-rc.1 → 1.5.0
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/esm/common/src/BrowserSession.d.ts +7 -4
- package/dist/esm/common/src/BrowserSession.js +60 -25
- package/dist/esm/common/src/services/Handler.d.ts +1 -1
- package/dist/esm/common/src/services/Handler.js +3 -2
- package/dist/esm/common/src/util/helpers.d.ts +1 -0
- package/dist/esm/common/src/util/helpers.js +34 -2
- package/dist/esm/common/src/util/interfaces.d.ts +2 -0
- package/dist/esm/common/src/webrtc/BaseCall.js +198 -87
- package/dist/esm/common/src/webrtc/Call.js +12 -5
- package/dist/esm/common/src/webrtc/Peer.js +39 -21
- package/dist/esm/common/src/webrtc/WebRTC.d.ts +51 -0
- package/dist/esm/common/src/webrtc/WebRTC.js +91 -0
- package/dist/esm/common/src/webrtc/helpers.d.ts +1 -1
- package/dist/esm/common/src/webrtc/helpers.js +36 -20
- package/dist/esm/js/index.d.ts +1 -1
- package/dist/esm/js/index.js +1 -1
- package/dist/esm/js/src/SignalWire.js +8 -2
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.LICENSE.txt +1 -1
- package/package.json +1 -1
|
@@ -12,11 +12,11 @@ import logger from '../util/logger';
|
|
|
12
12
|
import { Invite, Answer, Attach, Bye, Modify, Info } from '../messages/Verto';
|
|
13
13
|
import Peer from './Peer';
|
|
14
14
|
import { SwEvent } from '../util/constants';
|
|
15
|
-
import { State, DEFAULT_CALL_OPTIONS, ConferenceAction, Role, PeerType, VertoMethod, NOTIFICATION_TYPE, Direction } from './constants';
|
|
15
|
+
import { State, DEFAULT_CALL_OPTIONS, ConferenceAction, Role, PeerType, VertoMethod, NOTIFICATION_TYPE, Direction, } from './constants';
|
|
16
16
|
import { trigger, register, deRegister } from '../services/Handler';
|
|
17
|
-
import { sdpStereoHack, sdpMediaOrderHack, checkSubscribeResponse, enableAudioTracks, disableAudioTracks, toggleAudioTracks, enableVideoTracks, disableVideoTracks, toggleVideoTracks } from './helpers';
|
|
17
|
+
import { sdpStereoHack, sdpMediaOrderHack, checkSubscribeResponse, enableAudioTracks, disableAudioTracks, toggleAudioTracks, enableVideoTracks, disableVideoTracks, toggleVideoTracks, } from './helpers';
|
|
18
18
|
import { objEmpty, mutateLiveArrayData, isFunction } from '../util/helpers';
|
|
19
|
-
import { attachMediaStream, detachMediaStream, sdpToJsonHack, stopStream, getUserMedia, setMediaElementSinkId } from '
|
|
19
|
+
import { attachMediaStream, detachMediaStream, sdpToJsonHack, stopStream, getUserMedia, setMediaElementSinkId, } from './WebRTC';
|
|
20
20
|
import { MCULayoutEventHandler } from './LayoutHandler';
|
|
21
21
|
export default class BaseCall {
|
|
22
22
|
constructor(session, opts) {
|
|
@@ -36,14 +36,27 @@ export default class BaseCall {
|
|
|
36
36
|
this._iceTimeout = null;
|
|
37
37
|
this._iceDone = false;
|
|
38
38
|
this._checkConferenceSerno = (serno) => {
|
|
39
|
-
const check =
|
|
39
|
+
const check = serno < 0 ||
|
|
40
|
+
!this._lastSerno ||
|
|
41
|
+
(this._lastSerno && serno === this._lastSerno + 1);
|
|
40
42
|
if (check && serno >= 0) {
|
|
41
43
|
this._lastSerno = serno;
|
|
42
44
|
}
|
|
43
45
|
return check;
|
|
44
46
|
};
|
|
45
|
-
const { iceServers, speaker: speakerId, micId, micLabel, camId, camLabel, localElement, remoteElement, mediaConstraints: { audio, video } } = session;
|
|
46
|
-
this.options = Object.assign({}, DEFAULT_CALL_OPTIONS, {
|
|
47
|
+
const { iceServers, speaker: speakerId, micId, micLabel, camId, camLabel, localElement, remoteElement, mediaConstraints: { audio, video }, } = session;
|
|
48
|
+
this.options = Object.assign({}, DEFAULT_CALL_OPTIONS, {
|
|
49
|
+
audio,
|
|
50
|
+
video,
|
|
51
|
+
iceServers,
|
|
52
|
+
localElement,
|
|
53
|
+
remoteElement,
|
|
54
|
+
micId,
|
|
55
|
+
micLabel,
|
|
56
|
+
camId,
|
|
57
|
+
camLabel,
|
|
58
|
+
speakerId,
|
|
59
|
+
}, opts);
|
|
47
60
|
this._onMediaError = this._onMediaError.bind(this);
|
|
48
61
|
this._init();
|
|
49
62
|
}
|
|
@@ -78,8 +91,7 @@ export default class BaseCall {
|
|
|
78
91
|
applyMediaConstraints(params) {
|
|
79
92
|
const { mediaParams } = params;
|
|
80
93
|
if (mediaParams) {
|
|
81
|
-
Object.keys(mediaParams)
|
|
82
|
-
.forEach(kind => this.peer.applyMediaConstraints(kind, mediaParams[kind]));
|
|
94
|
+
Object.keys(mediaParams).forEach((kind) => this.peer.applyMediaConstraints(kind, mediaParams[kind]));
|
|
83
95
|
}
|
|
84
96
|
}
|
|
85
97
|
hangup(params = {}, execute = true) {
|
|
@@ -91,9 +103,12 @@ export default class BaseCall {
|
|
|
91
103
|
this.setState(State.Destroy);
|
|
92
104
|
};
|
|
93
105
|
if (execute) {
|
|
94
|
-
const bye = new Bye({
|
|
106
|
+
const bye = new Bye({
|
|
107
|
+
sessid: this.session.sessionid,
|
|
108
|
+
dialogParams: this.options,
|
|
109
|
+
});
|
|
95
110
|
this._execute(bye)
|
|
96
|
-
.catch(error => logger.error('verto.bye failed!', error))
|
|
111
|
+
.catch((error) => logger.error('verto.bye failed!', error))
|
|
97
112
|
.then(_close.bind(this));
|
|
98
113
|
}
|
|
99
114
|
else {
|
|
@@ -101,38 +116,68 @@ export default class BaseCall {
|
|
|
101
116
|
}
|
|
102
117
|
}
|
|
103
118
|
transfer(destination) {
|
|
104
|
-
const msg = new Modify({
|
|
119
|
+
const msg = new Modify({
|
|
120
|
+
sessid: this.session.sessionid,
|
|
121
|
+
action: 'transfer',
|
|
122
|
+
destination,
|
|
123
|
+
dialogParams: this.options,
|
|
124
|
+
});
|
|
105
125
|
this._execute(msg);
|
|
106
126
|
}
|
|
107
127
|
replace(replaceCallID) {
|
|
108
|
-
const msg = new Modify({
|
|
128
|
+
const msg = new Modify({
|
|
129
|
+
sessid: this.session.sessionid,
|
|
130
|
+
action: 'replace',
|
|
131
|
+
replaceCallID,
|
|
132
|
+
dialogParams: this.options,
|
|
133
|
+
});
|
|
109
134
|
this._execute(msg);
|
|
110
135
|
}
|
|
111
136
|
hold() {
|
|
112
|
-
const msg = new Modify({
|
|
137
|
+
const msg = new Modify({
|
|
138
|
+
sessid: this.session.sessionid,
|
|
139
|
+
action: 'hold',
|
|
140
|
+
dialogParams: this.options,
|
|
141
|
+
});
|
|
113
142
|
return this._execute(msg)
|
|
114
143
|
.then(this._handleChangeHoldStateSuccess.bind(this))
|
|
115
144
|
.catch(this._handleChangeHoldStateError.bind(this));
|
|
116
145
|
}
|
|
117
146
|
unhold() {
|
|
118
|
-
const msg = new Modify({
|
|
147
|
+
const msg = new Modify({
|
|
148
|
+
sessid: this.session.sessionid,
|
|
149
|
+
action: 'unhold',
|
|
150
|
+
dialogParams: this.options,
|
|
151
|
+
});
|
|
119
152
|
return this._execute(msg)
|
|
120
153
|
.then(this._handleChangeHoldStateSuccess.bind(this))
|
|
121
154
|
.catch(this._handleChangeHoldStateError.bind(this));
|
|
122
155
|
}
|
|
123
156
|
toggleHold() {
|
|
124
|
-
const msg = new Modify({
|
|
157
|
+
const msg = new Modify({
|
|
158
|
+
sessid: this.session.sessionid,
|
|
159
|
+
action: 'toggleHold',
|
|
160
|
+
dialogParams: this.options,
|
|
161
|
+
});
|
|
125
162
|
return this._execute(msg)
|
|
126
163
|
.then(this._handleChangeHoldStateSuccess.bind(this))
|
|
127
164
|
.catch(this._handleChangeHoldStateError.bind(this));
|
|
128
165
|
}
|
|
129
166
|
dtmf(dtmf) {
|
|
130
|
-
const msg = new Info({
|
|
167
|
+
const msg = new Info({
|
|
168
|
+
sessid: this.session.sessionid,
|
|
169
|
+
dtmf,
|
|
170
|
+
dialogParams: this.options,
|
|
171
|
+
});
|
|
131
172
|
this._execute(msg);
|
|
132
173
|
}
|
|
133
174
|
message(to, body) {
|
|
134
175
|
const msg = { from: this.session.options.login, to, body };
|
|
135
|
-
const info = new Info({
|
|
176
|
+
const info = new Info({
|
|
177
|
+
sessid: this.session.sessionid,
|
|
178
|
+
msg,
|
|
179
|
+
dialogParams: this.options,
|
|
180
|
+
});
|
|
136
181
|
this._execute(info);
|
|
137
182
|
}
|
|
138
183
|
muteAudio() {
|
|
@@ -147,15 +192,18 @@ export default class BaseCall {
|
|
|
147
192
|
setAudioInDevice(deviceId) {
|
|
148
193
|
return __awaiter(this, void 0, void 0, function* () {
|
|
149
194
|
const { instance } = this.peer;
|
|
150
|
-
const
|
|
195
|
+
const senders = yield instance.getSenders();
|
|
196
|
+
const sender = senders.find(({ track: { kind } }) => kind === 'audio');
|
|
151
197
|
if (sender) {
|
|
152
|
-
const newStream = yield getUserMedia({
|
|
198
|
+
const newStream = yield getUserMedia({
|
|
199
|
+
audio: { deviceId: { exact: deviceId } },
|
|
200
|
+
});
|
|
153
201
|
const audioTrack = newStream.getAudioTracks()[0];
|
|
154
202
|
sender.replaceTrack(audioTrack);
|
|
155
203
|
this.options.micId = deviceId;
|
|
156
204
|
const { localStream } = this.options;
|
|
157
|
-
localStream.getAudioTracks().forEach(t => t.stop());
|
|
158
|
-
localStream.getVideoTracks().forEach(t => newStream.addTrack(t));
|
|
205
|
+
localStream.getAudioTracks().forEach((t) => t.stop());
|
|
206
|
+
localStream.getVideoTracks().forEach((t) => newStream.addTrack(t));
|
|
159
207
|
this.options.localStream = newStream;
|
|
160
208
|
}
|
|
161
209
|
});
|
|
@@ -172,16 +220,19 @@ export default class BaseCall {
|
|
|
172
220
|
setVideoDevice(deviceId) {
|
|
173
221
|
return __awaiter(this, void 0, void 0, function* () {
|
|
174
222
|
const { instance } = this.peer;
|
|
175
|
-
const
|
|
223
|
+
const senders = yield instance.getSenders();
|
|
224
|
+
const sender = senders.find(({ track: { kind } }) => kind === 'video');
|
|
176
225
|
if (sender) {
|
|
177
|
-
const newStream = yield getUserMedia({
|
|
226
|
+
const newStream = yield getUserMedia({
|
|
227
|
+
video: { deviceId: { exact: deviceId } },
|
|
228
|
+
});
|
|
178
229
|
const videoTrack = newStream.getVideoTracks()[0];
|
|
179
230
|
sender.replaceTrack(videoTrack);
|
|
180
231
|
const { localElement, localStream } = this.options;
|
|
181
232
|
attachMediaStream(localElement, newStream);
|
|
182
233
|
this.options.camId = deviceId;
|
|
183
|
-
localStream.getAudioTracks().forEach(t => newStream.addTrack(t));
|
|
184
|
-
localStream.getVideoTracks().forEach(t => t.stop());
|
|
234
|
+
localStream.getAudioTracks().forEach((t) => newStream.addTrack(t));
|
|
235
|
+
localStream.getVideoTracks().forEach((t) => t.stop());
|
|
185
236
|
this.options.localStream = newStream;
|
|
186
237
|
}
|
|
187
238
|
});
|
|
@@ -201,7 +252,10 @@ export default class BaseCall {
|
|
|
201
252
|
this.state = State[this._state].toLowerCase();
|
|
202
253
|
this.prevState = State[this._prevState].toLowerCase();
|
|
203
254
|
logger.info(`Call ${this.id} state change from ${this.prevState} to ${this.state}`);
|
|
204
|
-
this._dispatchNotification({
|
|
255
|
+
this._dispatchNotification({
|
|
256
|
+
type: NOTIFICATION_TYPE.callUpdate,
|
|
257
|
+
call: this,
|
|
258
|
+
});
|
|
205
259
|
switch (state) {
|
|
206
260
|
case State.Purge:
|
|
207
261
|
this.hangup({ cause: 'PURGE', causeCode: '01' }, false);
|
|
@@ -246,10 +300,18 @@ export default class BaseCall {
|
|
|
246
300
|
}
|
|
247
301
|
case VertoMethod.Display:
|
|
248
302
|
case VertoMethod.Attach: {
|
|
249
|
-
const { display_name: displayName, display_number: displayNumber, display_direction } = params;
|
|
303
|
+
const { display_name: displayName, display_number: displayNumber, display_direction, } = params;
|
|
250
304
|
this.extension = displayNumber;
|
|
251
|
-
const displayDirection = display_direction === Direction.Inbound
|
|
252
|
-
|
|
305
|
+
const displayDirection = display_direction === Direction.Inbound
|
|
306
|
+
? Direction.Outbound
|
|
307
|
+
: Direction.Inbound;
|
|
308
|
+
const notification = {
|
|
309
|
+
type: NOTIFICATION_TYPE[method],
|
|
310
|
+
call: this,
|
|
311
|
+
displayName,
|
|
312
|
+
displayNumber,
|
|
313
|
+
displayDirection,
|
|
314
|
+
};
|
|
253
315
|
if (!trigger(SwEvent.Notification, notification, this.id)) {
|
|
254
316
|
trigger(SwEvent.Notification, notification, this.session.uuid);
|
|
255
317
|
}
|
|
@@ -273,16 +335,22 @@ export default class BaseCall {
|
|
|
273
335
|
}
|
|
274
336
|
handleConferenceUpdate(packet, initialPvtData) {
|
|
275
337
|
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
-
if (!this._checkConferenceSerno(packet.wireSerno) &&
|
|
338
|
+
if (!this._checkConferenceSerno(packet.wireSerno) &&
|
|
339
|
+
packet.name !== initialPvtData.laName) {
|
|
277
340
|
logger.error('ConferenceUpdate invalid wireSerno or packet name:', packet);
|
|
278
341
|
return 'INVALID_PACKET';
|
|
279
342
|
}
|
|
280
|
-
const { action, data, hashKey: callId = String(this._lastSerno), arrIndex: index } = packet;
|
|
343
|
+
const { action, data, hashKey: callId = String(this._lastSerno), arrIndex: index, } = packet;
|
|
281
344
|
switch (action) {
|
|
282
345
|
case 'bootObj': {
|
|
283
346
|
this._lastSerno = 0;
|
|
284
|
-
const { chatID, chatChannel, infoChannel, modChannel, laName, conferenceMemberID, role } = initialPvtData;
|
|
285
|
-
this._dispatchConferenceUpdate({
|
|
347
|
+
const { chatID, chatChannel, infoChannel, modChannel, laName, conferenceMemberID, role, } = initialPvtData;
|
|
348
|
+
this._dispatchConferenceUpdate({
|
|
349
|
+
action: ConferenceAction.Join,
|
|
350
|
+
conferenceName: laName,
|
|
351
|
+
participantId: Number(conferenceMemberID),
|
|
352
|
+
role,
|
|
353
|
+
});
|
|
286
354
|
if (chatChannel) {
|
|
287
355
|
yield this._subscribeConferenceChat(chatChannel);
|
|
288
356
|
}
|
|
@@ -296,18 +364,24 @@ export default class BaseCall {
|
|
|
296
364
|
for (const i in data) {
|
|
297
365
|
participants.push(Object.assign({ callId: data[i][0], index: Number(i) }, mutateLiveArrayData(data[i][1])));
|
|
298
366
|
}
|
|
299
|
-
this._dispatchConferenceUpdate({
|
|
367
|
+
this._dispatchConferenceUpdate({
|
|
368
|
+
action: ConferenceAction.Bootstrap,
|
|
369
|
+
participants,
|
|
370
|
+
});
|
|
300
371
|
break;
|
|
301
372
|
}
|
|
302
373
|
case 'add': {
|
|
303
|
-
this._dispatchConferenceUpdate(Object.assign({ action: ConferenceAction.Add, callId,
|
|
374
|
+
this._dispatchConferenceUpdate(Object.assign({ action: ConferenceAction.Add, callId,
|
|
375
|
+
index }, mutateLiveArrayData(data)));
|
|
304
376
|
break;
|
|
305
377
|
}
|
|
306
378
|
case 'modify':
|
|
307
|
-
this._dispatchConferenceUpdate(Object.assign({ action: ConferenceAction.Modify, callId,
|
|
379
|
+
this._dispatchConferenceUpdate(Object.assign({ action: ConferenceAction.Modify, callId,
|
|
380
|
+
index }, mutateLiveArrayData(data)));
|
|
308
381
|
break;
|
|
309
382
|
case 'del':
|
|
310
|
-
this._dispatchConferenceUpdate(Object.assign({ action: ConferenceAction.Delete, callId,
|
|
383
|
+
this._dispatchConferenceUpdate(Object.assign({ action: ConferenceAction.Delete, callId,
|
|
384
|
+
index }, mutateLiveArrayData(data)));
|
|
311
385
|
break;
|
|
312
386
|
case 'clear':
|
|
313
387
|
this._dispatchConferenceUpdate({ action: ConferenceAction.Clear });
|
|
@@ -333,12 +407,19 @@ export default class BaseCall {
|
|
|
333
407
|
nodeId: this.nodeId,
|
|
334
408
|
channels: [channel],
|
|
335
409
|
handler: (params) => {
|
|
336
|
-
const { direction, from: participantNumber, fromDisplay: participantName, message: messageText, type: messageType } = params.data;
|
|
337
|
-
this._dispatchConferenceUpdate({
|
|
338
|
-
|
|
410
|
+
const { direction, from: participantNumber, fromDisplay: participantName, message: messageText, type: messageType, } = params.data;
|
|
411
|
+
this._dispatchConferenceUpdate({
|
|
412
|
+
action: ConferenceAction.ChatMessage,
|
|
413
|
+
direction,
|
|
414
|
+
participantNumber,
|
|
415
|
+
participantName,
|
|
416
|
+
messageText,
|
|
417
|
+
messageType,
|
|
418
|
+
messageId: params.eventSerno,
|
|
419
|
+
});
|
|
420
|
+
},
|
|
339
421
|
};
|
|
340
|
-
const response = yield this.session.vertoSubscribe(tmp)
|
|
341
|
-
.catch(error => {
|
|
422
|
+
const response = yield this.session.vertoSubscribe(tmp).catch((error) => {
|
|
342
423
|
logger.error('ConfChat subscription error:', error);
|
|
343
424
|
});
|
|
344
425
|
if (checkSubscribeResponse(response, channel)) {
|
|
@@ -347,9 +428,13 @@ export default class BaseCall {
|
|
|
347
428
|
sendChatMessage: {
|
|
348
429
|
configurable: true,
|
|
349
430
|
value: (message, type) => {
|
|
350
|
-
this.session.vertoBroadcast({
|
|
351
|
-
|
|
352
|
-
|
|
431
|
+
this.session.vertoBroadcast({
|
|
432
|
+
nodeId: this.nodeId,
|
|
433
|
+
channel,
|
|
434
|
+
data: { action: 'send', message, type },
|
|
435
|
+
});
|
|
436
|
+
},
|
|
437
|
+
},
|
|
353
438
|
});
|
|
354
439
|
}
|
|
355
440
|
});
|
|
@@ -369,10 +454,9 @@ export default class BaseCall {
|
|
|
369
454
|
default:
|
|
370
455
|
logger.error('Conference-Info unknown contentType', params);
|
|
371
456
|
}
|
|
372
|
-
}
|
|
457
|
+
},
|
|
373
458
|
};
|
|
374
|
-
const response = yield this.session.vertoSubscribe(tmp)
|
|
375
|
-
.catch(error => {
|
|
459
|
+
const response = yield this.session.vertoSubscribe(tmp).catch((error) => {
|
|
376
460
|
logger.error('ConfInfo subscription error:', error);
|
|
377
461
|
});
|
|
378
462
|
if (checkSubscribeResponse(response, channel)) {
|
|
@@ -392,7 +476,8 @@ export default class BaseCall {
|
|
|
392
476
|
};
|
|
393
477
|
const _videoRequired = () => {
|
|
394
478
|
const { video } = this.options;
|
|
395
|
-
if ((typeof video === 'boolean' && !video) ||
|
|
479
|
+
if ((typeof video === 'boolean' && !video) ||
|
|
480
|
+
(typeof video === 'object' && objEmpty(video))) {
|
|
396
481
|
throw `Conference ${this.id} has no video!`;
|
|
397
482
|
}
|
|
398
483
|
};
|
|
@@ -405,16 +490,22 @@ export default class BaseCall {
|
|
|
405
490
|
case 'list-videoLayouts':
|
|
406
491
|
if (data.responseData) {
|
|
407
492
|
const tmp = JSON.stringify(data.responseData).replace(/IDS"/g, 'Ids"');
|
|
408
|
-
this._dispatchConferenceUpdate({
|
|
493
|
+
this._dispatchConferenceUpdate({
|
|
494
|
+
action: ConferenceAction.LayoutList,
|
|
495
|
+
layouts: JSON.parse(tmp),
|
|
496
|
+
});
|
|
409
497
|
}
|
|
410
498
|
break;
|
|
411
499
|
default:
|
|
412
|
-
this._dispatchConferenceUpdate({
|
|
500
|
+
this._dispatchConferenceUpdate({
|
|
501
|
+
action: ConferenceAction.ModCmdResponse,
|
|
502
|
+
command: data['conf-command'],
|
|
503
|
+
response: data.response,
|
|
504
|
+
});
|
|
413
505
|
}
|
|
414
|
-
}
|
|
506
|
+
},
|
|
415
507
|
};
|
|
416
|
-
const response = yield this.session.vertoSubscribe(tmp)
|
|
417
|
-
.catch(error => {
|
|
508
|
+
const response = yield this.session.vertoSubscribe(tmp).catch((error) => {
|
|
418
509
|
logger.error('ConfMod subscription error:', error);
|
|
419
510
|
});
|
|
420
511
|
if (checkSubscribeResponse(response, channel)) {
|
|
@@ -425,50 +516,50 @@ export default class BaseCall {
|
|
|
425
516
|
configurable: true,
|
|
426
517
|
value: () => {
|
|
427
518
|
_modCommand('list-videoLayouts');
|
|
428
|
-
}
|
|
519
|
+
},
|
|
429
520
|
},
|
|
430
521
|
playMedia: {
|
|
431
522
|
configurable: true,
|
|
432
523
|
value: (file) => {
|
|
433
524
|
_modCommand('play', null, file);
|
|
434
|
-
}
|
|
525
|
+
},
|
|
435
526
|
},
|
|
436
527
|
stopMedia: {
|
|
437
528
|
configurable: true,
|
|
438
529
|
value: () => {
|
|
439
530
|
_modCommand('stop', null, 'all');
|
|
440
|
-
}
|
|
531
|
+
},
|
|
441
532
|
},
|
|
442
533
|
deaf: {
|
|
443
534
|
configurable: true,
|
|
444
535
|
value: (memberID) => {
|
|
445
536
|
_modCommand('deaf', memberID);
|
|
446
|
-
}
|
|
537
|
+
},
|
|
447
538
|
},
|
|
448
539
|
undeaf: {
|
|
449
540
|
configurable: true,
|
|
450
541
|
value: (memberID) => {
|
|
451
542
|
_modCommand('undeaf', memberID);
|
|
452
|
-
}
|
|
543
|
+
},
|
|
453
544
|
},
|
|
454
545
|
startRecord: {
|
|
455
546
|
configurable: true,
|
|
456
547
|
value: (file) => {
|
|
457
548
|
_modCommand('recording', null, ['start', file]);
|
|
458
|
-
}
|
|
549
|
+
},
|
|
459
550
|
},
|
|
460
551
|
stopRecord: {
|
|
461
552
|
configurable: true,
|
|
462
553
|
value: () => {
|
|
463
554
|
_modCommand('recording', null, ['stop', 'all']);
|
|
464
|
-
}
|
|
555
|
+
},
|
|
465
556
|
},
|
|
466
557
|
snapshot: {
|
|
467
558
|
configurable: true,
|
|
468
559
|
value: (file) => {
|
|
469
560
|
_videoRequired();
|
|
470
561
|
_modCommand('vid-write-png', null, file);
|
|
471
|
-
}
|
|
562
|
+
},
|
|
472
563
|
},
|
|
473
564
|
setVideoLayout: {
|
|
474
565
|
configurable: true,
|
|
@@ -476,84 +567,86 @@ export default class BaseCall {
|
|
|
476
567
|
_videoRequired();
|
|
477
568
|
const value = canvasID ? [layout, canvasID] : layout;
|
|
478
569
|
_modCommand('vid-layout', null, value);
|
|
479
|
-
}
|
|
570
|
+
},
|
|
480
571
|
},
|
|
481
572
|
kick: {
|
|
482
573
|
configurable: true,
|
|
483
574
|
value: (memberID) => {
|
|
484
575
|
_modCommand('kick', memberID);
|
|
485
|
-
}
|
|
576
|
+
},
|
|
486
577
|
},
|
|
487
578
|
muteMic: {
|
|
488
579
|
configurable: true,
|
|
489
580
|
value: (memberID) => {
|
|
490
581
|
_modCommand('tmute', memberID);
|
|
491
|
-
}
|
|
582
|
+
},
|
|
492
583
|
},
|
|
493
584
|
muteVideo: {
|
|
494
585
|
configurable: true,
|
|
495
586
|
value: (memberID) => {
|
|
496
587
|
_videoRequired();
|
|
497
588
|
_modCommand('tvmute', memberID);
|
|
498
|
-
}
|
|
589
|
+
},
|
|
499
590
|
},
|
|
500
591
|
presenter: {
|
|
501
592
|
configurable: true,
|
|
502
593
|
value: (memberID) => {
|
|
503
594
|
_videoRequired();
|
|
504
595
|
_modCommand('vid-res-id', memberID, 'presenter');
|
|
505
|
-
}
|
|
596
|
+
},
|
|
506
597
|
},
|
|
507
598
|
videoFloor: {
|
|
508
599
|
configurable: true,
|
|
509
600
|
value: (memberID) => {
|
|
510
601
|
_videoRequired();
|
|
511
602
|
_modCommand('vid-floor', memberID, 'force');
|
|
512
|
-
}
|
|
603
|
+
},
|
|
513
604
|
},
|
|
514
605
|
banner: {
|
|
515
606
|
configurable: true,
|
|
516
607
|
value: (memberID, text) => {
|
|
517
608
|
_videoRequired();
|
|
518
609
|
_modCommand('vid-banner', memberID, encodeURI(text));
|
|
519
|
-
}
|
|
610
|
+
},
|
|
520
611
|
},
|
|
521
612
|
volumeDown: {
|
|
522
613
|
configurable: true,
|
|
523
614
|
value: (memberID) => {
|
|
524
615
|
_modCommand('volume_out', memberID, 'down');
|
|
525
|
-
}
|
|
616
|
+
},
|
|
526
617
|
},
|
|
527
618
|
volumeUp: {
|
|
528
619
|
configurable: true,
|
|
529
620
|
value: (memberID) => {
|
|
530
621
|
_modCommand('volume_out', memberID, 'up');
|
|
531
|
-
}
|
|
622
|
+
},
|
|
532
623
|
},
|
|
533
624
|
gainDown: {
|
|
534
625
|
configurable: true,
|
|
535
626
|
value: (memberID) => {
|
|
536
627
|
_modCommand('volume_in', memberID, 'down');
|
|
537
|
-
}
|
|
628
|
+
},
|
|
538
629
|
},
|
|
539
630
|
gainUp: {
|
|
540
631
|
configurable: true,
|
|
541
632
|
value: (memberID) => {
|
|
542
633
|
_modCommand('volume_in', memberID, 'up');
|
|
543
|
-
}
|
|
634
|
+
},
|
|
544
635
|
},
|
|
545
636
|
transfer: {
|
|
546
637
|
configurable: true,
|
|
547
638
|
value: (memberID, exten) => {
|
|
548
639
|
_modCommand('transfer', memberID, exten);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
640
|
+
},
|
|
641
|
+
},
|
|
551
642
|
});
|
|
552
643
|
}
|
|
553
644
|
});
|
|
554
645
|
}
|
|
555
646
|
_handleChangeHoldStateSuccess(response) {
|
|
556
|
-
response.holdState === 'active'
|
|
647
|
+
response.holdState === 'active'
|
|
648
|
+
? this.setState(State.Active)
|
|
649
|
+
: this.setState(State.Held);
|
|
557
650
|
return true;
|
|
558
651
|
}
|
|
559
652
|
_handleChangeHoldStateError(error) {
|
|
@@ -565,8 +658,12 @@ export default class BaseCall {
|
|
|
565
658
|
if (this.options.useStereo) {
|
|
566
659
|
sdp = sdpStereoHack(sdp);
|
|
567
660
|
}
|
|
568
|
-
const sessionDescr = sdpToJsonHack({
|
|
569
|
-
|
|
661
|
+
const sessionDescr = sdpToJsonHack({
|
|
662
|
+
sdp,
|
|
663
|
+
type: PeerType.Answer,
|
|
664
|
+
});
|
|
665
|
+
this.peer.instance
|
|
666
|
+
.setRemoteDescription(sessionDescr)
|
|
570
667
|
.then(() => {
|
|
571
668
|
if (this.gotEarly) {
|
|
572
669
|
this.setState(State.Early);
|
|
@@ -575,7 +672,7 @@ export default class BaseCall {
|
|
|
575
672
|
this.setState(State.Active);
|
|
576
673
|
}
|
|
577
674
|
})
|
|
578
|
-
.catch(error => {
|
|
675
|
+
.catch((error) => {
|
|
579
676
|
logger.error('Call setRemoteDescription Error: ', error);
|
|
580
677
|
this.hangup();
|
|
581
678
|
});
|
|
@@ -586,7 +683,9 @@ export default class BaseCall {
|
|
|
586
683
|
trigger(SwEvent.Error, new Error('SDP without candidates for the second time!'), this.session.uuid);
|
|
587
684
|
return;
|
|
588
685
|
}
|
|
589
|
-
Object.defineProperty(this.peer, 'onSdpReadyTwice', {
|
|
686
|
+
Object.defineProperty(this.peer, 'onSdpReadyTwice', {
|
|
687
|
+
value: this._onIceSdp.bind(this),
|
|
688
|
+
});
|
|
590
689
|
this._iceDone = false;
|
|
591
690
|
this.peer.startNegotiation();
|
|
592
691
|
}
|
|
@@ -604,7 +703,11 @@ export default class BaseCall {
|
|
|
604
703
|
return;
|
|
605
704
|
}
|
|
606
705
|
let msg = null;
|
|
607
|
-
const tmpParams = {
|
|
706
|
+
const tmpParams = {
|
|
707
|
+
sessid: this.session.sessionid,
|
|
708
|
+
sdp,
|
|
709
|
+
dialogParams: this.options,
|
|
710
|
+
};
|
|
608
711
|
switch (type) {
|
|
609
712
|
case PeerType.Offer:
|
|
610
713
|
this.setState(State.Requesting);
|
|
@@ -612,19 +715,24 @@ export default class BaseCall {
|
|
|
612
715
|
break;
|
|
613
716
|
case PeerType.Answer:
|
|
614
717
|
this.setState(State.Answering);
|
|
615
|
-
msg =
|
|
718
|
+
msg =
|
|
719
|
+
this.options.attach === true
|
|
720
|
+
? new Attach(tmpParams)
|
|
721
|
+
: new Answer(tmpParams);
|
|
616
722
|
break;
|
|
617
723
|
default:
|
|
618
724
|
logger.error(`${this.id} - Unknown local SDP type:`, data);
|
|
619
725
|
return this.hangup({}, false);
|
|
620
726
|
}
|
|
621
727
|
this._execute(msg)
|
|
622
|
-
.then(response => {
|
|
728
|
+
.then((response) => {
|
|
623
729
|
const { node_id = null } = response;
|
|
624
730
|
this._targetNodeId = node_id;
|
|
625
|
-
type === PeerType.Offer
|
|
731
|
+
type === PeerType.Offer
|
|
732
|
+
? this.setState(State.Trying)
|
|
733
|
+
: this.setState(State.Active);
|
|
626
734
|
})
|
|
627
|
-
.catch(error => {
|
|
735
|
+
.catch((error) => {
|
|
628
736
|
logger.error(`${this.id} - Sending ${type} error:`, error);
|
|
629
737
|
this.hangup();
|
|
630
738
|
});
|
|
@@ -632,7 +740,7 @@ export default class BaseCall {
|
|
|
632
740
|
_registerPeerEvents() {
|
|
633
741
|
const { instance } = this.peer;
|
|
634
742
|
this._iceDone = false;
|
|
635
|
-
instance.onicecandidate = event => {
|
|
743
|
+
instance.onicecandidate = (event) => {
|
|
636
744
|
if (this._iceDone) {
|
|
637
745
|
return;
|
|
638
746
|
}
|
|
@@ -659,7 +767,10 @@ export default class BaseCall {
|
|
|
659
767
|
});
|
|
660
768
|
}
|
|
661
769
|
_onMediaError(error) {
|
|
662
|
-
this._dispatchNotification({
|
|
770
|
+
this._dispatchNotification({
|
|
771
|
+
type: NOTIFICATION_TYPE.userMediaError,
|
|
772
|
+
error,
|
|
773
|
+
});
|
|
663
774
|
this.hangup({}, false);
|
|
664
775
|
}
|
|
665
776
|
_dispatchConferenceUpdate(params) {
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import logger from '../util/logger';
|
|
11
11
|
import BaseCall from './BaseCall';
|
|
12
|
-
import { getDisplayMedia, setMediaElementSinkId } from '
|
|
12
|
+
import { getDisplayMedia, setMediaElementSinkId } from './WebRTC';
|
|
13
13
|
export default class Call extends BaseCall {
|
|
14
14
|
constructor() {
|
|
15
15
|
super(...arguments);
|
|
@@ -24,7 +24,7 @@ export default class Call extends BaseCall {
|
|
|
24
24
|
startScreenShare(opts) {
|
|
25
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
26
|
const displayStream = yield getDisplayMedia({ video: true });
|
|
27
|
-
displayStream.getTracks().forEach(t => {
|
|
27
|
+
displayStream.getTracks().forEach((t) => {
|
|
28
28
|
t.addEventListener('ended', () => {
|
|
29
29
|
if (this.screenShare) {
|
|
30
30
|
this.screenShare.hangup();
|
|
@@ -65,14 +65,21 @@ export default class Call extends BaseCall {
|
|
|
65
65
|
this._statsInterval = window.setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
66
66
|
const stats = yield this.peer.instance.getStats(null);
|
|
67
67
|
let statsOutput = '';
|
|
68
|
-
const invalidReport = [
|
|
68
|
+
const invalidReport = [
|
|
69
|
+
'certificate',
|
|
70
|
+
'codec',
|
|
71
|
+
'peer-connection',
|
|
72
|
+
'stream',
|
|
73
|
+
'local-candidate',
|
|
74
|
+
'remote-candidate',
|
|
75
|
+
];
|
|
69
76
|
const invalidStat = ['id', 'type', 'timestamp'];
|
|
70
|
-
stats.forEach(report => {
|
|
77
|
+
stats.forEach((report) => {
|
|
71
78
|
if (invalidReport.includes(report.type)) {
|
|
72
79
|
return;
|
|
73
80
|
}
|
|
74
81
|
statsOutput += `\n${report.type}\n`;
|
|
75
|
-
Object.keys(report).forEach(statName => {
|
|
82
|
+
Object.keys(report).forEach((statName) => {
|
|
76
83
|
if (!invalidStat.includes(statName)) {
|
|
77
84
|
statsOutput += `\t${statName}: ${report[statName]}\n`;
|
|
78
85
|
}
|