From d149ba6fc5cc214295a5f3e89c1755d63be18bb2 Mon Sep 17 00:00:00 2001 From: tsareg Date: Fri, 24 Jun 2016 12:47:13 +0300 Subject: [PATCH] Fire an optional JitsiMediaDevices.PERMISSION_PROMPT_IS_SHOWN event when browser shows user media permission prompt when calling createLocalTracks --- conference.js | 132 ++++++++++-------- lang/main.json | 1 + modules/UI/UI.js | 6 +- .../UserMediaPermissionsGuidanceOverlay.js | 15 +- modules/devices/mediaDeviceHelper.js | 19 ++- 5 files changed, 99 insertions(+), 74 deletions(-) diff --git a/conference.js b/conference.js index 93ec80ac7..70da1dc49 100644 --- a/conference.js +++ b/conference.js @@ -27,8 +27,6 @@ let room, connection, localAudio, localVideo, roomLocker; import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/LargeVideo"; -const USER_MEDIA_PERMISSIONS_GUIDANCE_OVERLAY_TIMEOUT = 500; - /** * Known custom conference commands. */ @@ -68,32 +66,26 @@ function connect(roomName) { */ function createInitialLocalTracksAndConnect(roomName) { let audioAndVideoError, - audioOnlyError, - tracksCreated; + audioOnlyError; + + JitsiMeetJS.mediaDevices.addEventListener( + JitsiMeetJS.events.mediaDevices.PERMISSION_PROMPT_IS_SHOWN, + browser => APP.UI.showUserMediaPermissionsGuidanceOverlay(browser)); // First try to retrieve both audio and video. - let tryCreateLocalTracks = createLocalTracks(['audio', 'video']) + let tryCreateLocalTracks = createLocalTracks( + { devices: ['audio', 'video'] }, true) .catch(err => { // If failed then try to retrieve only audio. audioAndVideoError = err; - return createLocalTracks(['audio']); + return createLocalTracks({ devices: ['audio'] }, true); }) .catch(err => { // If audio failed too then just return empty array for tracks. audioOnlyError = err; return []; - }) - .then(tracks => { - tracksCreated = true; - return tracks; }); - window.setTimeout(() => { - if (!audioAndVideoError && !audioOnlyError && !tracksCreated) { - APP.UI.showUserMediaPermissionsGuidanceOverlay(); - } - }, USER_MEDIA_PERMISSIONS_GUIDANCE_OVERLAY_TIMEOUT); - return Promise.all([ tryCreateLocalTracks, connect(roomName) ]) .then(([tracks, con]) => { APP.UI.hideUserMediaPermissionsGuidanceOverlay(); @@ -245,32 +237,42 @@ function hangup (requestFeedback = false) { /** * Create local tracks of specified types. - * @param {string[]} devices - required track types ('audio', 'video' etc.) - * @param {string|null} [cameraDeviceId] - camera device id, if undefined - one - * from settings will be used - * @param {string|null} [micDeviceId] - microphone device id, if undefined - one - * from settings will be used + * @param {Object} options + * @param {string[]} options.devices - required track types + * ('audio', 'video' etc.) + * @param {string|null} (options.cameraDeviceId) - camera device id, if + * undefined - one from settings will be used + * @param {string|null} (options.micDeviceId) - microphone device id, if + * undefined - one from settings will be used + * @param {boolean} (checkForPermissionPrompt) - if lib-jitsi-meet should check + * for gUM permission prompt * @returns {Promise} */ -function createLocalTracks (devices, cameraDeviceId, micDeviceId) { - return JitsiMeetJS.createLocalTracks({ - // copy array to avoid mutations inside library - devices: devices.slice(0), - resolution: config.resolution, - cameraDeviceId: typeof cameraDeviceId === 'undefined' - || cameraDeviceId === null +function createLocalTracks (options, checkForPermissionPrompt) { + options || (options = {}); + + return JitsiMeetJS + .createLocalTracks({ + // copy array to avoid mutations inside library + devices: options.devices.slice(0), + resolution: config.resolution, + cameraDeviceId: typeof options.cameraDeviceId === 'undefined' || + options.cameraDeviceId === null ? APP.settings.getCameraDeviceId() - : cameraDeviceId, - micDeviceId: typeof micDeviceId === 'undefined' || micDeviceId === null - ? APP.settings.getMicDeviceId() - : micDeviceId, - // adds any ff fake device settings if any - firefox_fake_device: config.firefox_fake_device - }).catch(function (err) { - console.error('failed to create local tracks', ...devices, err); - return Promise.reject(err); - }); -} + : options.cameraDeviceId, + micDeviceId: typeof options.micDeviceId === 'undefined' || + options.micDeviceId === null + ? APP.settings.getMicDeviceId() + : options.micDeviceId, + // adds any ff fake device settings if any + firefox_fake_device: config.firefox_fake_device + }, checkForPermissionPrompt) + .catch(function (err) { + console.error( + 'failed to create local tracks', options.devices, err); + return Promise.reject(err); + }); + } /** * Changes the email for the local user @@ -861,7 +863,7 @@ export default { this.videoSwitchInProgress = true; if (shareScreen) { - createLocalTracks(['desktop']).then(([stream]) => { + createLocalTracks({ devices: ['desktop'] }).then(([stream]) => { stream.on( TrackEvents.LOCAL_TRACK_STOPPED, () => { @@ -918,7 +920,7 @@ export default { APP.UI.messageHandler.openDialog(dialogTitle, dialogTxt, false); }); } else { - createLocalTracks(['video']).then( + createLocalTracks({ devices: ['video'] }).then( ([stream]) => this.useVideoStream(stream) ).then(() => { this.videoSwitchInProgress = false; @@ -1260,32 +1262,40 @@ export default { APP.UI.addListener( UIEvents.VIDEO_DEVICE_CHANGED, (cameraDeviceId) => { - createLocalTracks(['video'], cameraDeviceId, null) - .then(([stream]) => { - this.useVideoStream(stream); - console.log('switched local video device'); - APP.settings.setCameraDeviceId(cameraDeviceId); - }) - .catch((err) => { - APP.UI.showDeviceErrorDialog(null, err); - APP.UI.setSelectedCameraFromSettings(); - }); + createLocalTracks({ + devices: ['video'], + cameraDeviceId: cameraDeviceId, + micDeviceId: null + }) + .then(([stream]) => { + this.useVideoStream(stream); + console.log('switched local video device'); + APP.settings.setCameraDeviceId(cameraDeviceId); + }) + .catch((err) => { + APP.UI.showDeviceErrorDialog(null, err); + APP.UI.setSelectedCameraFromSettings(); + }); } ); APP.UI.addListener( UIEvents.AUDIO_DEVICE_CHANGED, (micDeviceId) => { - createLocalTracks(['audio'], null, micDeviceId) - .then(([stream]) => { - this.useAudioStream(stream); - console.log('switched local audio device'); - APP.settings.setMicDeviceId(micDeviceId); - }) - .catch((err) => { - APP.UI.showDeviceErrorDialog(err, null); - APP.UI.setSelectedMicFromSettings(); - }); + createLocalTracks({ + devices: ['audio'], + cameraDeviceId: null, + micDeviceId: micDeviceId + }) + .then(([stream]) => { + this.useAudioStream(stream); + console.log('switched local audio device'); + APP.settings.setMicDeviceId(micDeviceId); + }) + .catch((err) => { + APP.UI.showDeviceErrorDialog(err, null); + APP.UI.setSelectedMicFromSettings(); + }); } ); diff --git a/lang/main.json b/lang/main.json index 0f3735857..04796672c 100644 --- a/lang/main.json +++ b/lang/main.json @@ -14,6 +14,7 @@ "userMedia": { "react-nativeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing Allow button", "chromeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing Allow button", + "androidGrantPermissions": "Please grant permissions to use your camera and microphone by pressing Allow button", "firefoxGrantPermissions": "Please grant permissions to use your camera and microphone by pressing Share Selected Device button", "operaGrantPermissions": "Please grant permissions to use your camera and microphone by pressing Allow button", "iexplorerGrantPermissions": "Please grant permissions to use your camera and microphone by pressing OK button", diff --git a/modules/UI/UI.js b/modules/UI/UI.js index e7619d893..2eb8f97f7 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -1388,9 +1388,11 @@ UI.hideRingOverLay = function () { /** * Shows browser-specific overlay with guidance how to proceed with gUM prompt. + * @param {string} browser - name of browser for which to show the guidance + * overlay. */ -UI.showUserMediaPermissionsGuidanceOverlay = function () { - GumPermissionsOverlay.show(); +UI.showUserMediaPermissionsGuidanceOverlay = function (browser) { + GumPermissionsOverlay.show(browser); }; /** diff --git a/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js b/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js index 8c72a4a7e..ef2cfc9c1 100644 --- a/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js +++ b/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js @@ -5,11 +5,10 @@ let $overlay; /** * Internal function that constructs overlay with guidance how to proceed with * gUM prompt. + * @param {string} browser - name of browser for which to construct the + * guidance overlay. */ -function buildOverlayHtml() { - let browser = JitsiMeetJS.environment.getBrowserType() - .split('rtc_browser.')[1] || 'chrome'; - +function buildOverlayHtml(browser) { $overlay = $(`
@@ -28,11 +27,13 @@ export default { /** * Shows browser-specific overlay with guidance how to proceed with * gUM prompt. + * @param {string} browser - name of browser for which to show the + * guidance overlay. */ - show() { - !$overlay && buildOverlayHtml(); + show(browser) { + !$overlay && buildOverlayHtml(browser); - $overlay && $overlay.appendTo('body'); + !$overlay.parents('body').length && $overlay.appendTo('body'); }, /** diff --git a/modules/devices/mediaDeviceHelper.js b/modules/devices/mediaDeviceHelper.js index 8b68ad838..c4e1953ec 100644 --- a/modules/devices/mediaDeviceHelper.js +++ b/modules/devices/mediaDeviceHelper.js @@ -191,8 +191,11 @@ export default { if (audioRequested && videoRequested) { // First we try to create both audio and video tracks together. - return createLocalTracks( - ['audio', 'video'], cameraDeviceId, micDeviceId) + return createLocalTracks({ + devices: ['audio', 'video'], + cameraDeviceId: cameraDeviceId, + micDeviceId: micDeviceId + }) // If we fail to do this, try to create them separately. .catch(() => Promise.all( [createAudioTrack(false), createVideoTrack(false)])) @@ -213,7 +216,11 @@ export default { } function createAudioTrack(showError) { - return createLocalTracks(['audio'], null, micDeviceId) + return createLocalTracks({ + devices: ['audio'], + cameraDeviceId: null, + micDeviceId: micDeviceId + }) .catch(err => { audioTrackError = err; showError && APP.UI.showDeviceErrorDialog(err, null); @@ -222,7 +229,11 @@ export default { } function createVideoTrack(showError) { - return createLocalTracks(['video'], cameraDeviceId, null) + return createLocalTracks({ + devices: ['video'], + cameraDeviceId: cameraDeviceId, + micDeviceId: null + }) .catch(err => { videoTrackError = err; showError && APP.UI.showDeviceErrorDialog(null, err);