Merge pull request #1034 from thecodingmachine/close_game_webcam_in_jitsi

Close game webcam when in Jitsi
This commit is contained in:
David Négrier 2021-05-11 15:56:22 +02:00 committed by GitHub
commit 5674b99734
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 30 deletions

View File

@ -1475,6 +1475,8 @@ ${escapedMessage}
mediaManager.addTriggerCloseJitsiFrameButton('close-jisi',() => { mediaManager.addTriggerCloseJitsiFrameButton('close-jisi',() => {
this.stopJitsi(); this.stopJitsi();
}); });
this.onVisibilityChange();
} }
public stopJitsi(): void { public stopJitsi(): void {
@ -1483,6 +1485,7 @@ ${escapedMessage}
mediaManager.showGameOverlay(); mediaManager.showGameOverlay();
mediaManager.removeTriggerCloseJitsiFrameButton('close-jisi'); mediaManager.removeTriggerCloseJitsiFrameButton('close-jisi');
this.onVisibilityChange();
} }
//todo: put this into an 'orchestrator' scene (EntryScene?) //todo: put this into an 'orchestrator' scene (EntryScene?)
@ -1519,6 +1522,12 @@ ${escapedMessage}
} }
private onVisibilityChange(): void { private onVisibilityChange(): void {
// If the overlay is not displayed, we are in Jitsi. We don't need the webcam.
if (!mediaManager.isGameOverlayVisible()) {
mediaManager.blurCamera();
return;
}
if (document.visibilityState === 'visible') { if (document.visibilityState === 'visible') {
mediaManager.focusCamera(); mediaManager.focusCamera();
} else { } else {

View File

@ -10,9 +10,10 @@ interface jitsiConfigInterface {
} }
const getDefaultConfig = () : jitsiConfigInterface => { const getDefaultConfig = () : jitsiConfigInterface => {
const constraints = mediaManager.getConstraintRequestedByUser();
return { return {
startWithAudioMuted: !mediaManager.constraintsMedia.audio, startWithAudioMuted: !constraints.audio,
startWithVideoMuted: mediaManager.constraintsMedia.video === false, startWithVideoMuted: constraints.video === false,
prejoinPageEnabled: false prejoinPageEnabled: false
} }
} }
@ -71,7 +72,7 @@ class JitsiFactory {
private jitsiApi: any; // eslint-disable-line @typescript-eslint/no-explicit-any private jitsiApi: any; // eslint-disable-line @typescript-eslint/no-explicit-any
private audioCallback = this.onAudioChange.bind(this); private audioCallback = this.onAudioChange.bind(this);
private videoCallback = this.onVideoChange.bind(this); private videoCallback = this.onVideoChange.bind(this);
private previousConfigMeet? : jitsiConfigInterface; private previousConfigMeet! : jitsiConfigInterface;
private jitsiScriptLoaded: boolean = false; private jitsiScriptLoaded: boolean = false;
/** /**
@ -136,32 +137,24 @@ class JitsiFactory {
//restore previous config //restore previous config
if(this.previousConfigMeet?.startWithAudioMuted){ if(this.previousConfigMeet?.startWithAudioMuted){
mediaManager.disableMicrophone(); await mediaManager.disableMicrophone();
}else{ }else{
mediaManager.enableMicrophone(); await mediaManager.enableMicrophone();
} }
if(this.previousConfigMeet?.startWithVideoMuted){ if(this.previousConfigMeet?.startWithVideoMuted){
mediaManager.disableCamera(); await mediaManager.disableCamera();
}else{ }else{
mediaManager.enableCamera(); await mediaManager.enableCamera();
} }
} }
private onAudioChange({muted}: {muted: boolean}): void { private onAudioChange({muted}: {muted: boolean}): void {
if (muted && mediaManager.constraintsMedia.audio === true) { this.previousConfigMeet.startWithAudioMuted = muted;
mediaManager.disableMicrophone();
} else if(!muted && mediaManager.constraintsMedia.audio === false) {
mediaManager.enableMicrophone();
}
} }
private onVideoChange({muted}: {muted: boolean}): void { private onVideoChange({muted}: {muted: boolean}): void {
if (muted && mediaManager.constraintsMedia.video !== false) { this.previousConfigMeet.startWithVideoMuted = muted;
mediaManager.disableCamera();
} else if(!muted && mediaManager.constraintsMedia.video === false) {
mediaManager.enableCamera();
}
} }
private async loadJitsiScript(domain: string): Promise<void> { private async loadJitsiScript(domain: string): Promise<void> {

View File

@ -155,6 +155,13 @@ export class MediaManager {
this.disableCamera(); this.disableCamera();
} }
/**
* Returns the constraint that the user wants (independently of the visibility / jitsi state...)
*/
public getConstraintRequestedByUser(): MediaStreamConstraints {
return this.previousConstraint ?? this.constraintsMedia;
}
public focusCamera() { public focusCamera() {
if(this.focused){ if(this.focused){
return; return;
@ -197,7 +204,7 @@ export class MediaManager {
} }
} }
public showGameOverlay(){ public showGameOverlay(): void {
const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay'); const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay');
gameOverlay.classList.add('active'); gameOverlay.classList.add('active');
@ -208,7 +215,7 @@ export class MediaManager {
buttonCloseFrame.removeEventListener('click', functionTrigger); buttonCloseFrame.removeEventListener('click', functionTrigger);
} }
public hideGameOverlay(){ public hideGameOverlay(): void {
const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay'); const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay');
gameOverlay.classList.remove('active'); gameOverlay.classList.remove('active');
@ -219,6 +226,11 @@ export class MediaManager {
buttonCloseFrame.addEventListener('click', functionTrigger); buttonCloseFrame.addEventListener('click', functionTrigger);
} }
public isGameOverlayVisible(): boolean {
const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay');
return gameOverlay.classList.contains('active');
}
public updateCameraQuality(value: number) { public updateCameraQuality(value: number) {
this.enableCameraStyle(); this.enableCameraStyle();
const newVideoConstraint = JSON.parse(JSON.stringify(videoConstraint)); const newVideoConstraint = JSON.parse(JSON.stringify(videoConstraint));
@ -230,29 +242,32 @@ export class MediaManager {
}); });
} }
public enableCamera() { public async enableCamera() {
this.constraintsMedia.video = videoConstraint; this.constraintsMedia.video = videoConstraint;
this.getCamera().then((stream: MediaStream) => { try {
const stream = await this.getCamera()
//TODO show error message tooltip upper of camera button //TODO show error message tooltip upper of camera button
//TODO message : please check camera permission of your navigator //TODO message : please check camera permission of your navigator
if(stream.getVideoTracks().length === 0) { if(stream.getVideoTracks().length === 0) {
throw Error('Video track is empty, please check camera permission of your navigator') throw new Error('Video track is empty, please check camera permission of your navigator')
} }
this.enableCameraStyle(); this.enableCameraStyle();
this.triggerUpdatedLocalStreamCallbacks(stream); this.triggerUpdatedLocalStreamCallbacks(stream);
}).catch((err) => { } catch(err) {
console.error(err); console.error(err);
this.disableCameraStyle(); this.disableCameraStyle();
this.stopCamera();
layoutManager.addInformation('warning', 'Camera access denied. Click here and check navigators permissions.', () => { layoutManager.addInformation('warning', 'Camera access denied. Click here and check navigators permissions.', () => {
this.showHelpCameraSettingsCallBack(); this.showHelpCameraSettingsCallBack();
}, this.userInputManager); }, this.userInputManager);
}); }
} }
public async disableCamera() { public async disableCamera() {
this.disableCameraStyle(); this.disableCameraStyle();
this.stopCamera();
if (this.constraintsMedia.audio !== false) { if (this.constraintsMedia.audio !== false) {
const stream = await this.getCamera(); const stream = await this.getCamera();
@ -262,25 +277,27 @@ export class MediaManager {
} }
} }
public enableMicrophone() { public async enableMicrophone() {
this.constraintsMedia.audio = audioConstraint; this.constraintsMedia.audio = audioConstraint;
this.getCamera().then((stream) => { try {
const stream = await this.getCamera();
//TODO show error message tooltip upper of camera button //TODO show error message tooltip upper of camera button
//TODO message : please check microphone permission of your navigator //TODO message : please check microphone permission of your navigator
if(stream.getAudioTracks().length === 0) { if (stream.getAudioTracks().length === 0) {
throw Error('Audio track is empty, please check microphone permission of your navigator') throw Error('Audio track is empty, please check microphone permission of your navigator')
} }
this.enableMicrophoneStyle(); this.enableMicrophoneStyle();
this.triggerUpdatedLocalStreamCallbacks(stream); this.triggerUpdatedLocalStreamCallbacks(stream);
}).catch((err) => { } catch(err) {
console.error(err); console.error(err);
this.disableMicrophoneStyle(); this.disableMicrophoneStyle();
layoutManager.addInformation('warning', 'Microphone access denied. Click here and check navigators permissions.', () => { layoutManager.addInformation('warning', 'Microphone access denied. Click here and check navigators permissions.', () => {
this.showHelpCameraSettingsCallBack(); this.showHelpCameraSettingsCallBack();
}, this.userInputManager); }, this.userInputManager);
}); }
} }
public async disableMicrophone() { public async disableMicrophone() {
@ -325,7 +342,6 @@ export class MediaManager {
this.cinemaBtn.classList.add("disabled"); this.cinemaBtn.classList.add("disabled");
this.constraintsMedia.video = false; this.constraintsMedia.video = false;
this.myCamVideo.srcObject = null; this.myCamVideo.srcObject = null;
this.stopCamera();
} }
private enableMicrophoneStyle(){ private enableMicrophoneStyle(){
@ -436,6 +452,8 @@ export class MediaManager {
return this.getLocalStream().catch((err) => { return this.getLocalStream().catch((err) => {
console.info('Error get camera, trying with video option at null =>', err); console.info('Error get camera, trying with video option at null =>', err);
this.disableCameraStyle(); this.disableCameraStyle();
this.stopCamera();
return this.getLocalStream().then((stream : MediaStream) => { return this.getLocalStream().then((stream : MediaStream) => {
this.hasCamera = false; this.hasCamera = false;
return stream; return stream;