@webex/plugin-meetings 3.0.0-beta.40 → 3.0.0-beta.42
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/meeting/index.js +33 -24
- package/dist/meeting/index.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +19 -32
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/types/multistream/receiveSlotManager.d.ts +7 -4
- package/package.json +18 -18
- package/src/meeting/index.ts +21 -7
- package/src/multistream/receiveSlotManager.ts +18 -20
- package/test/unit/spec/meeting/index.js +82 -2
- package/test/unit/spec/multistream/receiveSlotManager.ts +21 -27
|
@@ -6,9 +6,8 @@ _Object$defineProperty(exports, "__esModule", {
|
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
8
|
exports.ReceiveSlotManager = void 0;
|
|
9
|
-
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
|
|
10
|
-
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
11
9
|
var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
|
|
10
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
|
|
12
11
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
|
|
13
12
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
|
|
14
13
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
@@ -27,15 +26,17 @@ var ReceiveSlotManager = /*#__PURE__*/function () {
|
|
|
27
26
|
* Constructor
|
|
28
27
|
* @param {Meeting} meeting
|
|
29
28
|
*/
|
|
30
|
-
function ReceiveSlotManager(
|
|
29
|
+
function ReceiveSlotManager(createSlotCallback, findMemberIdByCsiCallback) {
|
|
31
30
|
var _this$allocatedSlots, _this$freeSlots;
|
|
32
31
|
(0, _classCallCheck2.default)(this, ReceiveSlotManager);
|
|
33
32
|
(0, _defineProperty2.default)(this, "allocatedSlots", void 0);
|
|
34
33
|
(0, _defineProperty2.default)(this, "freeSlots", void 0);
|
|
35
|
-
(0, _defineProperty2.default)(this, "
|
|
34
|
+
(0, _defineProperty2.default)(this, "createSlotCallback", void 0);
|
|
35
|
+
(0, _defineProperty2.default)(this, "findMemberIdByCsiCallback", void 0);
|
|
36
36
|
this.allocatedSlots = (_this$allocatedSlots = {}, (0, _defineProperty2.default)(_this$allocatedSlots, _internalMediaCore.MediaType.AudioMain, []), (0, _defineProperty2.default)(_this$allocatedSlots, _internalMediaCore.MediaType.VideoMain, []), (0, _defineProperty2.default)(_this$allocatedSlots, _internalMediaCore.MediaType.AudioSlides, []), (0, _defineProperty2.default)(_this$allocatedSlots, _internalMediaCore.MediaType.VideoSlides, []), _this$allocatedSlots);
|
|
37
37
|
this.freeSlots = (_this$freeSlots = {}, (0, _defineProperty2.default)(_this$freeSlots, _internalMediaCore.MediaType.AudioMain, []), (0, _defineProperty2.default)(_this$freeSlots, _internalMediaCore.MediaType.VideoMain, []), (0, _defineProperty2.default)(_this$freeSlots, _internalMediaCore.MediaType.AudioSlides, []), (0, _defineProperty2.default)(_this$freeSlots, _internalMediaCore.MediaType.VideoSlides, []), _this$freeSlots);
|
|
38
|
-
this.
|
|
38
|
+
this.createSlotCallback = createSlotCallback;
|
|
39
|
+
this.findMemberIdByCsiCallback = findMemberIdByCsiCallback;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -48,43 +49,29 @@ var ReceiveSlotManager = /*#__PURE__*/function () {
|
|
|
48
49
|
key: "allocateSlot",
|
|
49
50
|
value: function () {
|
|
50
51
|
var _allocateSlot = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(mediaType) {
|
|
51
|
-
var _this$meeting,
|
|
52
|
-
_this$meeting$mediaPr,
|
|
53
|
-
_this = this;
|
|
54
52
|
var availableSlot, wcmeReceiveSlot, receiveSlot;
|
|
55
53
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
56
54
|
while (1) switch (_context.prev = _context.next) {
|
|
57
55
|
case 0:
|
|
58
|
-
if ((_this$meeting = this.meeting) !== null && _this$meeting !== void 0 && (_this$meeting$mediaPr = _this$meeting.mediaProperties) !== null && _this$meeting$mediaPr !== void 0 && _this$meeting$mediaPr.webrtcMediaConnection) {
|
|
59
|
-
_context.next = 2;
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
return _context.abrupt("return", _promise.default.reject(new Error('Webrtc media connection is missing')));
|
|
63
|
-
case 2:
|
|
64
56
|
// try to use one of the free ones
|
|
65
57
|
availableSlot = this.freeSlots[mediaType].pop();
|
|
66
58
|
if (!availableSlot) {
|
|
67
|
-
_context.next =
|
|
59
|
+
_context.next = 5;
|
|
68
60
|
break;
|
|
69
61
|
}
|
|
70
62
|
this.allocatedSlots[mediaType].push(availableSlot);
|
|
71
63
|
_loggerProxy.default.logger.log("receive slot re-used: ".concat(availableSlot.id));
|
|
72
64
|
return _context.abrupt("return", availableSlot);
|
|
65
|
+
case 5:
|
|
66
|
+
_context.next = 7;
|
|
67
|
+
return this.createSlotCallback(mediaType);
|
|
73
68
|
case 7:
|
|
74
|
-
_context.next = 9;
|
|
75
|
-
return this.meeting.mediaProperties.webrtcMediaConnection.createReceiveSlot(mediaType);
|
|
76
|
-
case 9:
|
|
77
69
|
wcmeReceiveSlot = _context.sent;
|
|
78
|
-
receiveSlot = new _receiveSlot.ReceiveSlot(mediaType, wcmeReceiveSlot,
|
|
79
|
-
// @ts-ignore
|
|
80
|
-
function (csi) {
|
|
81
|
-
var _this$meeting$members;
|
|
82
|
-
return (_this$meeting$members = _this.meeting.members.findMemberByCsi(csi)) === null || _this$meeting$members === void 0 ? void 0 : _this$meeting$members.id;
|
|
83
|
-
});
|
|
70
|
+
receiveSlot = new _receiveSlot.ReceiveSlot(mediaType, wcmeReceiveSlot, this.findMemberIdByCsiCallback);
|
|
84
71
|
this.allocatedSlots[mediaType].push(receiveSlot);
|
|
85
72
|
_loggerProxy.default.logger.log("new receive slot allocated: ".concat(receiveSlot.id));
|
|
86
73
|
return _context.abrupt("return", receiveSlot);
|
|
87
|
-
case
|
|
74
|
+
case 12:
|
|
88
75
|
case "end":
|
|
89
76
|
return _context.stop();
|
|
90
77
|
}
|
|
@@ -133,17 +120,17 @@ var ReceiveSlotManager = /*#__PURE__*/function () {
|
|
|
133
120
|
}, {
|
|
134
121
|
key: "getStats",
|
|
135
122
|
value: function getStats() {
|
|
136
|
-
var
|
|
123
|
+
var _this = this;
|
|
137
124
|
var numAllocatedSlots = {};
|
|
138
125
|
var numFreeSlots = {};
|
|
139
126
|
(0, _keys.default)(this.allocatedSlots).forEach(function (key) {
|
|
140
|
-
if (
|
|
141
|
-
numAllocatedSlots[key] =
|
|
127
|
+
if (_this.allocatedSlots[key].length > 0) {
|
|
128
|
+
numAllocatedSlots[key] = _this.allocatedSlots[key].length;
|
|
142
129
|
}
|
|
143
130
|
});
|
|
144
131
|
(0, _keys.default)(this.freeSlots).forEach(function (key) {
|
|
145
|
-
if (
|
|
146
|
-
numFreeSlots[key] =
|
|
132
|
+
if (_this.freeSlots[key].length > 0) {
|
|
133
|
+
numFreeSlots[key] = _this.freeSlots[key].length;
|
|
147
134
|
}
|
|
148
135
|
});
|
|
149
136
|
return {
|
|
@@ -159,9 +146,9 @@ var ReceiveSlotManager = /*#__PURE__*/function () {
|
|
|
159
146
|
}, {
|
|
160
147
|
key: "updateMemberIds",
|
|
161
148
|
value: function updateMemberIds() {
|
|
162
|
-
var
|
|
149
|
+
var _this2 = this;
|
|
163
150
|
(0, _keys.default)(this.allocatedSlots).forEach(function (key) {
|
|
164
|
-
|
|
151
|
+
_this2.allocatedSlots[key].forEach(function (slot) {
|
|
165
152
|
slot.findMemberId();
|
|
166
153
|
});
|
|
167
154
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ReceiveSlotManager","
|
|
1
|
+
{"version":3,"names":["ReceiveSlotManager","createSlotCallback","findMemberIdByCsiCallback","allocatedSlots","MediaType","AudioMain","VideoMain","AudioSlides","VideoSlides","freeSlots","mediaType","availableSlot","pop","push","LoggerProxy","logger","log","id","wcmeReceiveSlot","receiveSlot","ReceiveSlot","slot","idx","findIndex","allocatedSlot","splice","warn","numAllocatedSlots","numFreeSlots","forEach","key","length","findMemberId"],"sources":["receiveSlotManager.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\n/* eslint-disable import/prefer-default-export */\nimport {MediaType, ReceiveSlot as WcmeReceiveSlot} from '@webex/internal-media-core';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {FindMemberIdCallback, ReceiveSlot} from './receiveSlot';\n\nexport type CreateSlotCallback = (mediaType: MediaType) => Promise<WcmeReceiveSlot>;\n\nexport type {CSI, FindMemberIdCallback} from './receiveSlot';\n\n/**\n * Manages all receive slots used by a meeting. WMCE receive slots cannot be ever deleted,\n * so this manager has a pool in order to re-use the slots that were released earlier.\n */\nexport class ReceiveSlotManager {\n private allocatedSlots: {[key in MediaType]: ReceiveSlot[]};\n\n private freeSlots: {[key in MediaType]: ReceiveSlot[]};\n\n private createSlotCallback: CreateSlotCallback;\n\n private findMemberIdByCsiCallback: FindMemberIdCallback;\n\n /**\n * Constructor\n * @param {Meeting} meeting\n */\n constructor(\n createSlotCallback: CreateSlotCallback,\n findMemberIdByCsiCallback: FindMemberIdCallback\n ) {\n this.allocatedSlots = {\n [MediaType.AudioMain]: [],\n [MediaType.VideoMain]: [],\n [MediaType.AudioSlides]: [],\n [MediaType.VideoSlides]: [],\n };\n this.freeSlots = {\n [MediaType.AudioMain]: [],\n [MediaType.VideoMain]: [],\n [MediaType.AudioSlides]: [],\n [MediaType.VideoSlides]: [],\n };\n this.createSlotCallback = createSlotCallback;\n this.findMemberIdByCsiCallback = findMemberIdByCsiCallback;\n }\n\n /**\n * Creates a new receive slot or returns one from the existing pool of free slots\n *\n * @param {MediaType} mediaType\n * @returns {Promise<ReceiveSlot>}\n */\n async allocateSlot(mediaType: MediaType): Promise<ReceiveSlot> {\n // try to use one of the free ones\n const availableSlot = this.freeSlots[mediaType].pop();\n\n if (availableSlot) {\n this.allocatedSlots[mediaType].push(availableSlot);\n\n LoggerProxy.logger.log(`receive slot re-used: ${availableSlot.id}`);\n\n return availableSlot;\n }\n\n // we have to create a new one\n const wcmeReceiveSlot = await this.createSlotCallback(mediaType);\n\n const receiveSlot = new ReceiveSlot(mediaType, wcmeReceiveSlot, this.findMemberIdByCsiCallback);\n\n this.allocatedSlots[mediaType].push(receiveSlot);\n LoggerProxy.logger.log(`new receive slot allocated: ${receiveSlot.id}`);\n\n return receiveSlot;\n }\n\n /**\n * Releases the slot back to the pool so it can be re-used by others in the future\n * @param {ReceiveSlot} slot\n */\n releaseSlot(slot: ReceiveSlot) {\n const idx = this.allocatedSlots[slot.mediaType].findIndex(\n (allocatedSlot) => allocatedSlot === slot\n );\n\n if (idx >= 0) {\n this.allocatedSlots[slot.mediaType].splice(idx, 1);\n this.freeSlots[slot.mediaType].push(slot);\n LoggerProxy.logger.log(`receive slot released: ${slot.id}`);\n } else {\n LoggerProxy.logger.warn(\n 'ReceiveSlotManager#releaseSlot --> trying to release a slot that is not managed by this ReceiveSlotManager'\n );\n }\n }\n\n /**\n * Resets the slot manager - this method should be called when the media connection is torn down\n */\n reset() {\n this.allocatedSlots = {\n [MediaType.AudioMain]: [],\n [MediaType.VideoMain]: [],\n [MediaType.AudioSlides]: [],\n [MediaType.VideoSlides]: [],\n };\n this.freeSlots = {\n [MediaType.AudioMain]: [],\n [MediaType.VideoMain]: [],\n [MediaType.AudioSlides]: [],\n [MediaType.VideoSlides]: [],\n };\n }\n\n /**\n * Returns statistics about the managed slots\n *\n * @returns {Object}\n */\n getStats() {\n const numAllocatedSlots = {};\n const numFreeSlots = {};\n\n Object.keys(this.allocatedSlots).forEach((key) => {\n if (this.allocatedSlots[key].length > 0) {\n numAllocatedSlots[key] = this.allocatedSlots[key].length;\n }\n });\n\n Object.keys(this.freeSlots).forEach((key) => {\n if (this.freeSlots[key].length > 0) {\n numFreeSlots[key] = this.freeSlots[key].length;\n }\n });\n\n return {\n numAllocatedSlots,\n numFreeSlots,\n };\n }\n\n /**\n * Tries to find the member id on all allocated receive slots\n * This function should be called when new members are added to the meeting.\n */\n updateMemberIds() {\n Object.keys(this.allocatedSlots).forEach((key) => {\n this.allocatedSlots[key].forEach((slot: ReceiveSlot) => {\n slot.findMemberId();\n });\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { MediaType } from '@webex/internal-media-core';
|
|
2
|
-
import { ReceiveSlot } from './receiveSlot';
|
|
1
|
+
import { MediaType, ReceiveSlot as WcmeReceiveSlot } from '@webex/internal-media-core';
|
|
2
|
+
import { FindMemberIdCallback, ReceiveSlot } from './receiveSlot';
|
|
3
|
+
export type CreateSlotCallback = (mediaType: MediaType) => Promise<WcmeReceiveSlot>;
|
|
4
|
+
export type { CSI, FindMemberIdCallback } from './receiveSlot';
|
|
3
5
|
/**
|
|
4
6
|
* Manages all receive slots used by a meeting. WMCE receive slots cannot be ever deleted,
|
|
5
7
|
* so this manager has a pool in order to re-use the slots that were released earlier.
|
|
@@ -7,12 +9,13 @@ import { ReceiveSlot } from './receiveSlot';
|
|
|
7
9
|
export declare class ReceiveSlotManager {
|
|
8
10
|
private allocatedSlots;
|
|
9
11
|
private freeSlots;
|
|
10
|
-
private
|
|
12
|
+
private createSlotCallback;
|
|
13
|
+
private findMemberIdByCsiCallback;
|
|
11
14
|
/**
|
|
12
15
|
* Constructor
|
|
13
16
|
* @param {Meeting} meeting
|
|
14
17
|
*/
|
|
15
|
-
constructor(
|
|
18
|
+
constructor(createSlotCallback: CreateSlotCallback, findMemberIdByCsiCallback: FindMemberIdCallback);
|
|
16
19
|
/**
|
|
17
20
|
* Creates a new receive slot or returns one from the existing pool of free slots
|
|
18
21
|
*
|
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.42",
|
|
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.42",
|
|
36
|
+
"@webex/test-helper-chai": "3.0.0-beta.42",
|
|
37
|
+
"@webex/test-helper-mocha": "3.0.0-beta.42",
|
|
38
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.42",
|
|
39
|
+
"@webex/test-helper-retry": "3.0.0-beta.42",
|
|
40
|
+
"@webex/test-helper-test-users": "3.0.0-beta.42",
|
|
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.42",
|
|
50
50
|
"@webex/internal-media-core": "1.35.2",
|
|
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.42",
|
|
52
|
+
"@webex/internal-plugin-device": "3.0.0-beta.42",
|
|
53
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.42",
|
|
54
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.42",
|
|
55
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.42",
|
|
56
|
+
"@webex/internal-plugin-support": "3.0.0-beta.42",
|
|
57
|
+
"@webex/internal-plugin-user": "3.0.0-beta.42",
|
|
58
|
+
"@webex/plugin-people": "3.0.0-beta.42",
|
|
59
|
+
"@webex/plugin-rooms": "3.0.0-beta.42",
|
|
60
|
+
"@webex/webex-core": "3.0.0-beta.42",
|
|
61
61
|
"ampersand-collection": "^2.0.2",
|
|
62
62
|
"bowser": "^2.11.0",
|
|
63
63
|
"btoa": "^1.2.1",
|
package/src/meeting/index.ts
CHANGED
|
@@ -33,7 +33,12 @@ import MeetingStateMachine from './state';
|
|
|
33
33
|
import {createMuteState} from './muteState';
|
|
34
34
|
import LocusInfo from '../locus-info';
|
|
35
35
|
import Metrics from '../metrics';
|
|
36
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
trigger,
|
|
38
|
+
mediaType as MetricsMediaType,
|
|
39
|
+
error as MetricsError,
|
|
40
|
+
eventType,
|
|
41
|
+
} from '../metrics/config';
|
|
37
42
|
import ReconnectionManager from '../reconnection-manager';
|
|
38
43
|
import MeetingRequest from './request';
|
|
39
44
|
import Members from '../members/index';
|
|
@@ -90,7 +95,7 @@ import {
|
|
|
90
95
|
MeetingInfoV2CaptchaError,
|
|
91
96
|
} from '../meeting-info/meeting-info-v2';
|
|
92
97
|
import BrowserDetection from '../common/browser-detection';
|
|
93
|
-
import {ReceiveSlotManager} from '../multistream/receiveSlotManager';
|
|
98
|
+
import {CSI, ReceiveSlotManager} from '../multistream/receiveSlotManager';
|
|
94
99
|
import {MediaRequestManager} from '../multistream/mediaRequestManager';
|
|
95
100
|
import {
|
|
96
101
|
RemoteMediaManager,
|
|
@@ -609,7 +614,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
609
614
|
/**
|
|
610
615
|
* helper class for managing receive slots (for multistream media connections)
|
|
611
616
|
*/
|
|
612
|
-
this.receiveSlotManager = new ReceiveSlotManager(
|
|
617
|
+
this.receiveSlotManager = new ReceiveSlotManager(
|
|
618
|
+
(mediaType: MediaType) => {
|
|
619
|
+
if (!this.mediaProperties?.webrtcMediaConnection) {
|
|
620
|
+
return Promise.reject(new Error('Webrtc media connection is missing'));
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return this.mediaProperties.webrtcMediaConnection.createReceiveSlot(mediaType);
|
|
624
|
+
},
|
|
625
|
+
(csi: CSI) => (this.members.findMemberByCsi(csi) as any)?.id
|
|
626
|
+
);
|
|
613
627
|
/**
|
|
614
628
|
* Object containing helper classes for managing media requests for audio/video/screenshare (for multistream media connections)
|
|
615
629
|
* All multistream media requests sent out for this meeting have to go through them.
|
|
@@ -3436,7 +3450,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3436
3450
|
Metrics.postEvent({
|
|
3437
3451
|
event: eventType.MUTED,
|
|
3438
3452
|
meeting: this,
|
|
3439
|
-
data: {trigger: trigger.USER_INTERACTION, mediaType:
|
|
3453
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: MetricsMediaType.AUDIO},
|
|
3440
3454
|
});
|
|
3441
3455
|
})
|
|
3442
3456
|
.catch((error) => {
|
|
@@ -3489,7 +3503,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3489
3503
|
Metrics.postEvent({
|
|
3490
3504
|
event: eventType.UNMUTED,
|
|
3491
3505
|
meeting: this,
|
|
3492
|
-
data: {trigger: trigger.USER_INTERACTION, mediaType:
|
|
3506
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: MetricsMediaType.AUDIO},
|
|
3493
3507
|
});
|
|
3494
3508
|
})
|
|
3495
3509
|
.catch((error) => {
|
|
@@ -3541,7 +3555,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3541
3555
|
Metrics.postEvent({
|
|
3542
3556
|
event: eventType.MUTED,
|
|
3543
3557
|
meeting: this,
|
|
3544
|
-
data: {trigger: trigger.USER_INTERACTION, mediaType:
|
|
3558
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: MetricsMediaType.VIDEO},
|
|
3545
3559
|
});
|
|
3546
3560
|
})
|
|
3547
3561
|
.catch((error) => {
|
|
@@ -3593,7 +3607,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3593
3607
|
Metrics.postEvent({
|
|
3594
3608
|
event: eventType.UNMUTED,
|
|
3595
3609
|
meeting: this,
|
|
3596
|
-
data: {trigger: trigger.USER_INTERACTION, mediaType:
|
|
3610
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: MetricsMediaType.VIDEO},
|
|
3597
3611
|
});
|
|
3598
3612
|
})
|
|
3599
3613
|
.catch((error) => {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/* eslint-disable valid-jsdoc */
|
|
2
2
|
/* eslint-disable import/prefer-default-export */
|
|
3
|
-
import {MediaType} from '@webex/internal-media-core';
|
|
4
|
-
|
|
3
|
+
import {MediaType, ReceiveSlot as WcmeReceiveSlot} from '@webex/internal-media-core';
|
|
5
4
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
6
|
-
import Meeting from '../meeting';
|
|
7
5
|
|
|
8
|
-
import {
|
|
6
|
+
import {FindMemberIdCallback, ReceiveSlot} from './receiveSlot';
|
|
7
|
+
|
|
8
|
+
export type CreateSlotCallback = (mediaType: MediaType) => Promise<WcmeReceiveSlot>;
|
|
9
|
+
|
|
10
|
+
export type {CSI, FindMemberIdCallback} from './receiveSlot';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Manages all receive slots used by a meeting. WMCE receive slots cannot be ever deleted,
|
|
@@ -16,13 +18,18 @@ export class ReceiveSlotManager {
|
|
|
16
18
|
|
|
17
19
|
private freeSlots: {[key in MediaType]: ReceiveSlot[]};
|
|
18
20
|
|
|
19
|
-
private
|
|
21
|
+
private createSlotCallback: CreateSlotCallback;
|
|
22
|
+
|
|
23
|
+
private findMemberIdByCsiCallback: FindMemberIdCallback;
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* Constructor
|
|
23
27
|
* @param {Meeting} meeting
|
|
24
28
|
*/
|
|
25
|
-
constructor(
|
|
29
|
+
constructor(
|
|
30
|
+
createSlotCallback: CreateSlotCallback,
|
|
31
|
+
findMemberIdByCsiCallback: FindMemberIdCallback
|
|
32
|
+
) {
|
|
26
33
|
this.allocatedSlots = {
|
|
27
34
|
[MediaType.AudioMain]: [],
|
|
28
35
|
[MediaType.VideoMain]: [],
|
|
@@ -35,7 +42,8 @@ export class ReceiveSlotManager {
|
|
|
35
42
|
[MediaType.AudioSlides]: [],
|
|
36
43
|
[MediaType.VideoSlides]: [],
|
|
37
44
|
};
|
|
38
|
-
this.
|
|
45
|
+
this.createSlotCallback = createSlotCallback;
|
|
46
|
+
this.findMemberIdByCsiCallback = findMemberIdByCsiCallback;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
/**
|
|
@@ -45,10 +53,6 @@ export class ReceiveSlotManager {
|
|
|
45
53
|
* @returns {Promise<ReceiveSlot>}
|
|
46
54
|
*/
|
|
47
55
|
async allocateSlot(mediaType: MediaType): Promise<ReceiveSlot> {
|
|
48
|
-
if (!this.meeting?.mediaProperties?.webrtcMediaConnection) {
|
|
49
|
-
return Promise.reject(new Error('Webrtc media connection is missing'));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
56
|
// try to use one of the free ones
|
|
53
57
|
const availableSlot = this.freeSlots[mediaType].pop();
|
|
54
58
|
|
|
@@ -61,15 +65,9 @@ export class ReceiveSlotManager {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
// we have to create a new one
|
|
64
|
-
const wcmeReceiveSlot =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const receiveSlot = new ReceiveSlot(
|
|
68
|
-
mediaType,
|
|
69
|
-
wcmeReceiveSlot,
|
|
70
|
-
// @ts-ignore
|
|
71
|
-
(csi: CSI) => this.meeting.members.findMemberByCsi(csi)?.id
|
|
72
|
-
);
|
|
68
|
+
const wcmeReceiveSlot = await this.createSlotCallback(mediaType);
|
|
69
|
+
|
|
70
|
+
const receiveSlot = new ReceiveSlot(mediaType, wcmeReceiveSlot, this.findMemberIdByCsiCallback);
|
|
73
71
|
|
|
74
72
|
this.allocatedSlots[mediaType].push(receiveSlot);
|
|
75
73
|
LoggerProxy.logger.log(`new receive slot allocated: ${receiveSlot.id}`);
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
PC_BAIL_TIMEOUT,
|
|
24
24
|
} from '@webex/plugin-meetings/src/constants';
|
|
25
25
|
import * as InternalMediaCoreModule from '@webex/internal-media-core';
|
|
26
|
-
import {ConnectionState, Event, Errors, ErrorType, LocalTrackEvents, RemoteTrackType} from '@webex/internal-media-core';
|
|
26
|
+
import {ConnectionState, Event, Errors, ErrorType, LocalTrackEvents, RemoteTrackType, MediaType} from '@webex/internal-media-core';
|
|
27
27
|
import * as StatsAnalyzerModule from '@webex/plugin-meetings/src/statsAnalyzer';
|
|
28
28
|
import * as MuteStateModule from '@webex/plugin-meetings/src/meeting/muteState';
|
|
29
29
|
import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
|
|
@@ -47,8 +47,8 @@ import BrowserDetection from '@webex/plugin-meetings/src/common/browser-detectio
|
|
|
47
47
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
48
48
|
import {trigger, eventType} from '@webex/plugin-meetings/src/metrics/config';
|
|
49
49
|
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
50
|
-
import {IceGatheringFailed} from '@webex/plugin-meetings/src/common/errors/webex-errors';
|
|
51
50
|
import {MediaRequestManager} from '@webex/plugin-meetings/src/multistream/mediaRequestManager';
|
|
51
|
+
import * as ReceiveSlotManagerModule from '@webex/plugin-meetings/src/multistream/receiveSlotManager';
|
|
52
52
|
|
|
53
53
|
import LLM from '@webex/internal-plugin-llm';
|
|
54
54
|
import Mercury from '@webex/internal-plugin-mercury';
|
|
@@ -274,6 +274,86 @@ describe('plugin-meetings', () => {
|
|
|
274
274
|
assert.instanceOf(meeting.mediaRequestManagers.screenShareAudio, MediaRequestManager);
|
|
275
275
|
assert.instanceOf(meeting.mediaRequestManagers.screenShareVideo, MediaRequestManager);
|
|
276
276
|
});
|
|
277
|
+
|
|
278
|
+
describe('creates ReceiveSlot manager instance', () => {
|
|
279
|
+
let mockReceiveSlotManagerCtor;
|
|
280
|
+
let providedCreateSlotCallback;
|
|
281
|
+
let providedFindMemberIdByCsiCallback;
|
|
282
|
+
|
|
283
|
+
beforeEach(() => {
|
|
284
|
+
mockReceiveSlotManagerCtor = sinon.stub(ReceiveSlotManagerModule, 'ReceiveSlotManager').callsFake((createSlotCallback, findMemberIdByCsiCallback) => {
|
|
285
|
+
providedCreateSlotCallback = createSlotCallback;
|
|
286
|
+
providedFindMemberIdByCsiCallback = findMemberIdByCsiCallback;
|
|
287
|
+
|
|
288
|
+
return {updateMemberIds: sinon.stub()};
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
meeting = new Meeting(
|
|
292
|
+
{
|
|
293
|
+
userId: uuid1,
|
|
294
|
+
resource: uuid2,
|
|
295
|
+
deviceUrl: uuid3,
|
|
296
|
+
locus: {url: url1},
|
|
297
|
+
destination: testDestination,
|
|
298
|
+
destinationType: _MEETING_ID_,
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
parent: webex,
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
meeting.mediaProperties.webrtcMediaConnection = {createReceiveSlot: sinon.stub()};
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('calls ReceiveSlotManager constructor', () => {
|
|
309
|
+
assert.calledOnce(mockReceiveSlotManagerCtor);
|
|
310
|
+
assert.isDefined(providedCreateSlotCallback);
|
|
311
|
+
assert.isDefined(providedFindMemberIdByCsiCallback);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('calls createReceiveSlot on the webrtc media connection in the createSlotCallback', async () => {
|
|
315
|
+
assert.isDefined(providedCreateSlotCallback);
|
|
316
|
+
|
|
317
|
+
await providedCreateSlotCallback(MediaType.VideoMain);
|
|
318
|
+
|
|
319
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
|
|
320
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.createReceiveSlot, MediaType.VideoMain);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('rejects createSlotCallback if there is no webrtc media connection', () => {
|
|
324
|
+
assert.isDefined(providedCreateSlotCallback);
|
|
325
|
+
|
|
326
|
+
meeting.mediaProperties.webrtcMediaConnection.createReceiveSlot.rejects({});
|
|
327
|
+
|
|
328
|
+
assert.isRejected(providedCreateSlotCallback(MediaType.VideoMain));
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('calls findMemberByCsi in findMemberIdByCsiCallback and returns the right value', () => {
|
|
332
|
+
assert.isDefined(providedFindMemberIdByCsiCallback);
|
|
333
|
+
|
|
334
|
+
const fakeMember = {id: 'aaa-bbb'};
|
|
335
|
+
|
|
336
|
+
sinon.stub(meeting.members, 'findMemberByCsi').returns(fakeMember)
|
|
337
|
+
|
|
338
|
+
const memberId = providedFindMemberIdByCsiCallback(123);
|
|
339
|
+
|
|
340
|
+
assert.calledOnce(meeting.members.findMemberByCsi);
|
|
341
|
+
assert.calledWith(meeting.members.findMemberByCsi, 123);
|
|
342
|
+
assert.equal(memberId, fakeMember.id);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('returns undefined if findMemberByCsi does not find the member', () => {
|
|
346
|
+
assert.isDefined(providedFindMemberIdByCsiCallback);
|
|
347
|
+
|
|
348
|
+
sinon.stub(meeting.members, 'findMemberByCsi').returns(undefined)
|
|
349
|
+
|
|
350
|
+
const memberId = providedFindMemberIdByCsiCallback(123);
|
|
351
|
+
|
|
352
|
+
assert.calledOnce(meeting.members.findMemberByCsi);
|
|
353
|
+
assert.calledWith(meeting.members.findMemberByCsi, 123);
|
|
354
|
+
assert.equal(memberId, undefined);
|
|
355
|
+
});
|
|
356
|
+
})
|
|
277
357
|
});
|
|
278
358
|
describe('#invite', () => {
|
|
279
359
|
it('should have #invite', () => {
|
|
@@ -6,26 +6,17 @@ import {ReceiveSlotManager} from '@webex/plugin-meetings/src/multistream/receive
|
|
|
6
6
|
import * as ReceiveSlotModule from '@webex/plugin-meetings/src/multistream/receiveSlot';
|
|
7
7
|
|
|
8
8
|
describe('ReceiveSlotManager', () => {
|
|
9
|
-
let fakeMeeting;
|
|
10
9
|
let fakeWcmeSlot;
|
|
11
10
|
let fakeReceiveSlots;
|
|
12
11
|
let mockReceiveSlotCtor;
|
|
13
12
|
let receiveSlotManager;
|
|
13
|
+
let createSlotCallbackStub;
|
|
14
|
+
let findMemberIdCallbackStub;
|
|
14
15
|
|
|
15
16
|
beforeEach(() => {
|
|
16
17
|
fakeWcmeSlot = {
|
|
17
18
|
id: 'fake wcme slot',
|
|
18
19
|
};
|
|
19
|
-
fakeMeeting = {
|
|
20
|
-
mediaProperties: {
|
|
21
|
-
webrtcMediaConnection: {
|
|
22
|
-
createReceiveSlot: sinon.stub().resolves(fakeWcmeSlot),
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
members: {
|
|
26
|
-
findMemberByCsi: sinon.stub(),
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
20
|
fakeReceiveSlots = [];
|
|
30
21
|
mockReceiveSlotCtor = sinon.stub(ReceiveSlotModule, 'ReceiveSlot').callsFake((mediaType) => {
|
|
31
22
|
const fakeReceiveSlot = {
|
|
@@ -39,7 +30,10 @@ describe('ReceiveSlotManager', () => {
|
|
|
39
30
|
return fakeReceiveSlot;
|
|
40
31
|
});
|
|
41
32
|
|
|
42
|
-
|
|
33
|
+
createSlotCallbackStub = sinon.stub().resolves(fakeWcmeSlot);
|
|
34
|
+
findMemberIdCallbackStub = sinon.stub();
|
|
35
|
+
|
|
36
|
+
receiveSlotManager = new ReceiveSlotManager(createSlotCallbackStub, findMemberIdCallbackStub);
|
|
43
37
|
});
|
|
44
38
|
|
|
45
39
|
afterEach(() => {
|
|
@@ -47,7 +41,7 @@ describe('ReceiveSlotManager', () => {
|
|
|
47
41
|
});
|
|
48
42
|
|
|
49
43
|
it('rejects if there is no media connection', async () => {
|
|
50
|
-
|
|
44
|
+
createSlotCallbackStub.rejects(new Error('Webrtc media connection is missing'));
|
|
51
45
|
|
|
52
46
|
assert.isRejected(
|
|
53
47
|
receiveSlotManager.allocateSlot(MediaType.VideoMain),
|
|
@@ -60,14 +54,14 @@ describe('ReceiveSlotManager', () => {
|
|
|
60
54
|
|
|
61
55
|
const slot = await receiveSlotManager.allocateSlot(MediaType.VideoMain);
|
|
62
56
|
|
|
63
|
-
assert.calledOnce(
|
|
57
|
+
assert.calledOnce(createSlotCallbackStub);
|
|
64
58
|
assert.calledWith(
|
|
65
|
-
|
|
59
|
+
createSlotCallbackStub,
|
|
66
60
|
MediaType.VideoMain
|
|
67
61
|
);
|
|
68
62
|
|
|
69
63
|
assert.calledOnce(mockReceiveSlotCtor);
|
|
70
|
-
assert.calledWith(mockReceiveSlotCtor, MediaType.VideoMain, fakeWcmeSlot,
|
|
64
|
+
assert.calledWith(mockReceiveSlotCtor, MediaType.VideoMain, fakeWcmeSlot, findMemberIdCallbackStub);
|
|
71
65
|
assert.strictEqual(slot, fakeReceiveSlots[0]);
|
|
72
66
|
|
|
73
67
|
assert.deepEqual(receiveSlotManager.getStats(), {
|
|
@@ -79,7 +73,7 @@ describe('ReceiveSlotManager', () => {
|
|
|
79
73
|
it('reuses previously freed slot when allocateSlot() is called and a free slot is available', async () => {
|
|
80
74
|
const slot1 = await receiveSlotManager.allocateSlot(MediaType.VideoMain);
|
|
81
75
|
|
|
82
|
-
assert.calledOnce(
|
|
76
|
+
assert.calledOnce(createSlotCallbackStub);
|
|
83
77
|
assert.calledOnce(mockReceiveSlotCtor);
|
|
84
78
|
assert.strictEqual(slot1, fakeReceiveSlots[0]);
|
|
85
79
|
|
|
@@ -91,13 +85,13 @@ describe('ReceiveSlotManager', () => {
|
|
|
91
85
|
numFreeSlots: {'VIDEO-MAIN': 1},
|
|
92
86
|
});
|
|
93
87
|
|
|
94
|
-
|
|
88
|
+
createSlotCallbackStub.resetHistory();
|
|
95
89
|
mockReceiveSlotCtor.resetHistory();
|
|
96
90
|
|
|
97
91
|
// allocate another slot, this time the previous one should be returned instead of allocating any new ones
|
|
98
92
|
const slot2 = await receiveSlotManager.allocateSlot(MediaType.VideoMain);
|
|
99
93
|
|
|
100
|
-
assert.notCalled(
|
|
94
|
+
assert.notCalled(createSlotCallbackStub);
|
|
101
95
|
assert.notCalled(mockReceiveSlotCtor);
|
|
102
96
|
|
|
103
97
|
// verify that in fact we got the same slot again
|
|
@@ -112,7 +106,7 @@ describe('ReceiveSlotManager', () => {
|
|
|
112
106
|
it('does not reuse any slots after reset() is called', async () => {
|
|
113
107
|
const slot1 = await receiveSlotManager.allocateSlot(MediaType.VideoMain);
|
|
114
108
|
|
|
115
|
-
assert.calledOnce(
|
|
109
|
+
assert.calledOnce(createSlotCallbackStub);
|
|
116
110
|
assert.calledOnce(mockReceiveSlotCtor);
|
|
117
111
|
assert.strictEqual(slot1, fakeReceiveSlots[0]);
|
|
118
112
|
|
|
@@ -121,7 +115,7 @@ describe('ReceiveSlotManager', () => {
|
|
|
121
115
|
receiveSlotManager.reset();
|
|
122
116
|
|
|
123
117
|
// reset the mocks and set the ReceiveSlot constructor to return a different slot
|
|
124
|
-
|
|
118
|
+
createSlotCallbackStub.resetHistory();
|
|
125
119
|
mockReceiveSlotCtor.resetHistory();
|
|
126
120
|
|
|
127
121
|
assert.deepEqual(receiveSlotManager.getStats(), {numAllocatedSlots: {}, numFreeSlots: {}});
|
|
@@ -129,7 +123,7 @@ describe('ReceiveSlotManager', () => {
|
|
|
129
123
|
// allocate another slot, because we called reset(), the old free slot should not be reused
|
|
130
124
|
const slot2 = await receiveSlotManager.allocateSlot(MediaType.VideoMain);
|
|
131
125
|
|
|
132
|
-
assert.calledOnce(
|
|
126
|
+
assert.calledOnce(createSlotCallbackStub);
|
|
133
127
|
assert.calledOnce(mockReceiveSlotCtor);
|
|
134
128
|
|
|
135
129
|
// verify that in fact we got a brand new slot
|
|
@@ -144,25 +138,25 @@ describe('ReceiveSlotManager', () => {
|
|
|
144
138
|
it('does not reuse slots if they have different media type', async () => {
|
|
145
139
|
const slot1 = await receiveSlotManager.allocateSlot(MediaType.VideoMain);
|
|
146
140
|
|
|
147
|
-
assert.calledOnce(
|
|
141
|
+
assert.calledOnce(createSlotCallbackStub);
|
|
148
142
|
assert.calledOnce(mockReceiveSlotCtor);
|
|
149
143
|
|
|
150
144
|
receiveSlotManager.releaseSlot(slot1);
|
|
151
145
|
|
|
152
|
-
|
|
146
|
+
createSlotCallbackStub.resetHistory();
|
|
153
147
|
mockReceiveSlotCtor.resetHistory();
|
|
154
148
|
|
|
155
149
|
// allocate another slot, this time for main audio, so it should be a completely new slot
|
|
156
150
|
const slot2 = await receiveSlotManager.allocateSlot(MediaType.AudioMain);
|
|
157
151
|
|
|
158
|
-
assert.calledOnce(
|
|
152
|
+
assert.calledOnce(createSlotCallbackStub);
|
|
159
153
|
assert.calledWith(
|
|
160
|
-
|
|
154
|
+
createSlotCallbackStub,
|
|
161
155
|
MediaType.AudioMain
|
|
162
156
|
);
|
|
163
157
|
|
|
164
158
|
assert.calledOnce(mockReceiveSlotCtor);
|
|
165
|
-
assert.calledWith(mockReceiveSlotCtor, MediaType.AudioMain, fakeWcmeSlot,
|
|
159
|
+
assert.calledWith(mockReceiveSlotCtor, MediaType.AudioMain, fakeWcmeSlot, findMemberIdCallbackStub);
|
|
166
160
|
|
|
167
161
|
// verify that in fact we got a brand new slot
|
|
168
162
|
assert.strictEqual(slot2, fakeReceiveSlots[1]);
|