|
@@ -56,6 +56,58 @@ function connect(roomName) {
|
56
|
56
|
});
|
57
|
57
|
}
|
58
|
58
|
|
|
59
|
+/**
|
|
60
|
+ * Creates local media tracks and connects to room. Will show error
|
|
61
|
+ * dialogs in case if accessing local microphone and/or camera failed. Will
|
|
62
|
+ * show guidance overlay for users on how to give access to camera and/or
|
|
63
|
+ * microphone,
|
|
64
|
+ * @param {string} roomName
|
|
65
|
+ * @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
|
|
66
|
+ */
|
|
67
|
+function createInitialLocalTracksAndConnect(roomName) {
|
|
68
|
+ let audioAndVideoError,
|
|
69
|
+ audioOnlyError;
|
|
70
|
+
|
|
71
|
+ JitsiMeetJS.mediaDevices.addEventListener(
|
|
72
|
+ JitsiMeetJS.events.mediaDevices.PERMISSION_PROMPT_IS_SHOWN,
|
|
73
|
+ browser => APP.UI.showUserMediaPermissionsGuidanceOverlay(browser));
|
|
74
|
+
|
|
75
|
+ // First try to retrieve both audio and video.
|
|
76
|
+ let tryCreateLocalTracks = createLocalTracks(
|
|
77
|
+ { devices: ['audio', 'video'] }, true)
|
|
78
|
+ .catch(err => {
|
|
79
|
+ // If failed then try to retrieve only audio.
|
|
80
|
+ audioAndVideoError = err;
|
|
81
|
+ return createLocalTracks({ devices: ['audio'] }, true);
|
|
82
|
+ })
|
|
83
|
+ .catch(err => {
|
|
84
|
+ // If audio failed too then just return empty array for tracks.
|
|
85
|
+ audioOnlyError = err;
|
|
86
|
+ return [];
|
|
87
|
+ });
|
|
88
|
+
|
|
89
|
+ return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
|
|
90
|
+ .then(([tracks, con]) => {
|
|
91
|
+ APP.UI.hideUserMediaPermissionsGuidanceOverlay();
|
|
92
|
+
|
|
93
|
+ if (audioAndVideoError) {
|
|
94
|
+ if (audioOnlyError) {
|
|
95
|
+ // If both requests for 'audio' + 'video' and 'audio' only
|
|
96
|
+ // failed, we assume that there is some problems with user's
|
|
97
|
+ // microphone and show corresponding dialog.
|
|
98
|
+ APP.UI.showDeviceErrorDialog(audioOnlyError, null);
|
|
99
|
+ } else {
|
|
100
|
+ // If request for 'audio' + 'video' failed, but request for
|
|
101
|
+ // 'audio' only was OK, we assume that we had problems with
|
|
102
|
+ // camera and show corresponding dialog.
|
|
103
|
+ APP.UI.showDeviceErrorDialog(null, audioAndVideoError);
|
|
104
|
+ }
|
|
105
|
+ }
|
|
106
|
+
|
|
107
|
+ return [tracks, con];
|
|
108
|
+ });
|
|
109
|
+}
|
|
110
|
+
|
59
|
111
|
/**
|
60
|
112
|
* Share data to other users.
|
61
|
113
|
* @param command the command
|
|
@@ -182,32 +234,42 @@ function hangup (requestFeedback = false) {
|
182
|
234
|
|
183
|
235
|
/**
|
184
|
236
|
* Create local tracks of specified types.
|
185
|
|
- * @param {string[]} devices - required track types ('audio', 'video' etc.)
|
186
|
|
- * @param {string|null} [cameraDeviceId] - camera device id, if undefined - one
|
187
|
|
- * from settings will be used
|
188
|
|
- * @param {string|null} [micDeviceId] - microphone device id, if undefined - one
|
189
|
|
- * from settings will be used
|
|
237
|
+ * @param {Object} options
|
|
238
|
+ * @param {string[]} options.devices - required track types
|
|
239
|
+ * ('audio', 'video' etc.)
|
|
240
|
+ * @param {string|null} (options.cameraDeviceId) - camera device id, if
|
|
241
|
+ * undefined - one from settings will be used
|
|
242
|
+ * @param {string|null} (options.micDeviceId) - microphone device id, if
|
|
243
|
+ * undefined - one from settings will be used
|
|
244
|
+ * @param {boolean} (checkForPermissionPrompt) - if lib-jitsi-meet should check
|
|
245
|
+ * for gUM permission prompt
|
190
|
246
|
* @returns {Promise<JitsiLocalTrack[]>}
|
191
|
247
|
*/
|
192
|
|
-function createLocalTracks (devices, cameraDeviceId, micDeviceId) {
|
193
|
|
- return JitsiMeetJS.createLocalTracks({
|
194
|
|
- // copy array to avoid mutations inside library
|
195
|
|
- devices: devices.slice(0),
|
196
|
|
- resolution: config.resolution,
|
197
|
|
- cameraDeviceId: typeof cameraDeviceId === 'undefined'
|
198
|
|
- || cameraDeviceId === null
|
|
248
|
+function createLocalTracks (options, checkForPermissionPrompt) {
|
|
249
|
+ options || (options = {});
|
|
250
|
+
|
|
251
|
+ return JitsiMeetJS
|
|
252
|
+ .createLocalTracks({
|
|
253
|
+ // copy array to avoid mutations inside library
|
|
254
|
+ devices: options.devices.slice(0),
|
|
255
|
+ resolution: config.resolution,
|
|
256
|
+ cameraDeviceId: typeof options.cameraDeviceId === 'undefined' ||
|
|
257
|
+ options.cameraDeviceId === null
|
199
|
258
|
? APP.settings.getCameraDeviceId()
|
200
|
|
- : cameraDeviceId,
|
201
|
|
- micDeviceId: typeof micDeviceId === 'undefined' || micDeviceId === null
|
202
|
|
- ? APP.settings.getMicDeviceId()
|
203
|
|
- : micDeviceId,
|
204
|
|
- // adds any ff fake device settings if any
|
205
|
|
- firefox_fake_device: config.firefox_fake_device
|
206
|
|
- }).catch(function (err) {
|
207
|
|
- console.error('failed to create local tracks', ...devices, err);
|
208
|
|
- return Promise.reject(err);
|
209
|
|
- });
|
210
|
|
-}
|
|
259
|
+ : options.cameraDeviceId,
|
|
260
|
+ micDeviceId: typeof options.micDeviceId === 'undefined' ||
|
|
261
|
+ options.micDeviceId === null
|
|
262
|
+ ? APP.settings.getMicDeviceId()
|
|
263
|
+ : options.micDeviceId,
|
|
264
|
+ // adds any ff fake device settings if any
|
|
265
|
+ firefox_fake_device: config.firefox_fake_device
|
|
266
|
+ }, checkForPermissionPrompt)
|
|
267
|
+ .catch(function (err) {
|
|
268
|
+ console.error(
|
|
269
|
+ 'failed to create local tracks', options.devices, err);
|
|
270
|
+ return Promise.reject(err);
|
|
271
|
+ });
|
|
272
|
+ }
|
211
|
273
|
|
212
|
274
|
/**
|
213
|
275
|
* Changes the email for the local user
|
|
@@ -406,7 +468,6 @@ export default {
|
406
|
468
|
* @returns {Promise}
|
407
|
469
|
*/
|
408
|
470
|
init(options) {
|
409
|
|
- let self = this;
|
410
|
471
|
this.roomName = options.roomName;
|
411
|
472
|
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
|
412
|
473
|
|
|
@@ -432,65 +493,35 @@ export default {
|
432
|
493
|
};
|
433
|
494
|
}
|
434
|
495
|
|
435
|
|
- let audioAndVideoError, audioOnlyError;
|
436
|
|
-
|
437
|
|
- return JitsiMeetJS.init(config).then(() => {
|
438
|
|
- return Promise.all([
|
439
|
|
- // try to retrieve audio and video
|
440
|
|
- createLocalTracks(['audio', 'video'])
|
441
|
|
- // if failed then try to retrieve only audio
|
442
|
|
- .catch(err => {
|
443
|
|
- audioAndVideoError = err;
|
444
|
|
- return createLocalTracks(['audio']);
|
445
|
|
- })
|
446
|
|
- // if audio also failed then just return empty array
|
447
|
|
- .catch(err => {
|
448
|
|
- audioOnlyError = err;
|
449
|
|
- return [];
|
450
|
|
- }),
|
451
|
|
- connect(options.roomName)
|
452
|
|
- ]);
|
453
|
|
- }).then(([tracks, con]) => {
|
454
|
|
- if (audioAndVideoError) {
|
455
|
|
- if (audioOnlyError) {
|
456
|
|
- // If both requests for 'audio' + 'video' and 'audio' only
|
457
|
|
- // failed, we assume that there is some problems with user's
|
458
|
|
- // microphone and show corresponding dialog.
|
459
|
|
- APP.UI.showDeviceErrorDialog(audioOnlyError, null);
|
460
|
|
- } else {
|
461
|
|
- // If request for 'audio' + 'video' failed, but request for
|
462
|
|
- // 'audio' only was OK, we assume that we had problems with
|
463
|
|
- // camera and show corresponding dialog.
|
464
|
|
- APP.UI.showDeviceErrorDialog(null, audioAndVideoError);
|
|
496
|
+ return JitsiMeetJS.init(config)
|
|
497
|
+ .then(() => createInitialLocalTracksAndConnect(options.roomName))
|
|
498
|
+ .then(([tracks, con]) => {
|
|
499
|
+ console.log('initialized with %s local tracks', tracks.length);
|
|
500
|
+ APP.connection = connection = con;
|
|
501
|
+ this._createRoom(tracks);
|
|
502
|
+ this.isDesktopSharingEnabled =
|
|
503
|
+ JitsiMeetJS.isDesktopSharingEnabled();
|
|
504
|
+
|
|
505
|
+ // if user didn't give access to mic or camera or doesn't have
|
|
506
|
+ // them at all, we disable corresponding toolbar buttons
|
|
507
|
+ if (!tracks.find((t) => t.isAudioTrack())) {
|
|
508
|
+ APP.UI.disableMicrophoneButton();
|
465
|
509
|
}
|
466
|
|
- }
|
467
|
|
-
|
468
|
|
- console.log('initialized with %s local tracks', tracks.length);
|
469
|
|
- APP.connection = connection = con;
|
470
|
|
- this._createRoom(tracks);
|
471
|
|
- this.isDesktopSharingEnabled =
|
472
|
|
- JitsiMeetJS.isDesktopSharingEnabled();
|
473
|
510
|
|
474
|
|
- // if user didn't give access to mic or camera or doesn't have
|
475
|
|
- // them at all, we disable corresponding toolbar buttons
|
476
|
|
- if (!tracks.find((t) => t.isAudioTrack())) {
|
477
|
|
- APP.UI.disableMicrophoneButton();
|
478
|
|
- }
|
479
|
|
-
|
480
|
|
- if (!tracks.find((t) => t.isVideoTrack())) {
|
481
|
|
- APP.UI.disableCameraButton();
|
482
|
|
- }
|
|
511
|
+ if (!tracks.find((t) => t.isVideoTrack())) {
|
|
512
|
+ APP.UI.disableCameraButton();
|
|
513
|
+ }
|
483
|
514
|
|
484
|
|
- this._initDeviceList();
|
|
515
|
+ this._initDeviceList();
|
485
|
516
|
|
486
|
|
- if (config.iAmRecorder)
|
487
|
|
- this.recorder = new Recorder();
|
|
517
|
+ if (config.iAmRecorder)
|
|
518
|
+ this.recorder = new Recorder();
|
488
|
519
|
|
489
|
|
- // XXX The API will take care of disconnecting from the XMPP server
|
490
|
|
- // (and, thus, leaving the room) on unload.
|
491
|
|
- return new Promise((resolve, reject) => {
|
492
|
|
- (new ConferenceConnector(resolve, reject)).connect();
|
493
|
|
- });
|
|
520
|
+ // XXX The API will take care of disconnecting from the XMPP
|
|
521
|
+ // server (and, thus, leaving the room) on unload.
|
|
522
|
+ return new Promise((resolve, reject) => {
|
|
523
|
+ (new ConferenceConnector(resolve, reject)).connect();
|
|
524
|
+ });
|
494
|
525
|
});
|
495
|
526
|
},
|
496
|
527
|
/**
|
|
@@ -834,7 +865,7 @@ export default {
|
834
|
865
|
this.videoSwitchInProgress = true;
|
835
|
866
|
|
836
|
867
|
if (shareScreen) {
|
837
|
|
- createLocalTracks(['desktop']).then(([stream]) => {
|
|
868
|
+ createLocalTracks({ devices: ['desktop'] }).then(([stream]) => {
|
838
|
869
|
stream.on(
|
839
|
870
|
TrackEvents.LOCAL_TRACK_STOPPED,
|
840
|
871
|
() => {
|
|
@@ -891,7 +922,7 @@ export default {
|
891
|
922
|
APP.UI.messageHandler.openDialog(dialogTitle, dialogTxt, false);
|
892
|
923
|
});
|
893
|
924
|
} else {
|
894
|
|
- createLocalTracks(['video']).then(
|
|
925
|
+ createLocalTracks({ devices: ['video'] }).then(
|
895
|
926
|
([stream]) => this.useVideoStream(stream)
|
896
|
927
|
).then(() => {
|
897
|
928
|
this.videoSwitchInProgress = false;
|
|
@@ -1247,32 +1278,40 @@ export default {
|
1247
|
1278
|
APP.UI.addListener(
|
1248
|
1279
|
UIEvents.VIDEO_DEVICE_CHANGED,
|
1249
|
1280
|
(cameraDeviceId) => {
|
1250
|
|
- createLocalTracks(['video'], cameraDeviceId, null)
|
1251
|
|
- .then(([stream]) => {
|
1252
|
|
- this.useVideoStream(stream);
|
1253
|
|
- console.log('switched local video device');
|
1254
|
|
- APP.settings.setCameraDeviceId(cameraDeviceId);
|
1255
|
|
- })
|
1256
|
|
- .catch((err) => {
|
1257
|
|
- APP.UI.showDeviceErrorDialog(null, err);
|
1258
|
|
- APP.UI.setSelectedCameraFromSettings();
|
1259
|
|
- });
|
|
1281
|
+ createLocalTracks({
|
|
1282
|
+ devices: ['video'],
|
|
1283
|
+ cameraDeviceId: cameraDeviceId,
|
|
1284
|
+ micDeviceId: null
|
|
1285
|
+ })
|
|
1286
|
+ .then(([stream]) => {
|
|
1287
|
+ this.useVideoStream(stream);
|
|
1288
|
+ console.log('switched local video device');
|
|
1289
|
+ APP.settings.setCameraDeviceId(cameraDeviceId);
|
|
1290
|
+ })
|
|
1291
|
+ .catch((err) => {
|
|
1292
|
+ APP.UI.showDeviceErrorDialog(null, err);
|
|
1293
|
+ APP.UI.setSelectedCameraFromSettings();
|
|
1294
|
+ });
|
1260
|
1295
|
}
|
1261
|
1296
|
);
|
1262
|
1297
|
|
1263
|
1298
|
APP.UI.addListener(
|
1264
|
1299
|
UIEvents.AUDIO_DEVICE_CHANGED,
|
1265
|
1300
|
(micDeviceId) => {
|
1266
|
|
- createLocalTracks(['audio'], null, micDeviceId)
|
1267
|
|
- .then(([stream]) => {
|
1268
|
|
- this.useAudioStream(stream);
|
1269
|
|
- console.log('switched local audio device');
|
1270
|
|
- APP.settings.setMicDeviceId(micDeviceId);
|
1271
|
|
- })
|
1272
|
|
- .catch((err) => {
|
1273
|
|
- APP.UI.showDeviceErrorDialog(err, null);
|
1274
|
|
- APP.UI.setSelectedMicFromSettings();
|
1275
|
|
- });
|
|
1301
|
+ createLocalTracks({
|
|
1302
|
+ devices: ['audio'],
|
|
1303
|
+ cameraDeviceId: null,
|
|
1304
|
+ micDeviceId: micDeviceId
|
|
1305
|
+ })
|
|
1306
|
+ .then(([stream]) => {
|
|
1307
|
+ this.useAudioStream(stream);
|
|
1308
|
+ console.log('switched local audio device');
|
|
1309
|
+ APP.settings.setMicDeviceId(micDeviceId);
|
|
1310
|
+ })
|
|
1311
|
+ .catch((err) => {
|
|
1312
|
+ APP.UI.showDeviceErrorDialog(err, null);
|
|
1313
|
+ APP.UI.setSelectedMicFromSettings();
|
|
1314
|
+ });
|
1276
|
1315
|
}
|
1277
|
1316
|
);
|
1278
|
1317
|
|