Преглед изворни кода

Separates the logic for obtaining a screen capture from the logic

for switching between camera and screen.
master
Boris Grozev пре 10 година
родитељ
комит
e5184358c2
2 измењених фајлова са 290 додато и 265 уклоњено
  1. 265
    0
      modules/desktopsharing/ScreenObtainer.js
  2. 25
    265
      modules/desktopsharing/desktopsharing.js

+ 265
- 0
modules/desktopsharing/ScreenObtainer.js Прегледај датотеку

@@ -0,0 +1,265 @@
1
+/* global config, APP, chrome, $, alert */
2
+/* jshint -W003 */
3
+var RTCBrowserType = require("../RTC/RTCBrowserType");
4
+var AdapterJS = require("../RTC/adapter.screenshare");
5
+
6
+/**
7
+ * Indicates whether the Chrome desktop sharing extension is installed.
8
+ * @type {boolean}
9
+ */
10
+var chromeExtInstalled = false;
11
+/**
12
+ * Indicates whether an update of the Chrome desktop sharing extension is
13
+ * required.
14
+ * @type {boolean}
15
+ */
16
+var chromeExtUpdateRequired = false;
17
+
18
+/**
19
+ * Handles obtaining a stream from a screen capture on different browsers.
20
+ */
21
+function ScreenObtainer(){
22
+}
23
+
24
+/**
25
+ * Initializes the function used to obtain a screen capture (this.obtainStream).
26
+ *
27
+ * If the browser is Chrome, it uses the value of 'config.desktopSharing' to
28
+ * decide whether to use the a Chrome extension (if the value is 'ext'), use
29
+ * the "screen" media source (if the value is 'webrtc'), or disable screen
30
+ * capture (if the value is other).
31
+ * Note that for the "screen" media source to work the
32
+ * 'chrome://flags/#enable-usermedia-screen-capture' flag must be set.
33
+ */
34
+ScreenObtainer.prototype.init = function() {
35
+    var obtainDesktopStream = null;
36
+
37
+    // When TemasysWebRTC plugin is used we always use getUserMedia, so we don't
38
+    // care about the value of config.desktopSharing.
39
+    if (RTCBrowserType.isTemasysPluginUsed()) {
40
+        if (!AdapterJS.WebRTCPlugin.plugin.HasScreensharingFeature) {
41
+            console.info("Screensharing not supported by this plugin version");
42
+        } else if (!AdapterJS.WebRTCPlugin.plugin.isScreensharingAvailable) {
43
+            console.info(
44
+                "Screensharing not available with Temasys plugin on this site");
45
+        } else {
46
+            obtainDesktopStream = obtainWebRTCScreen;
47
+            console.info("Using Temasys plugin for desktop sharing");
48
+        }
49
+    } else if (RTCBrowserType.isChrome()) {
50
+        if (config.desktopSharing == "ext") {
51
+            if (RTCBrowserType.getChromeVersion() >= 34) {
52
+                obtainDesktopStream = obtainScreenFromExtension;
53
+                console.info("Using Chrome extension for desktop sharing");
54
+                initChromeExtension();
55
+            } else {
56
+                console.info("Chrome extension not supported until ver 34");
57
+            }
58
+        } else if (config.desktopSharing == "webrtc") {
59
+            obtainDesktopStream = obtainWebRTCScreen;
60
+            console.info("Using Chrome WebRTC for desktop sharing");
61
+        }
62
+    } else if (RTCBrowserType.isFirefox()) {
63
+        obtainDesktopStream = obtainWebRTCScreen;
64
+    }
65
+
66
+    if (!obtainDesktopStream) {
67
+        console.info("Desktop sharing disabled");
68
+    }
69
+
70
+    ScreenObtainer.prototype.obtainStream = obtainDesktopStream.bind(this);
71
+};
72
+
73
+ScreenObtainer.prototype.obtainStream = null;
74
+
75
+/**
76
+ * Checks whether obtaining a screen capture is supported in the current
77
+ * environment.
78
+ * @returns {boolean}
79
+ */
80
+ScreenObtainer.prototype.isSupported = function() {
81
+    return !!this.obtainStream;
82
+};
83
+
84
+/**
85
+ * Obtains a desktop stream using getUserMedia.
86
+ * For this to work on Chrome, the
87
+ * 'chrome://flags/#enable-usermedia-screen-capture' flag must be enabled.
88
+ *
89
+ * On firefox, the document's domain must be white-listed in the
90
+ * 'media.getusermedia.screensharing.allowed_domains' preference in
91
+ * 'about:config'.
92
+ */
93
+function obtainWebRTCScreen(streamCallback, failCallback) {
94
+    APP.RTC.getUserMediaWithConstraints(
95
+        ['screen'],
96
+        streamCallback,
97
+        failCallback
98
+    );
99
+}
100
+
101
+/**
102
+ * Constructs inline install URL for Chrome desktop streaming extension.
103
+ * The 'chromeExtensionId' must be defined in config.js.
104
+ * @returns {string}
105
+ */
106
+function getWebStoreInstallUrl()
107
+{
108
+    return "https://chrome.google.com/webstore/detail/" +
109
+        config.chromeExtensionId;
110
+}
111
+
112
+/**
113
+ * Checks whether an update of the Chrome extension is required.
114
+ * @param minVersion minimal required version
115
+ * @param extVersion current extension version
116
+ * @returns {boolean}
117
+ */
118
+function isUpdateRequired(minVersion, extVersion) {
119
+    try {
120
+        var s1 = minVersion.split('.');
121
+        var s2 = extVersion.split('.');
122
+
123
+        var len = Math.max(s1.length, s2.length);
124
+        for (var i = 0; i < len; i++) {
125
+            var n1 = 0,
126
+                n2 = 0;
127
+
128
+            if (i < s1.length)
129
+                n1 = parseInt(s1[i]);
130
+            if (i < s2.length)
131
+                n2 = parseInt(s2[i]);
132
+
133
+            if (isNaN(n1) || isNaN(n2)) {
134
+                return true;
135
+            } else if (n1 !== n2) {
136
+                return n1 > n2;
137
+            }
138
+        }
139
+
140
+        // will happen if both versions have identical numbers in
141
+        // their components (even if one of them is longer, has more components)
142
+        return false;
143
+    }
144
+    catch (e) {
145
+        console.error("Failed to parse extension version", e);
146
+        APP.UI.messageHandler.showError("dialog.error",
147
+            "dialog.detectext");
148
+        return true;
149
+    }
150
+}
151
+
152
+function checkChromeExtInstalled(callback) {
153
+    if (!chrome || !chrome.runtime) {
154
+        // No API, so no extension for sure
155
+        callback(false, false);
156
+        return;
157
+    }
158
+    chrome.runtime.sendMessage(
159
+        config.chromeExtensionId,
160
+        { getVersion: true },
161
+        function (response) {
162
+            if (!response || !response.version) {
163
+                // Communication failure - assume that no endpoint exists
164
+                console.warn(
165
+                    "Extension not installed?: ", chrome.runtime.lastError);
166
+                callback(false, false);
167
+                return;
168
+            }
169
+            // Check installed extension version
170
+            var extVersion = response.version;
171
+            console.log('Extension version is: ' + extVersion);
172
+            var updateRequired
173
+                = isUpdateRequired(config.minChromeExtVersion, extVersion);
174
+            callback(!updateRequired, updateRequired);
175
+        }
176
+    );
177
+}
178
+
179
+function doGetStreamFromExtension(streamCallback, failCallback) {
180
+    // Sends 'getStream' msg to the extension.
181
+    // Extension id must be defined in the config.
182
+    chrome.runtime.sendMessage(
183
+        config.chromeExtensionId,
184
+        { getStream: true, sources: config.desktopSharingSources },
185
+        function (response) {
186
+            if (!response) {
187
+                failCallback(chrome.runtime.lastError);
188
+                return;
189
+            }
190
+            console.log("Response from extension: " + response);
191
+            if (response.streamId) {
192
+                APP.RTC.getUserMediaWithConstraints(
193
+                    ['desktop'],
194
+                    function (stream) {
195
+                        streamCallback(stream);
196
+                    },
197
+                    failCallback,
198
+                    null, null, null,
199
+                    response.streamId);
200
+            } else {
201
+                failCallback("Extension failed to get the stream");
202
+            }
203
+        }
204
+    );
205
+}
206
+
207
+/**
208
+ * Asks Chrome extension to call chooseDesktopMedia and gets chrome 'desktop'
209
+ * stream for returned stream token.
210
+ */
211
+function obtainScreenFromExtension(streamCallback, failCallback) {
212
+    if (chromeExtInstalled) {
213
+        doGetStreamFromExtension(streamCallback, failCallback);
214
+    } else {
215
+        if (chromeExtUpdateRequired) {
216
+            alert(
217
+                'Jitsi Desktop Streamer requires update. ' +
218
+                'Changes will take effect after next Chrome restart.');
219
+        }
220
+
221
+        chrome.webstore.install(
222
+            getWebStoreInstallUrl(),
223
+            function (arg) {
224
+                console.log("Extension installed successfully", arg);
225
+                chromeExtInstalled = true;
226
+                // We need to give a moment for the endpoint to become available
227
+                window.setTimeout(function () {
228
+                    doGetStreamFromExtension(streamCallback, failCallback);
229
+                }, 500);
230
+            },
231
+            function (arg) {
232
+                console.log("Failed to install the extension", arg);
233
+                failCallback(arg);
234
+                APP.UI.messageHandler.showError("dialog.error",
235
+                    "dialog.failtoinstall");
236
+            }
237
+        );
238
+    }
239
+}
240
+
241
+/**
242
+ * Initializes <link rel=chrome-webstore-item /> with extension id set in
243
+ * config.js to support inline installs. Host site must be selected as main
244
+ * website of published extension.
245
+ */
246
+function initInlineInstalls()
247
+{
248
+    $("link[rel=chrome-webstore-item]").attr("href", getWebStoreInstallUrl());
249
+}
250
+
251
+function initChromeExtension() {
252
+    // Initialize Chrome extension inline installs
253
+    initInlineInstalls();
254
+    // Check if extension is installed
255
+    checkChromeExtInstalled(function (installed, updateRequired) {
256
+        chromeExtInstalled = installed;
257
+        chromeExtUpdateRequired = updateRequired;
258
+        console.info(
259
+            "Chrome extension installed: " + chromeExtInstalled +
260
+            " updateRequired: " + chromeExtUpdateRequired);
261
+    });
262
+}
263
+
264
+
265
+module.exports = ScreenObtainer;

+ 25
- 265
modules/desktopsharing/desktopsharing.js Прегледај датотеку

@@ -1,17 +1,17 @@
1
-/* global $, alert, APP, changeLocalVideo, chrome, config, getConferenceHandler,
2
- getUserMediaWithConstraints */
3
-var AdapterJS = require("../RTC/adapter.screenshare");
1
+/* global APP, config */
4 2
 var EventEmitter = require("events");
5 3
 var DesktopSharingEventTypes
6 4
     = require("../../service/desktopsharing/DesktopSharingEventTypes");
7 5
 var RTCBrowserType = require("../RTC/RTCBrowserType");
8 6
 var RTCEvents = require("../../service/RTC/RTCEvents");
7
+var ScreenObtainer = require("./ScreenObtainer");
9 8
 
10 9
 /**
11
- * Indicates that desktop stream is currently in use(for toggle purpose).
10
+ * Indicates that desktop stream is currently in use (for toggle purpose).
12 11
  * @type {boolean}
13 12
  */
14 13
 var isUsingScreenStream = false;
14
+
15 15
 /**
16 16
  * Indicates that switch stream operation is in progress and prevent from
17 17
  * triggering new events.
@@ -20,251 +20,22 @@ var isUsingScreenStream = false;
20 20
 var switchInProgress = false;
21 21
 
22 22
 /**
23
- * Method used to get screen sharing stream.
24
- *
25
- * @type {function (stream_callback, failure_callback}
26
- */
27
-var obtainDesktopStream = null;
28
-
29
-/**
30
- * Indicates whether desktop sharing extension is installed.
31
- * @type {boolean}
32
- */
33
-var extInstalled = false;
34
-
35
-/**
36
- * Indicates whether update of desktop sharing extension is required.
37
- * @type {boolean}
23
+ * Used to obtain the screen sharing stream from the browser.
38 24
  */
39
-var extUpdateRequired = false;
25
+var screenObtainer = new ScreenObtainer();
40 26
 
41 27
 var eventEmitter = new EventEmitter();
42 28
 
43
-/**
44
- * Method obtains desktop stream from WebRTC 'screen' source.
45
- * Flag 'chrome://flags/#enable-usermedia-screen-capture' must be enabled.
46
- */
47
-function obtainWebRTCScreen(streamCallback, failCallback) {
48
-    APP.RTC.getUserMediaWithConstraints(
49
-        ['screen'],
50
-        streamCallback,
51
-        failCallback
52
-    );
53
-}
54
-
55
-/**
56
- * Constructs inline install URL for Chrome desktop streaming extension.
57
- * The 'chromeExtensionId' must be defined in config.js.
58
- * @returns {string}
59
- */
60
-function getWebStoreInstallUrl()
61
-{
62
-    return "https://chrome.google.com/webstore/detail/" +
63
-        config.chromeExtensionId;
64
-}
65
-
66
-/**
67
- * Checks whether extension update is required.
68
- * @param minVersion minimal required version
69
- * @param extVersion current extension version
70
- * @returns {boolean}
71
- */
72
-function isUpdateRequired(minVersion, extVersion)
73
-{
74
-    try
75
-    {
76
-        var s1 = minVersion.split('.');
77
-        var s2 = extVersion.split('.');
78
-
79
-        var len = Math.max(s1.length, s2.length);
80
-        for (var i = 0; i < len; i++)
81
-        {
82
-            var n1 = 0,
83
-                n2 = 0;
84
-
85
-            if (i < s1.length)
86
-                n1 = parseInt(s1[i]);
87
-            if (i < s2.length)
88
-                n2 = parseInt(s2[i]);
89
-
90
-            if (isNaN(n1) || isNaN(n2))
91
-            {
92
-                return true;
93
-            }
94
-            else if (n1 !== n2)
95
-            {
96
-                return n1 > n2;
97
-            }
98
-        }
99
-
100
-        // will happen if boths version has identical numbers in
101
-        // their components (even if one of them is longer, has more components)
102
-        return false;
103
-    }
104
-    catch (e)
105
-    {
106
-        console.error("Failed to parse extension version", e);
107
-        APP.UI.messageHandler.showError("dialog.error",
108
-            "dialog.detectext");
109
-        return true;
110
-    }
111
-}
112
-
113
-function checkChromeExtInstalled(callback) {
114
-    if (!chrome.runtime) {
115
-        // No API, so no extension for sure
116
-        callback(false, false);
117
-        return;
118
-    }
119
-    chrome.runtime.sendMessage(
120
-        config.chromeExtensionId,
121
-        { getVersion: true },
122
-        function (response) {
123
-            if (!response || !response.version) {
124
-                // Communication failure - assume that no endpoint exists
125
-                console.warn(
126
-                    "Extension not installed?: ", chrome.runtime.lastError);
127
-                callback(false, false);
128
-                return;
129
-            }
130
-            // Check installed extension version
131
-            var extVersion = response.version;
132
-            console.log('Extension version is: ' + extVersion);
133
-            var updateRequired
134
-                = isUpdateRequired(config.minChromeExtVersion, extVersion);
135
-            callback(!updateRequired, updateRequired);
136
-        }
137
-    );
138
-}
139
-
140
-function doGetStreamFromExtension(streamCallback, failCallback) {
141
-    // Sends 'getStream' msg to the extension.
142
-    // Extension id must be defined in the config.
143
-    chrome.runtime.sendMessage(
144
-        config.chromeExtensionId,
145
-        { getStream: true, sources: config.desktopSharingSources },
146
-        function (response) {
147
-            if (!response) {
148
-                failCallback(chrome.runtime.lastError);
149
-                return;
150
-            }
151
-            console.log("Response from extension: " + response);
152
-            if (response.streamId) {
153
-                APP.RTC.getUserMediaWithConstraints(
154
-                    ['desktop'],
155
-                    function (stream) {
156
-                        streamCallback(stream);
157
-                    },
158
-                    failCallback,
159
-                    null, null, null,
160
-                    response.streamId);
161
-            } else {
162
-                failCallback("Extension failed to get the stream");
163
-            }
164
-        }
165
-    );
166
-}
167
-/**
168
- * Asks Chrome extension to call chooseDesktopMedia and gets chrome 'desktop'
169
- * stream for returned stream token.
170
- */
171
-function obtainScreenFromExtension(streamCallback, failCallback) {
172
-    if (extInstalled) {
173
-        doGetStreamFromExtension(streamCallback, failCallback);
174
-    } else {
175
-        if (extUpdateRequired) {
176
-            alert(
177
-                'Jitsi Desktop Streamer requires update. ' +
178
-                'Changes will take effect after next Chrome restart.');
179
-        }
180
-
181
-        chrome.webstore.install(
182
-            getWebStoreInstallUrl(),
183
-            function (arg) {
184
-                console.log("Extension installed successfully", arg);
185
-                extInstalled = true;
186
-                // We need to give a moment for the endpoint to become available
187
-                window.setTimeout(function () {
188
-                    doGetStreamFromExtension(streamCallback, failCallback);
189
-                }, 500);
190
-            },
191
-            function (arg) {
192
-                console.log("Failed to install the extension", arg);
193
-                failCallback(arg);
194
-                APP.UI.messageHandler.showError("dialog.error",
195
-                    "dialog.failtoinstall");
196
-            }
197
-        );
198
-    }
199
-}
200
-
201
-/**
202
- * Call this method to toggle desktop sharing feature.
203
- * @param method pass "ext" to use chrome extension for desktop capture(chrome
204
- *        extension required), pass "webrtc" to use WebRTC "screen" desktop
205
- *        source('chrome://flags/#enable-usermedia-screen-capture' must be
206
- *        enabled), pass any other string or nothing in order to disable this
207
- *        feature completely.
208
- */
209
-function setDesktopSharing(method) {
210
-
211
-    obtainDesktopStream = null;
212
-
213
-    // When TemasysWebRTC plugin is used we always use getUserMedia, so we don't
214
-    // care about 'method' parameter
215
-    if (RTCBrowserType.isTemasysPluginUsed()) {
216
-        if (!AdapterJS.WebRTCPlugin.plugin.HasScreensharingFeature) {
217
-            console.info("Screensharing not supported by this plugin version");
218
-        } else if (!AdapterJS.WebRTCPlugin.plugin.isScreensharingAvailable) {
219
-            console.info(
220
-            "Screensharing not available with Temasys plugin on this site");
221
-        } else {
222
-            obtainDesktopStream = obtainWebRTCScreen;
223
-            console.info("Using Temasys plugin for desktop sharing");
224
-        }
225
-    } else if (RTCBrowserType.isChrome()) {
226
-        if (method == "ext") {
227
-            if (RTCBrowserType.getChromeVersion() >= 34) {
228
-                obtainDesktopStream = obtainScreenFromExtension;
229
-                console.info("Using Chrome extension for desktop sharing");
230
-                initChromeExtension();
231
-            } else {
232
-                console.info("Chrome extension not supported until ver 34");
233
-            }
234
-        } else if (method == "webrtc") {
235
-            obtainDesktopStream = obtainWebRTCScreen;
236
-            console.info("Using Chrome WebRTC for desktop sharing");
237
-        }
238
-    } else if (RTCBrowserType.isFirefox()) {
239
-        obtainDesktopStream = obtainWebRTCScreen;
240
-    }
241
-
242
-    if (!obtainDesktopStream) {
243
-        console.info("Desktop sharing disabled");
244
-    }
245
-}
246
-
247
-/**
248
- * Initializes <link rel=chrome-webstore-item /> with extension id set in
249
- * config.js to support inline installs. Host site must be selected as main
250
- * website of published extension.
251
- */
252
-function initInlineInstalls()
253
-{
254
-    $("link[rel=chrome-webstore-item]").attr("href", getWebStoreInstallUrl());
29
+function streamSwitchDone() {
30
+    switchInProgress = false;
31
+    eventEmitter.emit(
32
+        DesktopSharingEventTypes.SWITCHING_DONE,
33
+        isUsingScreenStream);
255 34
 }
256 35
 
257
-function initChromeExtension() {
258
-    // Initialize Chrome extension inline installs
259
-    initInlineInstalls();
260
-    // Check if extension is installed
261
-    checkChromeExtInstalled(function (installed, updateRequired) {
262
-        extInstalled = installed;
263
-        extUpdateRequired = updateRequired;
264
-        console.info(
265
-            "Chrome extension installed: " + extInstalled +
266
-            " updateRequired: " + extUpdateRequired);
267
-    });
36
+function newStreamCreated(stream) {
37
+    eventEmitter.emit(DesktopSharingEventTypes.NEW_STREAM_CREATED,
38
+        stream, isUsingScreenStream, streamSwitchDone);
268 39
 }
269 40
 
270 41
 function getVideoStreamFailed(error) {
@@ -279,19 +50,6 @@ function getDesktopStreamFailed(error) {
279 50
     switchInProgress = false;
280 51
 }
281 52
 
282
-function streamSwitchDone() {
283
-    switchInProgress = false;
284
-    eventEmitter.emit(
285
-        DesktopSharingEventTypes.SWITCHING_DONE,
286
-        isUsingScreenStream);
287
-}
288
-
289
-function newStreamCreated(stream)
290
-{
291
-    eventEmitter.emit(DesktopSharingEventTypes.NEW_STREAM_CREATED,
292
-        stream, isUsingScreenStream, streamSwitchDone);
293
-}
294
-
295 53
 function onEndedHandler(stream) {
296 54
     if (!switchInProgress && isUsingScreenStream) {
297 55
         APP.desktopsharing.toggleScreenSharing();
@@ -306,9 +64,7 @@ function onEndedHandler(stream) {
306 64
 
307 65
 // Called when RTC finishes initialization
308 66
 function onWebRtcReady() {
309
-
310
-    setDesktopSharing(config.desktopSharing);
311
-
67
+    screenObtainer.init();
312 68
     eventEmitter.emit(DesktopSharingEventTypes.INIT);
313 69
 }
314 70
 
@@ -321,7 +77,9 @@ module.exports = {
321 77
      * @returns {boolean} <tt>true</tt> if desktop sharing feature is available
322 78
      *          and enabled.
323 79
      */
324
-    isDesktopSharingEnabled: function () { return !!obtainDesktopStream; },
80
+    isDesktopSharingEnabled: function () {
81
+        return screenObtainer.isSupported();
82
+    },
325 83
     
326 84
     init: function () {
327 85
         APP.RTC.addListener(RTCEvents.RTC_READY, onWebRtcReady);
@@ -339,16 +97,18 @@ module.exports = {
339 97
      * Toggles screen sharing.
340 98
      */
341 99
     toggleScreenSharing: function () {
342
-        if (switchInProgress || !obtainDesktopStream) {
343
-            console.warn("Switch in progress or no method defined");
100
+        if (switchInProgress) {
101
+            console.warn("Switch in progress.");
102
+            return;
103
+        } else if (!screenObtainer.isSupported()) {
104
+            console.warn("Cannot toggle screen sharing: not supported.");
344 105
             return;
345 106
         }
346 107
         switchInProgress = true;
347 108
 
348
-        if (!isUsingScreenStream)
349
-        {
109
+        if (!isUsingScreenStream) {
350 110
             // Switch to desktop stream
351
-            obtainDesktopStream(
111
+            screenObtainer.obtainStream(
352 112
                 function (stream) {
353 113
                     // We now use screen stream
354 114
                     isUsingScreenStream = true;

Loading…
Откажи
Сачувај