@webex/plugin-meetings 3.0.0-next.2 → 3.0.0-next.21
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/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.d.ts +3 -9
- package/dist/constants.js +4 -9
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +3 -3
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/mediaSharesUtils.js +15 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/media/index.js +4 -1
- package/dist/media/index.js.map +1 -1
- package/dist/mediaQualityMetrics/config.d.ts +9 -1
- package/dist/mediaQualityMetrics/config.js +10 -1
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/index.d.ts +18 -7
- package/dist/meeting/index.js +745 -567
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.d.ts +2 -8
- package/dist/meeting/muteState.js +37 -25
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.d.ts +3 -0
- package/dist/meeting/request.js +32 -23
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +1 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/multistream/mediaRequestManager.d.ts +1 -2
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.d.ts +1 -1
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.d.ts +1 -2
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.d.ts +1 -2
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/request.js +12 -10
- package/dist/reachability/request.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -1
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.d.ts +10 -2
- package/dist/roap/index.js +15 -0
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +3 -3
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.d.ts +64 -17
- package/dist/roap/turnDiscovery.js +307 -126
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/statsAnalyzer/index.js +61 -41
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/constants.ts +3 -9
- package/src/index.ts +1 -0
- package/src/interpretation/index.ts +2 -2
- package/src/locus-info/mediaSharesUtils.ts +16 -0
- package/src/media/index.ts +3 -1
- package/src/mediaQualityMetrics/config.ts +11 -1
- package/src/meeting/index.ts +264 -90
- package/src/meeting/muteState.ts +34 -20
- package/src/meeting/request.ts +18 -2
- package/src/meeting/util.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +1 -1
- package/src/multistream/remoteMediaGroup.ts +1 -1
- package/src/multistream/remoteMediaManager.ts +1 -2
- package/src/multistream/sendSlotManager.ts +1 -2
- package/src/reachability/request.ts +15 -11
- package/src/reconnection-manager/index.ts +1 -1
- package/src/roap/index.ts +25 -3
- package/src/roap/request.ts +3 -3
- package/src/roap/turnDiscovery.ts +244 -78
- package/src/statsAnalyzer/index.ts +72 -43
- package/test/integration/spec/journey.js +14 -14
- package/test/integration/spec/space-meeting.js +1 -1
- package/test/unit/spec/interpretation/index.ts +4 -1
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +9 -0
- package/test/unit/spec/media/index.ts +89 -78
- package/test/unit/spec/meeting/index.js +611 -125
- package/test/unit/spec/meeting/muteState.js +219 -67
- package/test/unit/spec/meeting/request.js +21 -0
- package/test/unit/spec/meeting/utils.js +6 -1
- package/test/unit/spec/meetings/index.js +27 -20
- package/test/unit/spec/multistream/remoteMediaGroup.ts +0 -1
- package/test/unit/spec/multistream/remoteMediaManager.ts +0 -1
- package/test/unit/spec/reachability/request.js +15 -7
- package/test/unit/spec/reconnection-manager/index.js +28 -0
- package/test/unit/spec/roap/index.ts +61 -6
- package/test/unit/spec/roap/turnDiscovery.ts +298 -16
- package/test/unit/spec/stats-analyzer/index.js +183 -8
- package/dist/member/member.types.d.ts +0 -11
- package/dist/member/member.types.js +0 -17
- package/dist/member/member.types.js.map +0 -1
- package/src/member/member.types.ts +0 -13
package/src/meeting/muteState.ts
CHANGED
|
@@ -150,15 +150,30 @@ export class MuteState {
|
|
|
150
150
|
* @param {Boolean} [mute] true for muting, false for unmuting request
|
|
151
151
|
* @returns {void}
|
|
152
152
|
*/
|
|
153
|
-
public handleLocalStreamMuteStateChange(meeting?:
|
|
153
|
+
public handleLocalStreamMuteStateChange(meeting?: any) {
|
|
154
154
|
if (this.ignoreMuteStateChange) {
|
|
155
155
|
return;
|
|
156
156
|
}
|
|
157
|
+
|
|
158
|
+
// either user or system may have triggered a mute state change, but localMute should reflect both
|
|
159
|
+
let newMuteState: boolean;
|
|
160
|
+
let userMuteState: boolean;
|
|
161
|
+
let systemMuteState: boolean;
|
|
162
|
+
if (this.type === AUDIO) {
|
|
163
|
+
newMuteState = meeting.mediaProperties.audioStream?.muted;
|
|
164
|
+
userMuteState = meeting.mediaProperties.audioStream?.userMuted;
|
|
165
|
+
systemMuteState = meeting.mediaProperties.audioStream?.systemMuted;
|
|
166
|
+
} else {
|
|
167
|
+
newMuteState = meeting.mediaProperties.videoStream?.muted;
|
|
168
|
+
userMuteState = meeting.mediaProperties.videoStream?.userMuted;
|
|
169
|
+
systemMuteState = meeting.mediaProperties.videoStream?.systemMuted;
|
|
170
|
+
}
|
|
171
|
+
|
|
157
172
|
LoggerProxy.logger.info(
|
|
158
|
-
`Meeting:muteState#handleLocalStreamMuteStateChange --> ${this.type}: local stream new mute state: ${mute}`
|
|
173
|
+
`Meeting:muteState#handleLocalStreamMuteStateChange --> ${this.type}: local stream new mute state: ${newMuteState} (user mute: ${userMuteState}, system mute: ${systemMuteState})`
|
|
159
174
|
);
|
|
160
175
|
|
|
161
|
-
this.state.client.localMute =
|
|
176
|
+
this.state.client.localMute = newMuteState;
|
|
162
177
|
|
|
163
178
|
this.applyClientStateToServer(meeting);
|
|
164
179
|
}
|
|
@@ -249,7 +264,12 @@ export class MuteState {
|
|
|
249
264
|
`Meeting:muteState#applyClientStateToServer --> ${this.type}: error: ${e}`
|
|
250
265
|
);
|
|
251
266
|
|
|
252
|
-
|
|
267
|
+
// failed to apply client state to server, so revert stream mute state to server state
|
|
268
|
+
this.muteLocalStream(
|
|
269
|
+
meeting,
|
|
270
|
+
this.state.server.localMute || this.state.server.remoteMute,
|
|
271
|
+
'clientRequestFailed'
|
|
272
|
+
);
|
|
253
273
|
});
|
|
254
274
|
}
|
|
255
275
|
|
|
@@ -325,18 +345,6 @@ export class MuteState {
|
|
|
325
345
|
});
|
|
326
346
|
}
|
|
327
347
|
|
|
328
|
-
/** Sets the mute state of the local stream according to what server thinks is our state
|
|
329
|
-
* @param {Object} meeting - the meeting object
|
|
330
|
-
* @param {ServerMuteReason} serverMuteReason - reason why we're applying server mute to the local stream
|
|
331
|
-
* @returns {void}
|
|
332
|
-
*/
|
|
333
|
-
private applyServerMuteToLocalStream(meeting: any, serverMuteReason: ServerMuteReason) {
|
|
334
|
-
const muted = this.state.server.localMute || this.state.server.remoteMute;
|
|
335
|
-
|
|
336
|
-
// update the local stream mute state, but not this.state.client.localMute
|
|
337
|
-
this.muteLocalStream(meeting, muted, serverMuteReason);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
348
|
/** Applies the current value for unmute allowed to the underlying stream
|
|
341
349
|
*
|
|
342
350
|
* @param {Meeting} meeting
|
|
@@ -371,7 +379,7 @@ export class MuteState {
|
|
|
371
379
|
}
|
|
372
380
|
if (muted !== undefined) {
|
|
373
381
|
this.state.server.remoteMute = muted;
|
|
374
|
-
this.
|
|
382
|
+
this.muteLocalStream(meeting, muted, 'remotelyMuted');
|
|
375
383
|
}
|
|
376
384
|
}
|
|
377
385
|
|
|
@@ -383,7 +391,7 @@ export class MuteState {
|
|
|
383
391
|
* @param {Object} [meeting] the meeting object
|
|
384
392
|
* @returns {undefined}
|
|
385
393
|
*/
|
|
386
|
-
public handleServerLocalUnmuteRequired(meeting?:
|
|
394
|
+
public handleServerLocalUnmuteRequired(meeting?: any) {
|
|
387
395
|
if (!this.state.client.enabled) {
|
|
388
396
|
LoggerProxy.logger.warn(
|
|
389
397
|
`Meeting:muteState#handleServerLocalUnmuteRequired --> ${this.type}: localAudioUnmuteRequired received while ${this.type} is disabled -> local unmute will not result in ${this.type} being sent`
|
|
@@ -396,9 +404,15 @@ export class MuteState {
|
|
|
396
404
|
|
|
397
405
|
// todo: I'm seeing "you can now unmute yourself " popup when this happens - but same thing happens on web.w.c so we can ignore for now
|
|
398
406
|
this.state.server.remoteMute = false;
|
|
399
|
-
this.state.client.localMute = false;
|
|
400
407
|
|
|
401
|
-
|
|
408
|
+
// change user mute state to false, but keep localMute true if overall mute state is still true
|
|
409
|
+
this.muteLocalStream(meeting, false, 'localUnmuteRequired');
|
|
410
|
+
if (this.type === AUDIO) {
|
|
411
|
+
this.state.client.localMute = meeting.mediaProperties.audioStream?.muted;
|
|
412
|
+
} else {
|
|
413
|
+
this.state.client.localMute = meeting.mediaProperties.videoStream?.muted;
|
|
414
|
+
}
|
|
415
|
+
|
|
402
416
|
this.applyClientStateToServer(meeting);
|
|
403
417
|
}
|
|
404
418
|
|
package/src/meeting/request.ts
CHANGED
|
@@ -103,6 +103,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
103
103
|
* @param {String} options.locale,
|
|
104
104
|
* @param {Array} options.deviceCapabilities
|
|
105
105
|
* @param {boolean} options.liveAnnotationSupported
|
|
106
|
+
* @param {String} options.alias
|
|
106
107
|
* @returns {Promise}
|
|
107
108
|
*/
|
|
108
109
|
async joinMeeting(options: {
|
|
@@ -122,11 +123,13 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
122
123
|
meetingNumber: any;
|
|
123
124
|
permissionToken: any;
|
|
124
125
|
preferTranscoding: any;
|
|
126
|
+
reachability: any;
|
|
125
127
|
breakoutsSupported: boolean;
|
|
126
128
|
locale?: string;
|
|
127
129
|
deviceCapabilities?: Array<string>;
|
|
128
130
|
liveAnnotationSupported: boolean;
|
|
129
131
|
ipVersion?: IP_VERSION;
|
|
132
|
+
alias?: string;
|
|
130
133
|
}) {
|
|
131
134
|
const {
|
|
132
135
|
asResourceOccupant,
|
|
@@ -143,12 +146,14 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
143
146
|
pin,
|
|
144
147
|
moveToResource,
|
|
145
148
|
roapMessage,
|
|
149
|
+
reachability,
|
|
146
150
|
preferTranscoding,
|
|
147
151
|
breakoutsSupported,
|
|
148
152
|
locale,
|
|
149
153
|
deviceCapabilities = [],
|
|
150
154
|
liveAnnotationSupported,
|
|
151
155
|
ipVersion,
|
|
156
|
+
alias,
|
|
152
157
|
} = options;
|
|
153
158
|
|
|
154
159
|
LoggerProxy.logger.info('Meeting:request#joinMeeting --> Joining a meeting', correlationId);
|
|
@@ -178,6 +183,10 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
178
183
|
},
|
|
179
184
|
};
|
|
180
185
|
|
|
186
|
+
if (alias) {
|
|
187
|
+
body.alias = alias;
|
|
188
|
+
}
|
|
189
|
+
|
|
181
190
|
if (breakoutsSupported) {
|
|
182
191
|
deviceCapabilities.push(BREAKOUTS.BREAKOUTS_SUPPORTED);
|
|
183
192
|
}
|
|
@@ -260,8 +269,15 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
260
269
|
};
|
|
261
270
|
}
|
|
262
271
|
|
|
263
|
-
if (roapMessage) {
|
|
264
|
-
body.localMedias =
|
|
272
|
+
if (roapMessage || reachability) {
|
|
273
|
+
body.localMedias = [
|
|
274
|
+
{
|
|
275
|
+
localSdp: JSON.stringify({
|
|
276
|
+
roapMessage,
|
|
277
|
+
reachability,
|
|
278
|
+
}),
|
|
279
|
+
},
|
|
280
|
+
];
|
|
265
281
|
}
|
|
266
282
|
|
|
267
283
|
/// @ts-ignore
|
package/src/meeting/util.ts
CHANGED
|
@@ -149,6 +149,7 @@ const MeetingUtil = {
|
|
|
149
149
|
locusUrl: meeting.locusUrl,
|
|
150
150
|
locusClusterUrl: meeting.meetingInfo?.locusClusterUrl,
|
|
151
151
|
correlationId: meeting.correlationId,
|
|
152
|
+
reachability: options.reachability,
|
|
152
153
|
roapMessage: options.roapMessage,
|
|
153
154
|
permissionToken: meeting.permissionToken,
|
|
154
155
|
resourceId: options.resourceId || null,
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
H264Codec,
|
|
9
9
|
getRecommendedMaxBitrateForFrameSize,
|
|
10
10
|
RecommendedOpusBitrates,
|
|
11
|
+
NamedMediaGroup,
|
|
11
12
|
} from '@webex/internal-media-core';
|
|
12
13
|
import {cloneDeepWith, debounce, isEmpty} from 'lodash';
|
|
13
14
|
|
|
14
|
-
import {NamedMediaGroup} from '@webex/json-multistream';
|
|
15
15
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
16
16
|
|
|
17
17
|
import {ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable require-jsdoc */
|
|
3
3
|
/* eslint-disable import/prefer-default-export */
|
|
4
4
|
import {forEach} from 'lodash';
|
|
5
|
-
import {NamedMediaGroup} from '@webex/
|
|
5
|
+
import {NamedMediaGroup} from '@webex/internal-media-core';
|
|
6
6
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
7
|
|
|
8
8
|
import {getMaxFs, RemoteMedia, RemoteVideoResolution} from './remoteMedia';
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* eslint-disable valid-jsdoc */
|
|
2
2
|
import {cloneDeep, forEach, remove} from 'lodash';
|
|
3
3
|
import {EventMap} from 'typed-emitter';
|
|
4
|
-
import {MediaType} from '@webex/internal-media-core';
|
|
5
|
-
import {NamedMediaGroup} from '@webex/json-multistream';
|
|
4
|
+
import {MediaType, NamedMediaGroup} from '@webex/internal-media-core';
|
|
6
5
|
|
|
7
6
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
8
7
|
import EventsScope from '../common/events/events-scope';
|
|
@@ -3,10 +3,9 @@ import {
|
|
|
3
3
|
MediaType,
|
|
4
4
|
LocalStream,
|
|
5
5
|
MultistreamRoapMediaConnection,
|
|
6
|
+
NamedMediaGroup,
|
|
6
7
|
} from '@webex/internal-media-core';
|
|
7
8
|
|
|
8
|
-
import {NamedMediaGroup} from '@webex/json-multistream';
|
|
9
|
-
|
|
10
9
|
export default class SendSlotManager {
|
|
11
10
|
private readonly slots: Map<MediaType, SendSlot> = new Map();
|
|
12
11
|
private readonly LoggerProxy: any;
|
|
@@ -34,17 +34,21 @@ class ReachabilityRequest {
|
|
|
34
34
|
* @returns {Promise}
|
|
35
35
|
*/
|
|
36
36
|
getClusters = (ipVersion?: IP_VERSION): Promise<{clusters: ClusterList; joinCookie: any}> =>
|
|
37
|
-
this.webex
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies
|
|
38
|
+
.measureLatency(
|
|
39
|
+
() =>
|
|
40
|
+
this.webex.request({
|
|
41
|
+
method: HTTP_VERBS.GET,
|
|
42
|
+
shouldRefreshAccessToken: false,
|
|
43
|
+
api: API.CALLIOPEDISCOVERY,
|
|
44
|
+
resource: RESOURCE.CLUSTERS,
|
|
45
|
+
qs: {
|
|
46
|
+
JCSupport: 1,
|
|
47
|
+
ipver: ipVersion,
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
'internal.get.cluster.time'
|
|
51
|
+
)
|
|
48
52
|
.then((res) => {
|
|
49
53
|
const {clusters, joinCookie} = res.body;
|
|
50
54
|
|
|
@@ -568,7 +568,7 @@ export default class ReconnectionManager {
|
|
|
568
568
|
|
|
569
569
|
const iceServers = [];
|
|
570
570
|
|
|
571
|
-
if (turnServerResult.turnServerInfo) {
|
|
571
|
+
if (turnServerResult.turnServerInfo?.url) {
|
|
572
572
|
iceServers.push({
|
|
573
573
|
urls: turnServerResult.turnServerInfo.url,
|
|
574
574
|
username: turnServerResult.turnServerInfo.username || '',
|
package/src/roap/index.ts
CHANGED
|
@@ -5,12 +5,18 @@ import {ROAP} from '../constants';
|
|
|
5
5
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
6
6
|
|
|
7
7
|
import RoapRequest from './request';
|
|
8
|
-
import TurnDiscovery from './turnDiscovery';
|
|
8
|
+
import TurnDiscovery, {TurnDiscoveryResult} from './turnDiscovery';
|
|
9
9
|
import Meeting from '../meeting';
|
|
10
10
|
import MeetingUtil from '../meeting/util';
|
|
11
11
|
import Metrics from '../metrics';
|
|
12
12
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
13
13
|
|
|
14
|
+
export {
|
|
15
|
+
type TurnDiscoveryResult,
|
|
16
|
+
type TurnServerInfo,
|
|
17
|
+
type TurnDiscoverySkipReason,
|
|
18
|
+
} from './turnDiscovery';
|
|
19
|
+
|
|
14
20
|
/**
|
|
15
21
|
* Roap options
|
|
16
22
|
* @typedef {Object} RoapOptions
|
|
@@ -39,7 +45,7 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
39
45
|
options: any;
|
|
40
46
|
roapHandler: any;
|
|
41
47
|
roapRequest: any;
|
|
42
|
-
turnDiscovery:
|
|
48
|
+
turnDiscovery: TurnDiscovery;
|
|
43
49
|
|
|
44
50
|
/**
|
|
45
51
|
*
|
|
@@ -260,7 +266,23 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
260
266
|
* @param {Boolean} [isForced]
|
|
261
267
|
* @returns {Promise}
|
|
262
268
|
*/
|
|
263
|
-
doTurnDiscovery(
|
|
269
|
+
doTurnDiscovery(
|
|
270
|
+
meeting: Meeting,
|
|
271
|
+
isReconnecting: boolean,
|
|
272
|
+
isForced?: boolean
|
|
273
|
+
): Promise<TurnDiscoveryResult> {
|
|
264
274
|
return this.turnDiscovery.doTurnDiscovery(meeting, isReconnecting, isForced);
|
|
265
275
|
}
|
|
276
|
+
|
|
277
|
+
generateTurnDiscoveryRequestMessage(meeting: Meeting, isForced: boolean) {
|
|
278
|
+
return this.turnDiscovery.generateTurnDiscoveryRequestMessage(meeting, isForced);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
handleTurnDiscoveryHttpResponse(meeting: Meeting, httpResponse: object) {
|
|
282
|
+
return this.turnDiscovery.handleTurnDiscoveryHttpResponse(meeting, httpResponse);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
abortTurnDiscovery() {
|
|
286
|
+
return this.turnDiscovery.abort();
|
|
287
|
+
}
|
|
266
288
|
}
|
package/src/roap/request.ts
CHANGED
|
@@ -123,7 +123,7 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
123
123
|
);
|
|
124
124
|
const {locus} = res.body;
|
|
125
125
|
|
|
126
|
-
locus.roapSeq = roapMessage.seq;
|
|
126
|
+
locus.roapSeq = options.roapMessage.seq;
|
|
127
127
|
|
|
128
128
|
return {
|
|
129
129
|
locus,
|
|
@@ -139,9 +139,9 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
139
139
|
rawError: err,
|
|
140
140
|
},
|
|
141
141
|
});
|
|
142
|
-
LoggerProxy.logger.error(`Roap:request#sendRoap --> Error
|
|
142
|
+
LoggerProxy.logger.error(`Roap:request#sendRoap --> Error:`, err);
|
|
143
143
|
LoggerProxy.logger.error(
|
|
144
|
-
`Roap:request#sendRoapRequest -->
|
|
144
|
+
`Roap:request#sendRoapRequest --> roapMessage that caused error:${JSON.stringify(
|
|
145
145
|
roapMessage,
|
|
146
146
|
null,
|
|
147
147
|
2
|