@webex/plugin-meetings 3.0.0-beta.64 → 3.0.0-beta.66
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 +31 -1
- package/dist/breakouts/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +48 -6
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/types/multistream/mediaRequestManager.d.ts +17 -0
- package/package.json +18 -18
- package/src/breakouts/README.md +5 -0
- package/src/breakouts/index.ts +36 -0
- package/src/multistream/mediaRequestManager.ts +45 -3
- package/test/unit/spec/breakouts/index.ts +30 -0
- package/test/unit/spec/multistream/mediaRequestManager.ts +55 -8
package/dist/breakouts/index.js
CHANGED
|
@@ -731,7 +731,37 @@ var Breakouts = _webexCore.WebexPlugin.extend({
|
|
|
731
731
|
}
|
|
732
732
|
});
|
|
733
733
|
},
|
|
734
|
-
|
|
734
|
+
/**
|
|
735
|
+
* assign participants dynamically after breakout sessions started,
|
|
736
|
+
* but currently it only used for admitting participants from lobby into breakout directly
|
|
737
|
+
* @param {Array} sessions
|
|
738
|
+
* @returns {void}
|
|
739
|
+
*/
|
|
740
|
+
dynamicAssign: function dynamicAssign(sessions) {
|
|
741
|
+
var updatedSessions = sessions.map(function (item) {
|
|
742
|
+
return {
|
|
743
|
+
id: item.id,
|
|
744
|
+
participants: item.participants,
|
|
745
|
+
targetState: item.targetState
|
|
746
|
+
};
|
|
747
|
+
});
|
|
748
|
+
var body = {
|
|
749
|
+
groups: [{
|
|
750
|
+
id: this.breakoutGroupId,
|
|
751
|
+
sessions: updatedSessions
|
|
752
|
+
}],
|
|
753
|
+
editlock: null
|
|
754
|
+
};
|
|
755
|
+
if (this.editLock && this.editLock.token) {
|
|
756
|
+
body.editlock = this.editLock;
|
|
757
|
+
}
|
|
758
|
+
return this.request({
|
|
759
|
+
method: _constants.HTTP_VERBS.PUT,
|
|
760
|
+
uri: "".concat(this.url, "/dynamicAssign"),
|
|
761
|
+
body: body
|
|
762
|
+
});
|
|
763
|
+
},
|
|
764
|
+
version: "3.0.0-beta.66"
|
|
735
765
|
});
|
|
736
766
|
var _default = Breakouts;
|
|
737
767
|
exports.default = _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Breakouts","WebexPlugin","extend","namespace","MEETINGS","breakoutRequest","BreakoutRequest","collections","breakouts","BreakoutCollection","props","allowBackToMain","delayCloseTime","enableBreakoutSession","groupId","name","sessionId","sessionType","startTime","status","url","locusUrl","breakoutServiceUrl","mainLocusUrl","groups","editLock","intervalID","children","currentBreakoutSession","Breakout","derived","isInMainSession","deps","fn","BREAKOUTS","SESSION_TYPES","MAIN","breakoutGroupId","length","id","initialize","listenTo","STATUS","CLOSING","trigger","EVENTS","BREAKOUTS_CLOSING","debouncedQueryRosters","queryRosters","leading","trailing","listenToBroadcastMessages","listenToBreakoutRosters","webex","cleanUp","stopListening","locusUrlUpdate","set","breakoutServiceUrlUpdate","request","uri","qs","btoa","then","result","rosters","body","forEach","locus","handleRosterUpdate","MEMBERS_UPDATE","catch","error","LoggerProxy","logger","controls","breakout","session","get","parseRoster","internal","llm","event","data","senderUserId","sentTime","message","MESSAGE","mercury","updateBreakout","params","current","SESSION_STATES","ACTIVE","ALLOWED","ASSIGNED_CURRENT","REQUESTED","updateBreakoutSessions","payload","breakoutSessions","state","ASSIGNED","getMainSession","mainSession","filter","isMain","Error","askAllToReturn","method","HTTP_VERBS","POST","broadcast","options","enableBreakouts","err","reject","toggleBreakout","enable","undefined","info","doToggleBreakout","token","editlock","PUT","create","sessions","boServiceErrorHandler","breakInfo","_clearEditLockInfo","resolve","clearSessions","action","ACTION","DELETE","start","START","allowToJoinLater","duration","DEFAULT_DURATION","refresh","end","CLOSE","getBreakout","GET","keepEditLockAlive","enableAndLockBreakout","lockBreakout","EDIT_LOCK_STATUS","LOCKED","ttl","DEFAULT_TTL","window","setInterval","unLockEditBreakout","clearInterval","assign","internalSessions","map","item","assigned","memberIds","assignedEmails","emails","anyoneCanJoin","anyone"],"sources":["index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.\n */\nimport {WebexPlugin} from '@webex/webex-core';\nimport {debounce, forEach} from 'lodash';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {BREAKOUTS, MEETINGS, HTTP_VERBS} from '../constants';\n\nimport Breakout from './breakout';\nimport BreakoutCollection from './collection';\nimport BreakoutRequest from './request';\nimport {boServiceErrorHandler} from './utils';\n\n/**\n * @class Breakouts\n */\nconst Breakouts = WebexPlugin.extend({\n namespace: MEETINGS,\n breakoutRequest: BreakoutRequest,\n collections: {\n breakouts: BreakoutCollection,\n },\n\n props: {\n allowBackToMain: 'boolean', // only present when in a breakout session\n delayCloseTime: 'number', // appears once breakouts start\n enableBreakoutSession: 'boolean', // appears from the moment you enable breakouts\n groupId: 'string', // appears from the moment you enable breakouts\n name: 'string', // only present when in a breakout session\n sessionId: 'string', // appears from the moment you enable breakouts\n sessionType: 'string', // appears from the moment you enable breakouts\n startTime: 'string', // appears once breakouts start\n status: 'string', // only present when in a breakout session\n url: 'string', // appears from the moment you enable breakouts\n locusUrl: 'string', // the current locus url\n breakoutServiceUrl: 'string', // the current breakout resource url\n mainLocusUrl: 'string', // the locus url of the main session\n groups: 'array', // appears when create breakouts\n editLock: 'object', // appears when getBreakout info editlock = true\n intervalID: 'number',\n },\n\n children: {\n currentBreakoutSession: Breakout,\n },\n\n derived: {\n isInMainSession: {\n deps: ['sessionType'],\n /**\n * Returns true if the user is in the main session\n * @returns {boolean}\n */\n fn() {\n return this.sessionType === BREAKOUTS.SESSION_TYPES.MAIN;\n },\n },\n breakoutGroupId: {\n deps: ['groups'],\n /**\n * Returns the actived group id\n * @returns {boolean}\n */\n fn() {\n if (this.groups?.length) {\n return this.groups[0].id;\n }\n\n return '';\n },\n },\n },\n\n /**\n * initialize for the breakouts\n * @returns {void}\n */\n initialize() {\n this.listenTo(this, 'change:status', () => {\n if (this.status === BREAKOUTS.STATUS.CLOSING) {\n this.trigger(BREAKOUTS.EVENTS.BREAKOUTS_CLOSING);\n }\n });\n this.debouncedQueryRosters = debounce(this.queryRosters, 10, {\n leading: true,\n trailing: false,\n });\n this.listenTo(this.breakouts, 'add', () => {\n this.debouncedQueryRosters();\n });\n this.listenToBroadcastMessages();\n this.listenToBreakoutRosters();\n // @ts-ignore\n this.breakoutRequest = new BreakoutRequest({webex: this.webex});\n },\n\n /**\n * Calls this to clean up listeners\n * @returns {void}\n */\n cleanUp() {\n this.stopListening();\n },\n\n /**\n * Update the current locus url of the meeting\n * @param {string} locusUrl // locus url\n * @returns {void}\n */\n locusUrlUpdate(locusUrl) {\n this.set('locusUrl', locusUrl);\n const {isInMainSession, mainLocusUrl} = this;\n if (isInMainSession || !mainLocusUrl) {\n this.set('mainLocusUrl', locusUrl);\n }\n },\n\n /**\n * Update the current breakout resource url\n * @param {string} breakoutServiceUrl\n * @returns {void}\n */\n breakoutServiceUrlUpdate(breakoutServiceUrl) {\n this.set('breakoutServiceUrl', `${breakoutServiceUrl}/breakout/`);\n },\n\n /**\n * The initial roster lists need to be queried because you don't\n * get a breakout.roster event when you join the meeting\n * @returns {void}\n */\n queryRosters() {\n this.webex\n .request({uri: `${this.url}/roster`, qs: {locusUrl: btoa(this.locusUrl)}})\n .then((result) => {\n const {\n body: {rosters},\n } = result;\n\n rosters?.forEach(({locus}) => {\n this.handleRosterUpdate(locus);\n });\n\n this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);\n })\n .catch((error) => {\n LoggerProxy.logger.error('Meeting:breakouts#queryRosters failed', error);\n });\n },\n\n /**\n *\n * @param {Object} locus // locus object\n * @returns {void}\n */\n handleRosterUpdate(locus) {\n const sessionId = locus.controls?.breakout?.sessionId;\n\n const session = this.breakouts.get(sessionId);\n\n if (!session) {\n return;\n }\n\n session.parseRoster(locus);\n },\n\n /**\n * Sets up listener for broadcast messages sent to the breakout session\n * @returns {void}\n */\n listenToBroadcastMessages() {\n this.listenTo(this.webex.internal.llm, 'event:breakout.message', (event) => {\n const {\n data: {senderUserId, sentTime, message},\n } = event;\n\n this.trigger(BREAKOUTS.EVENTS.MESSAGE, {\n senderUserId,\n sentTime,\n message,\n // FIXME: This is only the current sessionId\n // We'd need to check that the dataChannelUrl is still the same\n // to guarantee that this message was sent to this session\n sessionId: this.currentBreakoutSession.sessionId,\n });\n });\n },\n\n /**\n * Sets up a listener for roster messags from mecury\n * @returns {void}\n */\n listenToBreakoutRosters() {\n this.listenTo(this.webex.internal.mercury, 'event:breakout.roster', (event) => {\n this.handleRosterUpdate(event.data.locus);\n this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);\n });\n },\n\n /**\n * Updates the information about the current breakout\n * @param {Object} params\n * @returns {void}\n */\n updateBreakout(params) {\n this.set(params);\n this.set('groups', params.groups);\n\n this.set('currentBreakoutSession', {\n sessionId: params.sessionId,\n groupId: params.groupId,\n name: params.name,\n current: true,\n sessionType: params.sessionType,\n url: params.url,\n [BREAKOUTS.SESSION_STATES.ACTIVE]: false,\n [BREAKOUTS.SESSION_STATES.ALLOWED]: false,\n [BREAKOUTS.SESSION_STATES.ALLOWED]: false,\n [BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT]: false,\n [BREAKOUTS.SESSION_STATES.REQUESTED]: false,\n });\n\n this.set('enableBreakoutSession', params.enableBreakoutSession);\n },\n\n /**\n * Updates the information about available breakouts\n * @param {Object} payload\n * @returns {void}\n */\n updateBreakoutSessions(payload) {\n const breakouts = {};\n\n if (payload.breakoutSessions) {\n forEach(BREAKOUTS.SESSION_STATES, (state) => {\n forEach(payload.breakoutSessions[state], (breakout) => {\n const {sessionId} = breakout;\n\n if (!breakouts[sessionId]) {\n breakouts[sessionId] = breakout;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ACTIVE] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ALLOWED] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.REQUESTED] = false;\n }\n\n breakouts[sessionId][state] = true;\n });\n });\n }\n\n forEach(breakouts, (breakout: typeof Breakout) => {\n // eslint-disable-next-line no-param-reassign\n breakout.url = this.url;\n });\n\n this.breakouts.set(Object.values(breakouts));\n },\n /**\n * get main session\n * @returns {Breakout}\n */\n getMainSession() {\n if (this.isInMainSession) {\n return this.currentBreakoutSession;\n }\n\n const mainSession = this.breakouts.filter((breakout) => breakout.isMain)[0];\n if (!mainSession) {\n throw new Error('no main session found');\n }\n\n return mainSession;\n },\n /**\n * Host/CoHost ask all participants return to main session\n * @returns {Promise}\n */\n askAllToReturn() {\n const mainSession = this.getMainSession();\n\n return this.webex.request({\n method: HTTP_VERBS.POST,\n uri: `${this.url}/requestMove`,\n body: {\n groupId: mainSession.groupId,\n sessionId: mainSession.sessionId,\n },\n });\n },\n\n /**\n * Broadcast message to all breakout session's participants\n * @param {String} message\n * @param {Object} options\n * @returns {Promise}\n */\n broadcast(message, options) {\n const {breakoutGroupId} = this;\n if (!breakoutGroupId) {\n throw new Error('Cannot broadcast, no breakout session found');\n }\n\n return this.breakoutRequest.broadcast({\n url: this.url,\n message,\n options,\n groupId: breakoutGroupId,\n });\n },\n /**\n * Make enable breakout resource\n * @returns {Promise}\n */\n enableBreakouts() {\n if (this.breakoutServiceUrl) {\n // @ts-ignore\n return this.webex\n .request({\n method: HTTP_VERBS.POST,\n uri: this.breakoutServiceUrl,\n body: {\n locusUrl: this.locusUrl,\n },\n })\n .catch((err) => {\n LoggerProxy.logger.error(\n `Meeting:request#touchBreakout --> Error provisioning error ${err}`\n );\n throw err;\n });\n }\n\n return Promise.reject(new Error(`enableBreakouts: the breakoutServiceUrl is empty`));\n },\n\n /**\n * Make the meeting enable or disable breakout session\n * @param {boolean} enable\n * @returns {Promise}\n */\n async toggleBreakout(enable) {\n if (this.enableBreakoutSession === undefined) {\n const info = await this.enableBreakouts();\n if (!enable) {\n // if enable is false, updateBreakout set the param then set enableBreakoutSession as false\n this.updateBreakout(info.body);\n await this.doToggleBreakout(enable);\n }\n } else {\n await this.doToggleBreakout(enable);\n }\n },\n\n /**\n * do toggle meeting breakout session enable or disable\n * @param {boolean} enable\n * @returns {Promise}\n */\n doToggleBreakout(enable) {\n const body = {\n ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),\n ...{enableBreakoutSession: enable},\n };\n\n // @ts-ignore\n return this.webex.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n });\n },\n\n /**\n * Create new breakout sessions\n * @param {object} sessions -- breakout session group\n * @returns {Promise}\n */\n async create(sessions) {\n const body = {\n ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),\n ...{groups: [{sessions}]},\n };\n // @ts-ignore\n const breakInfo = await this.webex\n .request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n })\n .catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#create --> Edit lock token mismatch')\n );\n });\n\n if (breakInfo.body?.groups) {\n this.set('groups', breakInfo.body.groups);\n }\n\n // clear edit lock info after save breakout session info\n this._clearEditLockInfo();\n\n return Promise.resolve(breakInfo);\n },\n\n /**\n * Delete all breakout sessions\n * @returns {Promise}\n */\n async clearSessions() {\n const body = {\n ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),\n ...{groups: [{action: BREAKOUTS.ACTION.DELETE}]},\n };\n // @ts-ignore\n const breakInfo = await this.webex\n .request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n })\n .catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#clearSessions --> Edit lock token mismatch')\n );\n });\n\n if (breakInfo.body?.groups) {\n this.set('groups', breakInfo.body.groups);\n }\n\n return Promise.resolve(breakInfo);\n },\n\n /**\n * Host or cohost starts breakout sessions\n * @param {object} params\n * @returns {Promise}\n */\n start(params = {}) {\n const action = BREAKOUTS.ACTION.START;\n const payload = {\n id: this.breakoutGroupId,\n action,\n allowBackToMain: false,\n allowToJoinLater: false,\n duration: BREAKOUTS.DEFAULT_DURATION,\n ...params,\n };\n\n const body = {\n ...(this.editLock && !!this.editLock.token\n ? {editlock: {token: this.editLock.token, refresh: true}}\n : {}),\n ...{groups: [payload]},\n };\n\n return this.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n }).catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#start --> Edit lock token mismatch')\n );\n });\n },\n\n /**\n * Host or cohost ends breakout sessions\n * @param {object} params\n * @returns {Promise}\n */\n end(params = {}) {\n const {delayCloseTime, breakoutGroupId: id} = this;\n const action = BREAKOUTS.ACTION.CLOSE;\n const payload = {\n id,\n action,\n delayCloseTime,\n ...params,\n };\n\n const body = {\n ...(this.editLock && !!this.editLock.token\n ? {editlock: {token: this.editLock.token, refresh: true}}\n : {}),\n ...{groups: [payload]},\n };\n\n return this.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n }).catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#end --> Edit lock token mismatch')\n );\n });\n },\n\n /**\n * get existed breakout sessions\n * @param {boolean} editlock -- lock operations of the breakout sessions\n * @returns {Promise}\n */\n async getBreakout(editlock) {\n const breakout = await this.request({\n method: HTTP_VERBS.GET,\n uri: this.url + (editlock ? `?editlock=${editlock}` : ''),\n });\n\n if (breakout.body?.groups) {\n this.set('groups', breakout.body.groups);\n }\n if (breakout.body?.editlock && editlock) {\n this.set('editLock', breakout.body.editlock);\n this.keepEditLockAlive();\n }\n\n return breakout;\n },\n\n /**\n * enable and edit lock breakout\n * @returns {void}\n */\n async enableAndLockBreakout() {\n if (this.enableBreakoutSession) {\n this.lockBreakout();\n } else {\n const info = await this.enableBreakouts();\n\n if (info.body) {\n this.lockBreakout();\n }\n }\n },\n\n /**\n * send breakout edit lock\n * @returns {void}\n */\n async lockBreakout() {\n if (this.editLock && !!this.editLock.token) {\n if (this.editLock.state === BREAKOUTS.EDIT_LOCK_STATUS.LOCKED) {\n throw new Error('Breakout already locked');\n } else {\n this.keepEditLockAlive();\n }\n } else {\n const breakout = await this.getBreakout(true);\n if (breakout.body?.editlock) {\n this.keepEditLockAlive();\n }\n }\n },\n\n /**\n * keep edit lock alive\n * @returns {void}\n */\n keepEditLockAlive() {\n if (this.editLock && !!this.editLock.token) {\n const ttl = this.editLock.ttl < 30 ? BREAKOUTS.DEFAULT_TTL : this.editLock.ttl;\n\n this.intervalID = window.setInterval(() => {\n this.request({\n method: HTTP_VERBS.PUT,\n uri: `${this.url}/editlock/${this.editLock.token}`,\n }).catch((error) => {\n this._clearEditLockInfo();\n\n return Promise.reject(boServiceErrorHandler(error, 'Breakouts#keepEditLockAlive'));\n });\n }, (ttl / 2) * 1000);\n }\n },\n\n /**\n * unlock edit breakout\n * @returns {void}\n */\n unLockEditBreakout() {\n if (this.editLock && !!this.editLock.token) {\n this.request({\n method: HTTP_VERBS.DELETE,\n uri: `${this.url}/editlock/${this.editLock.token}`,\n })\n .then(() => {\n this._clearEditLockInfo();\n })\n .catch((error) => {\n return Promise.reject(boServiceErrorHandler(error, 'Breakouts#unLockEditBreakout'));\n });\n }\n },\n\n /**\n * clear interval and edit lock info\n * @private\n * @returns {void}\n */\n _clearEditLockInfo() {\n if (this.intervalID) {\n clearInterval(this.intervalID);\n }\n this.set('editLock', {});\n },\n\n /**\n * assign participants to breakout session\n * @param {Array} sessions\n * @returns {void}\n */\n assign(sessions: any[]) {\n const internalSessions = sessions.map((item) => {\n return {\n id: item.id,\n assigned: item.memberIds,\n assignedEmails: item.emails,\n anyoneCanJoin: !!item.anyone,\n };\n });\n\n return this.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body: {\n groups: [\n {\n id: this.breakoutGroupId,\n sessions: internalSessions,\n },\n ],\n },\n });\n },\n});\n\nexport default Breakouts;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["Breakouts","WebexPlugin","extend","namespace","MEETINGS","breakoutRequest","BreakoutRequest","collections","breakouts","BreakoutCollection","props","allowBackToMain","delayCloseTime","enableBreakoutSession","groupId","name","sessionId","sessionType","startTime","status","url","locusUrl","breakoutServiceUrl","mainLocusUrl","groups","editLock","intervalID","children","currentBreakoutSession","Breakout","derived","isInMainSession","deps","fn","BREAKOUTS","SESSION_TYPES","MAIN","breakoutGroupId","length","id","initialize","listenTo","STATUS","CLOSING","trigger","EVENTS","BREAKOUTS_CLOSING","debouncedQueryRosters","queryRosters","leading","trailing","listenToBroadcastMessages","listenToBreakoutRosters","webex","cleanUp","stopListening","locusUrlUpdate","set","breakoutServiceUrlUpdate","request","uri","qs","btoa","then","result","rosters","body","forEach","locus","handleRosterUpdate","MEMBERS_UPDATE","catch","error","LoggerProxy","logger","controls","breakout","session","get","parseRoster","internal","llm","event","data","senderUserId","sentTime","message","MESSAGE","mercury","updateBreakout","params","current","SESSION_STATES","ACTIVE","ALLOWED","ASSIGNED_CURRENT","REQUESTED","updateBreakoutSessions","payload","breakoutSessions","state","ASSIGNED","getMainSession","mainSession","filter","isMain","Error","askAllToReturn","method","HTTP_VERBS","POST","broadcast","options","enableBreakouts","err","reject","toggleBreakout","enable","undefined","info","doToggleBreakout","token","editlock","PUT","create","sessions","boServiceErrorHandler","breakInfo","_clearEditLockInfo","resolve","clearSessions","action","ACTION","DELETE","start","START","allowToJoinLater","duration","DEFAULT_DURATION","refresh","end","CLOSE","getBreakout","GET","keepEditLockAlive","enableAndLockBreakout","lockBreakout","EDIT_LOCK_STATUS","LOCKED","ttl","DEFAULT_TTL","window","setInterval","unLockEditBreakout","clearInterval","assign","internalSessions","map","item","assigned","memberIds","assignedEmails","emails","anyoneCanJoin","anyone","dynamicAssign","updatedSessions","participants","targetState"],"sources":["index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.\n */\nimport {WebexPlugin} from '@webex/webex-core';\nimport {debounce, forEach} from 'lodash';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {BREAKOUTS, MEETINGS, HTTP_VERBS} from '../constants';\n\nimport Breakout from './breakout';\nimport BreakoutCollection from './collection';\nimport BreakoutRequest from './request';\nimport {boServiceErrorHandler} from './utils';\n\n/**\n * @class Breakouts\n */\nconst Breakouts = WebexPlugin.extend({\n namespace: MEETINGS,\n breakoutRequest: BreakoutRequest,\n collections: {\n breakouts: BreakoutCollection,\n },\n\n props: {\n allowBackToMain: 'boolean', // only present when in a breakout session\n delayCloseTime: 'number', // appears once breakouts start\n enableBreakoutSession: 'boolean', // appears from the moment you enable breakouts\n groupId: 'string', // appears from the moment you enable breakouts\n name: 'string', // only present when in a breakout session\n sessionId: 'string', // appears from the moment you enable breakouts\n sessionType: 'string', // appears from the moment you enable breakouts\n startTime: 'string', // appears once breakouts start\n status: 'string', // only present when in a breakout session\n url: 'string', // appears from the moment you enable breakouts\n locusUrl: 'string', // the current locus url\n breakoutServiceUrl: 'string', // the current breakout resource url\n mainLocusUrl: 'string', // the locus url of the main session\n groups: 'array', // appears when create breakouts\n editLock: 'object', // appears when getBreakout info editlock = true\n intervalID: 'number',\n },\n\n children: {\n currentBreakoutSession: Breakout,\n },\n\n derived: {\n isInMainSession: {\n deps: ['sessionType'],\n /**\n * Returns true if the user is in the main session\n * @returns {boolean}\n */\n fn() {\n return this.sessionType === BREAKOUTS.SESSION_TYPES.MAIN;\n },\n },\n breakoutGroupId: {\n deps: ['groups'],\n /**\n * Returns the actived group id\n * @returns {boolean}\n */\n fn() {\n if (this.groups?.length) {\n return this.groups[0].id;\n }\n\n return '';\n },\n },\n },\n\n /**\n * initialize for the breakouts\n * @returns {void}\n */\n initialize() {\n this.listenTo(this, 'change:status', () => {\n if (this.status === BREAKOUTS.STATUS.CLOSING) {\n this.trigger(BREAKOUTS.EVENTS.BREAKOUTS_CLOSING);\n }\n });\n this.debouncedQueryRosters = debounce(this.queryRosters, 10, {\n leading: true,\n trailing: false,\n });\n this.listenTo(this.breakouts, 'add', () => {\n this.debouncedQueryRosters();\n });\n this.listenToBroadcastMessages();\n this.listenToBreakoutRosters();\n // @ts-ignore\n this.breakoutRequest = new BreakoutRequest({webex: this.webex});\n },\n\n /**\n * Calls this to clean up listeners\n * @returns {void}\n */\n cleanUp() {\n this.stopListening();\n },\n\n /**\n * Update the current locus url of the meeting\n * @param {string} locusUrl // locus url\n * @returns {void}\n */\n locusUrlUpdate(locusUrl) {\n this.set('locusUrl', locusUrl);\n const {isInMainSession, mainLocusUrl} = this;\n if (isInMainSession || !mainLocusUrl) {\n this.set('mainLocusUrl', locusUrl);\n }\n },\n\n /**\n * Update the current breakout resource url\n * @param {string} breakoutServiceUrl\n * @returns {void}\n */\n breakoutServiceUrlUpdate(breakoutServiceUrl) {\n this.set('breakoutServiceUrl', `${breakoutServiceUrl}/breakout/`);\n },\n\n /**\n * The initial roster lists need to be queried because you don't\n * get a breakout.roster event when you join the meeting\n * @returns {void}\n */\n queryRosters() {\n this.webex\n .request({uri: `${this.url}/roster`, qs: {locusUrl: btoa(this.locusUrl)}})\n .then((result) => {\n const {\n body: {rosters},\n } = result;\n\n rosters?.forEach(({locus}) => {\n this.handleRosterUpdate(locus);\n });\n\n this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);\n })\n .catch((error) => {\n LoggerProxy.logger.error('Meeting:breakouts#queryRosters failed', error);\n });\n },\n\n /**\n *\n * @param {Object} locus // locus object\n * @returns {void}\n */\n handleRosterUpdate(locus) {\n const sessionId = locus.controls?.breakout?.sessionId;\n\n const session = this.breakouts.get(sessionId);\n\n if (!session) {\n return;\n }\n\n session.parseRoster(locus);\n },\n\n /**\n * Sets up listener for broadcast messages sent to the breakout session\n * @returns {void}\n */\n listenToBroadcastMessages() {\n this.listenTo(this.webex.internal.llm, 'event:breakout.message', (event) => {\n const {\n data: {senderUserId, sentTime, message},\n } = event;\n\n this.trigger(BREAKOUTS.EVENTS.MESSAGE, {\n senderUserId,\n sentTime,\n message,\n // FIXME: This is only the current sessionId\n // We'd need to check that the dataChannelUrl is still the same\n // to guarantee that this message was sent to this session\n sessionId: this.currentBreakoutSession.sessionId,\n });\n });\n },\n\n /**\n * Sets up a listener for roster messags from mecury\n * @returns {void}\n */\n listenToBreakoutRosters() {\n this.listenTo(this.webex.internal.mercury, 'event:breakout.roster', (event) => {\n this.handleRosterUpdate(event.data.locus);\n this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);\n });\n },\n\n /**\n * Updates the information about the current breakout\n * @param {Object} params\n * @returns {void}\n */\n updateBreakout(params) {\n this.set(params);\n this.set('groups', params.groups);\n\n this.set('currentBreakoutSession', {\n sessionId: params.sessionId,\n groupId: params.groupId,\n name: params.name,\n current: true,\n sessionType: params.sessionType,\n url: params.url,\n [BREAKOUTS.SESSION_STATES.ACTIVE]: false,\n [BREAKOUTS.SESSION_STATES.ALLOWED]: false,\n [BREAKOUTS.SESSION_STATES.ALLOWED]: false,\n [BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT]: false,\n [BREAKOUTS.SESSION_STATES.REQUESTED]: false,\n });\n\n this.set('enableBreakoutSession', params.enableBreakoutSession);\n },\n\n /**\n * Updates the information about available breakouts\n * @param {Object} payload\n * @returns {void}\n */\n updateBreakoutSessions(payload) {\n const breakouts = {};\n\n if (payload.breakoutSessions) {\n forEach(BREAKOUTS.SESSION_STATES, (state) => {\n forEach(payload.breakoutSessions[state], (breakout) => {\n const {sessionId} = breakout;\n\n if (!breakouts[sessionId]) {\n breakouts[sessionId] = breakout;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ACTIVE] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ALLOWED] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT] = false;\n breakouts[sessionId][BREAKOUTS.SESSION_STATES.REQUESTED] = false;\n }\n\n breakouts[sessionId][state] = true;\n });\n });\n }\n\n forEach(breakouts, (breakout: typeof Breakout) => {\n // eslint-disable-next-line no-param-reassign\n breakout.url = this.url;\n });\n\n this.breakouts.set(Object.values(breakouts));\n },\n /**\n * get main session\n * @returns {Breakout}\n */\n getMainSession() {\n if (this.isInMainSession) {\n return this.currentBreakoutSession;\n }\n\n const mainSession = this.breakouts.filter((breakout) => breakout.isMain)[0];\n if (!mainSession) {\n throw new Error('no main session found');\n }\n\n return mainSession;\n },\n /**\n * Host/CoHost ask all participants return to main session\n * @returns {Promise}\n */\n askAllToReturn() {\n const mainSession = this.getMainSession();\n\n return this.webex.request({\n method: HTTP_VERBS.POST,\n uri: `${this.url}/requestMove`,\n body: {\n groupId: mainSession.groupId,\n sessionId: mainSession.sessionId,\n },\n });\n },\n\n /**\n * Broadcast message to all breakout session's participants\n * @param {String} message\n * @param {Object} options\n * @returns {Promise}\n */\n broadcast(message, options) {\n const {breakoutGroupId} = this;\n if (!breakoutGroupId) {\n throw new Error('Cannot broadcast, no breakout session found');\n }\n\n return this.breakoutRequest.broadcast({\n url: this.url,\n message,\n options,\n groupId: breakoutGroupId,\n });\n },\n /**\n * Make enable breakout resource\n * @returns {Promise}\n */\n enableBreakouts() {\n if (this.breakoutServiceUrl) {\n // @ts-ignore\n return this.webex\n .request({\n method: HTTP_VERBS.POST,\n uri: this.breakoutServiceUrl,\n body: {\n locusUrl: this.locusUrl,\n },\n })\n .catch((err) => {\n LoggerProxy.logger.error(\n `Meeting:request#touchBreakout --> Error provisioning error ${err}`\n );\n throw err;\n });\n }\n\n return Promise.reject(new Error(`enableBreakouts: the breakoutServiceUrl is empty`));\n },\n\n /**\n * Make the meeting enable or disable breakout session\n * @param {boolean} enable\n * @returns {Promise}\n */\n async toggleBreakout(enable) {\n if (this.enableBreakoutSession === undefined) {\n const info = await this.enableBreakouts();\n if (!enable) {\n // if enable is false, updateBreakout set the param then set enableBreakoutSession as false\n this.updateBreakout(info.body);\n await this.doToggleBreakout(enable);\n }\n } else {\n await this.doToggleBreakout(enable);\n }\n },\n\n /**\n * do toggle meeting breakout session enable or disable\n * @param {boolean} enable\n * @returns {Promise}\n */\n doToggleBreakout(enable) {\n const body = {\n ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),\n ...{enableBreakoutSession: enable},\n };\n\n // @ts-ignore\n return this.webex.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n });\n },\n\n /**\n * Create new breakout sessions\n * @param {object} sessions -- breakout session group\n * @returns {Promise}\n */\n async create(sessions) {\n const body = {\n ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),\n ...{groups: [{sessions}]},\n };\n // @ts-ignore\n const breakInfo = await this.webex\n .request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n })\n .catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#create --> Edit lock token mismatch')\n );\n });\n\n if (breakInfo.body?.groups) {\n this.set('groups', breakInfo.body.groups);\n }\n\n // clear edit lock info after save breakout session info\n this._clearEditLockInfo();\n\n return Promise.resolve(breakInfo);\n },\n\n /**\n * Delete all breakout sessions\n * @returns {Promise}\n */\n async clearSessions() {\n const body = {\n ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),\n ...{groups: [{action: BREAKOUTS.ACTION.DELETE}]},\n };\n // @ts-ignore\n const breakInfo = await this.webex\n .request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n })\n .catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#clearSessions --> Edit lock token mismatch')\n );\n });\n\n if (breakInfo.body?.groups) {\n this.set('groups', breakInfo.body.groups);\n }\n\n return Promise.resolve(breakInfo);\n },\n\n /**\n * Host or cohost starts breakout sessions\n * @param {object} params\n * @returns {Promise}\n */\n start(params = {}) {\n const action = BREAKOUTS.ACTION.START;\n const payload = {\n id: this.breakoutGroupId,\n action,\n allowBackToMain: false,\n allowToJoinLater: false,\n duration: BREAKOUTS.DEFAULT_DURATION,\n ...params,\n };\n\n const body = {\n ...(this.editLock && !!this.editLock.token\n ? {editlock: {token: this.editLock.token, refresh: true}}\n : {}),\n ...{groups: [payload]},\n };\n\n return this.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n }).catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#start --> Edit lock token mismatch')\n );\n });\n },\n\n /**\n * Host or cohost ends breakout sessions\n * @param {object} params\n * @returns {Promise}\n */\n end(params = {}) {\n const {delayCloseTime, breakoutGroupId: id} = this;\n const action = BREAKOUTS.ACTION.CLOSE;\n const payload = {\n id,\n action,\n delayCloseTime,\n ...params,\n };\n\n const body = {\n ...(this.editLock && !!this.editLock.token\n ? {editlock: {token: this.editLock.token, refresh: true}}\n : {}),\n ...{groups: [payload]},\n };\n\n return this.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body,\n }).catch((error) => {\n return Promise.reject(\n boServiceErrorHandler(error, 'Breakouts#end --> Edit lock token mismatch')\n );\n });\n },\n\n /**\n * get existed breakout sessions\n * @param {boolean} editlock -- lock operations of the breakout sessions\n * @returns {Promise}\n */\n async getBreakout(editlock) {\n const breakout = await this.request({\n method: HTTP_VERBS.GET,\n uri: this.url + (editlock ? `?editlock=${editlock}` : ''),\n });\n\n if (breakout.body?.groups) {\n this.set('groups', breakout.body.groups);\n }\n if (breakout.body?.editlock && editlock) {\n this.set('editLock', breakout.body.editlock);\n this.keepEditLockAlive();\n }\n\n return breakout;\n },\n\n /**\n * enable and edit lock breakout\n * @returns {void}\n */\n async enableAndLockBreakout() {\n if (this.enableBreakoutSession) {\n this.lockBreakout();\n } else {\n const info = await this.enableBreakouts();\n\n if (info.body) {\n this.lockBreakout();\n }\n }\n },\n\n /**\n * send breakout edit lock\n * @returns {void}\n */\n async lockBreakout() {\n if (this.editLock && !!this.editLock.token) {\n if (this.editLock.state === BREAKOUTS.EDIT_LOCK_STATUS.LOCKED) {\n throw new Error('Breakout already locked');\n } else {\n this.keepEditLockAlive();\n }\n } else {\n const breakout = await this.getBreakout(true);\n if (breakout.body?.editlock) {\n this.keepEditLockAlive();\n }\n }\n },\n\n /**\n * keep edit lock alive\n * @returns {void}\n */\n keepEditLockAlive() {\n if (this.editLock && !!this.editLock.token) {\n const ttl = this.editLock.ttl < 30 ? BREAKOUTS.DEFAULT_TTL : this.editLock.ttl;\n\n this.intervalID = window.setInterval(() => {\n this.request({\n method: HTTP_VERBS.PUT,\n uri: `${this.url}/editlock/${this.editLock.token}`,\n }).catch((error) => {\n this._clearEditLockInfo();\n\n return Promise.reject(boServiceErrorHandler(error, 'Breakouts#keepEditLockAlive'));\n });\n }, (ttl / 2) * 1000);\n }\n },\n\n /**\n * unlock edit breakout\n * @returns {void}\n */\n unLockEditBreakout() {\n if (this.editLock && !!this.editLock.token) {\n this.request({\n method: HTTP_VERBS.DELETE,\n uri: `${this.url}/editlock/${this.editLock.token}`,\n })\n .then(() => {\n this._clearEditLockInfo();\n })\n .catch((error) => {\n return Promise.reject(boServiceErrorHandler(error, 'Breakouts#unLockEditBreakout'));\n });\n }\n },\n\n /**\n * clear interval and edit lock info\n * @private\n * @returns {void}\n */\n _clearEditLockInfo() {\n if (this.intervalID) {\n clearInterval(this.intervalID);\n }\n this.set('editLock', {});\n },\n\n /**\n * assign participants to breakout session\n * @param {Array} sessions\n * @returns {void}\n */\n assign(sessions: any[]) {\n const internalSessions = sessions.map((item) => {\n return {\n id: item.id,\n assigned: item.memberIds,\n assignedEmails: item.emails,\n anyoneCanJoin: !!item.anyone,\n };\n });\n\n return this.request({\n method: HTTP_VERBS.PUT,\n uri: this.url,\n body: {\n groups: [\n {\n id: this.breakoutGroupId,\n sessions: internalSessions,\n },\n ],\n },\n });\n },\n\n /**\n * assign participants dynamically after breakout sessions started,\n * but currently it only used for admitting participants from lobby into breakout directly\n * @param {Array} sessions\n * @returns {void}\n */\n dynamicAssign(sessions: any[]) {\n const updatedSessions = sessions.map((item) => {\n return {\n id: item.id,\n participants: item.participants,\n targetState: item.targetState,\n };\n });\n\n const body = {\n groups: [\n {\n id: this.breakoutGroupId,\n sessions: updatedSessions,\n },\n ],\n editlock: null,\n };\n\n if (this.editLock && this.editLock.token) {\n body.editlock = this.editLock;\n }\n\n return this.request({\n method: HTTP_VERBS.PUT,\n uri: `${this.url}/dynamicAssign`,\n body,\n });\n },\n});\n\nexport default Breakouts;\n"],"mappings":"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"}
|
|
@@ -7,11 +7,13 @@ _Object$defineProperty(exports, "__esModule", {
|
|
|
7
7
|
});
|
|
8
8
|
exports.MediaRequestManager = void 0;
|
|
9
9
|
var _entries = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/entries"));
|
|
10
|
+
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
|
|
10
11
|
var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
|
|
11
12
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
|
|
12
13
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
|
|
13
14
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
14
15
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
|
|
16
|
+
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
|
|
15
17
|
var _debounce2 = _interopRequireDefault(require("lodash/debounce"));
|
|
16
18
|
var _cloneDeep2 = _interopRequireDefault(require("lodash/cloneDeep"));
|
|
17
19
|
var _internalMediaCore = require("@webex/internal-media-core");
|
|
@@ -37,6 +39,7 @@ var MediaRequestManager = /*#__PURE__*/function () {
|
|
|
37
39
|
(0, _defineProperty2.default)(this, "degradationPreferences", void 0);
|
|
38
40
|
(0, _defineProperty2.default)(this, "sourceUpdateListener", void 0);
|
|
39
41
|
(0, _defineProperty2.default)(this, "debouncedSourceUpdateListener", void 0);
|
|
42
|
+
(0, _defineProperty2.default)(this, "previousWCMEMediaRequests", []);
|
|
40
43
|
this.sendMediaRequestsCallback = sendMediaRequestsCallback;
|
|
41
44
|
this.counter = 0;
|
|
42
45
|
this.clientRequests = {};
|
|
@@ -88,6 +91,36 @@ var MediaRequestManager = /*#__PURE__*/function () {
|
|
|
88
91
|
}
|
|
89
92
|
return clientRequests;
|
|
90
93
|
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns true if two media requests are the same, false otherwise.
|
|
97
|
+
*
|
|
98
|
+
* @param {WcmeMediaRequest} mediaRequestA - Media request A for comparison.
|
|
99
|
+
* @param {WcmeMediaRequest} mediaRequestB - Media request B for comparison.
|
|
100
|
+
* @returns {boolean} - Whether they are equal.
|
|
101
|
+
*/
|
|
102
|
+
// eslint-disable-next-line class-methods-use-this
|
|
103
|
+
}, {
|
|
104
|
+
key: "isEqual",
|
|
105
|
+
value: function isEqual(mediaRequestA, mediaRequestB) {
|
|
106
|
+
return (0, _stringify.default)(mediaRequestA._toJmpScrRequest()) === (0, _stringify.default)(mediaRequestB._toJmpScrRequest());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Compares new media requests to previous ones and determines
|
|
111
|
+
* if they are the same.
|
|
112
|
+
*
|
|
113
|
+
* @param {WcmeMediaRequest[]} newRequests - Array with new requests.
|
|
114
|
+
* @returns {boolean} - True if they are equal, false otherwise.
|
|
115
|
+
*/
|
|
116
|
+
}, {
|
|
117
|
+
key: "checkIsNewRequestsEqualToPrev",
|
|
118
|
+
value: function checkIsNewRequestsEqualToPrev(newRequests) {
|
|
119
|
+
var _this2 = this;
|
|
120
|
+
return !(0, _isEmpty2.default)(this.previousWCMEMediaRequests) && this.previousWCMEMediaRequests.length === newRequests.length && this.previousWCMEMediaRequests.every(function (req, idx) {
|
|
121
|
+
return _this2.isEqual(req, newRequests[idx]);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
91
124
|
}, {
|
|
92
125
|
key: "sendRequests",
|
|
93
126
|
value: function sendRequests() {
|
|
@@ -101,22 +134,31 @@ var MediaRequestManager = /*#__PURE__*/function () {
|
|
|
101
134
|
return receiveSlot.wcmeReceiveSlot;
|
|
102
135
|
}), maxPayloadBitsPerSecond, mr.codecInfo && [new _internalMediaCore.CodecInfo(0x80, new _internalMediaCore.H264Codec(mr.codecInfo.maxFs, mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps, mr.codecInfo.maxMbps || CODEC_DEFAULTS.h264.maxMbps, mr.codecInfo.maxWidth, mr.codecInfo.maxHeight))]));
|
|
103
136
|
});
|
|
104
|
-
|
|
137
|
+
|
|
138
|
+
//! IMPORTANT: this is only a temporary fix. This will soon be done in the jmp layer (@webex/jmp-multistream)
|
|
139
|
+
// https://jira-eng-gpk2.cisco.com/jira/browse/WEBEX-326713
|
|
140
|
+
if (!this.checkIsNewRequestsEqualToPrev(wcmeMediaRequests)) {
|
|
141
|
+
this.sendMediaRequestsCallback(wcmeMediaRequests);
|
|
142
|
+
this.previousWCMEMediaRequests = wcmeMediaRequests;
|
|
143
|
+
_loggerProxy.default.logger.info("multistream:sendRequests --> media requests sent. ");
|
|
144
|
+
} else {
|
|
145
|
+
_loggerProxy.default.logger.info("multistream:sendRequests --> detected duplicate WCME requests, skipping them... ");
|
|
146
|
+
}
|
|
105
147
|
}
|
|
106
148
|
}, {
|
|
107
149
|
key: "addRequest",
|
|
108
150
|
value: function addRequest(mediaRequest) {
|
|
109
|
-
var
|
|
151
|
+
var _this3 = this;
|
|
110
152
|
var commit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
111
153
|
// eslint-disable-next-line no-plusplus
|
|
112
154
|
var newId = "".concat(this.counter++);
|
|
113
155
|
this.clientRequests[newId] = mediaRequest;
|
|
114
156
|
mediaRequest.receiveSlots.forEach(function (rs) {
|
|
115
|
-
rs.on(_receiveSlot.ReceiveSlotEvents.SourceUpdate,
|
|
157
|
+
rs.on(_receiveSlot.ReceiveSlotEvents.SourceUpdate, _this3.sourceUpdateListener);
|
|
116
158
|
rs.on(_receiveSlot.ReceiveSlotEvents.MaxFsUpdate, function (_ref3) {
|
|
117
159
|
var maxFs = _ref3.maxFs;
|
|
118
160
|
mediaRequest.preferredMaxFs = maxFs;
|
|
119
|
-
|
|
161
|
+
_this3.debouncedSourceUpdateListener();
|
|
120
162
|
});
|
|
121
163
|
});
|
|
122
164
|
if (commit) {
|
|
@@ -128,10 +170,10 @@ var MediaRequestManager = /*#__PURE__*/function () {
|
|
|
128
170
|
key: "cancelRequest",
|
|
129
171
|
value: function cancelRequest(requestId) {
|
|
130
172
|
var _this$clientRequests$,
|
|
131
|
-
|
|
173
|
+
_this4 = this;
|
|
132
174
|
var commit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
133
175
|
(_this$clientRequests$ = this.clientRequests[requestId]) === null || _this$clientRequests$ === void 0 ? void 0 : _this$clientRequests$.receiveSlots.forEach(function (rs) {
|
|
134
|
-
rs.off(_receiveSlot.ReceiveSlotEvents.SourceUpdate,
|
|
176
|
+
rs.off(_receiveSlot.ReceiveSlotEvents.SourceUpdate, _this4.sourceUpdateListener);
|
|
135
177
|
});
|
|
136
178
|
delete this.clientRequests[requestId];
|
|
137
179
|
if (commit) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CODEC_DEFAULTS","h264","maxFs","maxFps","maxMbps","DEBOUNCED_SOURCE_UPDATE_TIME","MediaRequestManager","degradationPreferences","sendMediaRequestsCallback","counter","clientRequests","sourceUpdateListener","commit","bind","debouncedSourceUpdateListener","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","forEach","id","mr","codecInfo","Math","min","preferredMaxFs","i","slotsWithLiveSource","receiveSlots","filter","rs","sourceState","length","maxMacroblocksLimit","LoggerProxy","logger","warn","wcmeMediaRequests","getDegradedClientRequests","maxPayloadBitsPerSecond","push","WcmeMediaRequest","policyInfo","policy","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","priority","crossPriorityDuplication","crossPolicyDuplication","preferLiveVideo","ReceiverSelectedInfo","csi","map","receiveSlot","wcmeReceiveSlot","WcmeCodecInfo","H264Codec","maxWidth","maxHeight","mediaRequest","newId","on","ReceiveSlotEvents","SourceUpdate","MaxFsUpdate","requestId","off"],"sources":["mediaRequestManager.ts"],"sourcesContent":["/* eslint-disable require-jsdoc */\nimport {\n MediaRequest as WcmeMediaRequest,\n Policy,\n ActiveSpeakerInfo,\n ReceiverSelectedInfo,\n CodecInfo as WcmeCodecInfo,\n H264Codec,\n} from '@webex/internal-media-core';\nimport {cloneDeep, debounce} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {ReceiveSlot, ReceiveSlotEvents, ReceiveSlotId} from './receiveSlot';\nimport {getMaxFs} from './remoteMedia';\n\nexport interface ActiveSpeakerPolicyInfo {\n policy: 'active-speaker';\n priority: number;\n crossPriorityDuplication: boolean;\n crossPolicyDuplication: boolean;\n preferLiveVideo: boolean;\n}\n\nexport interface ReceiverSelectedPolicyInfo {\n policy: 'receiver-selected';\n csi: number;\n}\n\nexport type PolicyInfo = ActiveSpeakerPolicyInfo | ReceiverSelectedPolicyInfo;\n\nexport interface H264CodecInfo {\n codec: 'h264';\n maxFs?: number;\n maxFps?: number;\n maxMbps?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\nexport type CodecInfo = H264CodecInfo; // we'll add AV1 here in the future when it's available\n\nexport interface MediaRequest {\n policyInfo: PolicyInfo;\n receiveSlots: Array<ReceiveSlot>;\n codecInfo?: CodecInfo;\n preferredMaxFs?: number;\n}\n\nexport type MediaRequestId = string;\n\nconst CODEC_DEFAULTS = {\n h264: {\n maxFs: 8192,\n maxFps: 3000,\n maxMbps: 245760,\n },\n};\n\nconst DEBOUNCED_SOURCE_UPDATE_TIME = 1000;\n\ntype DegradationPreferences = {\n maxMacroblocksLimit: number;\n};\n\ntype SendMediaRequestsCallback = (mediaRequests: WcmeMediaRequest[]) => void;\n\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private counter: number;\n\n private clientRequests: {[key: MediaRequestId]: MediaRequest};\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n private debouncedSourceUpdateListener: () => void;\n\n constructor(\n degradationPreferences: DegradationPreferences,\n sendMediaRequestsCallback: SendMediaRequestsCallback\n ) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.clientRequests = {};\n this.degradationPreferences = degradationPreferences;\n this.sourceUpdateListener = this.commit.bind(this);\n this.debouncedSourceUpdateListener = debounce(\n this.sourceUpdateListener,\n DEBOUNCED_SOURCE_UPDATE_TIME\n );\n }\n\n public setDegradationPreferences(degradationPreferences: DegradationPreferences) {\n this.degradationPreferences = degradationPreferences;\n this.sendRequests(); // re-send requests after preferences are set\n }\n\n private getDegradedClientRequests() {\n const clientRequests = cloneDeep(this.clientRequests);\n const maxFsLimits = [\n getMaxFs('best'),\n getMaxFs('large'),\n getMaxFs('medium'),\n getMaxFs('small'),\n getMaxFs('very small'),\n getMaxFs('thumbnail'),\n ];\n\n // reduce max-fs until total macroblocks is below limit\n for (let i = 0; i < maxFsLimits.length; i += 1) {\n let totalMacroblocksRequested = 0;\n Object.entries(clientRequests).forEach(([id, mr]) => {\n if (mr.codecInfo) {\n mr.codecInfo.maxFs = Math.min(\n mr.preferredMaxFs || CODEC_DEFAULTS.h264.maxFs,\n mr.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs,\n maxFsLimits[i]\n );\n // we only consider sources with \"live\" state\n const slotsWithLiveSource = this.clientRequests[id].receiveSlots.filter(\n (rs) => rs.sourceState === 'live'\n );\n totalMacroblocksRequested += mr.codecInfo.maxFs * slotsWithLiveSource.length;\n }\n });\n if (totalMacroblocksRequested <= this.degradationPreferences.maxMacroblocksLimit) {\n if (i !== 0) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> too many streams with high max-fs, frame size will be limited to ${maxFsLimits[i]}`\n );\n }\n break;\n } else if (i === maxFsLimits.length - 1) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> even with frame size limited to ${maxFsLimits[i]} you are still requesting too many streams, consider reducing the number of requests`\n );\n }\n }\n\n return clientRequests;\n }\n\n private sendRequests() {\n const wcmeMediaRequests: WcmeMediaRequest[] = [];\n\n const clientRequests = this.getDegradedClientRequests();\n const maxPayloadBitsPerSecond = 10 * 1000 * 1000;\n\n // map all the client media requests to wcme media requests\n Object.values(clientRequests).forEach((mr) => {\n wcmeMediaRequests.push(\n new WcmeMediaRequest(\n mr.policyInfo.policy === 'active-speaker'\n ? Policy.ActiveSpeaker\n : Policy.ReceiverSelected,\n mr.policyInfo.policy === 'active-speaker'\n ? new ActiveSpeakerInfo(\n mr.policyInfo.priority,\n mr.policyInfo.crossPriorityDuplication,\n mr.policyInfo.crossPolicyDuplication,\n mr.policyInfo.preferLiveVideo\n )\n : new ReceiverSelectedInfo(mr.policyInfo.csi),\n mr.receiveSlots.map((receiveSlot) => receiveSlot.wcmeReceiveSlot),\n maxPayloadBitsPerSecond,\n mr.codecInfo && [\n new WcmeCodecInfo(\n 0x80,\n new H264Codec(\n mr.codecInfo.maxFs,\n mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps,\n mr.codecInfo.maxMbps || CODEC_DEFAULTS.h264.maxMbps,\n mr.codecInfo.maxWidth,\n mr.codecInfo.maxHeight\n )\n ),\n ]\n )\n );\n });\n\n this.sendMediaRequestsCallback(wcmeMediaRequests);\n }\n\n public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {\n // eslint-disable-next-line no-plusplus\n const newId = `${this.counter++}`;\n\n this.clientRequests[newId] = mediaRequest;\n\n mediaRequest.receiveSlots.forEach((rs) => {\n rs.on(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n rs.on(ReceiveSlotEvents.MaxFsUpdate, ({maxFs}) => {\n mediaRequest.preferredMaxFs = maxFs;\n this.debouncedSourceUpdateListener();\n });\n });\n\n if (commit) {\n this.commit();\n }\n\n return newId;\n }\n\n public cancelRequest(requestId: MediaRequestId, commit = true) {\n this.clientRequests[requestId]?.receiveSlots.forEach((rs) => {\n rs.off(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n });\n\n delete this.clientRequests[requestId];\n\n if (commit) {\n this.commit();\n }\n }\n\n public commit() {\n return this.sendRequests();\n }\n\n public reset() {\n this.clientRequests = {};\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["CODEC_DEFAULTS","h264","maxFs","maxFps","maxMbps","DEBOUNCED_SOURCE_UPDATE_TIME","MediaRequestManager","degradationPreferences","sendMediaRequestsCallback","counter","clientRequests","sourceUpdateListener","commit","bind","debouncedSourceUpdateListener","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","forEach","id","mr","codecInfo","Math","min","preferredMaxFs","i","slotsWithLiveSource","receiveSlots","filter","rs","sourceState","length","maxMacroblocksLimit","LoggerProxy","logger","warn","mediaRequestA","mediaRequestB","_toJmpScrRequest","newRequests","previousWCMEMediaRequests","every","req","idx","isEqual","wcmeMediaRequests","getDegradedClientRequests","maxPayloadBitsPerSecond","push","WcmeMediaRequest","policyInfo","policy","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","priority","crossPriorityDuplication","crossPolicyDuplication","preferLiveVideo","ReceiverSelectedInfo","csi","map","receiveSlot","wcmeReceiveSlot","WcmeCodecInfo","H264Codec","maxWidth","maxHeight","checkIsNewRequestsEqualToPrev","info","mediaRequest","newId","on","ReceiveSlotEvents","SourceUpdate","MaxFsUpdate","requestId","off"],"sources":["mediaRequestManager.ts"],"sourcesContent":["/* eslint-disable require-jsdoc */\nimport {\n MediaRequest as WcmeMediaRequest,\n Policy,\n ActiveSpeakerInfo,\n ReceiverSelectedInfo,\n CodecInfo as WcmeCodecInfo,\n H264Codec,\n} from '@webex/internal-media-core';\nimport {cloneDeep, debounce, isEmpty} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';\nimport {getMaxFs} from './remoteMedia';\n\nexport interface ActiveSpeakerPolicyInfo {\n policy: 'active-speaker';\n priority: number;\n crossPriorityDuplication: boolean;\n crossPolicyDuplication: boolean;\n preferLiveVideo: boolean;\n}\n\nexport interface ReceiverSelectedPolicyInfo {\n policy: 'receiver-selected';\n csi: number;\n}\n\nexport type PolicyInfo = ActiveSpeakerPolicyInfo | ReceiverSelectedPolicyInfo;\n\nexport interface H264CodecInfo {\n codec: 'h264';\n maxFs?: number;\n maxFps?: number;\n maxMbps?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\nexport type CodecInfo = H264CodecInfo; // we'll add AV1 here in the future when it's available\n\nexport interface MediaRequest {\n policyInfo: PolicyInfo;\n receiveSlots: Array<ReceiveSlot>;\n codecInfo?: CodecInfo;\n preferredMaxFs?: number;\n}\n\nexport type MediaRequestId = string;\n\nconst CODEC_DEFAULTS = {\n h264: {\n maxFs: 8192,\n maxFps: 3000,\n maxMbps: 245760,\n },\n};\n\nconst DEBOUNCED_SOURCE_UPDATE_TIME = 1000;\n\ntype DegradationPreferences = {\n maxMacroblocksLimit: number;\n};\n\ntype SendMediaRequestsCallback = (mediaRequests: WcmeMediaRequest[]) => void;\n\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private counter: number;\n\n private clientRequests: {[key: MediaRequestId]: MediaRequest};\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n private debouncedSourceUpdateListener: () => void;\n\n private previousWCMEMediaRequests: Array<WcmeMediaRequest> = [];\n\n constructor(\n degradationPreferences: DegradationPreferences,\n sendMediaRequestsCallback: SendMediaRequestsCallback\n ) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.clientRequests = {};\n this.degradationPreferences = degradationPreferences;\n this.sourceUpdateListener = this.commit.bind(this);\n this.debouncedSourceUpdateListener = debounce(\n this.sourceUpdateListener,\n DEBOUNCED_SOURCE_UPDATE_TIME\n );\n }\n\n public setDegradationPreferences(degradationPreferences: DegradationPreferences) {\n this.degradationPreferences = degradationPreferences;\n this.sendRequests(); // re-send requests after preferences are set\n }\n\n private getDegradedClientRequests() {\n const clientRequests = cloneDeep(this.clientRequests);\n const maxFsLimits = [\n getMaxFs('best'),\n getMaxFs('large'),\n getMaxFs('medium'),\n getMaxFs('small'),\n getMaxFs('very small'),\n getMaxFs('thumbnail'),\n ];\n\n // reduce max-fs until total macroblocks is below limit\n for (let i = 0; i < maxFsLimits.length; i += 1) {\n let totalMacroblocksRequested = 0;\n Object.entries(clientRequests).forEach(([id, mr]) => {\n if (mr.codecInfo) {\n mr.codecInfo.maxFs = Math.min(\n mr.preferredMaxFs || CODEC_DEFAULTS.h264.maxFs,\n mr.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs,\n maxFsLimits[i]\n );\n // we only consider sources with \"live\" state\n const slotsWithLiveSource = this.clientRequests[id].receiveSlots.filter(\n (rs) => rs.sourceState === 'live'\n );\n totalMacroblocksRequested += mr.codecInfo.maxFs * slotsWithLiveSource.length;\n }\n });\n if (totalMacroblocksRequested <= this.degradationPreferences.maxMacroblocksLimit) {\n if (i !== 0) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> too many streams with high max-fs, frame size will be limited to ${maxFsLimits[i]}`\n );\n }\n break;\n } else if (i === maxFsLimits.length - 1) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> even with frame size limited to ${maxFsLimits[i]} you are still requesting too many streams, consider reducing the number of requests`\n );\n }\n }\n\n return clientRequests;\n }\n\n /**\n * Returns true if two media requests are the same, false otherwise.\n *\n * @param {WcmeMediaRequest} mediaRequestA - Media request A for comparison.\n * @param {WcmeMediaRequest} mediaRequestB - Media request B for comparison.\n * @returns {boolean} - Whether they are equal.\n */\n // eslint-disable-next-line class-methods-use-this\n public isEqual(mediaRequestA: WcmeMediaRequest, mediaRequestB: WcmeMediaRequest) {\n return (\n JSON.stringify(mediaRequestA._toJmpScrRequest()) ===\n JSON.stringify(mediaRequestB._toJmpScrRequest())\n );\n }\n\n /**\n * Compares new media requests to previous ones and determines\n * if they are the same.\n *\n * @param {WcmeMediaRequest[]} newRequests - Array with new requests.\n * @returns {boolean} - True if they are equal, false otherwise.\n */\n private checkIsNewRequestsEqualToPrev(newRequests: WcmeMediaRequest[]) {\n return (\n !isEmpty(this.previousWCMEMediaRequests) &&\n this.previousWCMEMediaRequests.length === newRequests.length &&\n this.previousWCMEMediaRequests.every((req, idx) => this.isEqual(req, newRequests[idx]))\n );\n }\n\n private sendRequests() {\n const wcmeMediaRequests: WcmeMediaRequest[] = [];\n\n const clientRequests = this.getDegradedClientRequests();\n const maxPayloadBitsPerSecond = 10 * 1000 * 1000;\n\n // map all the client media requests to wcme media requests\n Object.values(clientRequests).forEach((mr) => {\n wcmeMediaRequests.push(\n new WcmeMediaRequest(\n mr.policyInfo.policy === 'active-speaker'\n ? Policy.ActiveSpeaker\n : Policy.ReceiverSelected,\n mr.policyInfo.policy === 'active-speaker'\n ? new ActiveSpeakerInfo(\n mr.policyInfo.priority,\n mr.policyInfo.crossPriorityDuplication,\n mr.policyInfo.crossPolicyDuplication,\n mr.policyInfo.preferLiveVideo\n )\n : new ReceiverSelectedInfo(mr.policyInfo.csi),\n mr.receiveSlots.map((receiveSlot) => receiveSlot.wcmeReceiveSlot),\n maxPayloadBitsPerSecond,\n mr.codecInfo && [\n new WcmeCodecInfo(\n 0x80,\n new H264Codec(\n mr.codecInfo.maxFs,\n mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps,\n mr.codecInfo.maxMbps || CODEC_DEFAULTS.h264.maxMbps,\n mr.codecInfo.maxWidth,\n mr.codecInfo.maxHeight\n )\n ),\n ]\n )\n );\n });\n\n //! IMPORTANT: this is only a temporary fix. This will soon be done in the jmp layer (@webex/jmp-multistream)\n // https://jira-eng-gpk2.cisco.com/jira/browse/WEBEX-326713\n if (!this.checkIsNewRequestsEqualToPrev(wcmeMediaRequests)) {\n this.sendMediaRequestsCallback(wcmeMediaRequests);\n this.previousWCMEMediaRequests = wcmeMediaRequests;\n LoggerProxy.logger.info(`multistream:sendRequests --> media requests sent. `);\n } else {\n LoggerProxy.logger.info(\n `multistream:sendRequests --> detected duplicate WCME requests, skipping them... `\n );\n }\n }\n\n public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {\n // eslint-disable-next-line no-plusplus\n const newId = `${this.counter++}`;\n\n this.clientRequests[newId] = mediaRequest;\n\n mediaRequest.receiveSlots.forEach((rs) => {\n rs.on(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n rs.on(ReceiveSlotEvents.MaxFsUpdate, ({maxFs}) => {\n mediaRequest.preferredMaxFs = maxFs;\n this.debouncedSourceUpdateListener();\n });\n });\n\n if (commit) {\n this.commit();\n }\n\n return newId;\n }\n\n public cancelRequest(requestId: MediaRequestId, commit = true) {\n this.clientRequests[requestId]?.receiveSlots.forEach((rs) => {\n rs.off(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n });\n\n delete this.clientRequests[requestId];\n\n if (commit) {\n this.commit();\n }\n }\n\n public commit() {\n return this.sendRequests();\n }\n\n public reset() {\n this.clientRequests = {};\n }\n}\n"],"mappings":"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"}
|
|
@@ -39,9 +39,26 @@ export declare class MediaRequestManager {
|
|
|
39
39
|
private degradationPreferences;
|
|
40
40
|
private sourceUpdateListener;
|
|
41
41
|
private debouncedSourceUpdateListener;
|
|
42
|
+
private previousWCMEMediaRequests;
|
|
42
43
|
constructor(degradationPreferences: DegradationPreferences, sendMediaRequestsCallback: SendMediaRequestsCallback);
|
|
43
44
|
setDegradationPreferences(degradationPreferences: DegradationPreferences): void;
|
|
44
45
|
private getDegradedClientRequests;
|
|
46
|
+
/**
|
|
47
|
+
* Returns true if two media requests are the same, false otherwise.
|
|
48
|
+
*
|
|
49
|
+
* @param {WcmeMediaRequest} mediaRequestA - Media request A for comparison.
|
|
50
|
+
* @param {WcmeMediaRequest} mediaRequestB - Media request B for comparison.
|
|
51
|
+
* @returns {boolean} - Whether they are equal.
|
|
52
|
+
*/
|
|
53
|
+
isEqual(mediaRequestA: WcmeMediaRequest, mediaRequestB: WcmeMediaRequest): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Compares new media requests to previous ones and determines
|
|
56
|
+
* if they are the same.
|
|
57
|
+
*
|
|
58
|
+
* @param {WcmeMediaRequest[]} newRequests - Array with new requests.
|
|
59
|
+
* @returns {boolean} - True if they are equal, false otherwise.
|
|
60
|
+
*/
|
|
61
|
+
private checkIsNewRequestsEqualToPrev;
|
|
45
62
|
private sendRequests;
|
|
46
63
|
addRequest(mediaRequest: MediaRequest, commit?: boolean): MediaRequestId;
|
|
47
64
|
cancelRequest(requestId: MediaRequestId, commit?: boolean): void;
|
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.66",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
36
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
35
|
+
"@webex/plugin-meetings": "3.0.0-beta.66",
|
|
36
|
+
"@webex/test-helper-chai": "3.0.0-beta.66",
|
|
37
|
+
"@webex/test-helper-mocha": "3.0.0-beta.66",
|
|
38
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.66",
|
|
39
|
+
"@webex/test-helper-retry": "3.0.0-beta.66",
|
|
40
|
+
"@webex/test-helper-test-users": "3.0.0-beta.66",
|
|
41
41
|
"chai": "^4.3.4",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"jsdom-global": "3.0.2",
|
|
@@ -46,18 +46,18 @@
|
|
|
46
46
|
"typescript": "^4.7.4"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@webex/common": "3.0.0-beta.
|
|
49
|
+
"@webex/common": "3.0.0-beta.66",
|
|
50
50
|
"@webex/internal-media-core": "1.35.7",
|
|
51
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
52
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
58
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
59
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
60
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
51
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.66",
|
|
52
|
+
"@webex/internal-plugin-device": "3.0.0-beta.66",
|
|
53
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.66",
|
|
54
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.66",
|
|
55
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.66",
|
|
56
|
+
"@webex/internal-plugin-support": "3.0.0-beta.66",
|
|
57
|
+
"@webex/internal-plugin-user": "3.0.0-beta.66",
|
|
58
|
+
"@webex/plugin-people": "3.0.0-beta.66",
|
|
59
|
+
"@webex/plugin-rooms": "3.0.0-beta.66",
|
|
60
|
+
"@webex/webex-core": "3.0.0-beta.66",
|
|
61
61
|
"ampersand-collection": "^2.0.2",
|
|
62
62
|
"bowser": "^2.11.0",
|
|
63
63
|
"btoa": "^1.2.1",
|
package/src/breakouts/README.md
CHANGED
|
@@ -134,6 +134,11 @@ breakouts.start(params)
|
|
|
134
134
|
// sessions should be like: [{id:'xx',memberIds:['111'],emails:['111@ss.com',anyone: true]},...]
|
|
135
135
|
breakouts.assign(sessions)
|
|
136
136
|
|
|
137
|
+
// Dynammic assign a particpant/participants to breakouts/main (not used by now)
|
|
138
|
+
// Admit lobby waiting participants to a breakout directly
|
|
139
|
+
// sessions should be like: [{id:'xx',participants:['111'],targetState:'JOINED'},...]
|
|
140
|
+
breakouts.dynamicAssign(sessions)
|
|
141
|
+
|
|
137
142
|
// End breakout sessions with necessary params
|
|
138
143
|
breakouts.end(params)
|
|
139
144
|
|
package/src/breakouts/index.ts
CHANGED
|
@@ -640,6 +640,42 @@ const Breakouts = WebexPlugin.extend({
|
|
|
640
640
|
},
|
|
641
641
|
});
|
|
642
642
|
},
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* assign participants dynamically after breakout sessions started,
|
|
646
|
+
* but currently it only used for admitting participants from lobby into breakout directly
|
|
647
|
+
* @param {Array} sessions
|
|
648
|
+
* @returns {void}
|
|
649
|
+
*/
|
|
650
|
+
dynamicAssign(sessions: any[]) {
|
|
651
|
+
const updatedSessions = sessions.map((item) => {
|
|
652
|
+
return {
|
|
653
|
+
id: item.id,
|
|
654
|
+
participants: item.participants,
|
|
655
|
+
targetState: item.targetState,
|
|
656
|
+
};
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
const body = {
|
|
660
|
+
groups: [
|
|
661
|
+
{
|
|
662
|
+
id: this.breakoutGroupId,
|
|
663
|
+
sessions: updatedSessions,
|
|
664
|
+
},
|
|
665
|
+
],
|
|
666
|
+
editlock: null,
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
if (this.editLock && this.editLock.token) {
|
|
670
|
+
body.editlock = this.editLock;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
return this.request({
|
|
674
|
+
method: HTTP_VERBS.PUT,
|
|
675
|
+
uri: `${this.url}/dynamicAssign`,
|
|
676
|
+
body,
|
|
677
|
+
});
|
|
678
|
+
},
|
|
643
679
|
});
|
|
644
680
|
|
|
645
681
|
export default Breakouts;
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
CodecInfo as WcmeCodecInfo,
|
|
8
8
|
H264Codec,
|
|
9
9
|
} from '@webex/internal-media-core';
|
|
10
|
-
import {cloneDeep, debounce} from 'lodash';
|
|
10
|
+
import {cloneDeep, debounce, isEmpty} from 'lodash';
|
|
11
11
|
|
|
12
12
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
13
13
|
|
|
14
|
-
import {ReceiveSlot, ReceiveSlotEvents
|
|
14
|
+
import {ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';
|
|
15
15
|
import {getMaxFs} from './remoteMedia';
|
|
16
16
|
|
|
17
17
|
export interface ActiveSpeakerPolicyInfo {
|
|
@@ -78,6 +78,8 @@ export class MediaRequestManager {
|
|
|
78
78
|
|
|
79
79
|
private debouncedSourceUpdateListener: () => void;
|
|
80
80
|
|
|
81
|
+
private previousWCMEMediaRequests: Array<WcmeMediaRequest> = [];
|
|
82
|
+
|
|
81
83
|
constructor(
|
|
82
84
|
degradationPreferences: DegradationPreferences,
|
|
83
85
|
sendMediaRequestsCallback: SendMediaRequestsCallback
|
|
@@ -143,6 +145,36 @@ export class MediaRequestManager {
|
|
|
143
145
|
return clientRequests;
|
|
144
146
|
}
|
|
145
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Returns true if two media requests are the same, false otherwise.
|
|
150
|
+
*
|
|
151
|
+
* @param {WcmeMediaRequest} mediaRequestA - Media request A for comparison.
|
|
152
|
+
* @param {WcmeMediaRequest} mediaRequestB - Media request B for comparison.
|
|
153
|
+
* @returns {boolean} - Whether they are equal.
|
|
154
|
+
*/
|
|
155
|
+
// eslint-disable-next-line class-methods-use-this
|
|
156
|
+
public isEqual(mediaRequestA: WcmeMediaRequest, mediaRequestB: WcmeMediaRequest) {
|
|
157
|
+
return (
|
|
158
|
+
JSON.stringify(mediaRequestA._toJmpScrRequest()) ===
|
|
159
|
+
JSON.stringify(mediaRequestB._toJmpScrRequest())
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Compares new media requests to previous ones and determines
|
|
165
|
+
* if they are the same.
|
|
166
|
+
*
|
|
167
|
+
* @param {WcmeMediaRequest[]} newRequests - Array with new requests.
|
|
168
|
+
* @returns {boolean} - True if they are equal, false otherwise.
|
|
169
|
+
*/
|
|
170
|
+
private checkIsNewRequestsEqualToPrev(newRequests: WcmeMediaRequest[]) {
|
|
171
|
+
return (
|
|
172
|
+
!isEmpty(this.previousWCMEMediaRequests) &&
|
|
173
|
+
this.previousWCMEMediaRequests.length === newRequests.length &&
|
|
174
|
+
this.previousWCMEMediaRequests.every((req, idx) => this.isEqual(req, newRequests[idx]))
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
146
178
|
private sendRequests() {
|
|
147
179
|
const wcmeMediaRequests: WcmeMediaRequest[] = [];
|
|
148
180
|
|
|
@@ -182,7 +214,17 @@ export class MediaRequestManager {
|
|
|
182
214
|
);
|
|
183
215
|
});
|
|
184
216
|
|
|
185
|
-
this.
|
|
217
|
+
//! IMPORTANT: this is only a temporary fix. This will soon be done in the jmp layer (@webex/jmp-multistream)
|
|
218
|
+
// https://jira-eng-gpk2.cisco.com/jira/browse/WEBEX-326713
|
|
219
|
+
if (!this.checkIsNewRequestsEqualToPrev(wcmeMediaRequests)) {
|
|
220
|
+
this.sendMediaRequestsCallback(wcmeMediaRequests);
|
|
221
|
+
this.previousWCMEMediaRequests = wcmeMediaRequests;
|
|
222
|
+
LoggerProxy.logger.info(`multistream:sendRequests --> media requests sent. `);
|
|
223
|
+
} else {
|
|
224
|
+
LoggerProxy.logger.info(
|
|
225
|
+
`multistream:sendRequests --> detected duplicate WCME requests, skipping them... `
|
|
226
|
+
);
|
|
227
|
+
}
|
|
186
228
|
}
|
|
187
229
|
|
|
188
230
|
public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {
|
|
@@ -996,5 +996,35 @@ describe('plugin-meetings', () => {
|
|
|
996
996
|
assert.equal(result, 'ASSIGN_RETURN_VALUE');
|
|
997
997
|
});
|
|
998
998
|
});
|
|
999
|
+
|
|
1000
|
+
describe('#dynamicAssign', () => {
|
|
1001
|
+
it('should make a PUT request with correct body and return the result', async () => {
|
|
1002
|
+
breakouts.dynamicAssign = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
|
|
1003
|
+
|
|
1004
|
+
const expectedBody = {
|
|
1005
|
+
groups: [
|
|
1006
|
+
{
|
|
1007
|
+
id: 'breakoutGroup1',
|
|
1008
|
+
sessions: [
|
|
1009
|
+
{
|
|
1010
|
+
id: 'session1',
|
|
1011
|
+
participants: ['participant1', 'participant2'],
|
|
1012
|
+
targetState: 'JOINED',
|
|
1013
|
+
},
|
|
1014
|
+
],
|
|
1015
|
+
},
|
|
1016
|
+
],
|
|
1017
|
+
editlock: {
|
|
1018
|
+
token: 'abcdefg',
|
|
1019
|
+
},
|
|
1020
|
+
};
|
|
1021
|
+
|
|
1022
|
+
const result = await breakouts.dynamicAssign(expectedBody);
|
|
1023
|
+
|
|
1024
|
+
assert.calledOnceWithExactly(breakouts.dynamicAssign, expectedBody);
|
|
1025
|
+
assert.equal(result, 'REQUEST_RETURN_VALUE');
|
|
1026
|
+
});
|
|
1027
|
+
});
|
|
1028
|
+
|
|
999
1029
|
});
|
|
1000
1030
|
});
|
|
@@ -552,28 +552,28 @@ describe('MediaRequestManager', () => {
|
|
|
552
552
|
]);
|
|
553
553
|
});
|
|
554
554
|
|
|
555
|
-
it('clears all the requests on reset()', () => {
|
|
555
|
+
it('avoids sending duplicate requests and clears all the requests on reset()', () => {
|
|
556
556
|
// send some requests and commit them one by one
|
|
557
|
-
addReceiverSelectedRequest(1500, fakeReceiveSlots[0], RECEIVER_SELECTED_MAX_FS,
|
|
558
|
-
addReceiverSelectedRequest(1501, fakeReceiveSlots[1], RECEIVER_SELECTED_MAX_FS,
|
|
557
|
+
addReceiverSelectedRequest(1500, fakeReceiveSlots[0], RECEIVER_SELECTED_MAX_FS, false);
|
|
558
|
+
addReceiverSelectedRequest(1501, fakeReceiveSlots[1], RECEIVER_SELECTED_MAX_FS, false);
|
|
559
559
|
addActiveSpeakerRequest(
|
|
560
560
|
255,
|
|
561
561
|
[fakeReceiveSlots[2], fakeReceiveSlots[3], fakeReceiveSlots[4]],
|
|
562
562
|
ACTIVE_SPEAKER_MAX_FS,
|
|
563
|
-
|
|
563
|
+
false
|
|
564
564
|
);
|
|
565
565
|
addActiveSpeakerRequest(
|
|
566
566
|
254,
|
|
567
567
|
[fakeReceiveSlots[5], fakeReceiveSlots[6], fakeReceiveSlots[7]],
|
|
568
568
|
ACTIVE_SPEAKER_MAX_FS,
|
|
569
|
-
|
|
569
|
+
false
|
|
570
570
|
);
|
|
571
571
|
|
|
572
|
-
|
|
572
|
+
// nothing should be sent out as we didn't commit the requests
|
|
573
|
+
assert.notCalled(sendMediaRequestsCallback);
|
|
573
574
|
|
|
574
|
-
// check that when calling commit() all requests are re-sent again
|
|
575
|
-
mediaRequestManager.commit();
|
|
576
575
|
|
|
576
|
+
mediaRequestManager.commit();
|
|
577
577
|
checkMediaRequestsSent([
|
|
578
578
|
{
|
|
579
579
|
policy: 'receiver-selected',
|
|
@@ -601,6 +601,13 @@ describe('MediaRequestManager', () => {
|
|
|
601
601
|
},
|
|
602
602
|
]);
|
|
603
603
|
|
|
604
|
+
|
|
605
|
+
// check that when calling commit()
|
|
606
|
+
// all requests are not re-sent again (avoid duplicate requests)
|
|
607
|
+
mediaRequestManager.commit();
|
|
608
|
+
|
|
609
|
+
assert.notCalled(sendMediaRequestsCallback);
|
|
610
|
+
|
|
604
611
|
// now reset everything
|
|
605
612
|
mediaRequestManager.reset();
|
|
606
613
|
|
|
@@ -609,6 +616,46 @@ describe('MediaRequestManager', () => {
|
|
|
609
616
|
checkMediaRequestsSent([]);
|
|
610
617
|
});
|
|
611
618
|
|
|
619
|
+
it('makes sure to call requests correctly after reset was called and another request was added', () => {
|
|
620
|
+
addReceiverSelectedRequest(1500, fakeReceiveSlots[0], RECEIVER_SELECTED_MAX_FS, false);
|
|
621
|
+
|
|
622
|
+
assert.notCalled(sendMediaRequestsCallback);
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
mediaRequestManager.commit();
|
|
626
|
+
checkMediaRequestsSent([
|
|
627
|
+
{
|
|
628
|
+
policy: 'receiver-selected',
|
|
629
|
+
csi: 1500,
|
|
630
|
+
receiveSlot: fakeWcmeSlots[0],
|
|
631
|
+
maxFs: RECEIVER_SELECTED_MAX_FS,
|
|
632
|
+
},
|
|
633
|
+
]);
|
|
634
|
+
|
|
635
|
+
// now reset everything
|
|
636
|
+
mediaRequestManager.reset();
|
|
637
|
+
|
|
638
|
+
// calling commit now should not cause any requests to be sent out
|
|
639
|
+
mediaRequestManager.commit();
|
|
640
|
+
checkMediaRequestsSent([]);
|
|
641
|
+
|
|
642
|
+
//add new request
|
|
643
|
+
addReceiverSelectedRequest(1501, fakeReceiveSlots[1], RECEIVER_SELECTED_MAX_FS, false);
|
|
644
|
+
|
|
645
|
+
// commit
|
|
646
|
+
mediaRequestManager.commit();
|
|
647
|
+
|
|
648
|
+
// check the new request was sent
|
|
649
|
+
checkMediaRequestsSent([
|
|
650
|
+
{
|
|
651
|
+
policy: 'receiver-selected',
|
|
652
|
+
csi: 1501,
|
|
653
|
+
receiveSlot: fakeWcmeSlots[1],
|
|
654
|
+
maxFs: RECEIVER_SELECTED_MAX_FS,
|
|
655
|
+
},
|
|
656
|
+
])
|
|
657
|
+
})
|
|
658
|
+
|
|
612
659
|
it('re-sends media requests after degradation preferences are set', () => {
|
|
613
660
|
// set max macroblocks limit
|
|
614
661
|
mediaRequestManager.setDegradationPreferences({maxMacroblocksLimit: 32400});
|