diff --git a/react/features/screenshot-capture/actions.js b/react/features/screenshot-capture/actions.js index ec028d09a6..211f182a7e 100644 --- a/react/features/screenshot-capture/actions.js +++ b/react/features/screenshot-capture/actions.js @@ -2,9 +2,11 @@ import { createScreenshotCaptureEffect } from '../stream-effects/screenshot-capture'; import { getLocalVideoTrack } from '../../features/base/tracks'; - +import logger from './logger'; import { SET_SCREENSHOT_CAPTURE } from './actionTypes'; +let ongoingEffect; + /** * Marks the on-off state of screenshot captures. * @@ -28,19 +30,34 @@ function setScreenshotCapture(enabled) { * @returns {Promise} */ export function toggleScreenshotCaptureEffect(enabled: boolean) { - return function(dispatch: (Object) => Object, getState: () => any) { + return async function(dispatch: (Object) => Object, getState: () => any) { const state = getState(); if (state['features/screenshot-capture'].capturesEnabled !== enabled) { const { jitsiTrack } = getLocalVideoTrack(state['features/base/tracks']); + if (!ongoingEffect) { + ongoingEffect = await createScreenshotCaptureEffect(state); + } + // Screenshot capture effect doesn't return a modified stream. Therefore, we don't have to // switch the stream at the conference level, starting/stopping the effect will suffice here. - return createScreenshotCaptureEffect(state) - .then(effect => { - enabled ? effect.startEffect(jitsiTrack.getOriginalStream()) : effect.stopEffect(); + if (enabled) { + try { + await ongoingEffect.startEffect( + jitsiTrack.getOriginalStream(), + jitsiTrack.videoType + ); dispatch(setScreenshotCapture(enabled)); - }); + } catch { + + // Handle promise rejection from {@code startEffect} due to stream type not being desktop. + logger.error('Unsupported stream type.'); + } + } else { + ongoingEffect.stopEffect(); + dispatch(setScreenshotCapture(enabled)); + } } return Promise.resolve(); diff --git a/react/features/screenshot-capture/logger.js b/react/features/screenshot-capture/logger.js new file mode 100644 index 0000000000..dbbcf07ac7 --- /dev/null +++ b/react/features/screenshot-capture/logger.js @@ -0,0 +1,5 @@ +// @flow + +import { getLogger } from '../base/logging/functions'; + +export default getLogger('features/screenshot-capture'); diff --git a/react/features/stream-effects/screenshot-capture/ScreenshotCaptureEffect.js b/react/features/stream-effects/screenshot-capture/ScreenshotCaptureEffect.js index b940ab6fe4..ee2e2785ee 100644 --- a/react/features/stream-effects/screenshot-capture/ScreenshotCaptureEffect.js +++ b/react/features/stream-effects/screenshot-capture/ScreenshotCaptureEffect.js @@ -50,40 +50,36 @@ export default class ScreenshotCaptureEffect { this._streamWorker.onmessage = this._handleWorkerAction; } - /** - * Checks if the local track supports this effect. - * - * @param {JitsiLocalTrack} jitsiLocalTrack - Targeted local track. - * @returns {boolean} - Returns true if this effect can run on the specified track, false otherwise. - */ - isEnabled(jitsiLocalTrack: Object) { - return jitsiLocalTrack.isVideoTrack() && jitsiLocalTrack.videoType === 'desktop'; - } - /** * Starts the screenshot capture event on a loop. * * @param {MediaStream} stream - The desktop stream from which screenshots are to be sent. - * @returns {MediaStream} - The same stream, with the interval set. + * @param {string} videoType - The type of the media stream. + * @returns {Promise} - Promise that resolves once effect has started or rejects if the + * videoType parameter is not desktop. */ - startEffect(stream: MediaStream) { - const desktopTrack = stream.getVideoTracks()[0]; - const { height, width } - = desktopTrack.getSettings() ?? desktopTrack.getConstraints(); + startEffect(stream: MediaStream, videoType: string) { + return new Promise((resolve, reject) => { + if (videoType !== 'desktop') { + reject(); + } + const desktopTrack = stream.getVideoTracks()[0]; + const { height, width } + = desktopTrack.getSettings() ?? desktopTrack.getConstraints(); - this._streamHeight = height; - this._streamWidth = width; - this._currentCanvas.height = parseInt(height, 10); - this._currentCanvas.width = parseInt(width, 10); - this._videoElement.height = parseInt(height, 10); - this._videoElement.width = parseInt(width, 10); - this._videoElement.srcObject = stream; - this._videoElement.play(); + this._streamHeight = height; + this._streamWidth = width; + this._currentCanvas.height = parseInt(height, 10); + this._currentCanvas.width = parseInt(width, 10); + this._videoElement.height = parseInt(height, 10); + this._videoElement.width = parseInt(width, 10); + this._videoElement.srcObject = stream; + this._videoElement.play(); - // Store first capture for comparisons in {@code this._handleScreenshot}. - this._videoElement.addEventListener('loadeddata', this._initScreenshotCapture); - - return stream; + // Store first capture for comparisons in {@code this._handleScreenshot}. + this._videoElement.addEventListener('loadeddata', this._initScreenshotCapture); + resolve(); + }); } /**