diff --git a/front/dist/index.html b/front/dist/index.html
index 92a7bf3c..360d5a9a 100644
--- a/front/dist/index.html
+++ b/front/dist/index.html
@@ -77,6 +77,10 @@
+
+
+
+
@@ -100,6 +104,13 @@
+
+
+
+
+
-->
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 30e099ef..413bce71 100644
--- a/front/dist/resources/style/style.css
+++ b/front/dist/resources/style/style.css
@@ -109,6 +109,10 @@ video#myCamVideo{
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 39a61738..a11532ac 100644
--- a/front/src/WebRtc/MediaManager.ts
+++ b/front/src/WebRtc/MediaManager.ts
@@ -5,6 +5,9 @@ const videoConstraint: boolean|MediaTrackConstraints = {
height: { ideal: 720 },
facingMode: "user"
};
+interface MediaServiceInterface extends MediaDevices{
+ getDisplayMedia(constrain: any) : Promise;
+}
type UpdatedLocalStreamCallback = (media: MediaStream) => void;
@@ -12,10 +15,13 @@ type UpdatedLocalStreamCallback = (media: MediaStream) => void;
// TODO: verify that microphone event listeners are not triggered plenty of time NOW (since MediaManager is created many times!!!!)
export class MediaManager {
localStream: MediaStream|null = null;
+ localScreenCapture: MediaStream|null = null;
private remoteVideo: Map = new Map();
myCamVideo: HTMLVideoElement;
cinemaClose: HTMLImageElement;
cinema: HTMLImageElement;
+ monitorClose: HTMLImageElement;
+ monitor: HTMLImageElement;
microphoneClose: HTMLImageElement;
microphone: HTMLImageElement;
webrtcInAudio: HTMLAudioElement;
@@ -57,6 +63,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
+ });
}
onUpdateLocalStream(callback: UpdatedLocalStreamCallback): void {
@@ -126,6 +147,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
async getCamera(): Promise {
if (navigator.mediaDevices === undefined) {
diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts
index fdc2d0c2..96f047b7 100644
--- a/front/src/WebRtc/SimplePeer.ts
+++ b/front/src/WebRtc/SimplePeer.ts
@@ -156,22 +156,11 @@ export class SimplePeer {
videoActive = true;
}
});
- if(microphoneActive){
- mediaManager.enabledMicrophoneByUserId(user.userId);
- }else{
- mediaManager.disabledMicrophoneByUserId(user.userId);
- }
- if(videoActive){
- mediaManager.enabledVideoByUserId(user.userId);
- }else{
- mediaManager.disabledVideoByUserId(user.userId);
- }
this.stream(user.userId, stream);
});
/*peer.on('track', (track: MediaStreamTrack, stream: MediaStream) => {
- this.stream(user.userId, stream);
});*/
peer.on('close', () => {
@@ -190,9 +179,19 @@ export class SimplePeer {
});
peer.on('data', (chunk: Buffer) => {
- const 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) {
+ mediaManager.enabledMicrophoneByUserId(user.userId);
+ } else {
+ mediaManager.disabledMicrophoneByUserId(user.userId);
+ }
+
+ if (constraint.video) {
+ mediaManager.enabledVideoByUserId(user.userId);
+ } else {
+ this.stream(user.userId);
+ mediaManager.disabledVideoByUserId(user.userId);
}
});
@@ -279,7 +278,7 @@ export class SimplePeer {
* @param userId
* @param stream
*/
- private stream(userId : string, stream: MediaStream) {
+ private stream(userId : string, stream?: MediaStream) {
if(!stream){
mediaManager.disabledVideoByUserId(userId);
mediaManager.disabledMicrophoneByUserId(userId);
@@ -294,24 +293,21 @@ export class SimplePeer {
*/
private addMedia (userId : string) {
try {
- const localStream: MediaStream|null = mediaManager.localStream;
- const 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;
- }
+ let localStream: MediaStream | null = mediaManager.localStream;
+ let localScreenCapture: MediaStream | null = mediaManager.localScreenCapture;
+ let peer = this.PeerConnectionArray.get(userId);
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(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);