@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.
@@ -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(meeting) {
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, "meeting", void 0);
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.meeting = meeting;
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 = 7;
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 14:
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 _this2 = this;
123
+ var _this = this;
137
124
  var numAllocatedSlots = {};
138
125
  var numFreeSlots = {};
139
126
  (0, _keys.default)(this.allocatedSlots).forEach(function (key) {
140
- if (_this2.allocatedSlots[key].length > 0) {
141
- numAllocatedSlots[key] = _this2.allocatedSlots[key].length;
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 (_this2.freeSlots[key].length > 0) {
146
- numFreeSlots[key] = _this2.freeSlots[key].length;
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 _this3 = this;
149
+ var _this2 = this;
163
150
  (0, _keys.default)(this.allocatedSlots).forEach(function (key) {
164
- _this3.allocatedSlots[key].forEach(function (slot) {
151
+ _this2.allocatedSlots[key].forEach(function (slot) {
165
152
  slot.findMemberId();
166
153
  });
167
154
  });
@@ -1 +1 @@
1
- {"version":3,"names":["ReceiveSlotManager","meeting","allocatedSlots","MediaType","AudioMain","VideoMain","AudioSlides","VideoSlides","freeSlots","mediaType","mediaProperties","webrtcMediaConnection","reject","Error","availableSlot","pop","push","LoggerProxy","logger","log","id","createReceiveSlot","wcmeReceiveSlot","receiveSlot","ReceiveSlot","csi","members","findMemberByCsi","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} from '@webex/internal-media-core';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport Meeting from '../meeting';\n\nimport {CSI, ReceiveSlot} 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 meeting: Meeting;\n\n /**\n * Constructor\n * @param {Meeting} meeting\n */\n constructor(meeting) {\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.meeting = meeting;\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 if (!this.meeting?.mediaProperties?.webrtcMediaConnection) {\n return Promise.reject(new Error('Webrtc media connection is missing'));\n }\n\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 =\n await this.meeting.mediaProperties.webrtcMediaConnection.createReceiveSlot(mediaType);\n\n const receiveSlot = new ReceiveSlot(\n mediaType,\n wcmeReceiveSlot,\n // @ts-ignore\n (csi: CSI) => this.meeting.members.findMemberByCsi(csi)?.id\n );\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
+ {"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 meeting;
12
+ private createSlotCallback;
13
+ private findMemberIdByCsiCallback;
11
14
  /**
12
15
  * Constructor
13
16
  * @param {Meeting} meeting
14
17
  */
15
- constructor(meeting: any);
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.40",
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.40",
36
- "@webex/test-helper-chai": "3.0.0-beta.40",
37
- "@webex/test-helper-mocha": "3.0.0-beta.40",
38
- "@webex/test-helper-mock-webex": "3.0.0-beta.40",
39
- "@webex/test-helper-retry": "3.0.0-beta.40",
40
- "@webex/test-helper-test-users": "3.0.0-beta.40",
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.40",
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.40",
52
- "@webex/internal-plugin-device": "3.0.0-beta.40",
53
- "@webex/internal-plugin-llm": "3.0.0-beta.40",
54
- "@webex/internal-plugin-mercury": "3.0.0-beta.40",
55
- "@webex/internal-plugin-metrics": "3.0.0-beta.40",
56
- "@webex/internal-plugin-support": "3.0.0-beta.40",
57
- "@webex/internal-plugin-user": "3.0.0-beta.40",
58
- "@webex/plugin-people": "3.0.0-beta.40",
59
- "@webex/plugin-rooms": "3.0.0-beta.40",
60
- "@webex/webex-core": "3.0.0-beta.40",
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",
@@ -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 {trigger, mediaType, error as MetricsError, eventType} from '../metrics/config';
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(this);
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: mediaType.AUDIO},
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: mediaType.AUDIO},
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: mediaType.VIDEO},
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: mediaType.VIDEO},
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 {CSI, ReceiveSlot} from './receiveSlot';
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 meeting: Meeting;
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(meeting) {
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.meeting = meeting;
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
- await this.meeting.mediaProperties.webrtcMediaConnection.createReceiveSlot(mediaType);
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
- receiveSlotManager = new ReceiveSlotManager(fakeMeeting);
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
- fakeMeeting.mediaProperties.webrtcMediaConnection = null;
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(fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
57
+ assert.calledOnce(createSlotCallbackStub);
64
58
  assert.calledWith(
65
- fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot,
59
+ createSlotCallbackStub,
66
60
  MediaType.VideoMain
67
61
  );
68
62
 
69
63
  assert.calledOnce(mockReceiveSlotCtor);
70
- assert.calledWith(mockReceiveSlotCtor, MediaType.VideoMain, fakeWcmeSlot, sinon.match.func);
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(fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
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
- fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot.resetHistory();
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(fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
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(fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
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
- fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot.resetHistory();
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(fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
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(fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
141
+ assert.calledOnce(createSlotCallbackStub);
148
142
  assert.calledOnce(mockReceiveSlotCtor);
149
143
 
150
144
  receiveSlotManager.releaseSlot(slot1);
151
145
 
152
- fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot.resetHistory();
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(fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot);
152
+ assert.calledOnce(createSlotCallbackStub);
159
153
  assert.calledWith(
160
- fakeMeeting.mediaProperties.webrtcMediaConnection.createReceiveSlot,
154
+ createSlotCallbackStub,
161
155
  MediaType.AudioMain
162
156
  );
163
157
 
164
158
  assert.calledOnce(mockReceiveSlotCtor);
165
- assert.calledWith(mockReceiveSlotCtor, MediaType.AudioMain, fakeWcmeSlot, sinon.match.func);
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]);