@webex/plugin-meetings 3.8.1-next.10 → 3.8.1-next.12

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.
@@ -66,6 +66,13 @@ export type AddMediaOptions = {
66
66
  remoteMediaManagerConfig?: RemoteMediaManagerConfiguration;
67
67
  bundlePolicy?: BundlePolicy;
68
68
  allowMediaInLobby?: boolean;
69
+ additionalMediaOptions?: AdditionalMediaOptions;
70
+ };
71
+ export type AdditionalMediaOptions = {
72
+ sendVideo?: boolean;
73
+ receiveVideo?: boolean;
74
+ sendAudio?: boolean;
75
+ receiveAudio?: boolean;
69
76
  };
70
77
  export type CallStateForMetrics = {
71
78
  correlationId?: string;
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.8.1-next.10"
461
+ version: "3.8.1-next.12"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.8.1-next.10",
46
+ "@webex/plugin-meetings": "3.8.1-next.12",
47
47
  "@webex/plugin-rooms": "3.8.1-next.2",
48
48
  "@webex/test-helper-chai": "3.8.1-next.5",
49
49
  "@webex/test-helper-mocha": "3.8.1-next.5",
@@ -63,7 +63,7 @@
63
63
  "dependencies": {
64
64
  "@webex/common": "3.8.1-next.5",
65
65
  "@webex/event-dictionary-ts": "^1.0.1819",
66
- "@webex/internal-media-core": "2.18.1",
66
+ "@webex/internal-media-core": "2.18.3",
67
67
  "@webex/internal-plugin-conversation": "3.8.1-next.5",
68
68
  "@webex/internal-plugin-device": "3.8.1-next.5",
69
69
  "@webex/internal-plugin-llm": "3.8.1-next.5",
@@ -71,12 +71,12 @@
71
71
  "@webex/internal-plugin-metrics": "3.8.1-next.5",
72
72
  "@webex/internal-plugin-support": "3.8.1-next.5",
73
73
  "@webex/internal-plugin-user": "3.8.1-next.5",
74
- "@webex/internal-plugin-voicea": "3.8.1-next.10",
75
- "@webex/media-helpers": "3.8.1-next.6",
74
+ "@webex/internal-plugin-voicea": "3.8.1-next.12",
75
+ "@webex/media-helpers": "3.8.1-next.7",
76
76
  "@webex/plugin-people": "3.8.1-next.5",
77
77
  "@webex/plugin-rooms": "3.8.1-next.2",
78
78
  "@webex/ts-sdp": "^1.8.1",
79
- "@webex/web-capabilities": "^1.4.0",
79
+ "@webex/web-capabilities": "^1.6.0",
80
80
  "@webex/webex-core": "3.8.1-next.5",
81
81
  "ampersand-collection": "^2.0.2",
82
82
  "bowser": "^2.11.0",
@@ -93,5 +93,5 @@
93
93
  "//": [
94
94
  "TODO: upgrade jwt-decode when moving to node 18"
95
95
  ],
96
- "version": "3.8.1-next.10"
96
+ "version": "3.8.1-next.12"
97
97
  }
@@ -239,8 +239,8 @@ Media.createMediaConnection = (
239
239
  screenShareAudio: shareAudioStream?.outputStream?.getTracks()[0], // TODO: add type for screenShareAudio in internal-media-core SPARK-446923
240
240
  } as unknown,
241
241
  direction: {
242
- audio: Media.getDirection(true, mediaDirection.receiveAudio, mediaDirection.sendAudio),
243
- video: Media.getDirection(true, mediaDirection.receiveVideo, mediaDirection.sendVideo),
242
+ audio: Media.getDirection(false, mediaDirection.receiveAudio, mediaDirection.sendAudio),
243
+ video: Media.getDirection(false, mediaDirection.receiveVideo, mediaDirection.sendVideo),
244
244
  screenShareVideo: Media.getDirection(
245
245
  false,
246
246
  mediaDirection.receiveShare,
@@ -231,6 +231,14 @@ export type AddMediaOptions = {
231
231
  remoteMediaManagerConfig?: RemoteMediaManagerConfiguration; // applies only to multistream meetings
232
232
  bundlePolicy?: BundlePolicy; // applies only to multistream meetings
233
233
  allowMediaInLobby?: boolean; // allows adding media when in the lobby
234
+ additionalMediaOptions?: AdditionalMediaOptions; // allows adding additional options like send/receive audio/video
235
+ };
236
+
237
+ export type AdditionalMediaOptions = {
238
+ sendVideo?: boolean; // if not specified, default value of videoEnabled is used
239
+ receiveVideo?: boolean; // if not specified, default value of videoEnabled is used
240
+ sendAudio?: boolean; // if not specified, default value of audioEnabled true is used
241
+ receiveAudio?: boolean; // if not specified, default value of audioEnabled true is used
234
242
  };
235
243
 
236
244
  export type CallStateForMetrics = {
@@ -7757,8 +7765,21 @@ export default class Meeting extends StatelessWebexPlugin {
7757
7765
  shareVideoEnabled = true,
7758
7766
  remoteMediaManagerConfig,
7759
7767
  bundlePolicy = 'max-bundle',
7768
+ additionalMediaOptions = {},
7760
7769
  } = options;
7761
7770
 
7771
+ const {
7772
+ sendVideo: rawSendVideo,
7773
+ receiveVideo: rawReceiveVideo,
7774
+ sendAudio: rawSendAudio,
7775
+ receiveAudio: rawReceiveAudio,
7776
+ } = additionalMediaOptions;
7777
+
7778
+ const sendVideo = videoEnabled && (rawSendVideo ?? true);
7779
+ const receiveVideo = videoEnabled && (rawReceiveVideo ?? true);
7780
+ const sendAudio = audioEnabled && (rawSendAudio ?? true);
7781
+ const receiveAudio = audioEnabled && (rawReceiveAudio ?? true);
7782
+
7762
7783
  this.allowMediaInLobby = options?.allowMediaInLobby;
7763
7784
 
7764
7785
  // If the user is unjoined or guest waiting in lobby dont allow the user to addMedia
@@ -7794,11 +7815,11 @@ export default class Meeting extends StatelessWebexPlugin {
7794
7815
  // when audioEnabled/videoEnabled is true, we set sendAudio/sendVideo to true even before any streams are published
7795
7816
  // to avoid doing an extra SDP exchange when they are published for the first time
7796
7817
  this.mediaProperties.setMediaDirection({
7797
- sendAudio: audioEnabled,
7798
- sendVideo: videoEnabled,
7818
+ sendAudio,
7819
+ sendVideo,
7799
7820
  sendShare: false,
7800
- receiveAudio: audioEnabled,
7801
- receiveVideo: videoEnabled,
7821
+ receiveAudio,
7822
+ receiveVideo,
7802
7823
  receiveShare: shareAudioEnabled || shareVideoEnabled,
7803
7824
  });
7804
7825
 
@@ -137,6 +137,113 @@ describe('createMediaConnection', () => {
137
137
  );
138
138
  });
139
139
 
140
+ it('should set direction to sendonly for both audio and video when only send flags are true', () => {
141
+ const roapMediaConnectionConstructorStub = sinon
142
+ .stub(InternalMediaCoreModule, 'RoapMediaConnection')
143
+ .returns(fakeRoapMediaConnection);
144
+
145
+ StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
146
+
147
+ const ENABLE_EXTMAP = false;
148
+ const ENABLE_RTX = true;
149
+
150
+ Media.createMediaConnection(false, 'sendonly-debug-id', 'meetingId', {
151
+ mediaProperties: {
152
+ mediaDirection: {
153
+ sendAudio: true,
154
+ receiveAudio: false,
155
+ sendVideo: true,
156
+ receiveVideo: false,
157
+ sendShare: false,
158
+ receiveShare: false,
159
+ },
160
+ audioStream: fakeAudioStream,
161
+ videoStream: fakeVideoStream,
162
+ shareVideoTrack: null,
163
+ shareAudioTrack: null,
164
+ },
165
+ remoteQualityLevel: 'HIGH',
166
+ enableRtx: ENABLE_RTX,
167
+ enableExtmap: ENABLE_EXTMAP,
168
+ turnServerInfo: undefined,
169
+ iceCandidatesTimeout: undefined,
170
+ });
171
+
172
+ assert.calledWith(
173
+ roapMediaConnectionConstructorStub,
174
+ sinon.match.any,
175
+ {
176
+ localTracks: {
177
+ audio: fakeTrack,
178
+ video: fakeTrack,
179
+ screenShareVideo: undefined,
180
+ screenShareAudio: undefined,
181
+ },
182
+ direction: {
183
+ audio: 'sendonly',
184
+ video: 'sendonly',
185
+ screenShareVideo: 'inactive',
186
+ },
187
+ remoteQualityLevel: 'HIGH',
188
+ },
189
+ 'sendonly-debug-id'
190
+ );
191
+ });
192
+
193
+ it('should set direction to recvonly for both audio and video when only receive flags are true', () => {
194
+ const roapMediaConnectionConstructorStub = sinon
195
+ .stub(InternalMediaCoreModule, 'RoapMediaConnection')
196
+ .returns(fakeRoapMediaConnection);
197
+
198
+ StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
199
+
200
+ const ENABLE_EXTMAP = true;
201
+ const ENABLE_RTX = false;
202
+
203
+ Media.createMediaConnection(false, 'recvonly-debug-id', 'meetingId', {
204
+ mediaProperties: {
205
+ mediaDirection: {
206
+ sendAudio: false,
207
+ receiveAudio: true,
208
+ sendVideo: false,
209
+ receiveVideo: true,
210
+ sendShare: false,
211
+ receiveShare: false,
212
+ },
213
+ audioStream: fakeAudioStream,
214
+ videoStream: fakeVideoStream,
215
+ shareVideoTrack: null,
216
+ shareAudioTrack: null,
217
+ },
218
+ remoteQualityLevel: 'HIGH',
219
+ enableRtx: ENABLE_RTX,
220
+ enableExtmap: ENABLE_EXTMAP,
221
+ turnServerInfo: undefined,
222
+ iceCandidatesTimeout: undefined,
223
+ });
224
+
225
+ assert.calledWith(
226
+ roapMediaConnectionConstructorStub,
227
+ sinon.match.any,
228
+ {
229
+ localTracks: {
230
+ audio: fakeTrack,
231
+ video: fakeTrack,
232
+ screenShareVideo: undefined,
233
+ screenShareAudio: undefined,
234
+ },
235
+ direction: {
236
+ audio: 'recvonly',
237
+ video: 'recvonly',
238
+ screenShareVideo: 'inactive',
239
+ },
240
+ remoteQualityLevel: 'HIGH',
241
+ },
242
+ 'recvonly-debug-id'
243
+ );
244
+ });
245
+
246
+
140
247
  it('creates a MultistreamRoapMediaConnection when multistream is enabled', () => {
141
248
  const multistreamRoapMediaConnectionConstructorStub = sinon
142
249
  .stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')
@@ -1208,8 +1208,76 @@ describe('plugin-meetings', () => {
1208
1208
  reason: 'joinWithMedia failure',
1209
1209
  });
1210
1210
  });
1211
- });
1212
1211
 
1212
+ it('should ignore sendVideo/receiveVideo when videoEnabled is false', async () => {
1213
+ await meeting.joinWithMedia({
1214
+ joinOptions,
1215
+ mediaOptions: {
1216
+ videoEnabled: false,
1217
+ sendVideo: true,
1218
+ receiveVideo: true,
1219
+ allowMediaInLobby: true,
1220
+ },
1221
+ });
1222
+
1223
+ assert.calledWithMatch(
1224
+ meeting.addMediaInternal,
1225
+ sinon.match.any,
1226
+ sinon.match.any,
1227
+ sinon.match.any,
1228
+ sinon.match.has('videoEnabled', false)
1229
+ .and(sinon.match.has('allowMediaInLobby', true))
1230
+ );
1231
+ });
1232
+
1233
+ it('should ignore sendAudio/receiveAudio when audioEnabled is false', async () => {
1234
+ await meeting.joinWithMedia({
1235
+ joinOptions,
1236
+ mediaOptions: {
1237
+ audioEnabled: false,
1238
+ sendAudio: true,
1239
+ receiveAudio: false,
1240
+ allowMediaInLobby: true,
1241
+ },
1242
+ });
1243
+
1244
+ assert.calledWithMatch(
1245
+ meeting.addMediaInternal,
1246
+ sinon.match.any,
1247
+ sinon.match.any,
1248
+ sinon.match.any,
1249
+ sinon.match.has('audioEnabled', false)
1250
+ .and(sinon.match.has('allowMediaInLobby', true))
1251
+ );
1252
+ });
1253
+
1254
+
1255
+ it('should use provided send/receive values when videoEnabled/audioEnabled are true or not set', async () => {
1256
+ await meeting.joinWithMedia({
1257
+ joinOptions,
1258
+ mediaOptions: {
1259
+ sendVideo: true,
1260
+ receiveVideo: false,
1261
+ sendAudio: false,
1262
+ receiveAudio: true,
1263
+ allowMediaInLobby: true,
1264
+ },
1265
+ });
1266
+
1267
+ assert.calledWith(
1268
+ meeting.addMediaInternal,
1269
+ sinon.match.any,
1270
+ sinon.match.any,
1271
+ sinon.match.any,
1272
+ sinon.match({
1273
+ sendVideo: true,
1274
+ receiveVideo: false,
1275
+ sendAudio: false,
1276
+ receiveAudio: true,
1277
+ })
1278
+ );
1279
+ });
1280
+ });
1213
1281
  describe('#isTranscriptionSupported', () => {
1214
1282
  it('should return false if the feature is not supported for the meeting', () => {
1215
1283
  meeting.locusInfo.controls = {transcribe: {caption: false}};