@webex/plugin-meetings 3.8.1-next.11 → 3.8.1-next.13
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/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/media/index.js +2 -2
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/index.js +65 -49
- package/dist/meeting/index.js.map +1 -1
- package/dist/types/meeting/index.d.ts +7 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +3 -3
- package/src/media/index.ts +2 -2
- package/src/meeting/index.ts +27 -6
- package/test/unit/spec/media/index.ts +107 -0
- package/test/unit/spec/meeting/index.js +73 -5
@@ -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;
|
package/dist/webinar/index.js
CHANGED
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.
|
46
|
+
"@webex/plugin-meetings": "3.8.1-next.13",
|
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",
|
@@ -71,7 +71,7 @@
|
|
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.
|
74
|
+
"@webex/internal-plugin-voicea": "3.8.1-next.13",
|
75
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",
|
@@ -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.
|
96
|
+
"version": "3.8.1-next.13"
|
97
97
|
}
|
package/src/media/index.ts
CHANGED
@@ -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(
|
243
|
-
video: Media.getDirection(
|
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,
|
package/src/meeting/index.ts
CHANGED
@@ -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 = {
|
@@ -2762,7 +2770,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2762
2770
|
this.transcription.languageOptions.currentSpokenLanguage = spokenLanguage;
|
2763
2771
|
}
|
2764
2772
|
// @ts-ignore
|
2765
|
-
this.webex.internal.voicea.onSpokenLanguageUpdate(spokenLanguage);
|
2773
|
+
this.webex.internal.voicea.onSpokenLanguageUpdate(spokenLanguage, this.id);
|
2766
2774
|
|
2767
2775
|
Trigger.trigger(
|
2768
2776
|
this,
|
@@ -2771,7 +2779,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2771
2779
|
function: 'setupLocusControlsListener',
|
2772
2780
|
},
|
2773
2781
|
EVENT_TRIGGERS.MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
|
2774
|
-
{spokenLanguage}
|
2782
|
+
{spokenLanguage, meetingId: this.id}
|
2775
2783
|
);
|
2776
2784
|
}
|
2777
2785
|
}
|
@@ -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
|
7798
|
-
sendVideo
|
7818
|
+
sendAudio,
|
7819
|
+
sendVideo,
|
7799
7820
|
sendShare: false,
|
7800
|
-
receiveAudio
|
7801
|
-
receiveVideo
|
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}};
|
@@ -1240,7 +1308,7 @@ describe('plugin-meetings', () => {
|
|
1240
1308
|
LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
|
1241
1309
|
{spokenLanguage: 'fr'},
|
1242
1310
|
);
|
1243
|
-
assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'fr');
|
1311
|
+
assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'fr', meeting.id);
|
1244
1312
|
assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'fr');
|
1245
1313
|
assert.calledWith(
|
1246
1314
|
TriggerProxy.trigger,
|
@@ -4286,11 +4354,11 @@ describe('plugin-meetings', () => {
|
|
4286
4354
|
|
4287
4355
|
const error = new Error();
|
4288
4356
|
meeting.meetingRequest.setBrb = sinon.stub().rejects(error);
|
4289
|
-
|
4357
|
+
|
4290
4358
|
await expect(
|
4291
4359
|
meeting.beRightBack(true)
|
4292
|
-
).to.be.rejectedWith(error);
|
4293
|
-
|
4360
|
+
).to.be.rejectedWith(error);
|
4361
|
+
|
4294
4362
|
assert.isFalse(meeting.brbState.state.syncToServerInProgress);
|
4295
4363
|
});
|
4296
4364
|
});
|