You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2018/11/09 06:54:52 UTC
[openmeetings] branch master updated: [OPENMEETINGS-1352]
screen-sharing seems to work in Chrome
This is an automated email from the ASF dual-hosted git repository.
solomax pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openmeetings.git
The following commit(s) were added to refs/heads/master by this push:
new 616672c [OPENMEETINGS-1352] screen-sharing seems to work in Chrome
616672c is described below
commit 616672cbcc14fe907a394ba7422b93ecf7fcf6f1
Author: Maxim Solodovnik <so...@gmail.com>
AuthorDate: Fri Nov 9 13:54:40 2018 +0700
[OPENMEETINGS-1352] screen-sharing seems to work in Chrome
---
.../openmeetings/core/remote/KurentoHandler.java | 2 +-
openmeetings-web/pom.xml | 1 -
.../apache/openmeetings/web/room/RoomPanel.html | 1 +
.../apache/openmeetings/web/room/RoomPanel.java | 4 +-
.../apache/openmeetings/web/room/getScreenId.js | 209 ---------------------
.../org/apache/openmeetings/web/room/raw-room.js | 2 +-
.../org/apache/openmeetings/web/room/raw-sharer.js | 95 +++++++++-
.../org/apache/openmeetings/web/room/raw-video.js | 47 +++--
pom.xml | 2 +-
9 files changed, 120 insertions(+), 243 deletions(-)
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java
index 6191a7f..bf2fdde 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java
@@ -264,7 +264,7 @@ public class KurentoHandler {
break;
case "wannaShare":
if (screenShareAllowed(c)) {
- startSharing(c, msg);
+ startSharing(c, msg, Activity.SCREEN);
}
break;
case "wannaRecord":
diff --git a/openmeetings-web/pom.xml b/openmeetings-web/pom.xml
index cdffadf..6185131 100644
--- a/openmeetings-web/pom.xml
+++ b/openmeetings-web/pom.xml
@@ -212,7 +212,6 @@
<jsSourceFile>jquery.dialogextend.js</jsSourceFile>
<jsSourceFile>raw-video.js</jsSourceFile>
<jsSourceFile>raw-video-manager.js</jsSourceFile>
- <jsSourceFile>getScreenId.js</jsSourceFile>
<jsSourceFile>raw-sharer.js</jsSourceFile>
<jsSourceFile>raw-room.js</jsSourceFile>
</jsSourceFiles>
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html
index 15c86df..e09e5da 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html
@@ -93,6 +93,7 @@
<option value="screen">Screen</option>
<option value="window">Window</option>
<option value="application">Application</option>
+ <option value="tab">Tab</option>
</select>
</div>
<div>
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
index e8d6ae0..4e287fc 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
@@ -138,12 +138,12 @@ public class RoomPanel extends BasePanel {
.put("interview", interview)
.put("audioOnly", r.isAudioOnly())
.put("showMicStatus", !r.getHiddenElements().contains(RoomElement.MicrophoneStatus))
- .put("exclusiveTitle", getString("1386"));
+ .put("exclusiveTitle", getString("1386"))
+ .put("chromeExtUrl", getChromeExtensionUrl());
if (!Strings.isEmpty(r.getRedirectURL()) && (ws.getSoapLogin() != null || ws.getInvitation() != null)) {
options.put("reloadUrl", r.getRedirectURL());
}
StringBuilder sb = new StringBuilder()
- .append("MuazKhan.init('").append(getChromeExtensionUrl()).append("');")
.append("Room.init(").append(options.toString(new NullStringer())).append(");")
.append(wb.getInitScript())
.append("Room.setSize();")
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/getScreenId.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/getScreenId.js
deleted file mode 100644
index ea96a98..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/getScreenId.js
+++ /dev/null
@@ -1,209 +0,0 @@
-// Licensed MIT
-// Last time updated on June 08, 2018
-
-// Latest file can be found here: https://cdn.webrtc-experiment.com/getScreenId.js
-
-// Muaz Khan - www.MuazKhan.com
-// MIT License - www.WebRTC-Experiment.com/licence
-// Documentation - https://github.com/muaz-khan/getScreenId.
-
-// ______________
-// getScreenId.js
-
-/*
-getScreenId(function (error, sourceId, screen_constraints) {
- // error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome'
- // sourceId == null || 'string' || 'firefox'
-
- if(microsoftEdge) {
- navigator.getDisplayMedia(screen_constraints).then(onSuccess, onFailure);
- }
- else {
- navigator.mediaDevices.getUserMedia(screen_constraints).then(onSuccess)catch(onFailure);
- }
-
-}, 'pass second parameter only if you want system audio');
-*/
-
-var MuazKhan = (function() {
- const self = {};
- let frameUrl = 'https://www.webrtc-experiment.com/getSourceId/';
-
- self.init = function(url) {
- frameUrl = url;
- }
- self.getScreenId = function(callback, custom_parameter) {
- window.addEventListener('message', onIFrameCallback);
-
- function onIFrameCallback(event) {
- if (!event.data) return;
-
- if (event.data.chromeMediaSourceId) {
- if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
- callback('permission-denied');
- } else {
- callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack));
- }
-
- // this event listener is no more needed
- window.removeEventListener('message', onIFrameCallback);
- }
-
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
-
- // this event listener is no more needed
- window.removeEventListener('message', onIFrameCallback);
- }
- }
-
- if(!custom_parameter) {
- setTimeout(postGetSourceIdMessage, 100);
- }
- else {
- setTimeout(function() {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- }
- };
-
- function getScreenConstraints(error, sourceId, canRequestAudioTrack) {
- var screen_constraints = {
- audio: false,
- video: {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
- maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
- },
- optional: []
- }
- };
-
- if(!!canRequestAudioTrack) {
- screen_constraints.audio = {
- mandatory: {
- chromeMediaSource: error ? 'screen' : 'desktop',
- // echoCancellation: true
- },
- optional: []
- };
- }
-
- if (sourceId) {
- screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
-
- if(screen_constraints.audio && screen_constraints.audio.mandatory) {
- screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId;
- }
- }
-
- return screen_constraints;
- }
-
- function postGetSourceIdMessage(custom_parameter) {
- if (!iframe) {
- loadIFrame(function() {
- postGetSourceIdMessage(custom_parameter);
- });
- return;
- }
-
- if (!iframe.isLoaded) {
- setTimeout(function() {
- postGetSourceIdMessage(custom_parameter);
- }, 100);
- return;
- }
-
- if(!custom_parameter) {
- iframe.contentWindow.postMessage({
- captureSourceId: true
- }, '*');
- }
- else if(!!custom_parameter.forEach) {
- iframe.contentWindow.postMessage({
- captureCustomSourceId: custom_parameter
- }, '*');
- }
- else {
- iframe.contentWindow.postMessage({
- captureSourceIdWithAudio: true
- }, '*');
- }
- }
-
- var iframe;
-
- // this function is used in RTCMultiConnection v3
- self.getScreenConstraints = function(callback) {
- loadIFrame(function() {
- self.getScreenId(function(error, sourceId, screen_constraints) {
- if(!screen_constraints) {
- screen_constraints = {
- video: true
- };
- }
-
- callback(error, screen_constraints.video);
- });
- });
- };
-
- function loadIFrame(loadCallback) {
- if (iframe) {
- loadCallback();
- return;
- }
-
- iframe = document.createElement('iframe');
- iframe.onload = function() {
- iframe.isLoaded = true;
-
- loadCallback();
- };
- iframe.src = frameUrl;
- iframe.style.display = 'none';
- (document.body || document.documentElement).appendChild(iframe);
- }
-
- self.getChromeExtensionStatus = function(callback) {
- // for Firefox:
- if (!!navigator.mozGetUserMedia) {
- callback('installed-enabled');
- return;
- }
-
- window.addEventListener('message', onIFrameCallback);
-
- function onIFrameCallback(event) {
- if (!event.data) return;
-
- if (event.data.chromeExtensionStatus) {
- callback(event.data.chromeExtensionStatus);
-
- // this event listener is no more needed
- window.removeEventListener('message', onIFrameCallback);
- }
- }
-
- setTimeout(postGetChromeExtensionStatusMessage, 100);
- };
-
- function postGetChromeExtensionStatusMessage() {
- if (!iframe) {
- loadIFrame(postGetChromeExtensionStatusMessage);
- return;
- }
-
- if (!iframe.isLoaded) {
- setTimeout(postGetChromeExtensionStatusMessage, 100);
- return;
- }
-
- iframe.contentWindow.postMessage({
- getChromeExtensionStatus: true
- }, '*');
- }
- return self;
-})();
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
index 992e0f3..286ef12 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
@@ -43,7 +43,7 @@ var Room = (function() {
if (typeof(Activities) !== 'undefined') {
Activities.init();
}
- Sharer.init();
+ Sharer.init(options.chromeExtUrl);
}
function _getSelfAudioClient() {
const vw = $('#video' + Room.getOptions().uid);
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js
index 63160b8..aec324e 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js
@@ -5,14 +5,19 @@ var SHARE_STOPED = 'stoped';
var Sharer = (function() {
const self = {};
let sharer, type, fps, sbtn, rbtn, width, height
- , shareState = SHARE_STOPED, recState = SHARE_STOPED;
+ , shareState = SHARE_STOPED, recState = SHARE_STOPED
+ , iframe, frameUrl = 'https://www.webrtc-experiment.com/getSourceId/';
- function _init() {
+ function _init(url) {
+ frameUrl = url;
sharer = $('#sharer').dialog({
width: 450
, autoOpen: false
});
- type = sharer.find('select.type').selectmenu({
+ type = sharer.find('select.type');
+ const b = kurentoUtils.WebRtcPeer.browser;
+ type.find('option[value="' + (b.name === 'Chrome' ? 'application' : 'tab') + '"]').remove();
+ type.selectmenu({
width: 150
, disabled: VideoUtil.isEdge()
});
@@ -105,6 +110,73 @@ var Sharer = (function() {
rbtn.button('enable');
}
}
+ // Following methods are based on
+ // Licensed MIT
+ // Last time updated on June 08, 2018
+ // Latest file can be found here: https://cdn.webrtc-experiment.com/getScreenId.js
+ // Muaz Khan - www.MuazKhan.com
+ function _getChromeConstraints(sd) {
+ return new Promise((resolve) => {
+ if (iframe) {
+ iframe.remove();
+ }
+ iframe = $('<iframe>')
+ .on('load', function() {
+ resolve();
+ })
+ .attr('src', frameUrl)
+ .hide();
+ $(document.body || document.documentElement).append(iframe);
+ }).then(() => {
+ return new Promise((resolve, reject) => {
+ window.addEventListener('message', _onIFrameCallback);
+
+ function _onIFrameCallback(event) {
+ if (!event.data) {
+ return;
+ }
+ if (event.data.chromeMediaSourceId) {
+ if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
+ reject('permission-denied');
+ } else {
+ resolve(_getScreenConstraints(sd, event.data.chromeMediaSourceId));
+ }
+ // this event listener is no more needed
+ window.removeEventListener('message', _onIFrameCallback);
+ }
+ if (event.data.chromeExtensionStatus) {
+ reject(event.data.chromeExtensionStatus);
+ // this event listener is no more needed
+ window.removeEventListener('message', _onIFrameCallback);
+ }
+ }
+
+ iframe[0].contentWindow.postMessage({
+ captureCustomSourceId: [sd.shareType]
+ }, '*');
+ });
+ });
+ };
+ function _getScreenConstraints(sd, sourceId) {
+ //Chrom screen constraints requires old school definition
+ const cnts = {
+ audio: false
+ , video: {
+ mandatory: {
+ maxWidth: sd.width
+ , maxHeight: sd.height
+ }
+ , optional: []
+ }
+ };
+ if (sourceId) {
+ cnts.video.mandatory = {
+ chromeMediaSourceId: sourceId
+ , chromeMediaSource: 'desktop'
+ };
+ }
+ return cnts;
+ }
self.init = _init;
self.open = function() {
@@ -119,5 +191,22 @@ var Sharer = (function() {
};
self.setShareState = _setShareState;
self.setRecState = _setRecState;
+ self.baseConstraints = function(sd) {
+ return {
+ video: {
+ frameRate: {
+ ideal: sd.fps
+ }
+ , width: {
+ ideal: sd.width
+ }
+ , height: {
+ ideal: sd.height
+ }
+ }
+ , audio: false
+ };
+ };
+ self.getChromeConstraints = _getChromeConstraints;
return self;
})();
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js
index 8b41b3f..4fb34cc 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js
@@ -45,40 +45,37 @@ var Video = (function() {
}
}
function _getScreenStream(msg, callback) {
+ function __handleScreenError(err) {
+ Sharer.setShareState(SHARE_STOPED);
+ Sharer.setRecState(SHARE_STOPED);
+ OmUtil.error(err);
+ }
const b = kurentoUtils.WebRtcPeer.browser;
+ let promise, cnts;
if (VideoUtil.isEdge() && b.major > 16) {
- const cnts = {
+ cnts = {
video: true
};
- navigator.getDisplayMedia(cnts).then(function(stream) {
- callback(msg, cnts, stream);
- }).catch(function(err) {
- Sharer.setShareState(SHARE_STOPED);
- Sharer.setRecState(SHARE_STOPED);
- OmUtil.error(err);
- });
+ promise = navigator.getDisplayMedia(cnts);
} else if (b.name === 'Firefox') {
// https://mozilla.github.io/webrtc-landing/gum_test.html
- const cnts = {
- video: {
- mediaSource: sd.shareType
- , frameRate: sd.fps //TODO ideal
- //TODO ideal width
- //TODO ideal height
- }};
- navigator.mediaDevices.getUserMedia(cnts).then(function(stream) {
- callback(msg, cnts, stream);
- }).catch(function(err) {
- Sharer.setShareState(SHARE_STOPED);
- Sharer.setRecState(SHARE_STOPED);
- OmUtil.error(err);
+ cnts = Sharer.baseConstraints(sd);
+ cnts.video.mediaSource = sd.shareType;
+ promise = navigator.mediaDevices.getUserMedia(cnts);
+ } else if (b.name === 'Chrome') {
+ promise = Sharer.getChromeConstraints(sd).then((_cnts) => {
+ cnts = _cnts;
+ return navigator.mediaDevices.getUserMedia(_cnts);
});
} else {
- Sharer.setShareState(SHARE_STOPED);
- Sharer.setRecState(SHARE_STOPED);
- Sharer.close();
- OmUtil.error('Screen-sharing is not supported in ' + b.name + '[' + b.major + ']');
+ promise = new Promise(() => {
+ Sharer.close();
+ throw 'Screen-sharing is not supported in ' + b.name + '[' + b.major + ']';
+ });
}
+ promise.then(function(stream) {
+ callback(msg, cnts, stream);
+ }).catch(__handleScreenError);
}
function _getVideoStream(msg, callback) {
VideoSettings.constraints(sd, function(cnts) {
diff --git a/pom.xml b/pom.xml
index 62e0fc5..82621c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,7 +114,7 @@
<!-- URL of the ASF SonarQube server -->
<sonar.host.url>https://builds.apache.org/analysis</sonar.host.url>
<!-- Exclude all generated code -->
- <sonar.exclusions>file:**/generated-sources/**, file:**/fabric.js, file:**/cssemoticons.js, file:**/kurento-utils.js, file:**/getScreenId.js, file:**/fileinput*.js, file:**/MathJax.js, file:**/network.js, file:**/jquery.dialogextend.js</sonar.exclusions>
+ <sonar.exclusions>file:**/generated-sources/**, file:**/fabric.js, file:**/cssemoticons.js, file:**/kurento-utils.js, file:**/fileinput*.js, file:**/MathJax.js, file:**/network.js, file:**/jquery.dialogextend.js</sonar.exclusions>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>