@wazo/sdk 0.37.2 → 0.37.6
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 +84 -22
- package/esm/__tests__/web-rtc-client.test.js +156 -55
- package/esm/api/call-logd.js +10 -22
- package/esm/api/calld.js +3 -0
- package/esm/api/confd.js +71 -0
- package/esm/api-client.js +84 -22
- package/esm/checker/Checker.js +160 -55
- package/esm/checker/checks/aor.js +84 -22
- package/esm/checker/checks/api.js +84 -22
- package/esm/checker/checks/index.js +160 -55
- package/esm/checker/checks/wazo-websocket.js +4 -0
- package/esm/checker/checks/webrtc-transport.js +156 -55
- package/esm/checker/checks/webrtc.js +156 -55
- package/esm/domain/AdHocAPIConference.js +84 -22
- package/esm/domain/CallLog.js +10 -22
- package/esm/domain/Features.js +84 -22
- package/esm/domain/Meeting.js +71 -0
- package/esm/domain/Phone/CTIPhone.js +84 -22
- package/esm/domain/Phone/WebRTCPhone.js +22 -8
- package/esm/domain/__tests__/CallLog.test.js +10 -22
- package/esm/index.js +726 -371
- package/esm/lib/WazoSessionDescriptionHandler.js +17 -9
- package/esm/service/CallApi.js +84 -22
- package/esm/service/getApiClient.js +84 -22
- package/esm/simple/Auth.js +717 -363
- package/esm/simple/Configuration.js +717 -363
- package/esm/simple/Directory.js +84 -22
- package/esm/simple/Phone.js +709 -355
- package/esm/simple/Websocket.js +6 -0
- package/esm/simple/index.js +719 -365
- package/esm/simple/room/LocalParticipant.js +689 -335
- package/esm/simple/room/Participant.js +689 -335
- package/esm/simple/room/RemoteParticipant.js +689 -335
- package/esm/simple/room/Room.js +689 -335
- package/esm/simple/room/SipRoom.js +13001 -0
- package/esm/simple/room/Stream.js +719 -365
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +4130 -3774
- package/esm/simple/utils.js +719 -365
- package/esm/web-rtc-client.js +156 -55
- package/esm/websocket-client.js +5 -1
- package/lib/__tests__/api-client.test.js +84 -22
- package/lib/__tests__/web-rtc-client.test.js +156 -55
- package/lib/api/call-logd.js +10 -22
- package/lib/api/calld.js +3 -0
- package/lib/api/confd.js +71 -0
- package/lib/api-client.js +84 -22
- package/lib/checker/Checker.js +160 -55
- package/lib/checker/checks/aor.js +84 -22
- package/lib/checker/checks/api.js +84 -22
- package/lib/checker/checks/index.js +160 -55
- package/lib/checker/checks/wazo-websocket.js +4 -0
- package/lib/checker/checks/webrtc-transport.js +156 -55
- package/lib/checker/checks/webrtc.js +156 -55
- package/lib/domain/AdHocAPIConference.js +84 -22
- package/lib/domain/CallLog.js +10 -22
- package/lib/domain/Features.js +84 -22
- package/lib/domain/Meeting.js +73 -0
- package/lib/domain/Phone/CTIPhone.js +84 -22
- package/lib/domain/Phone/WebRTCPhone.js +22 -8
- package/lib/domain/__tests__/CallLog.test.js +10 -22
- package/lib/index.js +726 -371
- package/lib/lib/WazoSessionDescriptionHandler.js +17 -9
- package/lib/service/CallApi.js +84 -22
- package/lib/service/getApiClient.js +84 -22
- package/lib/simple/Auth.js +717 -363
- package/lib/simple/Configuration.js +717 -363
- package/lib/simple/Directory.js +84 -22
- package/lib/simple/Phone.js +709 -355
- package/lib/simple/Websocket.js +6 -0
- package/lib/simple/index.js +719 -365
- package/lib/simple/room/LocalParticipant.js +689 -335
- package/lib/simple/room/Participant.js +689 -335
- package/lib/simple/room/RemoteParticipant.js +689 -335
- package/lib/simple/room/Room.js +689 -335
- package/lib/simple/room/SipRoom.js +13011 -0
- package/lib/simple/room/Stream.js +719 -365
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +4131 -3775
- package/lib/simple/utils.js +719 -365
- package/lib/web-rtc-client.js +156 -55
- package/lib/websocket-client.js +6 -0
- 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/Meeting.js +59 -0
- package/src/domain/Phone/WebRTCPhone.js +22 -8
- package/src/index.js +2 -0
- package/src/lib/WazoSessionDescriptionHandler.js +17 -9
- package/src/simple/Phone.js +13 -4
- package/src/simple/index.js +4 -0
- package/src/simple/room/Participant.js +7 -0
- package/src/simple/room/Room.js +158 -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 +55 -24
- package/src/websocket-client.js +4 -0
|
@@ -116,7 +116,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
116
116
|
.then(() => {
|
|
117
117
|
if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
|
|
118
118
|
// Add a video an empty bundle to be able to replaceTrack when joining a conference without video
|
|
119
|
-
this.peerConnection.addTransceiver
|
|
119
|
+
if (this.peerConnection.addTransceiver) {
|
|
120
|
+
this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
|
|
121
|
+
}
|
|
120
122
|
}
|
|
121
123
|
})
|
|
122
124
|
.then(() => this.createLocalOfferOrAnswer(options))
|
|
@@ -143,12 +145,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
143
145
|
};
|
|
144
146
|
})
|
|
145
147
|
.then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
|
|
146
|
-
.then((sessionDescription) => {
|
|
147
|
-
// Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
|
|
148
|
-
this.localMediaStreamConstraints = options.constraints;
|
|
149
|
-
|
|
150
|
-
return sessionDescription;
|
|
151
|
-
})
|
|
152
148
|
.then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
|
|
153
149
|
.catch((error) => {
|
|
154
150
|
wazoLogger.error('error when creating media', error);
|
|
@@ -343,6 +339,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
343
339
|
|
|
344
340
|
// set the transceiver direction to the answer direction
|
|
345
341
|
this._peerConnection.getTransceivers().forEach((transceiver) => {
|
|
342
|
+
if (transceiver.stopped) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
346
345
|
if (transceiver.direction /* guarding, but should always be true */) {
|
|
347
346
|
const { receiver } = transceiver;
|
|
348
347
|
if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
|
|
@@ -387,10 +386,15 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
387
386
|
if (kind !== 'audio' && kind !== 'video') {
|
|
388
387
|
throw new Error(`Unknown new track kind ${kind}.`);
|
|
389
388
|
}
|
|
390
|
-
const sender = pc.getSenders().find((otherSender) =>
|
|
389
|
+
const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
|
|
390
|
+
otherSender.track && otherSender.track.kind === kind);
|
|
391
391
|
|
|
392
392
|
// Do not reuse sender video tracks in SFU
|
|
393
393
|
if (sender && (!sfu || newTrack.kind === 'audio')) {
|
|
394
|
+
if (sender.track) {
|
|
395
|
+
// eslint-disable-next-line no-param-reassign
|
|
396
|
+
newTrack.enabled = sender.track.enabled;
|
|
397
|
+
}
|
|
394
398
|
trackUpdates.push(
|
|
395
399
|
new Promise((resolve) => {
|
|
396
400
|
this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
|
|
@@ -424,7 +428,11 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
424
428
|
// Review: could make streamless tracks a configurable option?
|
|
425
429
|
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
|
|
426
430
|
try {
|
|
427
|
-
pc.addTrack
|
|
431
|
+
if (pc.addTrack) {
|
|
432
|
+
pc.addTrack(newTrack, localStream);
|
|
433
|
+
} else {
|
|
434
|
+
pc.addStream(localStream);
|
|
435
|
+
}
|
|
428
436
|
} catch (error) {
|
|
429
437
|
this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
|
|
430
438
|
throw error;
|
package/src/simple/Phone.js
CHANGED
|
@@ -171,13 +171,18 @@ class Phone extends Emitter {
|
|
|
171
171
|
return adHocConference.start();
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
mute(callSession: CallSession) {
|
|
175
|
-
|
|
174
|
+
mute(callSession: CallSession, withApi: boolean = true) {
|
|
175
|
+
if (withApi) {
|
|
176
|
+
this.muteViaAPI(callSession);
|
|
177
|
+
}
|
|
178
|
+
|
|
176
179
|
return this.phone && this.phone.mute(callSession);
|
|
177
180
|
}
|
|
178
181
|
|
|
179
|
-
unmute(callSession: CallSession) {
|
|
180
|
-
|
|
182
|
+
unmute(callSession: CallSession, withApi: boolean = true) {
|
|
183
|
+
if (withApi) {
|
|
184
|
+
this.unmuteViaAPI(callSession);
|
|
185
|
+
}
|
|
181
186
|
|
|
182
187
|
return this.phone && this.phone.unmute(callSession);
|
|
183
188
|
}
|
|
@@ -283,6 +288,10 @@ class Phone extends Emitter {
|
|
|
283
288
|
return this.phone && this.phone.hasLocalVideo(callSession);
|
|
284
289
|
}
|
|
285
290
|
|
|
291
|
+
hasALocalVideoTrack(callSession: CallSession) {
|
|
292
|
+
return this.phone && this.phone.hasALocalVideoTrack(callSession);
|
|
293
|
+
}
|
|
294
|
+
|
|
286
295
|
// @Deprecated
|
|
287
296
|
getLocalMediaStream(callSession: CallSession) {
|
|
288
297
|
logger.warn('Phone.getLocalMediaStream is deprecated, use Phone.getLocalStream instead');
|
package/src/simple/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import Auth, { InvalidSubscription, InvalidAuthorization } from './Auth';
|
|
|
3
3
|
import Phone from './Phone';
|
|
4
4
|
import Websocket from './Websocket';
|
|
5
5
|
import Room from './room/Room';
|
|
6
|
+
import SipRoom from './room/SipRoom';
|
|
6
7
|
import RemoteParticipant from './room/RemoteParticipant';
|
|
7
8
|
import LocalParticipant from './room/LocalParticipant';
|
|
8
9
|
import Stream from './room/Stream';
|
|
@@ -35,6 +36,7 @@ import IndirectTransfer from '../domain/IndirectTransfer';
|
|
|
35
36
|
import SwitchboardCall from '../domain/SwitchboardCall';
|
|
36
37
|
import IssueReporter from '../service/IssueReporter';
|
|
37
38
|
import Features from '../domain/Features';
|
|
39
|
+
import Meeting from '../domain/Meeting';
|
|
38
40
|
import Checker from '../checker/Checker';
|
|
39
41
|
|
|
40
42
|
const Wazo = {
|
|
@@ -42,6 +44,7 @@ const Wazo = {
|
|
|
42
44
|
Phone,
|
|
43
45
|
Websocket,
|
|
44
46
|
Room,
|
|
47
|
+
SipRoom,
|
|
45
48
|
RemoteParticipant,
|
|
46
49
|
LocalParticipant,
|
|
47
50
|
Stream,
|
|
@@ -78,6 +81,7 @@ const Wazo = {
|
|
|
78
81
|
IndirectTransfer,
|
|
79
82
|
SwitchboardCall,
|
|
80
83
|
WebRTCPhone,
|
|
84
|
+
Meeting,
|
|
81
85
|
},
|
|
82
86
|
|
|
83
87
|
// Api
|
|
@@ -3,6 +3,7 @@ import Emitter from '../../utils/Emitter';
|
|
|
3
3
|
import IssueReporter from '../../service/IssueReporter';
|
|
4
4
|
|
|
5
5
|
import Room, { SIGNAL_TYPE_PARTICIPANT_UPDATE } from './Room';
|
|
6
|
+
import Contact from '../../domain/Contact';
|
|
6
7
|
|
|
7
8
|
const logger = IssueReporter.loggerFor('room');
|
|
8
9
|
|
|
@@ -38,6 +39,7 @@ class Participant extends Emitter {
|
|
|
38
39
|
ON_RESUME: string;
|
|
39
40
|
|
|
40
41
|
/**
|
|
42
|
+
* @param room Room The room where the participant is
|
|
41
43
|
* @param rawParticipant string Participant sent via the Wazo WS
|
|
42
44
|
* @param extra Object extra status of the participant
|
|
43
45
|
*/
|
|
@@ -267,6 +269,11 @@ class Participant extends Emitter {
|
|
|
267
269
|
// Poor man's object comparison
|
|
268
270
|
if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
|
|
269
271
|
this.extra = { ...this.extra, ...status.extra };
|
|
272
|
+
|
|
273
|
+
if (this.extra.contact && !(this.extra.contact instanceof Contact)) {
|
|
274
|
+
this.extra.contact = new Contact(this.extra.contact);
|
|
275
|
+
}
|
|
276
|
+
|
|
270
277
|
this.triggerUpdate(this.ON_EXTRA_CHANGE, broadcast);
|
|
271
278
|
}
|
|
272
279
|
}
|
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,42 @@ 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) =>
|
|
817
|
+
stream && stream.id === streamId);
|
|
818
|
+
return idx === -1 ? null : Object.keys(this._unassociatedVideoStreams)[idx];
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
_getStreamIdFrTrackId(trackId: string) {
|
|
822
|
+
const mapping: Object = Object.values(this._callIdStreamIdMap).find((map: Object) => map.trackId === trackId);
|
|
823
|
+
|
|
824
|
+
return mapping ? mapping.streamId : null;
|
|
825
|
+
}
|
|
826
|
+
|
|
748
827
|
_associateStreamTo(rawStream: any, participant: Participant) {
|
|
749
828
|
const stream = new Wazo.Stream(rawStream, participant);
|
|
750
829
|
participant.streams.push(stream);
|