From 39f44b8a9d3c2fbcc13a109110e0aaac7342610c Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 6 Jun 2020 17:03:10 +0200 Subject: [PATCH 1/3] Feature screen sharing - Send stream of screen sharing in peer connexion - Add button for share your screen --- front/dist/index.html | 4 ++ front/dist/resources/logos/monitor-close.svg | 44 ++++++++++++ front/dist/resources/logos/monitor.svg | 15 ++++ front/dist/resources/style/style.css | 4 ++ front/src/WebRtc/MediaManager.ts | 73 ++++++++++++++++++++ front/src/WebRtc/SimplePeer.ts | 57 +++++++-------- 6 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 front/dist/resources/logos/monitor-close.svg create mode 100644 front/dist/resources/logos/monitor.svg diff --git a/front/dist/index.html b/front/dist/index.html index a593e91a..aea7d761 100644 --- a/front/dist/index.html +++ b/front/dist/index.html @@ -25,6 +25,10 @@ +
+ + +
diff --git a/front/dist/resources/logos/monitor-close.svg b/front/dist/resources/logos/monitor-close.svg new file mode 100644 index 00000000..80056e2d --- /dev/null +++ b/front/dist/resources/logos/monitor-close.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/front/dist/resources/logos/monitor.svg b/front/dist/resources/logos/monitor.svg new file mode 100644 index 00000000..d4b586c6 --- /dev/null +++ b/front/dist/resources/logos/monitor.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/front/dist/resources/style/style.css b/front/dist/resources/style/style.css index 3f3c2c62..a1ff6b6a 100644 --- a/front/dist/resources/style/style.css +++ b/front/dist/resources/style/style.css @@ -138,6 +138,10 @@ video{ transition: all .2s; right: 134px; } +.btn-monitor{ + transition: all .2s; + right: 224px; +} /*.btn-call{ transition: all .1s; left: 0px; diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts index bb3f0cb9..1031b394 100644 --- a/front/src/WebRtc/MediaManager.ts +++ b/front/src/WebRtc/MediaManager.ts @@ -3,12 +3,18 @@ const videoConstraint: {width : any, height: any, facingMode : string} = { height: { ideal: 720 }, facingMode: "user" }; +interface MediaServiceInterface extends MediaDevices{ + getDisplayMedia(constrain: any) : Promise; +} export class MediaManager { localStream: MediaStream|null = null; + localScreenCapture: MediaStream|null = null; remoteVideo: Array = new Array(); myCamVideo: HTMLVideoElement; cinemaClose: any = null; cinema: any = null; + monitorClose: any = null; + monitor: any = null; microphoneClose: any = null; microphone: any = null; webrtcInAudio: HTMLAudioElement; @@ -52,6 +58,21 @@ export class MediaManager { this.disabledCamera(); //update tracking }); + + this.monitorClose = document.getElementById('monitor-close'); + this.monitorClose.style.display = "block"; + this.monitorClose.addEventListener('click', (e: any) => { + e.preventDefault(); + this.enabledMonitor(); + //update tracking + }); + this.monitor = document.getElementById('monitor'); + this.monitor.style.display = "none"; + this.monitor.addEventListener('click', (e: any) => { + e.preventDefault(); + this.disabledMonitor(); + //update tracking + }); } activeVisio(){ @@ -106,6 +127,58 @@ export class MediaManager { }); } + enabledMonitor() { + this.monitorClose.style.display = "none"; + this.monitor.style.display = "block"; + this.getScreenMedia().then((stream) => { + this.updatedLocalStreamCallBack(stream); + }); + } + + disabledMonitor() { + this.monitorClose.style.display = "block"; + this.monitor.style.display = "none"; + this.localScreenCapture?.getTracks().forEach((track: MediaStreamTrack) => { + track.stop(); + }); + this.localScreenCapture = null; + this.getCamera().then((stream) => { + this.updatedLocalStreamCallBack(stream); + }); + } + + //get screen + getScreenMedia() : Promise{ + try { + return this._startScreenCapture() + .then((stream: MediaStream) => { + this.localScreenCapture = stream; + return stream; + }) + .catch((err: any) => { + console.error("Error => getScreenMedia => " + err); + throw err; + }); + }catch (err) { + return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars + reject(err); + }); + } + } + + private _startScreenCapture() { + if ((navigator as any).getDisplayMedia) { + return (navigator as any).getDisplayMedia({video: true}); + } else if ((navigator.mediaDevices as any).getDisplayMedia) { + return (navigator.mediaDevices as any).getDisplayMedia({video: true}); + } else { + //return navigator.mediaDevices.getUserMedia(({video: {mediaSource: 'screen'}} as any)); + return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars + reject("error sharing screen"); + }); + } + } + //get camera getCamera() { let promise = null; diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 2af0be27..43ada6ee 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -127,22 +127,11 @@ export class SimplePeer { videoActive = true; } }); - if(microphoneActive){ - this.MediaManager.enabledMicrophoneByUserId(user.userId); - }else{ - this.MediaManager.disabledMicrophoneByUserId(user.userId); - } - if(videoActive){ - this.MediaManager.enabledVideoByUserId(user.userId); - }else{ - this.MediaManager.disabledVideoByUserId(user.userId); - } this.stream(user.userId, stream); }); /*peer.on('track', (track: MediaStreamTrack, stream: MediaStream) => { - this.stream(user.userId, stream); });*/ peer.on('close', () => { @@ -158,9 +147,19 @@ export class SimplePeer { }); peer.on('data', (chunk: Buffer) => { - let data = JSON.parse(chunk.toString('utf8')); - if(data.type === "stream"){ - this.stream(user.userId, data.stream); + let constraint = JSON.parse(chunk.toString('utf8')); + + if (constraint.audio) { + this.MediaManager.enabledMicrophoneByUserId(user.userId); + } else { + this.MediaManager.disabledMicrophoneByUserId(user.userId); + } + + if (constraint.video) { + this.MediaManager.enabledVideoByUserId(user.userId); + } else { + this.stream(user.userId); + this.MediaManager.disabledVideoByUserId(user.userId); } }); @@ -216,7 +215,7 @@ export class SimplePeer { * @param userId * @param stream */ - private stream(userId : any, stream: MediaStream) { + private stream(userId : any, stream?: MediaStream) { if(!stream){ this.MediaManager.disabledVideoByUserId(userId); this.MediaManager.disabledMicrophoneByUserId(userId); @@ -231,25 +230,21 @@ export class SimplePeer { */ private addMedia (userId : any = null) { try { - let transceiver : any = null; - let localStream: MediaStream|null = this.MediaManager.localStream; + let localStream: MediaStream | null = this.MediaManager.localStream; + let localScreenCapture: MediaStream | null = this.MediaManager.localScreenCapture; let peer = this.PeerConnectionArray.get(userId); - if(localStream === null) { - //send fake signal - if(peer === undefined){ - return; - } - peer.write(new Buffer(JSON.stringify({ - type: "stream", - stream: null - }))); - return; - } if (peer === undefined) { - throw new Error('While adding media, cannot find user with ID '+userId); + throw new Error('While adding media, cannot find user with ID ' + userId); } - for (const track of localStream.getTracks()) { - peer.addTrack(track, localStream); + peer.write(new Buffer(JSON.stringify(this.MediaManager.constraintsMedia))); + if (localScreenCapture !== null) { + for (const track of localScreenCapture.getTracks()) { + peer.addTrack(track, localScreenCapture); + } + } else if (localStream) { + for (const track of localStream.getTracks()) { + peer.addTrack(track, localStream); + } } }catch (e) { console.error(`addMedia => addMedia => ${userId}`, e); From 9b01dd00414b28b8ea9d074922b725541be14765 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 6 Jun 2020 19:52:34 +0200 Subject: [PATCH 2/3] Stability simple peer --- front/src/WebRtc/SimplePeer.ts | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 43ada6ee..7ada04aa 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -148,14 +148,13 @@ export class SimplePeer { peer.on('data', (chunk: Buffer) => { let constraint = JSON.parse(chunk.toString('utf8')); - if (constraint.audio) { this.MediaManager.enabledMicrophoneByUserId(user.userId); } else { this.MediaManager.disabledMicrophoneByUserId(user.userId); } - if (constraint.video) { + if (constraint.video || constraint.screen) { this.MediaManager.enabledVideoByUserId(user.userId); } else { this.stream(user.userId); @@ -232,18 +231,30 @@ export class SimplePeer { try { let localStream: MediaStream | null = this.MediaManager.localStream; let localScreenCapture: MediaStream | null = this.MediaManager.localScreenCapture; - let peer = this.PeerConnectionArray.get(userId); - if (peer === undefined) { + let PeerConnection : any = this.PeerConnectionArray.get(userId); + if (PeerConnection === undefined) { throw new Error('While adding media, cannot find user with ID ' + userId); } - peer.write(new Buffer(JSON.stringify(this.MediaManager.constraintsMedia))); + PeerConnection.write(new Buffer(JSON.stringify(Object.assign(this.MediaManager.constraintsMedia, {screen: localScreenCapture !== null})))); + + //remove current stream + try { + if (PeerConnection._pc) { + PeerConnection._pc.getRemoteStreams().forEach((stream: MediaStream) => { + stream.getTracks().forEach((track: MediaStreamTrack) => { + PeerConnection.removeTrack(track, stream); + }); + }); + } + }catch (e) {} + if (localScreenCapture !== null) { for (const track of localScreenCapture.getTracks()) { - peer.addTrack(track, localScreenCapture); + PeerConnection.addTrack(track, localScreenCapture); } } else if (localStream) { for (const track of localStream.getTracks()) { - peer.addTrack(track, localStream); + PeerConnection.addTrack(track, localStream); } } }catch (e) { From 228933184bbf10de9c6dcff76ed56287c625b803 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 6 Jun 2020 20:13:30 +0200 Subject: [PATCH 3/3] Fix CI --- front/src/WebRtc/SimplePeer.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 7ada04aa..d9e72ad2 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -231,23 +231,13 @@ export class SimplePeer { try { let localStream: MediaStream | null = this.MediaManager.localStream; let localScreenCapture: MediaStream | null = this.MediaManager.localScreenCapture; - let PeerConnection : any = this.PeerConnectionArray.get(userId); - if (PeerConnection === undefined) { + let PeerConnection = this.PeerConnectionArray.get(userId); + + if (!PeerConnection || PeerConnection === undefined) { throw new Error('While adding media, cannot find user with ID ' + userId); } PeerConnection.write(new Buffer(JSON.stringify(Object.assign(this.MediaManager.constraintsMedia, {screen: localScreenCapture !== null})))); - //remove current stream - try { - if (PeerConnection._pc) { - PeerConnection._pc.getRemoteStreams().forEach((stream: MediaStream) => { - stream.getTracks().forEach((track: MediaStreamTrack) => { - PeerConnection.removeTrack(track, stream); - }); - }); - } - }catch (e) {} - if (localScreenCapture !== null) { for (const track of localScreenCapture.getTracks()) { PeerConnection.addTrack(track, localScreenCapture);