@voicenter-team/opensips-js 1.0.21 → 1.0.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. package/dist/index.d.ts +737 -0
  2. package/dist/opensips-js.cjs.js +155 -0
  3. package/dist/opensips-js.es.js +21363 -0
  4. package/dist/opensips-js.iife.js +155 -0
  5. package/dist/opensips-js.umd.js +155 -0
  6. package/package.json +15 -9
  7. package/src/types/Dialog.d.ts +7 -0
  8. package/src/types/Socket.d.ts +8 -0
  9. package/src/types/Transactions.d.ts +9 -0
  10. package/src/types/UAExtended.d.ts +86 -0
  11. package/src/types/listeners.d.ts +26 -2
  12. package/src/types/msrp.d.ts +55 -0
  13. package/src/types/rtc.d.ts +23 -4
  14. package/src/types/timer.d.ts +7 -0
  15. package/build/enum/call.event.listener.type.d.ts +0 -7
  16. package/build/enum/call.event.listener.type.js +0 -10
  17. package/build/enum/metric.keys.to.include.d.ts +0 -2
  18. package/build/enum/metric.keys.to.include.js +0 -4
  19. package/build/helpers/UA/index.d.ts +0 -6
  20. package/build/helpers/UA/index.js +0 -9
  21. package/build/helpers/audio.helper.d.ts +0 -9
  22. package/build/helpers/audio.helper.js +0 -61
  23. package/build/helpers/filter.helper.d.ts +0 -2
  24. package/build/helpers/filter.helper.js +0 -14
  25. package/build/helpers/time.helper.d.ts +0 -16
  26. package/build/helpers/time.helper.js +0 -28
  27. package/build/helpers/volume.helper.d.ts +0 -2
  28. package/build/helpers/volume.helper.js +0 -76
  29. package/build/helpers/webrtcmetrics/collector.d.ts +0 -32
  30. package/build/helpers/webrtcmetrics/collector.js +0 -282
  31. package/build/helpers/webrtcmetrics/engine.d.ts +0 -20
  32. package/build/helpers/webrtcmetrics/engine.js +0 -164
  33. package/build/helpers/webrtcmetrics/exporter.d.ts +0 -116
  34. package/build/helpers/webrtcmetrics/exporter.js +0 -528
  35. package/build/helpers/webrtcmetrics/extractor.d.ts +0 -1
  36. package/build/helpers/webrtcmetrics/extractor.js +0 -976
  37. package/build/helpers/webrtcmetrics/index.d.ts +0 -63
  38. package/build/helpers/webrtcmetrics/index.js +0 -93
  39. package/build/helpers/webrtcmetrics/metrics.d.ts +0 -2
  40. package/build/helpers/webrtcmetrics/metrics.js +0 -8
  41. package/build/helpers/webrtcmetrics/probe.d.ts +0 -76
  42. package/build/helpers/webrtcmetrics/probe.js +0 -153
  43. package/build/helpers/webrtcmetrics/utils/config.d.ts +0 -12
  44. package/build/helpers/webrtcmetrics/utils/config.js +0 -28
  45. package/build/helpers/webrtcmetrics/utils/helper.d.ts +0 -13
  46. package/build/helpers/webrtcmetrics/utils/helper.js +0 -134
  47. package/build/helpers/webrtcmetrics/utils/log.d.ts +0 -7
  48. package/build/helpers/webrtcmetrics/utils/log.js +0 -71
  49. package/build/helpers/webrtcmetrics/utils/models.d.ts +0 -309
  50. package/build/helpers/webrtcmetrics/utils/models.js +0 -298
  51. package/build/helpers/webrtcmetrics/utils/score.d.ts +0 -4
  52. package/build/helpers/webrtcmetrics/utils/score.js +0 -235
  53. package/build/helpers/webrtcmetrics/utils/shortUUId.d.ts +0 -1
  54. package/build/helpers/webrtcmetrics/utils/shortUUId.js +0 -7
  55. package/build/index.d.ts +0 -181
  56. package/build/index.js +0 -911
package/build/index.js DELETED
@@ -1,911 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- const jssip_1 = __importDefault(require("jssip"));
16
- const UA_1 = __importDefault(require("./helpers/UA"));
17
- const p_iteration_1 = require("p-iteration");
18
- const time_helper_1 = require("./helpers/time.helper");
19
- const filter_helper_1 = require("./helpers/filter.helper");
20
- const audio_helper_1 = require("./helpers/audio.helper");
21
- const metrics_1 = __importDefault(require("./helpers/webrtcmetrics/metrics"));
22
- const metric_keys_to_include_1 = require("./enum/metric.keys.to.include");
23
- const call_event_listener_type_1 = require("./enum/call.event.listener.type");
24
- const CALL_STATUS_UNANSWERED = 0;
25
- const STORAGE_KEYS = {
26
- SELECTED_INPUT_DEVICE: 'selectedInputDevice',
27
- SELECTED_OUTPUT_DEVICE: 'selectedOutputDevice'
28
- };
29
- class OpenSIPSJS extends UA_1.default {
30
- constructor(options) {
31
- const configuration = Object.assign(Object.assign({}, options.configuration), { sockets: options.socketInterfaces.map(sock => new jssip_1.default.WebSocketInterface(sock)) });
32
- super(configuration);
33
- this.initialized = false;
34
- this.newRTCSessionEventName = 'newRTCSession';
35
- this.registeredEventName = 'registered';
36
- this.unregisteredEventName = 'unregistered';
37
- this.activeCalls = {};
38
- this.extendedCalls = {};
39
- this.state = {
40
- isMuted: false,
41
- isAutoAnswer: false,
42
- activeCalls: {},
43
- extendedCalls: {},
44
- availableMediaDevices: [],
45
- selectedMediaDevices: {
46
- input: 'default',
47
- output: 'default' //localStorage.getItem(STORAGE_KEYS.SELECTED_OUTPUT_DEVICE) || 'default'
48
- },
49
- microphoneInputLevel: 2,
50
- speakerVolume: 1,
51
- muteWhenJoin: false,
52
- originalStream: null,
53
- isDND: false,
54
- listeners: {},
55
- activeRooms: {},
56
- callStatus: {},
57
- callTime: {},
58
- timeIntervals: {},
59
- callMetrics: {},
60
- metricConfig: {
61
- refreshEvery: 1000,
62
- }
63
- };
64
- this.options = options;
65
- }
66
- on(type, listener) {
67
- return super.on(type, listener);
68
- }
69
- off(type, listener) {
70
- return super.off(type, listener);
71
- }
72
- emit(type, args) {
73
- return super.emit(type, args);
74
- }
75
- get sipDomain() {
76
- return this.options.sipDomain;
77
- }
78
- get sipOptions() {
79
- const options = Object.assign(Object.assign({}, this.options.sipOptions), { mediaConstraints: this.getUserMediaConstraints });
80
- return options;
81
- }
82
- get currentActiveRoomId() {
83
- return this._currentActiveRoomId;
84
- }
85
- set currentActiveRoomId(roomId) {
86
- this._currentActiveRoomId = roomId;
87
- this.emit('currentActiveRoomChanged', roomId);
88
- }
89
- get autoAnswer() {
90
- return this.state.isAutoAnswer;
91
- }
92
- set autoAnswer(value) {
93
- this.state.isAutoAnswer = value;
94
- }
95
- get callAddingInProgress() {
96
- return this._callAddingInProgress;
97
- }
98
- set callAddingInProgress(value) {
99
- this._callAddingInProgress = value;
100
- this.emit('callAddingInProgressChanged', value);
101
- }
102
- get muteWhenJoin() {
103
- return this.state.muteWhenJoin;
104
- }
105
- set muteWhenJoin(value) {
106
- this.state.muteWhenJoin = value;
107
- this.emit('changeMuteWhenJoin', value);
108
- }
109
- get isDND() {
110
- return this.state.isDND;
111
- }
112
- set isDND(value) {
113
- this.state.isDND = value;
114
- this.emit('changeIsDND', value);
115
- }
116
- get speakerVolume() {
117
- return this.state.speakerVolume;
118
- }
119
- set speakerVolume(value) {
120
- this.state.speakerVolume = value;
121
- Object.values(this.state.extendedCalls).forEach((call) => {
122
- if (call.audioTag) {
123
- call.audioTag.volume = value;
124
- }
125
- });
126
- }
127
- get microphoneInputLevel() {
128
- return this.state.microphoneInputLevel;
129
- }
130
- set microphoneInputLevel(value) {
131
- this.state.microphoneInputLevel = value;
132
- this.roomReconfigure(this.currentActiveRoomId);
133
- }
134
- get getActiveCalls() {
135
- return this.state.activeCalls;
136
- }
137
- get hasActiveCalls() {
138
- return Object.values(this.state.extendedCalls).length > 0;
139
- }
140
- get getActiveRooms() {
141
- return this.state.activeRooms;
142
- }
143
- get isMuted() {
144
- return this.state.isMuted;
145
- }
146
- set isMuted(value) {
147
- this.state.isMuted = value;
148
- this.emit('changeIsMuted', value);
149
- }
150
- get getInputDeviceList() {
151
- return this.state.availableMediaDevices.filter(device => device.kind === 'audioinput');
152
- }
153
- get getOutputDeviceList() {
154
- return this.state.availableMediaDevices.filter(device => device.kind === 'audiooutput');
155
- }
156
- /*getInputDeviceList: (state) => {
157
- return state.availableMediaDevices.filter(device => device.kind === 'audioinput');
158
- },
159
- getOutputDeviceList: (state) => {
160
- return state.availableMediaDevices.filter(device => device.kind === 'audiooutput');
161
- }*/
162
- get getUserMediaConstraints() {
163
- return {
164
- audio: {
165
- deviceId: {
166
- exact: this.state.selectedMediaDevices.input
167
- }
168
- },
169
- video: false
170
- };
171
- }
172
- get getInputDefaultDevice() {
173
- return this.getInputDeviceList.find(device => device.deviceId === 'default');
174
- }
175
- get getOutputDefaultDevice() {
176
- return this.getOutputDeviceList.find(device => device.deviceId === 'default');
177
- }
178
- get selectedInputDevice() {
179
- return this.state.selectedMediaDevices.input;
180
- }
181
- set selectedInputDevice(deviceId) {
182
- localStorage.setItem(STORAGE_KEYS.SELECTED_INPUT_DEVICE, deviceId);
183
- this.state.selectedMediaDevices.input = deviceId;
184
- this.emit('changeActiveInputMediaDevice', deviceId);
185
- }
186
- get selectedOutputDevice() {
187
- return this.state.selectedMediaDevices.output;
188
- }
189
- set selectedOutputDevice(deviceId) {
190
- localStorage.setItem(STORAGE_KEYS.SELECTED_OUTPUT_DEVICE, deviceId);
191
- this.state.selectedMediaDevices.output = deviceId;
192
- this.emit('changeActiveOutputMediaDevice', deviceId);
193
- }
194
- get originalStream() {
195
- return this.state.originalStream;
196
- }
197
- setAvailableMediaDevices(devices) {
198
- this.state.availableMediaDevices = devices;
199
- this.emit('changeAvailableDeviceList', devices);
200
- }
201
- updateDeviceList() {
202
- return __awaiter(this, void 0, void 0, function* () {
203
- yield navigator.mediaDevices.getUserMedia(this.getUserMediaConstraints);
204
- const devices = yield navigator.mediaDevices.enumerateDevices();
205
- this.setAvailableMediaDevices(devices);
206
- });
207
- }
208
- setMediaDevices(setDefaults = false) {
209
- var _a, _b;
210
- return __awaiter(this, void 0, void 0, function* () {
211
- this.state.selectedMediaDevices.input = localStorage.getItem(STORAGE_KEYS.SELECTED_INPUT_DEVICE) || 'default';
212
- this.state.selectedMediaDevices.output = localStorage.getItem(STORAGE_KEYS.SELECTED_OUTPUT_DEVICE) || 'default';
213
- yield navigator.mediaDevices.getUserMedia(this.getUserMediaConstraints);
214
- const devices = yield navigator.mediaDevices.enumerateDevices();
215
- this.setAvailableMediaDevices(devices);
216
- const defaultMicrophone = setDefaults
217
- ? ((_a = this.getInputDefaultDevice) === null || _a === void 0 ? void 0 : _a.deviceId) || ''
218
- : '';
219
- const defaultSpeaker = setDefaults
220
- ? ((_b = this.getOutputDefaultDevice) === null || _b === void 0 ? void 0 : _b.deviceId) || ''
221
- : '';
222
- yield this.setMicrophone(defaultMicrophone);
223
- yield this.setSpeaker(defaultSpeaker);
224
- });
225
- }
226
- setCallTime(value) {
227
- const time = Object.assign({}, value);
228
- delete time.callId;
229
- this.state.callTime = Object.assign(Object.assign({}, this.state.callTime), { [value.callId]: time });
230
- }
231
- removeCallTime(callId) {
232
- const callTimeCopy = Object.assign({}, this.state.callTime);
233
- delete callTimeCopy[callId];
234
- this.state.callTime = Object.assign({}, callTimeCopy);
235
- }
236
- setTimeInterval(callId, interval) {
237
- this.state.timeIntervals = Object.assign(Object.assign({}, this.state.timeIntervals), { [callId]: interval });
238
- }
239
- removeTimeInterval(callId) {
240
- const timeIntervalsCopy = Object.assign({}, this.state.timeIntervals);
241
- clearInterval(timeIntervalsCopy[callId]);
242
- delete timeIntervalsCopy[callId];
243
- this.state.timeIntervals = Object.assign({}, timeIntervalsCopy);
244
- }
245
- _stopCallTimer(callId) {
246
- this.removeTimeInterval(callId);
247
- this.removeCallTime(callId);
248
- }
249
- setMetricsConfig(config) {
250
- this.state.metricConfig = Object.assign(Object.assign({}, this.state.metricConfig), config);
251
- }
252
- sendDTMF(callId, value) {
253
- const validation_regex = /^[A-D0-9]+$/g;
254
- if (!validation_regex.test(value)) {
255
- throw new Error('Not allowed character in DTMF input');
256
- }
257
- const call = this.state.extendedCalls[callId];
258
- call.sendDTMF(value);
259
- }
260
- doMute(value) {
261
- const activeRoomId = this.currentActiveRoomId;
262
- this.isMuted = value;
263
- this.roomReconfigure(activeRoomId);
264
- }
265
- sendMessage(target, body, options) {
266
- return super.sendMessage(`sip:${target}@${this.sipDomain}`, body, options);
267
- }
268
- doCallHold({ callId, toHold, automatic }) {
269
- const call = this.state.extendedCalls[callId];
270
- call._automaticHold = automatic !== null && automatic !== void 0 ? automatic : false;
271
- if (toHold) {
272
- call.hold();
273
- }
274
- else {
275
- call.unhold();
276
- }
277
- }
278
- _cancelAllOutgoingUnanswered() {
279
- Object.values(this.getActiveCalls).filter(call => {
280
- return call.direction === 'outgoing'
281
- && call.status === CALL_STATUS_UNANSWERED;
282
- }).forEach(call => this.callTerminate(call._id));
283
- }
284
- callAnswer(callId) {
285
- const call = this.state.extendedCalls[callId];
286
- this._cancelAllOutgoingUnanswered();
287
- call.answer(this.sipOptions);
288
- this.updateCall(call);
289
- // TODO: maybe would be better to move to the top
290
- this.setCurrentActiveRoomId(call.roomId);
291
- call.connection.addEventListener('addstream', (event) => __awaiter(this, void 0, void 0, function* () {
292
- this._triggerAddStream(event, call);
293
- }));
294
- }
295
- callMove(callId, roomId) {
296
- return __awaiter(this, void 0, void 0, function* () {
297
- this._updateCallStatus({ callId, isMoving: true });
298
- yield this.callChangeRoom({ callId, roomId });
299
- this._updateCallStatus({ callId, isMoving: false });
300
- });
301
- }
302
- updateCall(value) {
303
- this.state.activeCalls[value._id] = (0, audio_helper_1.simplifyCallObject)(value);
304
- this.emit('changeActiveCalls', this.state.activeCalls);
305
- }
306
- updateRoom(value) {
307
- const room = this.state.activeRooms[value.roomId];
308
- const newRoomData = Object.assign(Object.assign({}, room), value);
309
- this.state.activeRooms = Object.assign(Object.assign({}, this.state.activeRooms), { [value.roomId]: Object.assign({}, newRoomData) });
310
- this.emit('updateRoom', { room: newRoomData, roomList: this.state.activeRooms });
311
- }
312
- hasAutoAnswerHeaders(event) {
313
- const regex = /answer-after=0/;
314
- const request = event.request;
315
- const callInfoHeader = request.getHeader('Call-Info');
316
- return callInfoHeader && regex.test(callInfoHeader);
317
- }
318
- _addCall(value, emitEvent = true) {
319
- this.state.activeCalls = Object.assign(Object.assign({}, this.state.activeCalls), { [value._id]: (0, audio_helper_1.simplifyCallObject)(value) });
320
- /*this.state.extendedCalls = {
321
- ...this.state.extendedCalls,
322
- [value._id]: value
323
- }*/
324
- this.state.extendedCalls[value._id] = value;
325
- if (emitEvent) {
326
- this.emit('changeActiveCalls', this.state.activeCalls);
327
- }
328
- }
329
- _addCallStatus(callId) {
330
- this.state.callStatus = Object.assign(Object.assign({}, this.state.callStatus), { [callId]: {
331
- isMoving: false,
332
- isTransferring: false,
333
- isMerging: false
334
- } });
335
- this.emit('changeCallStatus', this.state.callStatus);
336
- }
337
- _updateCallStatus(value) {
338
- const prevStatus = Object.assign({}, this.state.callStatus[value.callId]);
339
- const newStatus = Object.assign({}, prevStatus);
340
- if (value.isMoving !== undefined) {
341
- newStatus.isMoving = value.isMoving;
342
- }
343
- if (value.isTransferring !== undefined) {
344
- newStatus.isTransferring = value.isTransferring;
345
- }
346
- if (value.isMerging !== undefined) {
347
- newStatus.isMerging = value.isMerging;
348
- }
349
- this.state.callStatus = Object.assign(Object.assign({}, this.state.callStatus), { [value.callId]: Object.assign({}, newStatus) });
350
- this.emit('changeCallStatus', this.state.callStatus);
351
- }
352
- _removeCallStatus(callId) {
353
- const callStatusCopy = Object.assign({}, this.state.callStatus);
354
- delete callStatusCopy[callId];
355
- this.state.callStatus = Object.assign({}, callStatusCopy);
356
- this.emit('changeCallStatus', this.state.callStatus);
357
- }
358
- _addRoom(value) {
359
- this.state.activeRooms = Object.assign(Object.assign({}, this.state.activeRooms), { [value.roomId]: value });
360
- this.emit('addRoom', { room: value, roomList: this.state.activeRooms });
361
- }
362
- setMicrophone(dId) {
363
- return __awaiter(this, void 0, void 0, function* () {
364
- if (!this.getInputDeviceList.find(({ deviceId }) => deviceId === dId)) {
365
- return;
366
- }
367
- this.selectedInputDevice = dId;
368
- let stream; // = null
369
- try {
370
- stream = yield navigator.mediaDevices.getUserMedia(this.getUserMediaConstraints);
371
- }
372
- catch (err) {
373
- console.error(err);
374
- }
375
- if (Object.keys(this.getActiveCalls).length === 0) {
376
- return;
377
- }
378
- const callsInCurrentRoom = Object.values(this.state.extendedCalls).filter(call => call.roomId === this.currentActiveRoomId);
379
- if (callsInCurrentRoom.length === 1) {
380
- Object.values(callsInCurrentRoom).forEach(call => {
381
- const processedStream = (0, audio_helper_1.processAudioVolume)(stream, this.microphoneInputLevel);
382
- processedStream.getTracks().forEach(track => track.enabled = !this.isMuted);
383
- this._setOriginalStream(processedStream);
384
- call.connection.getSenders()[0].replaceTrack(processedStream.getTracks()[0]);
385
- this.updateCall(call);
386
- });
387
- }
388
- else {
389
- yield this._doConference(callsInCurrentRoom);
390
- }
391
- });
392
- }
393
- _setOriginalStream(value) {
394
- this.state.originalStream = value;
395
- this.emit('changeOriginalStream', value);
396
- }
397
- setSpeaker(dId) {
398
- return __awaiter(this, void 0, void 0, function* () {
399
- if (!this.getOutputDeviceList.find(({ deviceId }) => deviceId === dId)) {
400
- return;
401
- }
402
- this.selectedOutputDevice = dId;
403
- const activeCallList = Object.values(this.state.extendedCalls);
404
- if (activeCallList.length === 0) {
405
- return;
406
- }
407
- const callsInCurrentRoom = activeCallList.filter(call => call.roomId === this.currentActiveRoomId);
408
- if (callsInCurrentRoom.length === 1) {
409
- activeCallList.forEach(call => {
410
- var _a;
411
- (_a = call.audioTag) === null || _a === void 0 ? void 0 : _a.setSinkId(dId);
412
- this.updateCall(call);
413
- });
414
- }
415
- else {
416
- yield this._doConference(callsInCurrentRoom);
417
- }
418
- });
419
- }
420
- removeRoom(roomId) {
421
- const activeRoomsCopy = Object.assign({}, this.state.activeRooms);
422
- const roomToRemove = Object.assign({}, activeRoomsCopy[roomId]);
423
- delete activeRoomsCopy[roomId];
424
- this.state.activeRooms = Object.assign({}, activeRoomsCopy);
425
- this.emit('removeRoom', { room: roomToRemove, roomList: this.state.activeRooms });
426
- }
427
- deleteRoomIfEmpty(roomId) {
428
- if (roomId === undefined) {
429
- return;
430
- }
431
- if (Object.values(this.state.extendedCalls).filter(call => call.roomId === roomId).length === 0) {
432
- this.removeRoom(roomId);
433
- if (this.currentActiveRoomId === roomId) {
434
- this.currentActiveRoomId = undefined;
435
- }
436
- }
437
- }
438
- checkInitialized() {
439
- if (!this.initialized) {
440
- throw new Error('[OpenSIPSJS] You must call `start` method first!');
441
- }
442
- }
443
- muteReconfigure(call) {
444
- if (this.state.isMuted) {
445
- call.mute({ audio: true });
446
- }
447
- else {
448
- call.unmute({ audio: true });
449
- }
450
- }
451
- roomReconfigure(roomId) {
452
- return __awaiter(this, void 0, void 0, function* () {
453
- if (roomId === undefined) {
454
- return;
455
- }
456
- const callsInRoom = Object.values(this.state.extendedCalls).filter(call => call.roomId === roomId);
457
- // Let`s take care on the audio output first and check if passed room is our selected room
458
- if (this.currentActiveRoomId === roomId) {
459
- callsInRoom.forEach(call => {
460
- if (call.audioTag) {
461
- this.muteReconfigure(call);
462
- call.audioTag.muted = false;
463
- this.updateCall(call);
464
- }
465
- });
466
- }
467
- else {
468
- callsInRoom.forEach(call => {
469
- if (call.audioTag) {
470
- call.audioTag.muted = true;
471
- this.updateCall(call);
472
- }
473
- });
474
- }
475
- // Now let`s configure the sound we are sending for each active call on this room
476
- if (callsInRoom.length === 0) {
477
- this.deleteRoomIfEmpty(roomId);
478
- }
479
- else if (callsInRoom.length === 1 && this.currentActiveRoomId !== roomId) {
480
- if (!callsInRoom[0].isOnHold().local) {
481
- this.doCallHold({ callId: callsInRoom[0].id, toHold: true, automatic: true });
482
- }
483
- }
484
- else if (callsInRoom.length === 1 && this.currentActiveRoomId === roomId) {
485
- if (callsInRoom[0].isOnHold().local && callsInRoom[0]._automaticHold) {
486
- this.doCallHold({ callId: callsInRoom[0].id, toHold: false });
487
- }
488
- let stream;
489
- try {
490
- stream = yield navigator.mediaDevices.getUserMedia(this.getUserMediaConstraints);
491
- }
492
- catch (err) {
493
- console.error(err);
494
- }
495
- if (stream && callsInRoom[0].connection && callsInRoom[0].connection.getSenders()[0]) {
496
- const processedStream = (0, audio_helper_1.processAudioVolume)(stream, this.microphoneInputLevel);
497
- processedStream.getTracks().forEach(track => track.enabled = !this.state.isMuted);
498
- this._setOriginalStream(processedStream);
499
- yield callsInRoom[0].connection.getSenders()[0].replaceTrack(processedStream.getTracks()[0]);
500
- this.muteReconfigure(callsInRoom[0]);
501
- }
502
- }
503
- else if (callsInRoom.length > 1) {
504
- yield this._doConference(callsInRoom);
505
- }
506
- });
507
- }
508
- _doConference(sessions) {
509
- return __awaiter(this, void 0, void 0, function* () {
510
- sessions.forEach(call => {
511
- if (call._localHold) {
512
- this.doCallHold({ callId: call._id, toHold: false });
513
- }
514
- });
515
- // Take all received tracks from the sessions you want to merge
516
- const receivedTracks = [];
517
- sessions.forEach(session => {
518
- if (session !== null && session !== undefined) {
519
- session.connection.getReceivers().forEach((receiver) => {
520
- receivedTracks.push(receiver.track);
521
- });
522
- }
523
- });
524
- // Use the Web Audio API to mix the received tracks
525
- const audioContext = new AudioContext();
526
- const allReceivedMediaStreams = new MediaStream();
527
- // For each call we will build dedicated mix for all other calls
528
- yield (0, p_iteration_1.forEach)(sessions, (session) => __awaiter(this, void 0, void 0, function* () {
529
- if (session === null || session === undefined) {
530
- return;
531
- }
532
- const mixedOutput = audioContext.createMediaStreamDestination();
533
- session.connection.getReceivers().forEach((receiver) => {
534
- receivedTracks.forEach(track => {
535
- allReceivedMediaStreams.addTrack(receiver.track);
536
- if (receiver.track.id !== track.id) {
537
- const sourceStream = audioContext.createMediaStreamSource(new MediaStream([track]));
538
- sourceStream.connect(mixedOutput);
539
- }
540
- });
541
- });
542
- if (sessions[0].roomId === this.currentActiveRoomId) {
543
- // Mixing your voice with all the received audio
544
- const stream = yield navigator.mediaDevices.getUserMedia(this.getUserMediaConstraints);
545
- const processedStream = (0, audio_helper_1.processAudioVolume)(stream, this.microphoneInputLevel);
546
- processedStream.getTracks().forEach(track => track.enabled = !this.isMuted);
547
- this._setOriginalStream(processedStream);
548
- const sourceStream = audioContext.createMediaStreamSource(processedStream);
549
- // stream.getTracks().forEach(track => track.enabled = !getters.isMuted) // TODO: Fix this
550
- sourceStream.connect(mixedOutput);
551
- }
552
- if (session.connection.getSenders()[0]) {
553
- //mixedOutput.stream.getTracks().forEach(track => track.enabled = !getters.isMuted) // Uncomment to mute all callers on mute
554
- yield session.connection.getSenders()[0].replaceTrack(mixedOutput.stream.getTracks()[0]);
555
- this._muteReconfigure(session);
556
- }
557
- }));
558
- });
559
- }
560
- _muteReconfigure(call) {
561
- if (this.isMuted) {
562
- call.mute({ audio: true });
563
- }
564
- else {
565
- call.unmute({ audio: true });
566
- }
567
- }
568
- muteCaller(callId, value) {
569
- const call = this.state.extendedCalls[callId];
570
- if (call && call.connection.getReceivers().length) {
571
- call.localMuted = value;
572
- call.connection.getReceivers().forEach((receiver) => {
573
- receiver.track.enabled = !value;
574
- });
575
- this.updateCall(call);
576
- this.roomReconfigure(call.roomId);
577
- }
578
- }
579
- callTerminate(callId) {
580
- const call = this.state.extendedCalls[callId];
581
- if (call._status !== 8) {
582
- call.terminate();
583
- }
584
- }
585
- callTransfer(callId, target) {
586
- if (target.toString().length === 0) {
587
- return console.error('Target must be passed');
588
- }
589
- const call = this.state.extendedCalls[callId];
590
- if (!call._is_confirmed && !call._is_canceled) {
591
- const redirectTarget = `sip:${target}@${this.sipDomain}`;
592
- call.terminate({
593
- status_code: 302,
594
- reason_phrase: 'Moved Temporarily',
595
- extraHeaders: [`Contact: ${redirectTarget}`]
596
- });
597
- return;
598
- }
599
- this._updateCallStatus({ callId, isTransferring: true });
600
- call.refer(`sip:${target}@${this.sipDomain}`);
601
- this.updateCall(call);
602
- }
603
- callMerge(roomId) {
604
- const callsInRoom = Object.values(this.state.extendedCalls).filter((call) => call.roomId === roomId);
605
- if (callsInRoom.length !== 2)
606
- return;
607
- const firstCall = callsInRoom[0];
608
- const secondCall = callsInRoom[1];
609
- if (!firstCall || !secondCall) {
610
- return;
611
- }
612
- // TODO: Check all call.id for working in the same way as call._id
613
- this._updateCallStatus({ callId: firstCall._id, isMerging: true });
614
- this._updateCallStatus({ callId: secondCall._id, isMerging: true });
615
- firstCall.refer(secondCall.remote_identity.uri.toString(), { 'replaces': secondCall });
616
- this.updateCall(firstCall);
617
- }
618
- // TODO: Use this method in demo
619
- setDND(value) {
620
- this.isDND = value;
621
- }
622
- _startCallTimer(callId) {
623
- const timeData = {
624
- callId,
625
- hours: 0,
626
- minutes: 0,
627
- seconds: 0,
628
- formatted: ''
629
- };
630
- this.setCallTime(timeData);
631
- const interval = setInterval(() => {
632
- const callTime = Object.assign({}, this.state.callTime[callId]);
633
- const updatedTime = (0, time_helper_1.setupTime)(callTime);
634
- this.setCallTime(Object.assign({ callId }, updatedTime));
635
- }, 1000);
636
- this.setTimeInterval(callId, interval);
637
- }
638
- setCurrentActiveRoomId(roomId) {
639
- return __awaiter(this, void 0, void 0, function* () {
640
- const oldRoomId = this.currentActiveRoomId;
641
- if (roomId === oldRoomId) {
642
- return;
643
- }
644
- this.currentActiveRoomId = roomId;
645
- yield this.roomReconfigure(oldRoomId);
646
- yield this.roomReconfigure(roomId);
647
- });
648
- }
649
- getNewRoomId() {
650
- const roomIdList = Object.keys(this.state.activeRooms);
651
- if (roomIdList.length === 0) {
652
- return 1;
653
- }
654
- return (parseInt(roomIdList.sort()[roomIdList.length - 1]) + 1);
655
- }
656
- subscribe(type, listener) {
657
- const isListenerEmpty = !this.state.listeners[type] || !this.state.listeners[type].length;
658
- const newListeners = isListenerEmpty ? [listener] : [...this.state.listeners[type], listener];
659
- this.state.listeners = Object.assign(Object.assign({}, this.state.listeners), { [type]: newListeners });
660
- }
661
- removeIListener(value) {
662
- const listenersCopy = Object.assign({}, this.state.listeners);
663
- delete listenersCopy[value];
664
- this.state.listeners = Object.assign({}, listenersCopy);
665
- }
666
- addCall(event) {
667
- return __awaiter(this, void 0, void 0, function* () {
668
- const session = event.session;
669
- const sessionAlreadyInActiveCalls = this.getActiveCalls[session.id];
670
- if (sessionAlreadyInActiveCalls !== undefined) {
671
- return;
672
- }
673
- const roomId = this.getNewRoomId();
674
- const newRoomInfo = {
675
- started: new Date(),
676
- incomingInProgress: false,
677
- roomId
678
- };
679
- if (session.direction === 'incoming') {
680
- newRoomInfo.incomingInProgress = true;
681
- this.subscribe(call_event_listener_type_1.CALL_EVENT_LISTENER_TYPE.CALL_CONFIRMED, (call) => {
682
- if (session.id === call.id) {
683
- this.updateRoom({
684
- incomingInProgress: false,
685
- roomId
686
- });
687
- this._startCallTimer(session.id);
688
- }
689
- });
690
- this.subscribe(call_event_listener_type_1.CALL_EVENT_LISTENER_TYPE.CALL_FAILED, (call) => {
691
- if (session.id === call.id) {
692
- this.updateRoom({
693
- incomingInProgress: false,
694
- roomId
695
- });
696
- this.deleteRoomIfEmpty(roomId);
697
- }
698
- });
699
- }
700
- else if (session.direction === 'outgoing') {
701
- this._startCallTimer(session.id);
702
- }
703
- const call = session;
704
- const autoAnswerByHeaders = this.hasAutoAnswerHeaders(event);
705
- const doAutoAnswer = call.direction === 'incoming' && !this.hasActiveCalls && (autoAnswerByHeaders || this.autoAnswer);
706
- call.roomId = roomId;
707
- call.localMuted = false;
708
- call.autoAnswer = doAutoAnswer;
709
- if (doAutoAnswer) {
710
- this._addCall(call, false);
711
- }
712
- else {
713
- this._addCall(call);
714
- }
715
- // this._addCall(call)
716
- this._addCallStatus(session.id);
717
- this._addRoom(newRoomInfo);
718
- if (doAutoAnswer) {
719
- this.callAnswer(call._id);
720
- }
721
- });
722
- }
723
- _triggerListener({ listenerType, session, event }) {
724
- const listeners = this.state.listeners[listenerType];
725
- if (!listeners || !listeners.length) {
726
- return;
727
- }
728
- listeners.forEach((listener) => {
729
- listener(session, event);
730
- });
731
- }
732
- _removeCall(value) {
733
- const stateActiveCallsCopy = Object.assign({}, this.state.activeCalls);
734
- delete stateActiveCallsCopy[value];
735
- // delete activeCalls[value]
736
- this.state.activeCalls = Object.assign({}, stateActiveCallsCopy);
737
- const stateExtendedCallsCopy = Object.assign({}, this.state.extendedCalls);
738
- delete stateExtendedCallsCopy[value];
739
- this.state.extendedCalls = Object.assign({}, stateExtendedCallsCopy);
740
- this.emit('changeActiveCalls', this.state.activeCalls);
741
- }
742
- _activeCallListRemove(call) {
743
- const callRoomIdToConfigure = this.state.extendedCalls[call._id].roomId;
744
- this._removeCall(call._id);
745
- this.roomReconfigure(callRoomIdToConfigure);
746
- }
747
- newRTCSessionCallback(event) {
748
- const session = event.session;
749
- if (this.isDND) {
750
- session.terminate({ status_code: 486, reason_phrase: 'Do Not Disturb' });
751
- return;
752
- }
753
- // stop timers on ended and failed
754
- session.on('ended', (event) => {
755
- this._triggerListener({ listenerType: call_event_listener_type_1.CALL_EVENT_LISTENER_TYPE.CALL_ENDED, session, event });
756
- const s = this.getActiveCalls[session.id];
757
- if (s) {
758
- this._activeCallListRemove(s);
759
- }
760
- this._stopCallTimer(session.id);
761
- this._removeCallStatus(session.id);
762
- this._removeCallMetrics(session.id);
763
- if (!Object.keys(this.state.extendedCalls).length) {
764
- this.isMuted = false;
765
- }
766
- });
767
- session.on('progress', (event) => {
768
- this._triggerListener({ listenerType: call_event_listener_type_1.CALL_EVENT_LISTENER_TYPE.CALL_PROGRESS, session, event });
769
- });
770
- session.on('failed', (event) => {
771
- this._triggerListener({ listenerType: call_event_listener_type_1.CALL_EVENT_LISTENER_TYPE.CALL_FAILED, session, event });
772
- if (session.id === this.callAddingInProgress) {
773
- this.callAddingInProgress = undefined;
774
- }
775
- const s = this.getActiveCalls[session.id];
776
- if (s) {
777
- this._activeCallListRemove(s);
778
- }
779
- this._stopCallTimer(session.id);
780
- this._removeCallStatus(session.id);
781
- this._removeCallMetrics(session.id);
782
- if (!Object.keys(this.state.extendedCalls).length) {
783
- this.isMuted = false;
784
- }
785
- });
786
- session.on('confirmed', (event) => {
787
- this._triggerListener({ listenerType: call_event_listener_type_1.CALL_EVENT_LISTENER_TYPE.CALL_CONFIRMED, session, event });
788
- this.updateCall(session);
789
- if (session.id === this.callAddingInProgress) {
790
- this.callAddingInProgress = undefined;
791
- }
792
- });
793
- this.addCall(event);
794
- if (session.direction === 'outgoing') {
795
- const roomId = this.getActiveCalls[session.id].roomId;
796
- this.setCurrentActiveRoomId(roomId);
797
- }
798
- }
799
- setInitialized(value) {
800
- this.initialized = value;
801
- this.emit('ready', value);
802
- }
803
- start() {
804
- this.on(this.registeredEventName, () => {
805
- this.setInitialized(true);
806
- });
807
- this.on(this.unregisteredEventName, () => {
808
- this.setInitialized(false);
809
- });
810
- this.on(this.newRTCSessionEventName, this.newRTCSessionCallback.bind(this));
811
- super.start();
812
- this.setMediaDevices(true);
813
- return this;
814
- }
815
- setMuteWhenJoin(value) {
816
- this.muteWhenJoin = value;
817
- }
818
- _setCallMetrics(value) {
819
- const metrics = Object.assign({}, value);
820
- delete metrics['callId'];
821
- this.state.callMetrics = Object.assign(Object.assign({}, this.state.callMetrics), { [value.callId]: metrics });
822
- }
823
- _removeCallMetrics(callId) {
824
- const callMetricsCopy = Object.assign({}, this.state.callMetrics);
825
- delete callMetricsCopy[callId];
826
- this.state.callMetrics = Object.assign({}, callMetricsCopy);
827
- }
828
- _getCallQuality(call) {
829
- const metrics = new metrics_1.default(this.state.metricConfig);
830
- const probe = metrics.createProbe(call.connection, {
831
- cid: call._id
832
- });
833
- const inboundKeys = [];
834
- let inboundAudio;
835
- probe.onreport = (probe) => {
836
- //console.log('probe', probe)
837
- /*const inboundMetrics = Object.entries(probe.audio).filter(([ key, value ]) => {
838
- return value.direction === 'inbound'
839
- })*/
840
- //const ioo = Object.entries(probe.audio).
841
- Object.entries(probe.audio).forEach(([key, value]) => {
842
- if (value.direction === 'inbound' && !inboundKeys.includes(key)) {
843
- inboundKeys.push(key);
844
- inboundAudio = key;
845
- }
846
- });
847
- /*inboundMetrics.forEach(([ key, value ]) => {
848
- if (!inboundKeys.includes(key)) {
849
- inboundKeys.push(key)
850
- inboundAudio = key
851
- }
852
- })*/
853
- const inboundAudioMetric = probe.audio[inboundAudio];
854
- const metric = (0, filter_helper_1.filterObjectKeys)(inboundAudioMetric, metric_keys_to_include_1.METRIC_KEYS_TO_INCLUDE);
855
- metric.callId = call._id;
856
- this._setCallMetrics(metrics);
857
- };
858
- this.subscribe(call_event_listener_type_1.CALL_EVENT_LISTENER_TYPE.CALL_ENDED, (session) => {
859
- if (session._id === call._id) {
860
- metrics.stopAllProbes();
861
- }
862
- });
863
- metrics.startAllProbes();
864
- }
865
- _triggerAddStream(event, call) {
866
- return __awaiter(this, void 0, void 0, function* () {
867
- this.isMuted = this.muteWhenJoin;
868
- const stream = yield navigator.mediaDevices.getUserMedia(this.getUserMediaConstraints);
869
- const processedStream = (0, audio_helper_1.processAudioVolume)(stream, this.microphoneInputLevel);
870
- const muteMicro = this.isMuted || this.muteWhenJoin;
871
- processedStream.getTracks().forEach(track => track.enabled = !muteMicro);
872
- this._setOriginalStream(processedStream);
873
- yield call.connection.getSenders()[0].replaceTrack(processedStream.getTracks()[0]);
874
- (0, audio_helper_1.syncStream)(event, call, this.selectedOutputDevice, this.speakerVolume);
875
- this._getCallQuality(call);
876
- this.updateCall(call);
877
- });
878
- }
879
- doCall({ target, addToCurrentRoom }) {
880
- this.checkInitialized();
881
- if (target.length === 0) {
882
- return console.error('Target must be a valid string');
883
- }
884
- const call = this.call(`sip:${target}@${this.sipDomain}`, this.sipOptions);
885
- this.callAddingInProgress = call.id;
886
- if (addToCurrentRoom && this.currentActiveRoomId !== undefined) {
887
- this.callChangeRoom({
888
- callId: call.id,
889
- roomId: this.currentActiveRoomId
890
- });
891
- }
892
- call.connection.addEventListener('addstream', (event) => {
893
- this._triggerAddStream(event, call);
894
- });
895
- }
896
- callChangeRoom({ callId, roomId }) {
897
- return __awaiter(this, void 0, void 0, function* () {
898
- const oldRoomId = this.state.extendedCalls[callId].roomId;
899
- this.state.extendedCalls[callId].roomId = roomId;
900
- yield this.setCurrentActiveRoomId(roomId);
901
- return Promise.all([
902
- this.roomReconfigure(oldRoomId),
903
- this.roomReconfigure(roomId)
904
- ]).then(() => {
905
- this.deleteRoomIfEmpty(oldRoomId);
906
- this.deleteRoomIfEmpty(roomId);
907
- });
908
- });
909
- }
910
- }
911
- exports.default = OpenSIPSJS;