Merge pull request #251 from thecodingmachine/fix_camera_stop

Camera was not properly closed in EnableCameraScene
This commit is contained in:
David Négrier 2020-08-31 15:31:33 +02:00 committed by GitHub
commit 6f6873e870
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 31 deletions

View File

@ -266,6 +266,9 @@ export class EnableCameraScene extends Phaser.Scene {
this.soundMeter.stop(); this.soundMeter.stop();
window.removeEventListener('resize', this.repositionCallback); window.removeEventListener('resize', this.repositionCallback);
mediaManager.stopCamera();
mediaManager.stopMicrophone();
// Do we have a start URL in the address bar? If so, let's redirect to this address // Do we have a start URL in the address bar? If so, let's redirect to this address
const instanceAndMapUrl = this.findMapUrl(); const instanceAndMapUrl = this.findMapUrl();
if (instanceAndMapUrl !== null) { if (instanceAndMapUrl !== null) {

View File

@ -7,9 +7,9 @@ const videoConstraint: boolean|MediaTrackConstraints = {
facingMode: "user" facingMode: "user"
}; };
type UpdatedLocalStreamCallback = (media: MediaStream) => void; export type UpdatedLocalStreamCallback = (media: MediaStream|null) => void;
type StartScreenSharingCallback = (media: MediaStream) => void; export type StartScreenSharingCallback = (media: MediaStream) => void;
type StopScreenSharingCallback = (media: MediaStream) => void; export type StopScreenSharingCallback = (media: MediaStream) => void;
// TODO: Split MediaManager in 2 classes: MediaManagerUI (in charge of HTML) and MediaManager (singleton in charge of the camera only) // TODO: Split MediaManager in 2 classes: MediaManagerUI (in charge of HTML) and MediaManager (singleton in charge of the camera only)
// TODO: verify that microphone event listeners are not triggered plenty of time NOW (since MediaManager is created many times!!!!) // TODO: verify that microphone event listeners are not triggered plenty of time NOW (since MediaManager is created many times!!!!)
@ -109,7 +109,7 @@ export class MediaManager {
this.updatedLocalStreamCallBacks.delete(callback); this.updatedLocalStreamCallBacks.delete(callback);
} }
private triggerUpdatedLocalStreamCallbacks(stream: MediaStream): void { private triggerUpdatedLocalStreamCallbacks(stream: MediaStream|null): void {
for (const callback of this.updatedLocalStreamCallBacks) { for (const callback of this.updatedLocalStreamCallBacks) {
callback(stream); callback(stream);
} }
@ -127,7 +127,7 @@ export class MediaManager {
} }
} }
showGameOverlay(){ public showGameOverlay(){
const gameOverlay = this.getElementByIdOrFail('game-overlay'); const gameOverlay = this.getElementByIdOrFail('game-overlay');
gameOverlay.classList.add('active'); gameOverlay.classList.add('active');
} }
@ -142,20 +142,20 @@ export class MediaManager {
}); });
} }
private disableCamera() { private async disableCamera() {
this.cinemaClose.style.display = "block"; this.cinemaClose.style.display = "block";
this.cinema.style.display = "none"; this.cinema.style.display = "none";
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;
if (this.localStream) { this.stopCamera();
this.localStream.getVideoTracks().forEach((MediaStreamTrack: MediaStreamTrack) => {
MediaStreamTrack.stop(); if (this.constraintsMedia.audio !== false) {
}); const stream = await this.getCamera();
}
this.getCamera().then((stream) => {
this.triggerUpdatedLocalStreamCallbacks(stream); this.triggerUpdatedLocalStreamCallbacks(stream);
}); } else {
this.triggerUpdatedLocalStreamCallbacks(null);
}
} }
private enableMicrophone() { private enableMicrophone() {
@ -163,24 +163,25 @@ export class MediaManager {
this.microphone.style.display = "block"; this.microphone.style.display = "block";
this.microphoneBtn.classList.remove("disabled"); this.microphoneBtn.classList.remove("disabled");
this.constraintsMedia.audio = true; this.constraintsMedia.audio = true;
this.getCamera().then((stream) => { this.getCamera().then((stream) => {
this.triggerUpdatedLocalStreamCallbacks(stream); this.triggerUpdatedLocalStreamCallbacks(stream);
}); });
} }
private disableMicrophone() { private async disableMicrophone() {
this.microphoneClose.style.display = "block"; this.microphoneClose.style.display = "block";
this.microphone.style.display = "none"; this.microphone.style.display = "none";
this.microphoneBtn.classList.add("disabled"); this.microphoneBtn.classList.add("disabled");
this.constraintsMedia.audio = false; this.constraintsMedia.audio = false;
if(this.localStream) { this.stopMicrophone();
this.localStream.getAudioTracks().forEach((MediaStreamTrack: MediaStreamTrack) => {
MediaStreamTrack.stop(); if (this.constraintsMedia.video !== false) {
}); const stream = await this.getCamera();
}
this.getCamera().then((stream) => {
this.triggerUpdatedLocalStreamCallbacks(stream); this.triggerUpdatedLocalStreamCallbacks(stream);
}); } else {
this.triggerUpdatedLocalStreamCallbacks(null);
}
} }
private enableScreenSharing() { private enableScreenSharing() {
@ -287,6 +288,28 @@ export class MediaManager {
} }
} }
/**
* Stops the camera from filming
*/
public stopCamera(): void {
if (this.localStream) {
for (const track of this.localStream.getVideoTracks()) {
track.stop();
}
}
}
/**
* Stops the microphone from listening
*/
public stopMicrophone(): void {
if (this.localStream) {
for (const track of this.localStream.getAudioTracks()) {
track.stop();
}
}
}
setCamera(id: string): Promise<MediaStream> { setCamera(id: string): Promise<MediaStream> {
let video = this.constraintsMedia.video; let video = this.constraintsMedia.video;
if (typeof(video) === 'boolean' || video === undefined) { if (typeof(video) === 'boolean' || video === undefined) {

View File

@ -70,7 +70,7 @@ export class ScreenSharingPeer extends Peer {
} }
private sendWebrtcScreenSharingSignal(data: unknown) { private sendWebrtcScreenSharingSignal(data: unknown) {
console.log("sendWebrtcScreenSharingSignal", data); //console.log("sendWebrtcScreenSharingSignal", data);
try { try {
this.connection.sendWebrtcScreenSharingSignal(data, this.userId); this.connection.sendWebrtcScreenSharingSignal(data, this.userId);
}catch (e) { }catch (e) {
@ -82,8 +82,8 @@ export class ScreenSharingPeer extends Peer {
* Sends received stream to screen. * Sends received stream to screen.
*/ */
private stream(stream?: MediaStream) { private stream(stream?: MediaStream) {
console.log(`ScreenSharingPeer::stream => ${this.userId}`, stream); //console.log(`ScreenSharingPeer::stream => ${this.userId}`, stream);
console.log(`stream => ${this.userId} => `, stream); //console.log(`stream => ${this.userId} => `, stream);
if(!stream){ if(!stream){
mediaManager.removeActiveScreenSharingVideo(this.userId); mediaManager.removeActiveScreenSharingVideo(this.userId);
this.isReceivingStream = false; this.isReceivingStream = false;

View File

@ -4,7 +4,12 @@ import {
WebRtcSignalReceivedMessageInterface, WebRtcSignalReceivedMessageInterface,
WebRtcStartMessageInterface WebRtcStartMessageInterface
} from "../Connection"; } from "../Connection";
import { mediaManager } from "./MediaManager"; import {
mediaManager,
StartScreenSharingCallback,
StopScreenSharingCallback,
UpdatedLocalStreamCallback
} from "./MediaManager";
import * as SimplePeerNamespace from "simple-peer"; import * as SimplePeerNamespace from "simple-peer";
import {ScreenSharingPeer} from "./ScreenSharingPeer"; import {ScreenSharingPeer} from "./ScreenSharingPeer";
import {VideoPeer} from "./VideoPeer"; import {VideoPeer} from "./VideoPeer";
@ -32,9 +37,9 @@ export class SimplePeer {
private PeerScreenSharingConnectionArray: Map<string, ScreenSharingPeer> = new Map<string, ScreenSharingPeer>(); private PeerScreenSharingConnectionArray: Map<string, ScreenSharingPeer> = new Map<string, ScreenSharingPeer>();
private PeerConnectionArray: Map<string, VideoPeer> = new Map<string, VideoPeer>(); private PeerConnectionArray: Map<string, VideoPeer> = new Map<string, VideoPeer>();
private readonly sendLocalVideoStreamCallback: (media: MediaStream) => void; private readonly sendLocalVideoStreamCallback: UpdatedLocalStreamCallback;
private readonly sendLocalScreenSharingStreamCallback: (media: MediaStream) => void; private readonly sendLocalScreenSharingStreamCallback: StartScreenSharingCallback;
private readonly stopLocalScreenSharingStreamCallback: (media: MediaStream) => void; private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>(); private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>();
constructor(Connection: Connection, WebRtcRoomId: string = "test-webrtc") { constructor(Connection: Connection, WebRtcRoomId: string = "test-webrtc") {
@ -326,9 +331,9 @@ export class SimplePeer {
} }
public sendLocalVideoStream(){ public sendLocalVideoStream(){
this.Users.forEach((user: UserSimplePeerInterface) => { for (const user of this.Users) {
this.pushVideoToRemoteUser(user.userId); this.pushVideoToRemoteUser(user.userId);
}) }
} }
/** /**

View File

@ -85,7 +85,7 @@ export class VideoPeer extends Peer {
* Sends received stream to screen. * Sends received stream to screen.
*/ */
private stream(stream?: MediaStream) { private stream(stream?: MediaStream) {
console.log(`VideoPeer::stream => ${this.userId}`, stream); //console.log(`VideoPeer::stream => ${this.userId}`, stream);
if(!stream){ if(!stream){
mediaManager.disabledVideoByUserId(this.userId); mediaManager.disabledVideoByUserId(this.userId);
mediaManager.disabledMicrophoneByUserId(this.userId); mediaManager.disabledMicrophoneByUserId(this.userId);