@webex/plugin-meetings 3.0.0-beta.396 → 3.0.0-beta.398
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/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/index.js +31 -24
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +37 -25
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/meeting/index.d.ts +2 -2
- package/dist/types/meeting/muteState.d.ts +2 -8
- package/dist/webinar/index.js +1 -1
- package/package.json +20 -20
- package/src/index.ts +1 -0
- package/src/meeting/index.ts +62 -15
- package/src/meeting/muteState.ts +34 -20
- package/test/integration/spec/journey.js +13 -13
- package/test/unit/spec/meeting/index.js +111 -22
- package/test/unit/spec/meeting/muteState.js +219 -67
|
@@ -154,12 +154,28 @@ var MuteState = /*#__PURE__*/function () {
|
|
|
154
154
|
*/
|
|
155
155
|
}, {
|
|
156
156
|
key: "handleLocalStreamMuteStateChange",
|
|
157
|
-
value: function handleLocalStreamMuteStateChange(meeting
|
|
157
|
+
value: function handleLocalStreamMuteStateChange(meeting) {
|
|
158
158
|
if (this.ignoreMuteStateChange) {
|
|
159
159
|
return;
|
|
160
160
|
}
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
|
|
162
|
+
// either user or system may have triggered a mute state change, but localMute should reflect both
|
|
163
|
+
var newMuteState;
|
|
164
|
+
var userMuteState;
|
|
165
|
+
var systemMuteState;
|
|
166
|
+
if (this.type === _constants.AUDIO) {
|
|
167
|
+
var _meeting$mediaPropert5, _meeting$mediaPropert6, _meeting$mediaPropert7;
|
|
168
|
+
newMuteState = (_meeting$mediaPropert5 = meeting.mediaProperties.audioStream) === null || _meeting$mediaPropert5 === void 0 ? void 0 : _meeting$mediaPropert5.muted;
|
|
169
|
+
userMuteState = (_meeting$mediaPropert6 = meeting.mediaProperties.audioStream) === null || _meeting$mediaPropert6 === void 0 ? void 0 : _meeting$mediaPropert6.userMuted;
|
|
170
|
+
systemMuteState = (_meeting$mediaPropert7 = meeting.mediaProperties.audioStream) === null || _meeting$mediaPropert7 === void 0 ? void 0 : _meeting$mediaPropert7.systemMuted;
|
|
171
|
+
} else {
|
|
172
|
+
var _meeting$mediaPropert8, _meeting$mediaPropert9, _meeting$mediaPropert10;
|
|
173
|
+
newMuteState = (_meeting$mediaPropert8 = meeting.mediaProperties.videoStream) === null || _meeting$mediaPropert8 === void 0 ? void 0 : _meeting$mediaPropert8.muted;
|
|
174
|
+
userMuteState = (_meeting$mediaPropert9 = meeting.mediaProperties.videoStream) === null || _meeting$mediaPropert9 === void 0 ? void 0 : _meeting$mediaPropert9.userMuted;
|
|
175
|
+
systemMuteState = (_meeting$mediaPropert10 = meeting.mediaProperties.videoStream) === null || _meeting$mediaPropert10 === void 0 ? void 0 : _meeting$mediaPropert10.systemMuted;
|
|
176
|
+
}
|
|
177
|
+
_loggerProxy.default.logger.info("Meeting:muteState#handleLocalStreamMuteStateChange --> ".concat(this.type, ": local stream new mute state: ").concat(newMuteState, " (user mute: ").concat(userMuteState, ", system mute: ").concat(systemMuteState, ")"));
|
|
178
|
+
this.state.client.localMute = newMuteState;
|
|
163
179
|
this.applyClientStateToServer(meeting);
|
|
164
180
|
}
|
|
165
181
|
|
|
@@ -232,7 +248,9 @@ var MuteState = /*#__PURE__*/function () {
|
|
|
232
248
|
}).catch(function (e) {
|
|
233
249
|
_this.state.syncToServerInProgress = false;
|
|
234
250
|
_loggerProxy.default.logger.warn("Meeting:muteState#applyClientStateToServer --> ".concat(_this.type, ": error: ").concat(e));
|
|
235
|
-
|
|
251
|
+
|
|
252
|
+
// failed to apply client state to server, so revert stream mute state to server state
|
|
253
|
+
_this.muteLocalStream(meeting, _this.state.server.localMute || _this.state.server.remoteMute, 'clientRequestFailed');
|
|
236
254
|
});
|
|
237
255
|
}
|
|
238
256
|
|
|
@@ -287,20 +305,6 @@ var MuteState = /*#__PURE__*/function () {
|
|
|
287
305
|
});
|
|
288
306
|
}
|
|
289
307
|
|
|
290
|
-
/** Sets the mute state of the local stream according to what server thinks is our state
|
|
291
|
-
* @param {Object} meeting - the meeting object
|
|
292
|
-
* @param {ServerMuteReason} serverMuteReason - reason why we're applying server mute to the local stream
|
|
293
|
-
* @returns {void}
|
|
294
|
-
*/
|
|
295
|
-
}, {
|
|
296
|
-
key: "applyServerMuteToLocalStream",
|
|
297
|
-
value: function applyServerMuteToLocalStream(meeting, serverMuteReason) {
|
|
298
|
-
var muted = this.state.server.localMute || this.state.server.remoteMute;
|
|
299
|
-
|
|
300
|
-
// update the local stream mute state, but not this.state.client.localMute
|
|
301
|
-
this.muteLocalStream(meeting, muted, serverMuteReason);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
308
|
/** Applies the current value for unmute allowed to the underlying stream
|
|
305
309
|
*
|
|
306
310
|
* @param {Meeting} meeting
|
|
@@ -311,11 +315,11 @@ var MuteState = /*#__PURE__*/function () {
|
|
|
311
315
|
key: "applyUnmuteAllowedToStream",
|
|
312
316
|
value: function applyUnmuteAllowedToStream(meeting) {
|
|
313
317
|
if (this.type === _constants.AUDIO) {
|
|
314
|
-
var _meeting$
|
|
315
|
-
(_meeting$
|
|
318
|
+
var _meeting$mediaPropert11;
|
|
319
|
+
(_meeting$mediaPropert11 = meeting.mediaProperties.audioStream) === null || _meeting$mediaPropert11 === void 0 ? void 0 : _meeting$mediaPropert11.setUnmuteAllowed(this.state.server.unmuteAllowed);
|
|
316
320
|
} else {
|
|
317
|
-
var _meeting$
|
|
318
|
-
(_meeting$
|
|
321
|
+
var _meeting$mediaPropert12;
|
|
322
|
+
(_meeting$mediaPropert12 = meeting.mediaProperties.videoStream) === null || _meeting$mediaPropert12 === void 0 ? void 0 : _meeting$mediaPropert12.setUnmuteAllowed(this.state.server.unmuteAllowed);
|
|
319
323
|
}
|
|
320
324
|
}
|
|
321
325
|
|
|
@@ -339,7 +343,7 @@ var MuteState = /*#__PURE__*/function () {
|
|
|
339
343
|
}
|
|
340
344
|
if (muted !== undefined) {
|
|
341
345
|
this.state.server.remoteMute = muted;
|
|
342
|
-
this.
|
|
346
|
+
this.muteLocalStream(meeting, muted, 'remotelyMuted');
|
|
343
347
|
}
|
|
344
348
|
}
|
|
345
349
|
|
|
@@ -362,8 +366,16 @@ var MuteState = /*#__PURE__*/function () {
|
|
|
362
366
|
|
|
363
367
|
// 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
|
|
364
368
|
this.state.server.remoteMute = false;
|
|
365
|
-
|
|
366
|
-
|
|
369
|
+
|
|
370
|
+
// change user mute state to false, but keep localMute true if overall mute state is still true
|
|
371
|
+
this.muteLocalStream(meeting, false, 'localUnmuteRequired');
|
|
372
|
+
if (this.type === _constants.AUDIO) {
|
|
373
|
+
var _meeting$mediaPropert13;
|
|
374
|
+
this.state.client.localMute = (_meeting$mediaPropert13 = meeting.mediaProperties.audioStream) === null || _meeting$mediaPropert13 === void 0 ? void 0 : _meeting$mediaPropert13.muted;
|
|
375
|
+
} else {
|
|
376
|
+
var _meeting$mediaPropert14;
|
|
377
|
+
this.state.client.localMute = (_meeting$mediaPropert14 = meeting.mediaProperties.videoStream) === null || _meeting$mediaPropert14 === void 0 ? void 0 : _meeting$mediaPropert14.muted;
|
|
378
|
+
}
|
|
367
379
|
this.applyClientStateToServer(meeting);
|
|
368
380
|
}
|
|
369
381
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createMuteState","type","meeting","enabled","LoggerProxy","logger","info","id","muteState","MuteState","AUDIO","VIDEO","ParameterError","ignoreMuteStateChange","state","client","localMute","server","remoteMute","remoteMuted","remoteVideoMuted","unmuteAllowed","unmuteVideoAllowed","syncToServerInProgress","applyUnmuteAllowedToStream","muteLocalStream","initialMute","mediaProperties","audioStream","muted","videoStream","undefined","applyClientStateToServer","init","enable","mute","reason","setServerMuted","localMuteState","getClientLocalMuteState","localMuteRequiresSync","remoteMuteRequiresSync","localMuteSyncPromise","sendLocalMuteRequestToServer","resolve","then","sendRemoteMuteRequestToServer","catch","e","warn","applyServerMuteToLocalStream","audioMuted","videoMuted","MeetingUtil","remoteUpdateAudioVideo","locus","locusInfo","handleLocusDelta","remoteUpdateError","reject","members","muteMember","selfId","serverMuteReason","setUnmuteAllowed","applyClientStateLocally"],"sources":["muteState.ts"],"sourcesContent":["import {ServerMuteReason} from '@webex/media-helpers';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport ParameterError from '../common/errors/parameter';\nimport MeetingUtil from './util';\nimport {AUDIO, VIDEO} from '../constants';\n\n// eslint-disable-next-line import/prefer-default-export\nexport const createMuteState = (type, meeting, enabled: boolean) => {\n // todo: remove the meeting argument (SPARK-399695)\n\n LoggerProxy.logger.info(\n `Meeting:muteState#createMuteState --> ${type}: creating MuteState for meeting id ${meeting?.id}`\n );\n\n const muteState = new MuteState(type, meeting, enabled);\n\n return muteState;\n};\n\n/** The purpose of this class is to manage the local and remote mute state and make sure that the server state always matches\n the last requested state by the client.\n\n More info about Locus muting API: https://sqbu-github.cisco.com/pages/WebExSquared/locus/guides/mute.html#\n\n This class is exported only for unit tests. It should never be instantiated directly with new MuteState(), instead createMuteState() should be called\n*/\nexport class MuteState {\n state: {\n client: {\n enabled: boolean; // indicates if audio/video is enabled at all or not\n localMute: boolean;\n };\n server: {localMute: boolean; remoteMute: boolean; unmuteAllowed: boolean};\n syncToServerInProgress: boolean;\n };\n\n type: any;\n ignoreMuteStateChange: boolean;\n\n /**\n * Constructor\n *\n * @param {String} type - audio or video\n * @param {Object} meeting - the meeting object (used for reading current remote mute status)\n * @param {boolean} enabled - whether the client audio/video is enabled at all\n */\n constructor(type: string, meeting: any, enabled: boolean) {\n if (type !== AUDIO && type !== VIDEO) {\n throw new ParameterError('Mute state is designed for handling audio or video only');\n }\n this.type = type;\n this.ignoreMuteStateChange = false;\n this.state = {\n client: {\n enabled,\n localMute: true,\n },\n server: {\n localMute: true,\n // because remoteVideoMuted and unmuteVideoAllowed are updated seperately, they might be undefined\n remoteMute: type === AUDIO ? meeting.remoteMuted : meeting.remoteVideoMuted ?? false,\n unmuteAllowed: type === AUDIO ? meeting.unmuteAllowed : meeting.unmuteVideoAllowed ?? true,\n },\n syncToServerInProgress: false,\n };\n }\n\n /**\n * Starts the mute state machine. Needs to be called after a new MuteState instance is created.\n *\n * @param {Object} meeting - the meeting object\n * @returns {void}\n */\n public init(meeting: any) {\n this.applyUnmuteAllowedToStream(meeting);\n\n // if we are remotely muted, we need to apply that to the local stream now (mute on-entry)\n if (this.state.server.remoteMute) {\n this.muteLocalStream(meeting, this.state.server.remoteMute, 'remotelyMuted');\n }\n\n const initialMute =\n this.type === AUDIO\n ? meeting.mediaProperties.audioStream?.muted\n : meeting.mediaProperties.videoStream?.muted;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#init --> ${this.type}: local stream initial mute state: ${initialMute}`\n );\n\n if (initialMute !== undefined) {\n this.state.client.localMute = initialMute;\n } else {\n // there is no stream, so it's like we are locally muted\n // (this is important especially for transcoded meetings, in which the SDP m-line direction always stays \"sendrecv\")\n this.state.client.localMute = true;\n }\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * This method needs to be called whenever the local audio/video stream has changed.\n * It reapplies the remote mute state onto the new stream and also reads the current\n * local mute state from the stream and updates the internal state machine and sends\n * any required requests to the server.\n *\n * @param {Object} meeting - the meeting object\n * @returns {void}\n */\n public handleLocalStreamChange(meeting: any) {\n return this.init(meeting);\n }\n\n /**\n * Enables/disables audio/video\n *\n * @param {Object} meeting - the meeting object\n * @param {boolean} enable\n * @returns {void}\n */\n public enable(meeting: any, enable: boolean) {\n this.state.client.enabled = enable;\n\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Mutes/unmutes local stream\n *\n * @param {Object} meeting - the meeting object\n * @param {Boolean} mute - true to mute the stream, false to unmute it\n * @param {ServerMuteReason} reason - reason for muting/unmuting\n * @returns {void}\n */\n private muteLocalStream(meeting: any, mute: boolean, reason: ServerMuteReason) {\n this.ignoreMuteStateChange = true;\n if (this.type === AUDIO) {\n meeting.mediaProperties.audioStream?.setServerMuted(mute, reason);\n } else {\n meeting.mediaProperties.videoStream?.setServerMuted(mute, reason);\n }\n this.ignoreMuteStateChange = false;\n }\n\n /**\n * This method should be called when the local stream mute state is changed\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @param {Boolean} [mute] true for muting, false for unmuting request\n * @returns {void}\n */\n public handleLocalStreamMuteStateChange(meeting?: object, mute?: boolean) {\n if (this.ignoreMuteStateChange) {\n return;\n }\n LoggerProxy.logger.info(\n `Meeting:muteState#handleLocalStreamMuteStateChange --> ${this.type}: local stream new mute state: ${mute}`\n );\n\n this.state.client.localMute = mute;\n\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Applies the current mute state to the local stream (by enabling or disabling it accordingly)\n *\n * @public\n * @param {Object} [meeting] the meeting object\n * @param {ServerMuteReason} reason - reason why we're applying our client state to the local stream\n * @memberof MuteState\n * @returns {void}\n */\n public applyClientStateLocally(meeting?: any, reason?: ServerMuteReason) {\n this.muteLocalStream(meeting, this.state.client.localMute, reason);\n }\n\n /** Returns true if client is locally muted - it takes into account not just the client local mute state,\n * but also whether audio/video is enabled at all\n *\n * @returns {boolean}\n */\n private getClientLocalMuteState() {\n return this.state.client.enabled ? this.state.client.localMute : true;\n }\n\n /**\n * Updates the server local and remote mute values so that they match the current client desired state.\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {void}\n */\n private applyClientStateToServer(meeting?: any) {\n if (this.state.syncToServerInProgress) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: request to server in progress, we need to wait for it to complete`\n );\n\n return;\n }\n\n const localMuteState = this.getClientLocalMuteState();\n const localMuteRequiresSync = localMuteState !== this.state.server.localMute;\n const remoteMuteRequiresSync = !localMuteState && this.state.server.remoteMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: localMuteRequiresSync: ${localMuteRequiresSync} (${localMuteState} ?= ${this.state.server.localMute})`\n );\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: remoteMuteRequiresSync: ${remoteMuteRequiresSync}`\n );\n\n if (!localMuteRequiresSync && !remoteMuteRequiresSync) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: client state already matching server state, nothing to do`\n );\n\n return;\n }\n\n this.state.syncToServerInProgress = true;\n\n // first sync local mute with server\n const localMuteSyncPromise = localMuteRequiresSync\n ? this.sendLocalMuteRequestToServer(meeting)\n : Promise.resolve();\n\n localMuteSyncPromise\n .then(() =>\n // then follow it up with remote mute sync\n remoteMuteRequiresSync ? this.sendRemoteMuteRequestToServer(meeting) : Promise.resolve()\n )\n .then(() => {\n this.state.syncToServerInProgress = false;\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: sync with server completed`\n );\n\n // need to check if a new sync is required, because this.state.client may have changed while we were doing the current sync\n this.applyClientStateToServer(meeting);\n })\n .catch((e) => {\n this.state.syncToServerInProgress = false;\n\n LoggerProxy.logger.warn(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: error: ${e}`\n );\n\n this.applyServerMuteToLocalStream(meeting, 'clientRequestFailed');\n });\n }\n\n /**\n * Sets the local mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendLocalMuteRequestToServer(meeting?: any) {\n const audioMuted = this.type === AUDIO ? this.getClientLocalMuteState() : undefined;\n const videoMuted = this.type === VIDEO ? this.getClientLocalMuteState() : undefined;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: sending local mute (audio=${audioMuted}, video=${videoMuted}) to server`\n );\n\n return MeetingUtil.remoteUpdateAudioVideo(meeting, audioMuted, videoMuted)\n .then((locus) => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: local mute (audio=${audioMuted}, video=${videoMuted}) applied to server`\n );\n\n this.state.server.localMute = this.type === AUDIO ? audioMuted : videoMuted;\n\n if (locus) {\n meeting.locusInfo.handleLocusDelta(locus, meeting);\n }\n\n return locus;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: failed to apply local mute (audio=${audioMuted}, video=${videoMuted}) to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n /**\n * Sets the remote mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendRemoteMuteRequestToServer(meeting?: any) {\n const remoteMute = this.getClientLocalMuteState();\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: sending remote mute:${remoteMute} to server`\n );\n\n return meeting.members\n .muteMember(meeting.members.selfId, remoteMute, this.type === AUDIO)\n .then(() => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: remote mute:${remoteMute} applied to server`\n );\n\n this.state.server.remoteMute = remoteMute;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: failed to apply remote mute ${remoteMute} to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n /** Sets the mute state of the local stream according to what server thinks is our state\n * @param {Object} meeting - the meeting object\n * @param {ServerMuteReason} serverMuteReason - reason why we're applying server mute to the local stream\n * @returns {void}\n */\n private applyServerMuteToLocalStream(meeting: any, serverMuteReason: ServerMuteReason) {\n const muted = this.state.server.localMute || this.state.server.remoteMute;\n\n // update the local stream mute state, but not this.state.client.localMute\n this.muteLocalStream(meeting, muted, serverMuteReason);\n }\n\n /** Applies the current value for unmute allowed to the underlying stream\n *\n * @param {Meeting} meeting\n * @returns {void}\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n private applyUnmuteAllowedToStream(meeting: any) {\n if (this.type === AUDIO) {\n meeting.mediaProperties.audioStream?.setUnmuteAllowed(this.state.server.unmuteAllowed);\n } else {\n meeting.mediaProperties.videoStream?.setUnmuteAllowed(this.state.server.unmuteAllowed);\n }\n }\n\n /**\n * This method should be called whenever the server remote mute state is changed\n *\n * @public\n * @memberof MuteState\n * @param {Meeting} meeting\n * @param {Boolean} [muted] true if user is remotely muted, false otherwise\n * @param {Boolean} [unmuteAllowed] indicates if user is allowed to unmute self (false when \"hard mute\" feature is used)\n * @returns {undefined}\n */\n public handleServerRemoteMuteUpdate(meeting: any, muted?: boolean, unmuteAllowed?: boolean) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerRemoteMuteUpdate --> ${this.type}: updating server remoteMute to (${muted})`\n );\n if (unmuteAllowed !== undefined) {\n this.state.server.unmuteAllowed = unmuteAllowed;\n this.applyUnmuteAllowedToStream(meeting);\n }\n if (muted !== undefined) {\n this.state.server.remoteMute = muted;\n this.applyServerMuteToLocalStream(meeting, 'remotelyMuted');\n }\n }\n\n /**\n * This method should be called whenever we receive from the server a requirement to locally unmute\n *\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @returns {undefined}\n */\n public handleServerLocalUnmuteRequired(meeting?: object) {\n if (!this.state.client.enabled) {\n LoggerProxy.logger.warn(\n `Meeting:muteState#handleServerLocalUnmuteRequired --> ${this.type}: localAudioUnmuteRequired received while ${this.type} is disabled -> local unmute will not result in ${this.type} being sent`\n );\n } else {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerLocalUnmuteRequired --> ${this.type}: localAudioUnmuteRequired received -> doing local unmute`\n );\n }\n\n // 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\n this.state.server.remoteMute = false;\n this.state.client.localMute = false;\n\n this.applyClientStateLocally(meeting, 'localUnmuteRequired');\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Returns true if the user is locally or remotely muted.\n * It only checks the mute status, ignoring the fact whether audio/video is enabled.\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isMuted() {\n return (\n this.state.client.localMute || this.state.server.localMute || this.state.server.remoteMute\n );\n }\n\n /**\n * Returns true if the user is remotely muted\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isRemotelyMuted() {\n return this.state.server.remoteMute;\n }\n\n /**\n * Returns true if unmute is allowed\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isUnmuteAllowed() {\n return this.state.server.unmuteAllowed;\n }\n\n /**\n * Returns true if the user is locally muted or audio/video is disabled\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isLocallyMuted() {\n return this.getClientLocalMuteState();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["createMuteState","type","meeting","enabled","LoggerProxy","logger","info","id","muteState","MuteState","AUDIO","VIDEO","ParameterError","ignoreMuteStateChange","state","client","localMute","server","remoteMute","remoteMuted","remoteVideoMuted","unmuteAllowed","unmuteVideoAllowed","syncToServerInProgress","applyUnmuteAllowedToStream","muteLocalStream","initialMute","mediaProperties","audioStream","muted","videoStream","undefined","applyClientStateToServer","init","enable","mute","reason","setServerMuted","newMuteState","userMuteState","systemMuteState","userMuted","systemMuted","localMuteState","getClientLocalMuteState","localMuteRequiresSync","remoteMuteRequiresSync","localMuteSyncPromise","sendLocalMuteRequestToServer","resolve","then","sendRemoteMuteRequestToServer","catch","e","warn","audioMuted","videoMuted","MeetingUtil","remoteUpdateAudioVideo","locus","locusInfo","handleLocusDelta","remoteUpdateError","reject","members","muteMember","selfId","setUnmuteAllowed"],"sources":["muteState.ts"],"sourcesContent":["import {ServerMuteReason} from '@webex/media-helpers';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport ParameterError from '../common/errors/parameter';\nimport MeetingUtil from './util';\nimport {AUDIO, VIDEO} from '../constants';\n\n// eslint-disable-next-line import/prefer-default-export\nexport const createMuteState = (type, meeting, enabled: boolean) => {\n // todo: remove the meeting argument (SPARK-399695)\n\n LoggerProxy.logger.info(\n `Meeting:muteState#createMuteState --> ${type}: creating MuteState for meeting id ${meeting?.id}`\n );\n\n const muteState = new MuteState(type, meeting, enabled);\n\n return muteState;\n};\n\n/** The purpose of this class is to manage the local and remote mute state and make sure that the server state always matches\n the last requested state by the client.\n\n More info about Locus muting API: https://sqbu-github.cisco.com/pages/WebExSquared/locus/guides/mute.html#\n\n This class is exported only for unit tests. It should never be instantiated directly with new MuteState(), instead createMuteState() should be called\n*/\nexport class MuteState {\n state: {\n client: {\n enabled: boolean; // indicates if audio/video is enabled at all or not\n localMute: boolean;\n };\n server: {localMute: boolean; remoteMute: boolean; unmuteAllowed: boolean};\n syncToServerInProgress: boolean;\n };\n\n type: any;\n ignoreMuteStateChange: boolean;\n\n /**\n * Constructor\n *\n * @param {String} type - audio or video\n * @param {Object} meeting - the meeting object (used for reading current remote mute status)\n * @param {boolean} enabled - whether the client audio/video is enabled at all\n */\n constructor(type: string, meeting: any, enabled: boolean) {\n if (type !== AUDIO && type !== VIDEO) {\n throw new ParameterError('Mute state is designed for handling audio or video only');\n }\n this.type = type;\n this.ignoreMuteStateChange = false;\n this.state = {\n client: {\n enabled,\n localMute: true,\n },\n server: {\n localMute: true,\n // because remoteVideoMuted and unmuteVideoAllowed are updated seperately, they might be undefined\n remoteMute: type === AUDIO ? meeting.remoteMuted : meeting.remoteVideoMuted ?? false,\n unmuteAllowed: type === AUDIO ? meeting.unmuteAllowed : meeting.unmuteVideoAllowed ?? true,\n },\n syncToServerInProgress: false,\n };\n }\n\n /**\n * Starts the mute state machine. Needs to be called after a new MuteState instance is created.\n *\n * @param {Object} meeting - the meeting object\n * @returns {void}\n */\n public init(meeting: any) {\n this.applyUnmuteAllowedToStream(meeting);\n\n // if we are remotely muted, we need to apply that to the local stream now (mute on-entry)\n if (this.state.server.remoteMute) {\n this.muteLocalStream(meeting, this.state.server.remoteMute, 'remotelyMuted');\n }\n\n const initialMute =\n this.type === AUDIO\n ? meeting.mediaProperties.audioStream?.muted\n : meeting.mediaProperties.videoStream?.muted;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#init --> ${this.type}: local stream initial mute state: ${initialMute}`\n );\n\n if (initialMute !== undefined) {\n this.state.client.localMute = initialMute;\n } else {\n // there is no stream, so it's like we are locally muted\n // (this is important especially for transcoded meetings, in which the SDP m-line direction always stays \"sendrecv\")\n this.state.client.localMute = true;\n }\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * This method needs to be called whenever the local audio/video stream has changed.\n * It reapplies the remote mute state onto the new stream and also reads the current\n * local mute state from the stream and updates the internal state machine and sends\n * any required requests to the server.\n *\n * @param {Object} meeting - the meeting object\n * @returns {void}\n */\n public handleLocalStreamChange(meeting: any) {\n return this.init(meeting);\n }\n\n /**\n * Enables/disables audio/video\n *\n * @param {Object} meeting - the meeting object\n * @param {boolean} enable\n * @returns {void}\n */\n public enable(meeting: any, enable: boolean) {\n this.state.client.enabled = enable;\n\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Mutes/unmutes local stream\n *\n * @param {Object} meeting - the meeting object\n * @param {Boolean} mute - true to mute the stream, false to unmute it\n * @param {ServerMuteReason} reason - reason for muting/unmuting\n * @returns {void}\n */\n private muteLocalStream(meeting: any, mute: boolean, reason: ServerMuteReason) {\n this.ignoreMuteStateChange = true;\n if (this.type === AUDIO) {\n meeting.mediaProperties.audioStream?.setServerMuted(mute, reason);\n } else {\n meeting.mediaProperties.videoStream?.setServerMuted(mute, reason);\n }\n this.ignoreMuteStateChange = false;\n }\n\n /**\n * This method should be called when the local stream mute state is changed\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @param {Boolean} [mute] true for muting, false for unmuting request\n * @returns {void}\n */\n public handleLocalStreamMuteStateChange(meeting?: any) {\n if (this.ignoreMuteStateChange) {\n return;\n }\n\n // either user or system may have triggered a mute state change, but localMute should reflect both\n let newMuteState: boolean;\n let userMuteState: boolean;\n let systemMuteState: boolean;\n if (this.type === AUDIO) {\n newMuteState = meeting.mediaProperties.audioStream?.muted;\n userMuteState = meeting.mediaProperties.audioStream?.userMuted;\n systemMuteState = meeting.mediaProperties.audioStream?.systemMuted;\n } else {\n newMuteState = meeting.mediaProperties.videoStream?.muted;\n userMuteState = meeting.mediaProperties.videoStream?.userMuted;\n systemMuteState = meeting.mediaProperties.videoStream?.systemMuted;\n }\n\n LoggerProxy.logger.info(\n `Meeting:muteState#handleLocalStreamMuteStateChange --> ${this.type}: local stream new mute state: ${newMuteState} (user mute: ${userMuteState}, system mute: ${systemMuteState})`\n );\n\n this.state.client.localMute = newMuteState;\n\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Applies the current mute state to the local stream (by enabling or disabling it accordingly)\n *\n * @public\n * @param {Object} [meeting] the meeting object\n * @param {ServerMuteReason} reason - reason why we're applying our client state to the local stream\n * @memberof MuteState\n * @returns {void}\n */\n public applyClientStateLocally(meeting?: any, reason?: ServerMuteReason) {\n this.muteLocalStream(meeting, this.state.client.localMute, reason);\n }\n\n /** Returns true if client is locally muted - it takes into account not just the client local mute state,\n * but also whether audio/video is enabled at all\n *\n * @returns {boolean}\n */\n private getClientLocalMuteState() {\n return this.state.client.enabled ? this.state.client.localMute : true;\n }\n\n /**\n * Updates the server local and remote mute values so that they match the current client desired state.\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {void}\n */\n private applyClientStateToServer(meeting?: any) {\n if (this.state.syncToServerInProgress) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: request to server in progress, we need to wait for it to complete`\n );\n\n return;\n }\n\n const localMuteState = this.getClientLocalMuteState();\n const localMuteRequiresSync = localMuteState !== this.state.server.localMute;\n const remoteMuteRequiresSync = !localMuteState && this.state.server.remoteMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: localMuteRequiresSync: ${localMuteRequiresSync} (${localMuteState} ?= ${this.state.server.localMute})`\n );\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: remoteMuteRequiresSync: ${remoteMuteRequiresSync}`\n );\n\n if (!localMuteRequiresSync && !remoteMuteRequiresSync) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: client state already matching server state, nothing to do`\n );\n\n return;\n }\n\n this.state.syncToServerInProgress = true;\n\n // first sync local mute with server\n const localMuteSyncPromise = localMuteRequiresSync\n ? this.sendLocalMuteRequestToServer(meeting)\n : Promise.resolve();\n\n localMuteSyncPromise\n .then(() =>\n // then follow it up with remote mute sync\n remoteMuteRequiresSync ? this.sendRemoteMuteRequestToServer(meeting) : Promise.resolve()\n )\n .then(() => {\n this.state.syncToServerInProgress = false;\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: sync with server completed`\n );\n\n // need to check if a new sync is required, because this.state.client may have changed while we were doing the current sync\n this.applyClientStateToServer(meeting);\n })\n .catch((e) => {\n this.state.syncToServerInProgress = false;\n\n LoggerProxy.logger.warn(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: error: ${e}`\n );\n\n // failed to apply client state to server, so revert stream mute state to server state\n this.muteLocalStream(\n meeting,\n this.state.server.localMute || this.state.server.remoteMute,\n 'clientRequestFailed'\n );\n });\n }\n\n /**\n * Sets the local mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendLocalMuteRequestToServer(meeting?: any) {\n const audioMuted = this.type === AUDIO ? this.getClientLocalMuteState() : undefined;\n const videoMuted = this.type === VIDEO ? this.getClientLocalMuteState() : undefined;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: sending local mute (audio=${audioMuted}, video=${videoMuted}) to server`\n );\n\n return MeetingUtil.remoteUpdateAudioVideo(meeting, audioMuted, videoMuted)\n .then((locus) => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: local mute (audio=${audioMuted}, video=${videoMuted}) applied to server`\n );\n\n this.state.server.localMute = this.type === AUDIO ? audioMuted : videoMuted;\n\n if (locus) {\n meeting.locusInfo.handleLocusDelta(locus, meeting);\n }\n\n return locus;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: failed to apply local mute (audio=${audioMuted}, video=${videoMuted}) to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n /**\n * Sets the remote mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendRemoteMuteRequestToServer(meeting?: any) {\n const remoteMute = this.getClientLocalMuteState();\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: sending remote mute:${remoteMute} to server`\n );\n\n return meeting.members\n .muteMember(meeting.members.selfId, remoteMute, this.type === AUDIO)\n .then(() => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: remote mute:${remoteMute} applied to server`\n );\n\n this.state.server.remoteMute = remoteMute;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: failed to apply remote mute ${remoteMute} to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n /** Applies the current value for unmute allowed to the underlying stream\n *\n * @param {Meeting} meeting\n * @returns {void}\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n private applyUnmuteAllowedToStream(meeting: any) {\n if (this.type === AUDIO) {\n meeting.mediaProperties.audioStream?.setUnmuteAllowed(this.state.server.unmuteAllowed);\n } else {\n meeting.mediaProperties.videoStream?.setUnmuteAllowed(this.state.server.unmuteAllowed);\n }\n }\n\n /**\n * This method should be called whenever the server remote mute state is changed\n *\n * @public\n * @memberof MuteState\n * @param {Meeting} meeting\n * @param {Boolean} [muted] true if user is remotely muted, false otherwise\n * @param {Boolean} [unmuteAllowed] indicates if user is allowed to unmute self (false when \"hard mute\" feature is used)\n * @returns {undefined}\n */\n public handleServerRemoteMuteUpdate(meeting: any, muted?: boolean, unmuteAllowed?: boolean) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerRemoteMuteUpdate --> ${this.type}: updating server remoteMute to (${muted})`\n );\n if (unmuteAllowed !== undefined) {\n this.state.server.unmuteAllowed = unmuteAllowed;\n this.applyUnmuteAllowedToStream(meeting);\n }\n if (muted !== undefined) {\n this.state.server.remoteMute = muted;\n this.muteLocalStream(meeting, muted, 'remotelyMuted');\n }\n }\n\n /**\n * This method should be called whenever we receive from the server a requirement to locally unmute\n *\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @returns {undefined}\n */\n public handleServerLocalUnmuteRequired(meeting?: any) {\n if (!this.state.client.enabled) {\n LoggerProxy.logger.warn(\n `Meeting:muteState#handleServerLocalUnmuteRequired --> ${this.type}: localAudioUnmuteRequired received while ${this.type} is disabled -> local unmute will not result in ${this.type} being sent`\n );\n } else {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerLocalUnmuteRequired --> ${this.type}: localAudioUnmuteRequired received -> doing local unmute`\n );\n }\n\n // 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\n this.state.server.remoteMute = false;\n\n // change user mute state to false, but keep localMute true if overall mute state is still true\n this.muteLocalStream(meeting, false, 'localUnmuteRequired');\n if (this.type === AUDIO) {\n this.state.client.localMute = meeting.mediaProperties.audioStream?.muted;\n } else {\n this.state.client.localMute = meeting.mediaProperties.videoStream?.muted;\n }\n\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Returns true if the user is locally or remotely muted.\n * It only checks the mute status, ignoring the fact whether audio/video is enabled.\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isMuted() {\n return (\n this.state.client.localMute || this.state.server.localMute || this.state.server.remoteMute\n );\n }\n\n /**\n * Returns true if the user is remotely muted\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isRemotelyMuted() {\n return this.state.server.remoteMute;\n }\n\n /**\n * Returns true if unmute is allowed\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isUnmuteAllowed() {\n return this.state.server.unmuteAllowed;\n }\n\n /**\n * Returns true if the user is locally muted or audio/video is disabled\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isLocallyMuted() {\n return this.getClientLocalMuteState();\n }\n}\n"],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Meetings from './meetings';
|
|
2
|
-
export { getDevices, LocalStream, LocalDisplayStream, LocalSystemAudioStream, LocalStreamEventNames, StreamEventNames, type ServerMuteReason, LocalMicrophoneStreamEventNames, LocalCameraStreamEventNames, LocalMicrophoneStream, LocalCameraStream, createMicrophoneStream, createCameraStream, createDisplayStream, createDisplayStreamWithAudio, FacingMode, DisplaySurface, PresetCameraConstraints, type VideoContentHint, } from '@webex/media-helpers';
|
|
2
|
+
export { getDevices, LocalStream, LocalDisplayStream, LocalSystemAudioStream, LocalStreamEventNames, StreamEventNames, RemoteStreamEventNames, type ServerMuteReason, LocalMicrophoneStreamEventNames, LocalCameraStreamEventNames, LocalMicrophoneStream, LocalCameraStream, createMicrophoneStream, createCameraStream, createDisplayStream, createDisplayStreamWithAudio, FacingMode, DisplaySurface, PresetCameraConstraints, type VideoContentHint, } from '@webex/media-helpers';
|
|
3
3
|
export default Meetings;
|
|
4
4
|
export * as CONSTANTS from './constants';
|
|
5
5
|
export * as REACTIONS from './reactions/reactions';
|
|
@@ -435,8 +435,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
435
435
|
resourceUrl: string;
|
|
436
436
|
selfId: string;
|
|
437
437
|
state: any;
|
|
438
|
-
localAudioStreamMuteStateHandler: (
|
|
439
|
-
localVideoStreamMuteStateHandler: (
|
|
438
|
+
localAudioStreamMuteStateHandler: () => void;
|
|
439
|
+
localVideoStreamMuteStateHandler: () => void;
|
|
440
440
|
localOutputTrackChangeHandler: () => void;
|
|
441
441
|
roles: any[];
|
|
442
442
|
environment: string;
|
|
@@ -72,7 +72,7 @@ export declare class MuteState {
|
|
|
72
72
|
* @param {Boolean} [mute] true for muting, false for unmuting request
|
|
73
73
|
* @returns {void}
|
|
74
74
|
*/
|
|
75
|
-
handleLocalStreamMuteStateChange(meeting?:
|
|
75
|
+
handleLocalStreamMuteStateChange(meeting?: any): void;
|
|
76
76
|
/**
|
|
77
77
|
* Applies the current mute state to the local stream (by enabling or disabling it accordingly)
|
|
78
78
|
*
|
|
@@ -116,12 +116,6 @@ export declare class MuteState {
|
|
|
116
116
|
* @returns {Promise}
|
|
117
117
|
*/
|
|
118
118
|
private sendRemoteMuteRequestToServer;
|
|
119
|
-
/** Sets the mute state of the local stream according to what server thinks is our state
|
|
120
|
-
* @param {Object} meeting - the meeting object
|
|
121
|
-
* @param {ServerMuteReason} serverMuteReason - reason why we're applying server mute to the local stream
|
|
122
|
-
* @returns {void}
|
|
123
|
-
*/
|
|
124
|
-
private applyServerMuteToLocalStream;
|
|
125
119
|
/** Applies the current value for unmute allowed to the underlying stream
|
|
126
120
|
*
|
|
127
121
|
* @param {Meeting} meeting
|
|
@@ -147,7 +141,7 @@ export declare class MuteState {
|
|
|
147
141
|
* @param {Object} [meeting] the meeting object
|
|
148
142
|
* @returns {undefined}
|
|
149
143
|
*/
|
|
150
|
-
handleServerLocalUnmuteRequired(meeting?:
|
|
144
|
+
handleServerLocalUnmuteRequired(meeting?: any): void;
|
|
151
145
|
/**
|
|
152
146
|
* Returns true if the user is locally or remotely muted.
|
|
153
147
|
* It only checks the mute status, ignoring the fact whether audio/video is enabled.
|
package/dist/webinar/index.js
CHANGED
|
@@ -62,7 +62,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
|
|
|
62
62
|
updateCanManageWebcast: function updateCanManageWebcast(canManageWebcast) {
|
|
63
63
|
this.set('canManageWebcast', canManageWebcast);
|
|
64
64
|
},
|
|
65
|
-
version: "3.0.0-beta.
|
|
65
|
+
version: "3.0.0-beta.398"
|
|
66
66
|
});
|
|
67
67
|
var _default = Webinar;
|
|
68
68
|
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.398",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@peculiar/webcrypto": "^1.4.3",
|
|
36
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
41
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
36
|
+
"@webex/plugin-meetings": "3.0.0-beta.398",
|
|
37
|
+
"@webex/test-helper-chai": "3.0.0-beta.398",
|
|
38
|
+
"@webex/test-helper-mocha": "3.0.0-beta.398",
|
|
39
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.398",
|
|
40
|
+
"@webex/test-helper-retry": "3.0.0-beta.398",
|
|
41
|
+
"@webex/test-helper-test-users": "3.0.0-beta.398",
|
|
42
42
|
"chai": "^4.3.4",
|
|
43
43
|
"chai-as-promised": "^7.1.1",
|
|
44
44
|
"jsdom-global": "3.0.2",
|
|
@@ -47,19 +47,19 @@
|
|
|
47
47
|
"typescript": "^4.7.4"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@webex/common": "3.0.0-beta.
|
|
51
|
-
"@webex/internal-media-core": "2.
|
|
52
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
58
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
59
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
61
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
62
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
50
|
+
"@webex/common": "3.0.0-beta.398",
|
|
51
|
+
"@webex/internal-media-core": "2.3.0",
|
|
52
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.398",
|
|
53
|
+
"@webex/internal-plugin-device": "3.0.0-beta.398",
|
|
54
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.398",
|
|
55
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.398",
|
|
56
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.398",
|
|
57
|
+
"@webex/internal-plugin-support": "3.0.0-beta.398",
|
|
58
|
+
"@webex/internal-plugin-user": "3.0.0-beta.398",
|
|
59
|
+
"@webex/media-helpers": "3.0.0-beta.398",
|
|
60
|
+
"@webex/plugin-people": "3.0.0-beta.398",
|
|
61
|
+
"@webex/plugin-rooms": "3.0.0-beta.398",
|
|
62
|
+
"@webex/webex-core": "3.0.0-beta.398",
|
|
63
63
|
"ampersand-collection": "^2.0.2",
|
|
64
64
|
"bowser": "^2.11.0",
|
|
65
65
|
"btoa": "^1.2.1",
|
package/src/index.ts
CHANGED
package/src/meeting/index.ts
CHANGED
|
@@ -615,8 +615,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
615
615
|
resourceUrl: string;
|
|
616
616
|
selfId: string;
|
|
617
617
|
state: any;
|
|
618
|
-
localAudioStreamMuteStateHandler: (
|
|
619
|
-
localVideoStreamMuteStateHandler: (
|
|
618
|
+
localAudioStreamMuteStateHandler: () => void;
|
|
619
|
+
localVideoStreamMuteStateHandler: () => void;
|
|
620
620
|
localOutputTrackChangeHandler: () => void;
|
|
621
621
|
roles: any[];
|
|
622
622
|
environment: string;
|
|
@@ -1381,12 +1381,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1381
1381
|
*/
|
|
1382
1382
|
this.remoteMediaManager = null;
|
|
1383
1383
|
|
|
1384
|
-
this.localAudioStreamMuteStateHandler = (
|
|
1385
|
-
this.audio.handleLocalStreamMuteStateChange(this
|
|
1384
|
+
this.localAudioStreamMuteStateHandler = () => {
|
|
1385
|
+
this.audio.handleLocalStreamMuteStateChange(this);
|
|
1386
1386
|
};
|
|
1387
1387
|
|
|
1388
|
-
this.localVideoStreamMuteStateHandler = (
|
|
1389
|
-
this.video.handleLocalStreamMuteStateChange(this
|
|
1388
|
+
this.localVideoStreamMuteStateHandler = () => {
|
|
1389
|
+
this.video.handleLocalStreamMuteStateChange(this);
|
|
1390
1390
|
};
|
|
1391
1391
|
|
|
1392
1392
|
// The handling of output track changes should be done inside
|
|
@@ -3074,6 +3074,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3074
3074
|
options: {meetingId: this.id},
|
|
3075
3075
|
});
|
|
3076
3076
|
}
|
|
3077
|
+
this.updateLLMConnection();
|
|
3077
3078
|
});
|
|
3078
3079
|
|
|
3079
3080
|
// @ts-ignore - check if MEDIA_INACTIVITY exists
|
|
@@ -3895,7 +3896,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3895
3896
|
private async setLocalAudioStream(localStream?: LocalMicrophoneStream) {
|
|
3896
3897
|
const oldStream = this.mediaProperties.audioStream;
|
|
3897
3898
|
|
|
3898
|
-
oldStream?.off(
|
|
3899
|
+
oldStream?.off(
|
|
3900
|
+
LocalStreamEventNames.UserMuteStateChange,
|
|
3901
|
+
this.localAudioStreamMuteStateHandler
|
|
3902
|
+
);
|
|
3903
|
+
oldStream?.off(
|
|
3904
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
3905
|
+
this.localAudioStreamMuteStateHandler
|
|
3906
|
+
);
|
|
3899
3907
|
oldStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
3900
3908
|
|
|
3901
3909
|
// we don't update this.mediaProperties.mediaDirection.sendAudio, because we always keep it as true to avoid extra SDP exchanges
|
|
@@ -3903,7 +3911,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3903
3911
|
|
|
3904
3912
|
this.audio.handleLocalStreamChange(this);
|
|
3905
3913
|
|
|
3906
|
-
localStream?.on(
|
|
3914
|
+
localStream?.on(
|
|
3915
|
+
LocalStreamEventNames.UserMuteStateChange,
|
|
3916
|
+
this.localAudioStreamMuteStateHandler
|
|
3917
|
+
);
|
|
3918
|
+
localStream?.on(
|
|
3919
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
3920
|
+
this.localAudioStreamMuteStateHandler
|
|
3921
|
+
);
|
|
3907
3922
|
localStream?.on(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
3908
3923
|
|
|
3909
3924
|
if (!this.isMultistream || !localStream) {
|
|
@@ -3923,7 +3938,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3923
3938
|
private async setLocalVideoStream(localStream?: LocalCameraStream) {
|
|
3924
3939
|
const oldStream = this.mediaProperties.videoStream;
|
|
3925
3940
|
|
|
3926
|
-
oldStream?.off(
|
|
3941
|
+
oldStream?.off(
|
|
3942
|
+
LocalStreamEventNames.UserMuteStateChange,
|
|
3943
|
+
this.localVideoStreamMuteStateHandler
|
|
3944
|
+
);
|
|
3945
|
+
oldStream?.off(
|
|
3946
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
3947
|
+
this.localVideoStreamMuteStateHandler
|
|
3948
|
+
);
|
|
3927
3949
|
oldStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
3928
3950
|
|
|
3929
3951
|
// we don't update this.mediaProperties.mediaDirection.sendVideo, because we always keep it as true to avoid extra SDP exchanges
|
|
@@ -3931,7 +3953,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3931
3953
|
|
|
3932
3954
|
this.video.handleLocalStreamChange(this);
|
|
3933
3955
|
|
|
3934
|
-
localStream?.on(
|
|
3956
|
+
localStream?.on(
|
|
3957
|
+
LocalStreamEventNames.UserMuteStateChange,
|
|
3958
|
+
this.localVideoStreamMuteStateHandler
|
|
3959
|
+
);
|
|
3960
|
+
localStream?.on(
|
|
3961
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
3962
|
+
this.localVideoStreamMuteStateHandler
|
|
3963
|
+
);
|
|
3935
3964
|
localStream?.on(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
3936
3965
|
|
|
3937
3966
|
if (!this.isMultistream || !localStream) {
|
|
@@ -3952,14 +3981,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3952
3981
|
private async setLocalShareVideoStream(localDisplayStream?: LocalDisplayStream) {
|
|
3953
3982
|
const oldStream = this.mediaProperties.shareVideoStream;
|
|
3954
3983
|
|
|
3955
|
-
oldStream?.off(
|
|
3984
|
+
oldStream?.off(
|
|
3985
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
3986
|
+
this.handleShareVideoStreamMuteStateChange
|
|
3987
|
+
);
|
|
3956
3988
|
oldStream?.off(StreamEventNames.Ended, this.handleShareVideoStreamEnded);
|
|
3957
3989
|
oldStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
3958
3990
|
|
|
3959
3991
|
this.mediaProperties.setLocalShareVideoStream(localDisplayStream);
|
|
3960
3992
|
|
|
3961
3993
|
localDisplayStream?.on(
|
|
3962
|
-
|
|
3994
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
3963
3995
|
this.handleShareVideoStreamMuteStateChange
|
|
3964
3996
|
);
|
|
3965
3997
|
localDisplayStream?.on(StreamEventNames.Ended, this.handleShareVideoStreamEnded);
|
|
@@ -4045,10 +4077,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4045
4077
|
public cleanupLocalStreams() {
|
|
4046
4078
|
const {audioStream, videoStream, shareAudioStream, shareVideoStream} = this.mediaProperties;
|
|
4047
4079
|
|
|
4048
|
-
audioStream?.off(
|
|
4080
|
+
audioStream?.off(
|
|
4081
|
+
LocalStreamEventNames.UserMuteStateChange,
|
|
4082
|
+
this.localAudioStreamMuteStateHandler
|
|
4083
|
+
);
|
|
4084
|
+
audioStream?.off(
|
|
4085
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
4086
|
+
this.localAudioStreamMuteStateHandler
|
|
4087
|
+
);
|
|
4049
4088
|
audioStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
4050
4089
|
|
|
4051
|
-
videoStream?.off(
|
|
4090
|
+
videoStream?.off(
|
|
4091
|
+
LocalStreamEventNames.UserMuteStateChange,
|
|
4092
|
+
this.localVideoStreamMuteStateHandler
|
|
4093
|
+
);
|
|
4094
|
+
videoStream?.off(
|
|
4095
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
4096
|
+
this.localVideoStreamMuteStateHandler
|
|
4097
|
+
);
|
|
4052
4098
|
videoStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
4053
4099
|
|
|
4054
4100
|
shareAudioStream?.off(StreamEventNames.Ended, this.handleShareAudioStreamEnded);
|
|
@@ -4056,8 +4102,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4056
4102
|
LocalStreamEventNames.OutputTrackChange,
|
|
4057
4103
|
this.localOutputTrackChangeHandler
|
|
4058
4104
|
);
|
|
4105
|
+
|
|
4059
4106
|
shareVideoStream?.off(
|
|
4060
|
-
|
|
4107
|
+
LocalStreamEventNames.SystemMuteStateChange,
|
|
4061
4108
|
this.handleShareVideoStreamMuteStateChange
|
|
4062
4109
|
);
|
|
4063
4110
|
shareVideoStream?.off(StreamEventNames.Ended, this.handleShareVideoStreamEnded);
|
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
|
|