@webex/plugin-meetings 3.0.0-beta.48 → 3.0.0-beta.49

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.
@@ -436,7 +436,6 @@ export declare const LOCUSINFO: {
436
436
  CONTROLS_MEETING_BREAKOUT_UPDATED: string;
437
437
  CONTROLS_MEETING_CONTAINER_UPDATED: string;
438
438
  CONTROLS_ENTRY_EXIT_TONE_UPDATED: string;
439
- CONTROLS_VIDEO_ENABLED_UPDATED: string;
440
439
  SELF_UNADMITTED_GUEST: string;
441
440
  SELF_ADMITTED_GUEST: string;
442
441
  SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-beta.48",
3
+ "version": "3.0.0-beta.49",
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.48",
36
- "@webex/test-helper-chai": "3.0.0-beta.48",
37
- "@webex/test-helper-mocha": "3.0.0-beta.48",
38
- "@webex/test-helper-mock-webex": "3.0.0-beta.48",
39
- "@webex/test-helper-retry": "3.0.0-beta.48",
40
- "@webex/test-helper-test-users": "3.0.0-beta.48",
35
+ "@webex/plugin-meetings": "3.0.0-beta.49",
36
+ "@webex/test-helper-chai": "3.0.0-beta.49",
37
+ "@webex/test-helper-mocha": "3.0.0-beta.49",
38
+ "@webex/test-helper-mock-webex": "3.0.0-beta.49",
39
+ "@webex/test-helper-retry": "3.0.0-beta.49",
40
+ "@webex/test-helper-test-users": "3.0.0-beta.49",
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.48",
50
- "@webex/internal-media-core": "1.35.2",
51
- "@webex/internal-plugin-conversation": "3.0.0-beta.48",
52
- "@webex/internal-plugin-device": "3.0.0-beta.48",
53
- "@webex/internal-plugin-llm": "3.0.0-beta.48",
54
- "@webex/internal-plugin-mercury": "3.0.0-beta.48",
55
- "@webex/internal-plugin-metrics": "3.0.0-beta.48",
56
- "@webex/internal-plugin-support": "3.0.0-beta.48",
57
- "@webex/internal-plugin-user": "3.0.0-beta.48",
58
- "@webex/plugin-people": "3.0.0-beta.48",
59
- "@webex/plugin-rooms": "3.0.0-beta.48",
60
- "@webex/webex-core": "3.0.0-beta.48",
49
+ "@webex/common": "3.0.0-beta.49",
50
+ "@webex/internal-media-core": "1.35.3",
51
+ "@webex/internal-plugin-conversation": "3.0.0-beta.49",
52
+ "@webex/internal-plugin-device": "3.0.0-beta.49",
53
+ "@webex/internal-plugin-llm": "3.0.0-beta.49",
54
+ "@webex/internal-plugin-mercury": "3.0.0-beta.49",
55
+ "@webex/internal-plugin-metrics": "3.0.0-beta.49",
56
+ "@webex/internal-plugin-support": "3.0.0-beta.49",
57
+ "@webex/internal-plugin-user": "3.0.0-beta.49",
58
+ "@webex/plugin-people": "3.0.0-beta.49",
59
+ "@webex/plugin-rooms": "3.0.0-beta.49",
60
+ "@webex/webex-core": "3.0.0-beta.49",
61
61
  "ampersand-collection": "^2.0.2",
62
62
  "bowser": "^2.11.0",
63
63
  "btoa": "^1.2.1",
package/src/constants.ts CHANGED
@@ -568,7 +568,6 @@ export const LOCUSINFO = {
568
568
  CONTROLS_MEETING_BREAKOUT_UPDATED: 'CONTROLS_MEETING_BREAKOUT_UPDATED',
569
569
  CONTROLS_MEETING_CONTAINER_UPDATED: 'CONTROLS_MEETING_CONTAINER_UPDATED',
570
570
  CONTROLS_ENTRY_EXIT_TONE_UPDATED: 'CONTROLS_ENTRY_EXIT_TONE_UPDATED',
571
- CONTROLS_VIDEO_ENABLED_UPDATED: 'CONTROLS_VIDEO_ENABLED_UPDATED',
572
571
  SELF_UNADMITTED_GUEST: 'SELF_UNADMITTED_GUEST',
573
572
  SELF_ADMITTED_GUEST: 'SELF_ADMITTED_GUEST',
574
573
  SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED: 'SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED',
@@ -800,7 +800,7 @@ export default class LocusInfo extends EventsScope {
800
800
  file: 'locus-info',
801
801
  function: 'updateControls',
802
802
  },
803
- LOCUSINFO.EVENTS.CONTROLS_VIDEO_ENABLED_UPDATED,
803
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
804
804
  {
805
805
  // muted: not part of locus.controls
806
806
  unmuteAllowed: videoEnabled,
@@ -105,7 +105,7 @@ Media.getLocalMedia = (options: any, config: object) => {
105
105
  * @param {boolean} isMultistream
106
106
  * @param {string} debugId string useful for debugging (will appear in media connection logs)
107
107
  * @param {Object} options
108
- * @param {Object} [options.mediaProperties] only applicable to non-multistream connections, contains mediaDirection and local tracks:
108
+ * @param {Object} [options.mediaProperties] contains mediaDirection and local tracks:
109
109
  * audioTrack, videoTrack and shareTrack
110
110
  * @param {string} [options.remoteQualityLevel] LOW|MEDIUM|HIGH applicable only to non-multistream connections
111
111
  * @param {boolean} [options.enableRtx] applicable only to non-multistream connections
@@ -117,11 +117,14 @@ Media.createMediaConnection = (
117
117
  isMultistream: boolean,
118
118
  debugId: string,
119
119
  options: {
120
- mediaProperties?: {
120
+ mediaProperties: {
121
121
  mediaDirection?: {
122
122
  receiveAudio: boolean;
123
123
  receiveVideo: boolean;
124
124
  receiveShare: boolean;
125
+ sendAudio: boolean;
126
+ sendVideo: boolean;
127
+ sendShare: boolean;
125
128
  };
126
129
  audioTrack?: LocalMicrophoneTrack;
127
130
  videoTrack?: LocalCameraTrack;
@@ -153,6 +156,10 @@ Media.createMediaConnection = (
153
156
  return new MultistreamRoapMediaConnection(
154
157
  {
155
158
  iceServers,
159
+ enableMainAudio:
160
+ mediaProperties.mediaDirection?.sendAudio || mediaProperties.mediaDirection?.receiveAudio,
161
+ enableMainVideo:
162
+ mediaProperties.mediaDirection?.sendVideo || mediaProperties.mediaDirection?.receiveVideo,
156
163
  },
157
164
  debugId
158
165
  );
@@ -5571,14 +5571,16 @@ export default class Meeting extends StatelessWebexPlugin {
5571
5571
  ) {
5572
5572
  const LOG_HEADER = 'Meeting:index#updateMedia -->';
5573
5573
 
5574
- if (this.isMultistream) {
5575
- throw new Error(
5576
- 'updateMedia() is not supported with multistream, use publishTracks/unpublishTracks instead'
5577
- );
5578
- }
5579
5574
  if (!this.canUpdateMedia()) {
5580
5575
  return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.ALL, options);
5581
5576
  }
5577
+
5578
+ if (this.isMultistream) {
5579
+ const audioEnabled = options.mediaSettings?.sendAudio || options.mediaSettings?.receiveAudio;
5580
+
5581
+ return this.mediaProperties.webrtcMediaConnection.enableMultistreamAudio(audioEnabled);
5582
+ }
5583
+
5582
5584
  const {localStream, localShare, mediaSettings} = options;
5583
5585
 
5584
5586
  const previousSendShareStatus = this.mediaProperties.mediaDirection.sendShare;
@@ -431,7 +431,7 @@ describe('plugin-meetings', () => {
431
431
  file: 'locus-info',
432
432
  function: 'updateControls',
433
433
  },
434
- LOCUSINFO.EVENTS.CONTROLS_VIDEO_ENABLED_UPDATED,
434
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
435
435
  {unmuteAllowed: true}
436
436
  );
437
437
 
@@ -445,8 +445,8 @@ describe('plugin-meetings', () => {
445
445
  locusInfo.updateControls(newControls);
446
446
 
447
447
  locusInfo.emitScoped.getCalls().forEach((x) => {
448
- // check that no calls in emitScoped are for CONTROLS_VIDEO_ENABLED_UPDATED
449
- assert.notEqual(x.args[1], LOCUSINFO.EVENTS.CONTROLS_VIDEO_ENABLED_UPDATED);
448
+ // check that no calls in emitScoped are for SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED
449
+ assert.notEqual(x.args[1], LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED);
450
450
  });
451
451
 
452
452
  assert.equal(mockMeeting.unmuteVideoAllowed, undefined);
@@ -3,6 +3,7 @@ import Media from '@webex/plugin-meetings/src/media/index';
3
3
  import {assert} from '@webex/test-helper-chai';
4
4
  import sinon from 'sinon';
5
5
  import StaticConfig from '@webex/plugin-meetings/src/common/config';
6
+ import { forEach } from 'lodash';
6
7
 
7
8
  describe('createMediaConnection', () => {
8
9
  const fakeRoapMediaConnection = {
@@ -103,6 +104,16 @@ describe('createMediaConnection', () => {
103
104
  .returns(fakeRoapMediaConnection);
104
105
 
105
106
  Media.createMediaConnection(true, 'some debug id', {
107
+ mediaProperties: {
108
+ mediaDirection: {
109
+ sendAudio: true,
110
+ sendVideo: true,
111
+ sendShare: false,
112
+ receiveAudio: true,
113
+ receiveVideo: true,
114
+ receiveShare: true,
115
+ }
116
+ },
106
117
  turnServerInfo: {
107
118
  url: 'turn server url',
108
119
  username: 'turn username',
@@ -120,22 +131,73 @@ describe('createMediaConnection', () => {
120
131
  credential: 'turn password',
121
132
  },
122
133
  ],
134
+ enableMainAudio: true,
135
+ enableMainVideo: true,
123
136
  },
124
137
  'some debug id'
125
138
  );
126
139
  });
127
140
 
141
+ forEach([
142
+ {sendAudio: true, receiveAudio: true, sendVideo: true, receiveVideo: true, enableMainAudio: true, enableMainVideo: true,},
143
+ {sendAudio: true, receiveAudio: false, sendVideo: true, receiveVideo: false, enableMainAudio: true, enableMainVideo: true,},
144
+ {sendAudio: false, receiveAudio: true, sendVideo: false, receiveVideo: true, enableMainAudio: true, enableMainVideo: true,},
145
+ {sendAudio: false, receiveAudio: false, sendVideo: false, receiveVideo: false, enableMainAudio: false, enableMainVideo: false,},
146
+ ], ({sendAudio, sendVideo, receiveAudio, receiveVideo, enableMainAudio, enableMainVideo}) => {
147
+ it(`sets enableMainVideo to ${enableMainVideo} and enableMainAudio to ${enableMainAudio} when sendAudio: ${sendAudio} sendVideo: ${sendVideo} receiveAudio: ${receiveAudio} receiveVideo: ${receiveVideo}`, () => {
148
+ const multistreamRoapMediaConnectionConstructorStub = sinon
149
+ .stub(internalMediaModule, 'MultistreamRoapMediaConnection')
150
+ .returns(fakeRoapMediaConnection);
151
+
152
+ Media.createMediaConnection(true, 'some debug id', {
153
+ mediaProperties: {
154
+ mediaDirection: {
155
+ sendAudio,
156
+ sendVideo,
157
+ sendShare: false,
158
+ receiveAudio,
159
+ receiveVideo,
160
+ receiveShare: true,
161
+ },
162
+ },
163
+ });
164
+ assert.calledOnce(multistreamRoapMediaConnectionConstructorStub);
165
+ assert.calledWith(
166
+ multistreamRoapMediaConnectionConstructorStub,
167
+ {
168
+ iceServers: [],
169
+ enableMainAudio,
170
+ enableMainVideo,
171
+ },
172
+ 'some debug id'
173
+ );
174
+ });
175
+ });
176
+
128
177
  it('passes empty ICE servers array to MultistreamRoapMediaConnection if turnServerInfo is undefined (multistream enabled)', () => {
129
178
  const multistreamRoapMediaConnectionConstructorStub = sinon
130
179
  .stub(internalMediaModule, 'MultistreamRoapMediaConnection')
131
180
  .returns(fakeRoapMediaConnection);
132
181
 
133
- Media.createMediaConnection(true, 'debug string', {});
182
+ Media.createMediaConnection(true, 'debug string', {
183
+ mediaProperties: {
184
+ mediaDirection: {
185
+ sendAudio: true,
186
+ sendVideo: true,
187
+ sendShare: false,
188
+ receiveAudio: true,
189
+ receiveVideo: true,
190
+ receiveShare: true,
191
+ },
192
+ },
193
+ });
134
194
  assert.calledOnce(multistreamRoapMediaConnectionConstructorStub);
135
195
  assert.calledWith(
136
196
  multistreamRoapMediaConnectionConstructorStub,
137
197
  {
138
198
  iceServers: [],
199
+ enableMainAudio: true,
200
+ enableMainVideo: true,
139
201
  },
140
202
  'debug string'
141
203
  );
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
3
  */
4
4
  import 'jsdom-global/register';
5
- import {cloneDeep, isEqual} from 'lodash';
5
+ import {cloneDeep, forEach, isEqual} from 'lodash';
6
6
  import sinon from 'sinon';
7
7
  import StateMachine from 'javascript-state-machine';
8
8
  import uuid from 'uuid';
@@ -2195,6 +2195,43 @@ describe('plugin-meetings', () => {
2195
2195
  sandbox = null;
2196
2196
  });
2197
2197
 
2198
+ forEach(
2199
+ [
2200
+ {receiveAudio: true, sendAudio: true, enableMultistreamAudio: true},
2201
+ {receiveAudio: true, sendAudio: false, enableMultistreamAudio: true},
2202
+ {receiveAudio: false, sendAudio: true, enableMultistreamAudio: true},
2203
+ {receiveAudio: false, sendAudio: false, enableMultistreamAudio: false},
2204
+ ],
2205
+ ({receiveAudio, sendAudio, enableMultistreamAudio}) => {
2206
+ it(`should call enableMultistreamAudio with ${enableMultistreamAudio} if it is a multistream connection and receiveAudio: ${receiveAudio} sendAudio: ${sendAudio}`, async () => {
2207
+ const mediaSettings = {
2208
+ sendAudio,
2209
+ receiveAudio,
2210
+ sendVideo: true,
2211
+ receiveVideo: true,
2212
+ sendShare: true,
2213
+ receiveShare: true,
2214
+ isSharing: true,
2215
+ };
2216
+
2217
+ meeting.mediaProperties.webrtcMediaConnection = {
2218
+ enableMultistreamAudio: sinon.stub().resolves('some value'),
2219
+ };
2220
+ meeting.isMultistream = true;
2221
+
2222
+ const result = await meeting.updateMedia({
2223
+ mediaSettings,
2224
+ });
2225
+
2226
+ assert.calledOnceWithExactly(
2227
+ meeting.mediaProperties.webrtcMediaConnection.enableMultistreamAudio,
2228
+ enableMultistreamAudio
2229
+ );
2230
+ assert.equal(result, 'some value');
2231
+ });
2232
+ }
2233
+ );
2234
+
2198
2235
  it('should use a queue if currently busy', async () => {
2199
2236
  const mediaSettings = {
2200
2237
  sendAudio: true,