@wazo/sdk 0.37.0 → 0.37.4
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 +91 -23
- package/esm/__tests__/web-rtc-client.test.js +165 -56
- package/esm/api/agentd.js +7 -1
- package/esm/api/amid.js +7 -1
- package/esm/api/application.js +7 -1
- package/esm/api/auth.js +7 -1
- package/esm/api/call-logd.js +17 -23
- package/esm/api/calld.js +10 -18
- package/esm/api/chatd.js +7 -1
- package/esm/api/confd.js +78 -1
- package/esm/api/ctid-ng.js +7 -1
- package/esm/api/dird.js +7 -1
- package/esm/api/webhookd.js +7 -1
- package/esm/api-client.js +91 -23
- package/esm/checker/Checker.js +169 -56
- package/esm/checker/checks/aor.js +91 -23
- package/esm/checker/checks/api.js +91 -23
- package/esm/checker/checks/index.js +169 -56
- package/esm/checker/checks/wazo-websocket.js +11 -1
- package/esm/checker/checks/webrtc-transport.js +165 -56
- package/esm/checker/checks/webrtc.js +165 -56
- package/esm/domain/AdHocAPIConference.js +1722 -1654
- package/esm/domain/CallLog.js +10 -22
- package/esm/domain/CallSession.js +1 -18
- package/esm/domain/Features.js +91 -23
- package/esm/domain/IndirectTransfer.js +0 -17
- package/esm/domain/Meeting.js +71 -0
- package/esm/domain/Phone/CTIPhone.js +98 -26
- package/esm/domain/Phone/Phone.js +0 -17
- package/esm/domain/Phone/WebRTCPhone.js +47 -27
- package/esm/domain/Room.js +0 -17
- package/esm/domain/SwitchboardCall.js +0 -17
- package/esm/domain/__tests__/CallLog.test.js +10 -22
- package/esm/domain/__tests__/CallSession.test.js +1 -18
- package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/esm/domain/__tests__/Room.test.js +1 -18
- package/esm/index.js +3880 -3111
- package/esm/lib/WazoSessionDescriptionHandler.js +24 -10
- package/esm/service/CallApi.js +91 -23
- package/esm/service/IssueReporter.js +7 -1
- package/esm/service/__tests__/IssueReporter.test.js +9 -1
- package/esm/service/getApiClient.js +91 -23
- package/esm/simple/Auth.js +1126 -360
- package/esm/simple/Configuration.js +1126 -360
- package/esm/simple/Directory.js +91 -23
- package/esm/simple/Phone.js +3724 -2958
- package/esm/simple/Websocket.js +13 -1
- package/esm/simple/index.js +1128 -362
- package/esm/simple/room/LocalParticipant.js +1097 -331
- package/esm/simple/room/Participant.js +1097 -331
- package/esm/simple/room/RemoteParticipant.js +1097 -331
- package/esm/simple/room/Room.js +1097 -331
- package/esm/simple/room/SipRoom.js +12996 -0
- package/esm/simple/room/Stream.js +1128 -362
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
- package/esm/simple/utils.js +1128 -362
- package/esm/utils/__tests__/api-requester.test.js +7 -1
- package/esm/utils/api-requester.js +7 -1
- package/esm/web-rtc-client.js +165 -56
- package/esm/websocket-client.js +12 -2
- package/lib/__tests__/api-client.test.js +91 -23
- package/lib/__tests__/web-rtc-client.test.js +165 -56
- package/lib/api/agentd.js +7 -1
- package/lib/api/amid.js +7 -1
- package/lib/api/application.js +7 -1
- package/lib/api/auth.js +7 -1
- package/lib/api/call-logd.js +17 -23
- package/lib/api/calld.js +10 -18
- package/lib/api/chatd.js +7 -1
- package/lib/api/confd.js +78 -1
- package/lib/api/ctid-ng.js +7 -1
- package/lib/api/dird.js +7 -1
- package/lib/api/webhookd.js +7 -1
- package/lib/api-client.js +91 -23
- package/lib/checker/Checker.js +169 -56
- package/lib/checker/checks/aor.js +91 -23
- package/lib/checker/checks/api.js +91 -23
- package/lib/checker/checks/index.js +169 -56
- package/lib/checker/checks/wazo-websocket.js +11 -1
- package/lib/checker/checks/webrtc-transport.js +165 -56
- package/lib/checker/checks/webrtc.js +165 -56
- package/lib/domain/AdHocAPIConference.js +1722 -1654
- package/lib/domain/CallLog.js +10 -22
- package/lib/domain/CallSession.js +1 -18
- package/lib/domain/Features.js +91 -23
- package/lib/domain/IndirectTransfer.js +0 -17
- package/lib/domain/Meeting.js +73 -0
- package/lib/domain/Phone/CTIPhone.js +98 -26
- package/lib/domain/Phone/Phone.js +0 -16
- package/lib/domain/Phone/WebRTCPhone.js +47 -27
- package/lib/domain/Room.js +0 -17
- package/lib/domain/SwitchboardCall.js +0 -17
- package/lib/domain/__tests__/CallLog.test.js +10 -22
- package/lib/domain/__tests__/CallSession.test.js +1 -18
- package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/lib/domain/__tests__/Room.test.js +1 -18
- package/lib/index.js +3880 -3111
- package/lib/lib/WazoSessionDescriptionHandler.js +24 -10
- package/lib/service/CallApi.js +91 -23
- package/lib/service/IssueReporter.js +7 -1
- package/lib/service/__tests__/IssueReporter.test.js +9 -1
- package/lib/service/getApiClient.js +91 -23
- package/lib/simple/Auth.js +1126 -360
- package/lib/simple/Configuration.js +1126 -360
- package/lib/simple/Directory.js +91 -23
- package/lib/simple/Phone.js +3724 -2958
- package/lib/simple/Websocket.js +13 -1
- package/lib/simple/index.js +1128 -362
- package/lib/simple/room/LocalParticipant.js +1097 -331
- package/lib/simple/room/Participant.js +1097 -331
- package/lib/simple/room/RemoteParticipant.js +1097 -331
- package/lib/simple/room/Room.js +1097 -331
- package/lib/simple/room/SipRoom.js +13006 -0
- package/lib/simple/room/Stream.js +1128 -362
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
- package/lib/simple/utils.js +1128 -362
- package/lib/utils/__tests__/api-requester.test.js +7 -1
- package/lib/utils/api-requester.js +7 -1
- package/lib/web-rtc-client.js +165 -56
- package/lib/websocket-client.js +13 -1
- package/package.json +1 -1
- package/src/api/calld.js +3 -0
- package/src/api/confd.js +13 -0
- package/src/domain/CallLog.js +10 -22
- package/src/domain/CallSession.js +1 -2
- package/src/domain/Meeting.js +59 -0
- package/src/domain/Phone/CTIPhone.js +6 -2
- package/src/domain/Phone/Phone.js +2 -0
- package/src/domain/Phone/WebRTCPhone.js +22 -8
- package/src/index.js +6 -0
- package/src/lib/WazoSessionDescriptionHandler.js +17 -9
- package/src/service/IssueReporter.js +7 -1
- package/src/service/__tests__/IssueReporter.test.js +2 -0
- package/src/simple/Phone.js +13 -4
- package/src/simple/index.js +8 -0
- package/src/simple/room/Participant.js +7 -0
- package/src/simple/room/Room.js +157 -79
- package/src/simple/room/SipRoom.js +147 -0
- package/src/simple/room/Stream.js +1 -3
- package/src/simple/room/__tests__/RemoteParticipant.test.js +3 -2
- package/src/types/WebSocketMessage.js +21 -0
- package/src/web-rtc-client.js +57 -24
- package/src/websocket-client.js +4 -0
package/src/simple/room/Room.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* global document */
|
|
2
1
|
// @flow
|
|
3
2
|
import type { Message } from 'sip.js/lib/api/message';
|
|
4
3
|
import sdpParser from 'sdp-transform';
|
|
@@ -10,6 +9,7 @@ import Wazo from '../index';
|
|
|
10
9
|
import Participant from './Participant';
|
|
11
10
|
import RemoteParticipant from './RemoteParticipant';
|
|
12
11
|
import IssueReporter from '../../service/IssueReporter';
|
|
12
|
+
import LocalParticipant from './LocalParticipant';
|
|
13
13
|
|
|
14
14
|
export const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
|
|
15
15
|
export const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
|
|
@@ -21,6 +21,7 @@ class Room extends Emitter {
|
|
|
21
21
|
name: string;
|
|
22
22
|
extension: string;
|
|
23
23
|
sourceId: ?number;
|
|
24
|
+
meetingUuid: ?string;
|
|
24
25
|
participants: Participant[];
|
|
25
26
|
callId: ?string;
|
|
26
27
|
connected: boolean;
|
|
@@ -42,6 +43,8 @@ class Room extends Emitter {
|
|
|
42
43
|
|
|
43
44
|
CONFERENCE_USER_PARTICIPANT_JOINED: string;
|
|
44
45
|
CONFERENCE_USER_PARTICIPANT_LEFT: string;
|
|
46
|
+
MEETING_USER_PARTICIPANT_JOINED: string;
|
|
47
|
+
MEETING_USER_PARTICIPANT_LEFT: string;
|
|
45
48
|
ON_SHARE_SCREEN_ENDED: string;
|
|
46
49
|
ON_MESSAGE: string;
|
|
47
50
|
ON_CHAT: string;
|
|
@@ -59,6 +62,7 @@ class Room extends Emitter {
|
|
|
59
62
|
* @param extension string
|
|
60
63
|
* @param sourceId number
|
|
61
64
|
* @param callId string
|
|
65
|
+
* @param meetingUuid string
|
|
62
66
|
* @param extra Object
|
|
63
67
|
*/
|
|
64
68
|
constructor(
|
|
@@ -66,15 +70,17 @@ class Room extends Emitter {
|
|
|
66
70
|
extension: string,
|
|
67
71
|
sourceId: ?number,
|
|
68
72
|
callId: ?string,
|
|
73
|
+
meetingUuid: ?string,
|
|
69
74
|
extra: Object = {},
|
|
70
75
|
) {
|
|
71
76
|
super();
|
|
72
|
-
logger.info('room initialized', { callId, extension, sourceId });
|
|
77
|
+
logger.info('room initialized', { callId, extension, sourceId, meetingUuid });
|
|
73
78
|
|
|
74
79
|
// Represents the room callSession
|
|
75
80
|
this.callSession = callSession;
|
|
76
81
|
this.extension = extension;
|
|
77
82
|
this.sourceId = sourceId;
|
|
83
|
+
this.meetingUuid = meetingUuid;
|
|
78
84
|
this.callId = callId;
|
|
79
85
|
this.participants = [];
|
|
80
86
|
this.connected = false;
|
|
@@ -94,6 +100,8 @@ class Room extends Emitter {
|
|
|
94
100
|
// Sugar syntax for `room.EVENT_NAME`
|
|
95
101
|
this.CONFERENCE_USER_PARTICIPANT_JOINED = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_JOINED;
|
|
96
102
|
this.CONFERENCE_USER_PARTICIPANT_LEFT = Wazo.Websocket.CONFERENCE_USER_PARTICIPANT_LEFT;
|
|
103
|
+
this.MEETING_USER_PARTICIPANT_JOINED = Wazo.Websocket.MEETING_USER_PARTICIPANT_JOINED;
|
|
104
|
+
this.MEETING_USER_PARTICIPANT_LEFT = Wazo.Websocket.MEETING_USER_PARTICIPANT_LEFT;
|
|
97
105
|
this.ON_SHARE_SCREEN_ENDED = Wazo.Phone.ON_SHARE_SCREEN_ENDED;
|
|
98
106
|
this.ON_MESSAGE = Wazo.Phone.ON_MESSAGE;
|
|
99
107
|
this.ON_CHAT = Wazo.Phone.ON_CHAT;
|
|
@@ -128,9 +136,10 @@ class Room extends Emitter {
|
|
|
128
136
|
* @param audioOnly boolean
|
|
129
137
|
* @param extra Object
|
|
130
138
|
* @param room ?Room
|
|
139
|
+
* @param meeting ?Meeting
|
|
131
140
|
* @returns {Promise<Room>}
|
|
132
141
|
*/
|
|
133
|
-
static async connect({ extension, constraints, audioOnly = false, extra, room }: Object) {
|
|
142
|
+
static async connect({ extension, constraints, audioOnly = false, extra, room, meeting }: Object) {
|
|
134
143
|
logger.info('connecting to room', { extension, audioOnly, room: !!room });
|
|
135
144
|
|
|
136
145
|
if (!room) {
|
|
@@ -165,21 +174,31 @@ class Room extends Emitter {
|
|
|
165
174
|
room.setCallId(room.callSession.call.id);
|
|
166
175
|
}
|
|
167
176
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
177
|
+
if (!meeting) {
|
|
178
|
+
// Fetch conference source
|
|
179
|
+
const sources = await getApiClient().dird.fetchConferenceSource('default');
|
|
180
|
+
// Retrieve conference sources
|
|
181
|
+
const contacts = await getApiClient().dird.fetchConferenceContacts(sources.items[0]);
|
|
182
|
+
// Retrieve conference
|
|
183
|
+
const conference = contacts.find(contact => contact.numbers.find(number => number.number === extension));
|
|
174
184
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
logger.info('connected to room', {
|
|
186
|
+
sourceId: conference ? conference.sourceId : null,
|
|
187
|
+
name: conference ? conference.name : null,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
if (conference) {
|
|
191
|
+
room.setSourceId(conference.sourceId);
|
|
192
|
+
room.setName(conference.name);
|
|
193
|
+
}
|
|
194
|
+
} else if (meeting) {
|
|
195
|
+
logger.info('Already connected to meeting', {
|
|
196
|
+
uuid: meeting.uuid,
|
|
197
|
+
name: meeting.name,
|
|
198
|
+
});
|
|
179
199
|
|
|
180
|
-
|
|
181
|
-
room.
|
|
182
|
-
room.setName(conference.name);
|
|
200
|
+
room.setMeetingUuid(meeting.uuid);
|
|
201
|
+
room.setName(meeting.name);
|
|
183
202
|
}
|
|
184
203
|
|
|
185
204
|
return room;
|
|
@@ -207,10 +226,8 @@ class Room extends Emitter {
|
|
|
207
226
|
Wazo.Phone.phone.off(Wazo.Phone.phone.client.ON_REINVITE, this._boundOnReinvite);
|
|
208
227
|
Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
|
|
209
228
|
Wazo.Websocket.off(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
document.body.removeChild(this.roomAudioElement);
|
|
213
|
-
}
|
|
229
|
+
Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
|
|
230
|
+
Wazo.Websocket.off(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
|
|
214
231
|
}
|
|
215
232
|
|
|
216
233
|
setSourceId(sourceId: number) {
|
|
@@ -219,6 +236,12 @@ class Room extends Emitter {
|
|
|
219
236
|
this.sourceId = sourceId;
|
|
220
237
|
}
|
|
221
238
|
|
|
239
|
+
setMeetingUuid(meetingUuid: string) {
|
|
240
|
+
logger.info('set meeting uuid', { meetingUuid });
|
|
241
|
+
|
|
242
|
+
this.meetingUuid = meetingUuid;
|
|
243
|
+
}
|
|
244
|
+
|
|
222
245
|
setCallId(callId: string) {
|
|
223
246
|
logger.info('set room call id', { callId });
|
|
224
247
|
|
|
@@ -260,14 +283,22 @@ class Room extends Emitter {
|
|
|
260
283
|
return screensharingStream;
|
|
261
284
|
}
|
|
262
285
|
|
|
263
|
-
stopScreenSharing(restoreLocalStream: boolean = true) {
|
|
286
|
+
async stopScreenSharing(restoreLocalStream: boolean = true) {
|
|
264
287
|
logger.info('stop room screen sharing');
|
|
265
288
|
|
|
266
|
-
Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
|
|
289
|
+
const reinvited = await Wazo.Phone.stopScreenSharing(this.callSession, restoreLocalStream);
|
|
267
290
|
|
|
268
291
|
if (this.localParticipant) {
|
|
269
292
|
this.localParticipant.onStopScreensharing();
|
|
270
293
|
}
|
|
294
|
+
|
|
295
|
+
if (!reinvited && this.localParticipant) {
|
|
296
|
+
// When we had video and we made a screenshare we don't reinvite when stopping the screensahre
|
|
297
|
+
// So not REINVITE even is fired, we have to restore the video stream manually
|
|
298
|
+
const localVideoStream = Wazo.Phone.getLocalVideoStream(this.callSession);
|
|
299
|
+
// $FlowFixMe
|
|
300
|
+
this._associateStreamTo(localVideoStream, this.localParticipant);
|
|
301
|
+
}
|
|
271
302
|
}
|
|
272
303
|
|
|
273
304
|
turnCameraOff() {
|
|
@@ -370,6 +401,22 @@ class Room extends Emitter {
|
|
|
370
401
|
return response;
|
|
371
402
|
}
|
|
372
403
|
|
|
404
|
+
hasALocalVideoTrack() {
|
|
405
|
+
return Wazo.Phone.hasALocalVideoTrack(this.callSession);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
getLocalStream() {
|
|
409
|
+
return Wazo.Phone.getLocalStream(this.callSession);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
getRemoteStream() {
|
|
413
|
+
return Wazo.Phone.getRemoteStream(this.callSession);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
getRemoteVideoStream() {
|
|
417
|
+
return Wazo.Phone.getRemoteVideoStream(this.callSession);
|
|
418
|
+
}
|
|
419
|
+
|
|
373
420
|
_bindEvents() {
|
|
374
421
|
if (!Wazo.Phone.phone || !Wazo.Phone.phone.currentSipSession) {
|
|
375
422
|
return;
|
|
@@ -391,27 +438,10 @@ class Room extends Emitter {
|
|
|
391
438
|
logger.info('on room audio stream');
|
|
392
439
|
|
|
393
440
|
this.audioStream = stream;
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (!this.roomAudioElement) {
|
|
398
|
-
roomAudioElement = document.createElement('audio');
|
|
399
|
-
// $FlowFixMe
|
|
400
|
-
document.body.appendChild(roomAudioElement);
|
|
401
|
-
}
|
|
402
|
-
if (!roomAudioElement) {
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
this.roomAudioElement = roomAudioElement;
|
|
441
|
+
if (!this.roomAudioElement) {
|
|
442
|
+
const sessionId = Wazo.Phone.phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
|
|
443
|
+
this.roomAudioElement = Wazo.Phone.phone.createAudioElementFor(sessionId);
|
|
406
444
|
this.roomAudioElement.srcObject = stream;
|
|
407
|
-
this.roomAudioElement.autoplay = true;
|
|
408
|
-
this.roomAudioElement.id = 'audio-room';
|
|
409
|
-
|
|
410
|
-
// $FlowFixMe
|
|
411
|
-
if (this.roomAudioElement.setSinkId) {
|
|
412
|
-
// $FlowFixMe
|
|
413
|
-
this.roomAudioElement.setSinkId(Wazo.Phone.getOutputDevice());
|
|
414
|
-
}
|
|
415
445
|
}
|
|
416
446
|
});
|
|
417
447
|
|
|
@@ -486,6 +516,9 @@ class Room extends Emitter {
|
|
|
486
516
|
Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
|
|
487
517
|
Wazo.Websocket.on(this.CONFERENCE_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
|
|
488
518
|
|
|
519
|
+
Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_JOINED, this._boundOnParticipantJoined);
|
|
520
|
+
Wazo.Websocket.on(this.MEETING_USER_PARTICIPANT_LEFT, this._boundOnParticipantLeft);
|
|
521
|
+
|
|
489
522
|
// Phone events
|
|
490
523
|
Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
|
|
491
524
|
Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
|
|
@@ -496,15 +529,15 @@ class Room extends Emitter {
|
|
|
496
529
|
Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
|
|
497
530
|
}
|
|
498
531
|
|
|
499
|
-
_onMessage(message: Message) {
|
|
532
|
+
_onMessage(message: Message): ?Object {
|
|
500
533
|
if (message.method !== 'MESSAGE') {
|
|
501
|
-
return;
|
|
534
|
+
return null;
|
|
502
535
|
}
|
|
503
536
|
let body;
|
|
504
537
|
try {
|
|
505
538
|
body = JSON.parse(message.body);
|
|
506
539
|
} catch (e) {
|
|
507
|
-
return;
|
|
540
|
+
return null;
|
|
508
541
|
}
|
|
509
542
|
|
|
510
543
|
switch (body.type) {
|
|
@@ -525,6 +558,8 @@ class Room extends Emitter {
|
|
|
525
558
|
}
|
|
526
559
|
|
|
527
560
|
this.eventEmitter.emit(this.ON_MESSAGE, body);
|
|
561
|
+
|
|
562
|
+
return body;
|
|
528
563
|
}
|
|
529
564
|
|
|
530
565
|
_onChat(content: Object) {
|
|
@@ -589,23 +624,24 @@ class Room extends Emitter {
|
|
|
589
624
|
const session = Wazo.Auth.getSession();
|
|
590
625
|
let participants = [];
|
|
591
626
|
|
|
592
|
-
// @TODO: we could use a better function name here
|
|
593
|
-
const isJoining = part => {
|
|
594
|
-
this.__associateStreams(part);
|
|
595
|
-
// @VALIDATE: no need to publicize ourselves, no?
|
|
596
|
-
if (part instanceof RemoteParticipant) {
|
|
597
|
-
this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, part);
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
|
-
|
|
601
627
|
// When we join the room, we can call `getConferenceParticipantsAsUser`, not before.
|
|
602
628
|
if (participant.user_uuid === session.uuid) {
|
|
603
629
|
logger.info('room current user joined');
|
|
604
630
|
|
|
605
631
|
// Retrieve participants via an API calls
|
|
606
632
|
const conferenceId = this.sourceId || payload.data.conference_id;
|
|
607
|
-
|
|
608
|
-
|
|
633
|
+
let response;
|
|
634
|
+
try {
|
|
635
|
+
if (this.meetingUuid) {
|
|
636
|
+
logger.info('fetching meeting participants', { meetingUuid: this.meetingUuid });
|
|
637
|
+
response = await getApiClient().calld.getMeetingParticipantsAsUser(this.meetingUuid);
|
|
638
|
+
} else {
|
|
639
|
+
logger.info('fetching conference participants', { conferenceId });
|
|
640
|
+
response = await getApiClient().calld.getConferenceParticipantsAsUser(conferenceId);
|
|
641
|
+
}
|
|
642
|
+
} catch (e) {
|
|
643
|
+
logger.error('room participants fetching, error', e);
|
|
644
|
+
}
|
|
609
645
|
if (response) {
|
|
610
646
|
logger.info('conference participants fetched', { nb: response.items.length });
|
|
611
647
|
participants = response.items.map(item => {
|
|
@@ -620,25 +656,10 @@ class Room extends Emitter {
|
|
|
620
656
|
|
|
621
657
|
const localParticipant = participants.find(someParticipant => someParticipant instanceof Wazo.LocalParticipant);
|
|
622
658
|
if (!this.localParticipant && localParticipant) {
|
|
623
|
-
this.localParticipant
|
|
624
|
-
|
|
625
|
-
const localVideoStream = this._getLocalVideoStream();
|
|
626
|
-
if (localVideoStream) {
|
|
627
|
-
this._saveLocalVideoStream(localVideoStream);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
this.connected = true;
|
|
631
|
-
|
|
632
|
-
// we're in the room, now let's request everyone's status
|
|
633
|
-
if (this.localParticipant) {
|
|
634
|
-
this.sendSignal({
|
|
635
|
-
type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
|
|
636
|
-
origin: this.localParticipant.getStatus(),
|
|
637
|
-
});
|
|
638
|
-
}
|
|
659
|
+
this._onLocalParticipantJoined(localParticipant);
|
|
639
660
|
}
|
|
640
661
|
|
|
641
|
-
participants.forEach(someParticipant =>
|
|
662
|
+
participants.forEach(someParticipant => this._isParticipantJoining(someParticipant));
|
|
642
663
|
this.eventEmitter.emit(this.ON_JOINED, localParticipant, participants);
|
|
643
664
|
}
|
|
644
665
|
|
|
@@ -653,12 +674,41 @@ class Room extends Emitter {
|
|
|
653
674
|
|
|
654
675
|
if (remoteParticipant) {
|
|
655
676
|
this.participants.push(remoteParticipant);
|
|
656
|
-
|
|
677
|
+
this._isParticipantJoining(remoteParticipant);
|
|
657
678
|
}
|
|
658
679
|
|
|
659
680
|
return remoteParticipant;
|
|
660
681
|
}
|
|
661
682
|
|
|
683
|
+
_onLocalParticipantJoined(localParticipant: LocalParticipant) {
|
|
684
|
+
this.localParticipant = localParticipant;
|
|
685
|
+
|
|
686
|
+
const localVideoStream = this._getLocalVideoStream();
|
|
687
|
+
if (localVideoStream) {
|
|
688
|
+
this._saveLocalVideoStream(localVideoStream);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
this.connected = true;
|
|
692
|
+
|
|
693
|
+
localParticipant.broadcastStatus();
|
|
694
|
+
|
|
695
|
+
// we're in the room, now let's request everyone's status
|
|
696
|
+
if (this.localParticipant) {
|
|
697
|
+
this.sendSignal({
|
|
698
|
+
type: SIGNAL_TYPE_PARTICIPANT_REQUEST,
|
|
699
|
+
origin: this.localParticipant.getStatus(),
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
_isParticipantJoining(participant: Participant) {
|
|
705
|
+
this.__associateStreams(participant);
|
|
706
|
+
// @VALIDATE: no need to publicize ourselves, no?
|
|
707
|
+
if (participant instanceof RemoteParticipant) {
|
|
708
|
+
this.eventEmitter.emit(this.CONFERENCE_USER_PARTICIPANT_JOINED, participant);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
662
712
|
_saveLocalVideoStream(stream: MediaStream) {
|
|
663
713
|
const { localParticipant } = this;
|
|
664
714
|
|
|
@@ -704,9 +754,11 @@ class Room extends Emitter {
|
|
|
704
754
|
_onParticipantTrackUpdate(oldParticipant: Participant, update: string): Participant {
|
|
705
755
|
const newParticipant = oldParticipant;
|
|
706
756
|
|
|
707
|
-
const { trackId } = this._callIdStreamIdMap[newParticipant.callId] || {};
|
|
757
|
+
const { trackId, streamId } = this._callIdStreamIdMap[newParticipant.callId] || {};
|
|
708
758
|
const pc = Wazo.Phone.phone.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
709
|
-
|
|
759
|
+
// Can't use `getReceivers` here because on FF we make the mapping based on the streamId
|
|
760
|
+
const stream = pc.getRemoteStreams().find(someStream =>
|
|
761
|
+
someStream.id === streamId || someStream.getTracks().some(track => track.id === trackId));
|
|
710
762
|
|
|
711
763
|
if (update === 'downgrade') {
|
|
712
764
|
newParticipant.streams = [];
|
|
@@ -736,15 +788,41 @@ class Room extends Emitter {
|
|
|
736
788
|
return;
|
|
737
789
|
}
|
|
738
790
|
|
|
739
|
-
|
|
791
|
+
const streamId = this._getStreamIdFrTrackId(trackId);
|
|
792
|
+
const key = this._getUnassociatedMapIdFromTrackIdOrStreamId(trackId, streamId);
|
|
793
|
+
const stream = this._unassociatedVideoStreams[key];
|
|
794
|
+
|
|
795
|
+
if (stream) {
|
|
740
796
|
// Try to associate stream
|
|
741
|
-
this._associateStreamTo(
|
|
797
|
+
this._associateStreamTo(stream, participant);
|
|
742
798
|
|
|
743
|
-
delete this._unassociatedVideoStreams[
|
|
799
|
+
delete this._unassociatedVideoStreams[key];
|
|
744
800
|
delete this._unassociatedParticipants[participant.callId];
|
|
745
801
|
}
|
|
746
802
|
}
|
|
747
803
|
|
|
804
|
+
_getUnassociatedMapIdFromTrackIdOrStreamId(trackId: string, streamId: ?string) {
|
|
805
|
+
// Find by trackId
|
|
806
|
+
if (trackId in this._unassociatedVideoStreams) {
|
|
807
|
+
return trackId;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Find by streamId
|
|
811
|
+
if (streamId && streamId in this._unassociatedVideoStreams) {
|
|
812
|
+
return streamId;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// Find in all the streams by streamId (used on FF where we can't map by trackId)
|
|
816
|
+
const idx = Object.values(this._unassociatedVideoStreams).findIndex((stream: Object) => stream.id === streamId);
|
|
817
|
+
return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
_getStreamIdFrTrackId(trackId: string) {
|
|
821
|
+
const mapping: Object = Object.values(this._callIdStreamIdMap).find((map: Object) => map.trackId === trackId);
|
|
822
|
+
|
|
823
|
+
return mapping ? mapping.streamId : null;
|
|
824
|
+
}
|
|
825
|
+
|
|
748
826
|
_associateStreamTo(rawStream: any, participant: Participant) {
|
|
749
827
|
const stream = new Wazo.Stream(rawStream, participant);
|
|
750
828
|
participant.streams.push(stream);
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import type { Message } from 'sip.js/lib/api/message';
|
|
4
|
+
import IssueReporter from '../../service/IssueReporter';
|
|
5
|
+
import Wazo from '../index';
|
|
6
|
+
import Room from './Room';
|
|
7
|
+
|
|
8
|
+
const logger = IssueReporter.loggerFor('sdk-sip-room');
|
|
9
|
+
|
|
10
|
+
class SipRoom extends Room {
|
|
11
|
+
|
|
12
|
+
static async connect({ extension, constraints, audioOnly = false, extra, room }: Object) {
|
|
13
|
+
logger.info('connecting to sip room', { extension, audioOnly, room: !!room });
|
|
14
|
+
|
|
15
|
+
if (!room) {
|
|
16
|
+
await Wazo.Phone.connect();
|
|
17
|
+
|
|
18
|
+
const withCamera = constraints && !!constraints.video;
|
|
19
|
+
|
|
20
|
+
const callSession = await Wazo.Phone.call(extension, withCamera, null, audioOnly, true);
|
|
21
|
+
// eslint-disable-next-line no-param-reassign
|
|
22
|
+
room = new SipRoom(callSession, extension, null, null, extra);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (room && room.callSession && room.callSession.call) {
|
|
26
|
+
room.setCallId(room.callSession.call.id);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
logger.info('connected to room', {
|
|
30
|
+
extension: room.extension,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return room;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
mute() {
|
|
37
|
+
logger.info('mute sip room');
|
|
38
|
+
|
|
39
|
+
Wazo.Phone.mute(this.callSession, false);
|
|
40
|
+
|
|
41
|
+
this.sendMuteStatus();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
unmute() {
|
|
45
|
+
logger.info('unmute sip room');
|
|
46
|
+
|
|
47
|
+
Wazo.Phone.unmute(this.callSession, false);
|
|
48
|
+
|
|
49
|
+
this.sendUnMuteStatus();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getLocalGuestName() {
|
|
53
|
+
return Wazo.Phone.phone.client.userAgent.options.displayName;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Overridden to not listen to websocket messages
|
|
57
|
+
_transferEvents() {
|
|
58
|
+
// Phone events
|
|
59
|
+
Wazo.Phone.on(this.ON_MESSAGE, this._boundOnMessage);
|
|
60
|
+
Wazo.Phone.on(this.ON_CHAT, this._boundOnChat);
|
|
61
|
+
Wazo.Phone.on(this.ON_SIGNAL, this._boundOnSignal);
|
|
62
|
+
Wazo.Phone.on(this.ON_VIDEO_INPUT_CHANGE, this._boundSaveLocalVideoStream);
|
|
63
|
+
|
|
64
|
+
[this.ON_AUDIO_STREAM, this.ON_VIDEO_STREAM, this.ON_REMOVE_STREAM].forEach(event =>
|
|
65
|
+
Wazo.Phone.on(event, (...args) => this.eventEmitter.emit.apply(this.eventEmitter, [event, ...args])));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_onMessage(message: Message) {
|
|
69
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
70
|
+
const body = super._onMessage(message);
|
|
71
|
+
if (!body) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const getChannel = () => body.channels[0];
|
|
76
|
+
|
|
77
|
+
switch (body.type) {
|
|
78
|
+
case 'ConfbridgeWelcome':
|
|
79
|
+
body.channels.forEach(channel => {
|
|
80
|
+
this._onParticipantJoined(channel);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
break;
|
|
84
|
+
case 'ConfbridgeJoin': {
|
|
85
|
+
const channel = getChannel();
|
|
86
|
+
this._onParticipantJoined(channel);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
case 'ConfbridgeLeave': {
|
|
90
|
+
const channel = getChannel();
|
|
91
|
+
this._onParticipantLeft({
|
|
92
|
+
data: {
|
|
93
|
+
call_id: channel.id,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
default:
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async _onParticipantJoined(channel: Object) {
|
|
104
|
+
const isLocal = channel.channelvars.WAZO_SIP_CALL_ID === this._getCurrentSipCallIs();
|
|
105
|
+
const callId = channel.id;
|
|
106
|
+
const ParticipantClass = isLocal ? Wazo.LocalParticipant : Wazo.RemoteParticipant;
|
|
107
|
+
const name = channel.caller ? channel.caller.name : null;
|
|
108
|
+
const extra = isLocal ? { guestName: this.getLocalGuestName() } : {};
|
|
109
|
+
const participant = new ParticipantClass(this, {
|
|
110
|
+
caller_id_name: name,
|
|
111
|
+
call_id: callId,
|
|
112
|
+
}, extra);
|
|
113
|
+
|
|
114
|
+
const participantIdx = this.participants.findIndex(other => other.callId === participant.callId);
|
|
115
|
+
if (participantIdx !== -1 && name) {
|
|
116
|
+
this.participants[participantIdx].name = name;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (isLocal) {
|
|
121
|
+
// Should be updated by the Wazo WS but we don't have it for now
|
|
122
|
+
if (this.callSession) {
|
|
123
|
+
this.callSession.ringing = false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this._onLocalParticipantJoined(participant);
|
|
127
|
+
|
|
128
|
+
// Give some time for the stream to be updated
|
|
129
|
+
setTimeout(() => {
|
|
130
|
+
this.eventEmitter.emit(this.ON_JOINED, participant, this.participants);
|
|
131
|
+
}, 1000);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
this.participants.push(participant);
|
|
135
|
+
|
|
136
|
+
this._isParticipantJoining(participant);
|
|
137
|
+
|
|
138
|
+
return participant;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
_getCurrentSipCallIs() {
|
|
142
|
+
return Wazo.Phone.getSipSessionId(Wazo.Phone.phone.currentSipSession);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export default SipRoom;
|
|
@@ -52,9 +52,7 @@ class Stream {
|
|
|
52
52
|
return false;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
return this.htmlStream.getTracks().find(track => track.kind === 'video'
|
|
57
|
-
&& track.readyState !== 'ended' && 'width' in track.getSettings());
|
|
55
|
+
return this.htmlStream.getTracks().some(track => track.kind === 'video' && track.readyState !== 'ended');
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
get id() {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
// Using directly Wazo to avoid issues with require cycle
|
|
2
|
+
import Wazo from '../../index';
|
|
2
3
|
|
|
3
4
|
describe('RemoteParticipant', () => {
|
|
4
5
|
it('should fall back on number when name is <unknown>', () => {
|
|
5
6
|
const number = '1234';
|
|
6
|
-
const participant = new RemoteParticipant(null, { caller_id_name: '<unknown>', caller_id_number: number });
|
|
7
|
+
const participant = new Wazo.RemoteParticipant(null, { caller_id_name: '<unknown>', caller_id_number: number });
|
|
7
8
|
expect(participant.name).toEqual(number);
|
|
8
9
|
});
|
|
9
10
|
});
|
|
@@ -91,6 +91,17 @@ export type RoomParticipantUpdate = {
|
|
|
91
91
|
muted: boolean,
|
|
92
92
|
user_uuid: string,
|
|
93
93
|
};
|
|
94
|
+
export type MeetingParticipantUpdate = {
|
|
95
|
+
admin: boolean,
|
|
96
|
+
call_id: string,
|
|
97
|
+
caller_id_name: string,
|
|
98
|
+
caller_id_number: string,
|
|
99
|
+
room_uuid: string,
|
|
100
|
+
id: string,
|
|
101
|
+
language: string,
|
|
102
|
+
muted: boolean,
|
|
103
|
+
user_uuid: string,
|
|
104
|
+
};
|
|
94
105
|
|
|
95
106
|
export type FaxOutboundFailedEvent = {
|
|
96
107
|
call_id: string,
|
|
@@ -145,6 +156,14 @@ type ParticipantLeftRoom = WebSocketBaseMessage & {
|
|
|
145
156
|
data: RoomParticipantUpdate,
|
|
146
157
|
name: 'conference_user_participant_left',
|
|
147
158
|
};
|
|
159
|
+
type ParticipantJoinedMeeting = WebSocketBaseMessage & {
|
|
160
|
+
data: MeetingParticipantUpdate,
|
|
161
|
+
name: 'meeting_user_participant_joined',
|
|
162
|
+
};
|
|
163
|
+
type ParticipantLeftMeeting = WebSocketBaseMessage & {
|
|
164
|
+
data: MeetingParticipantUpdate,
|
|
165
|
+
name: 'meeting_user_participant_left',
|
|
166
|
+
};
|
|
148
167
|
type SwitchboardQueuedCallsUpdated = WebSocketBaseMessage & {
|
|
149
168
|
data: SwitchboardCallItems,
|
|
150
169
|
name: 'switchboard_queued_calls_updated',
|
|
@@ -194,6 +213,8 @@ export type WebSocketMessage =
|
|
|
194
213
|
| SwitchboardHeldCallAnswered
|
|
195
214
|
| ParticipantJoinedRoom
|
|
196
215
|
| ParticipantLeftRoom
|
|
216
|
+
| ParticipantJoinedMeeting
|
|
217
|
+
| ParticipantLeftMeeting
|
|
197
218
|
| FaxOutboundFailed
|
|
198
219
|
| FaxOutboundSucceeded
|
|
199
220
|
| AgentStatusUpdate
|