diff --git a/example/css/fonts.css b/example/css/fonts.css
index 9ee67c4..aa5a413 100644
--- a/example/css/fonts.css
+++ b/example/css/fonts.css
@@ -1 +1 @@
-@import url("http://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600");
+@import url("https://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600");
diff --git a/example/css/styles.css b/example/css/styles.css
index a39a361..8b5e047 100644
--- a/example/css/styles.css
+++ b/example/css/styles.css
@@ -15,7 +15,7 @@
/* Main Secondary color (2) */
/* Generated by Paletton.com ├é┬® 2002-2014 */
/* http://paletton.com */
-@import url("http://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600");
+@import url("https://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600");
/* line 1, ../sass/_viewport.scss */
#interactive.viewport {
width: 640px;
diff --git a/example/live_w_locator.html b/example/live_w_locator.html
index a8a3787..9fb8337 100644
--- a/example/live_w_locator.html
+++ b/example/live_w_locator.html
@@ -81,6 +81,11 @@
+
@@ -91,7 +96,7 @@
diff --git a/example/live_w_locator.js b/example/live_w_locator.js
index 327a0d8..412a14e 100644
--- a/example/live_w_locator.js
+++ b/example/live_w_locator.js
@@ -10,14 +10,14 @@ $(function() {
}
});
var App = {
- init : function() {
+ init: function() {
var self = this;
Quagga.init(this.state, function(err) {
if (err) {
return self.handleError(err);
}
- Quagga.registerResultCollector(resultCollector);
+ //Quagga.registerResultCollector(resultCollector);
App.attachListeners();
Quagga.start();
});
@@ -25,9 +25,31 @@ $(function() {
handleError: function(err) {
console.log(err);
},
+ initCameraSelection: function(){
+ var streamLabel = Quagga.CameraAccess.getActiveStreamLabel();
+
+ return Quagga.CameraAccess.enumerateVideoDevices()
+ .then(function(devices) {
+ function pruneText(text) {
+ return text.length > 30 ? text.substr(0, 30) : text;
+ }
+ var $deviceSelection = document.getElementById("deviceSelection");
+ while ($deviceSelection.firstChild) {
+ $deviceSelection.removeChild($deviceSelection.firstChild);
+ }
+ devices.forEach(function(device) {
+ var $option = document.createElement("option");
+ $option.value = device.deviceId || device.id;
+ $option.appendChild(document.createTextNode(pruneText(device.label || device.deviceId || device.id)));
+ $option.selected = streamLabel === device.label;
+ $deviceSelection.appendChild($option);
+ });
+ });
+ },
attachListeners: function() {
var self = this;
+ self.initCameraSelection();
$(".controls").on("click", "button.stop", function(e) {
e.preventDefault();
Quagga.stop();
@@ -64,7 +86,11 @@ $(function() {
return parts.reduce(function(o, key, i) {
if (setter && (i + 1) === depth) {
- o[key] = val;
+ if (typeof o[key] === "object" && typeof val === "object") {
+ Object.assign(o[key], val);
+ } else {
+ o[key] = val;
+ }
}
return key in o ? o[key] : {};
}, obj);
@@ -95,10 +121,15 @@ $(function() {
inputMapper: {
inputStream: {
constraints: function(value){
- var values = value.split('x');
+ if (/^(\d+)x(\d+)$/.test(value)) {
+ var values = value.split('x');
+ return {
+ width: {min: parseInt(values[0])},
+ height: {min: parseInt(values[1])}
+ };
+ }
return {
- width: {min: parseInt(values[0])},
- height: {min: parseInt(values[1])}
+ deviceId: value
};
}
},
diff --git a/karma-integration.conf.js b/karma-integration.conf.js
index b10e9f4..60a983d 100644
--- a/karma-integration.conf.js
+++ b/karma-integration.conf.js
@@ -37,7 +37,6 @@ module.exports = function(config) {
plugins: [
'karma-chrome-launcher',
'karma-mocha',
- 'karma-requirejs',
'karma-chai',
'karma-sinon',
'karma-sinon-chai',
diff --git a/karma.conf.js b/karma.conf.js
index 8c570ed..ce177aa 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -23,7 +23,7 @@ module.exports = function(config) {
}, {
test: /\.js$/,
include: path.resolve('src'),
- loader: 'babel-istanbul'
+ loader: 'babel-istanbul-loader'
}]
},
resolve: {
diff --git a/package.json b/package.json
index e858e20..222ead1 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"babel-cli": "^6.5.1",
"babel-core": "^6.21.0",
"babel-eslint": "^7.1.1",
+ "babel-istanbul": "^0.8.0",
"babel-istanbul-loader": "^0.1.0",
"babel-loader": "^6.2.10",
"babel-plugin-add-module-exports": "^0.2.1",
@@ -41,23 +42,23 @@
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"grunt-contrib-nodeunit": "^0.4.1",
- "grunt-karma": "^0.12.1",
+ "grunt-karma": "^2.0.0",
"isparta-loader": "^2.0.0",
- "karma": "^0.13.9",
+ "karma": "^1.3.0",
"karma-chai": "0.1.0",
- "karma-chrome-launcher": "^0.2.0",
- "karma-coverage": "^0.5.2",
+ "karma-chrome-launcher": "^2.0.0",
+ "karma-coverage": "^1.1.1",
"karma-firefox-launcher": "^0.1.7",
"karma-mocha": "~0.2.0",
"karma-phantomjs-launcher": "^0.2.1",
"karma-sinon": "^1.0.4",
"karma-sinon-chai": "^1.1.0",
"karma-source-map-support": "^1.1.0",
- "karma-webpack": "^1.7.0",
+ "karma-webpack": "^1.8.1",
"lolex": "^1.4.0",
"mocha": "^2.3.2",
"phantomjs": "^1.9.18",
- "sinon": "^1.16.1",
+ "sinon": "^1.17.7",
"sinon-chai": "^2.8.0",
"webpack": "^2.2.0-rc.3",
"webpack-sources": "^0.1.3"
diff --git a/server.pem b/server.pem
new file mode 100644
index 0000000..04fd185
--- /dev/null
+++ b/server.pem
@@ -0,0 +1,33 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQC9ORap3LvRegtrhRc8dLdH9Bp2QokcKEsWbtvyhtjisRRm2slK
+A6Q11McB/YTb7oImFfNaCX+7vdM1oVXVLJ0ekQaNljXG5Dy7DXEcT1V6gpN4xmZJ
+8f/KZ45VBINN0Ha74L7nS4kgImh5yvNolNr4IdlSjGf09kciFy8S3kPlGQIDAQAB
+AoGAYDlaxBCC1liY3Bl3IoA7//QrTL4zGUWIQaUoZmGag1UHifJycBf/9nv4o5N3
+b5wPRSzebofsE93JPTmI+3nPf62k5rS2xOo8swwOZc+f5/v0EnUNixD7P0jBiLVR
+B8kbMvNdNn33HuynW1/MSBFE0cfeDH2i8SVl+Z+fHYIUW10CQQD0yWB8xeM8AxYB
+/ZZWClem6gf1lQAYLzid3x51pkLqRFpX+rG251cSBUouE+kVO14j2xrBqCyyOwNu
+17eazy3DAkEAxeQdWP9b11ihKOf/kjXiczltLnBsotn6K9EEAe0QuH/6iXLm86mL
+ZiQe+TrY1GWbK3ns0sfXgNJ2aeaRkeZn8wJAWF5WedTKisCmckOEwTzslbJI+0w2
+A4UQkFWa3mgOIhpY7wfunhP35+aG+AlyDJspChKwHxdCQ3lwbNRtUPLYFwJBAK8G
+9QIbUbLlPB1/HOfH6xM4rp3NZ/idzQxmISJG+GwHHaPmUekfgyEDP7X2W4N4nsbU
+XyeLA8t32q4N9aDS5gsCQDHqhsXqnY6e4IEZrvf90l2V1PpnTKfEl/F5wye3g69G
+JN57scVUBHP/KKoyfge0fytWiQN/56KvWH+G5+N/JyA=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAkSgAwIBAgIJALUDN95Or7XlMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV
+BAYTAkFUMQ8wDQYDVQQIEwZTdHlyaWExDTALBgNVBAcTBEdyYXoxETAPBgNVBAoT
+CFF1YWdnYUpTMREwDwYDVQQDEwhxdWFnZ2FqczAeFw0xNzAxMDgxNjI5MjhaFw0x
+ODAxMDgxNjI5MjhaMFMxCzAJBgNVBAYTAkFUMQ8wDQYDVQQIEwZTdHlyaWExDTAL
+BgNVBAcTBEdyYXoxETAPBgNVBAoTCFF1YWdnYUpTMREwDwYDVQQDEwhxdWFnZ2Fq
+czCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvTkWqdy70XoLa4UXPHS3R/Qa
+dkKJHChLFm7b8obY4rEUZtrJSgOkNdTHAf2E2+6CJhXzWgl/u73TNaFV1SydHpEG
+jZY1xuQ8uw1xHE9VeoKTeMZmSfH/ymeOVQSDTdB2u+C+50uJICJoecrzaJTa+CHZ
+Uoxn9PZHIhcvEt5D5RkCAwEAAaOBtjCBszAdBgNVHQ4EFgQUYm5+uJVOOGiYa+Vx
+2o++VHyWkwIwgYMGA1UdIwR8MHqAFGJufriVTjhomGvlcdqPvlR8lpMCoVekVTBT
+MQswCQYDVQQGEwJBVDEPMA0GA1UECBMGU3R5cmlhMQ0wCwYDVQQHEwRHcmF6MREw
+DwYDVQQKEwhRdWFnZ2FKUzERMA8GA1UEAxMIcXVhZ2dhanOCCQC1AzfeTq+15TAM
+BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACyzC/CKL1mgTuNgFDuUf6u+
+YMnqlc9wcnEaFuvXnkSh6fT+qMZm188C/tlZwcWTrGmoCM0K6mX1TpHOjm8vbeXZ
+diezAVGIVN3VoHqm6yJldI2rgFI9r5BfwAWYC8XNjqnT3U6cm4k8iC7jmLC+dT9r
+Ysx2ucAF6lNHayekRmNq
+-----END CERTIFICATE-----
diff --git a/simple-https-server.py b/simple-https-server.py
new file mode 100644
index 0000000..6281cb5
--- /dev/null
+++ b/simple-https-server.py
@@ -0,0 +1,30 @@
+# taken from http://www.piware.de/2011/01/creating-an-https-server-in-python/
+# generate server.xml with the following command:
+# openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
+# run as follows:
+# python simple-https-server.py
+# then in your browser, visit:
+# https://localhost:4443
+
+import BaseHTTPServer, SimpleHTTPServer
+import ssl
+import sys, getopt
+
+host = 'localhost'
+port = 4443
+try:
+ opts, args = getopt.getopt(sys.argv[1:],"",["host=", "port="])
+except getopt.GetoptError:
+ print 'simple-https-server.py --host
--port '
+ sys.exit(2)
+for opt, arg in opts:
+ if opt in ("--host"):
+ host = arg
+ elif opt in ("--port"):
+ port = int(arg)
+print 'host is ', host
+print 'port is ', port
+
+httpd = BaseHTTPServer.HTTPServer((host, port), SimpleHTTPServer.SimpleHTTPRequestHandler)
+httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True)
+httpd.serve_forever()
diff --git a/src/common/typedefs.js b/src/common/typedefs.js
index 4d138b1..13d291b 100644
--- a/src/common/typedefs.js
+++ b/src/common/typedefs.js
@@ -24,3 +24,28 @@ Math.imul = Math.imul || function(a, b) {
// the final |0 converts the unsigned value into a signed value
return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
};
+
+if (typeof Object.assign !== 'function') {
+ Object.assign = function(target) { // .length of function is 2
+ 'use strict';
+ if (target === null) { // TypeError if undefined or null
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+
+ var to = Object(target);
+
+ for (var index = 1; index < arguments.length; index++) {
+ var nextSource = arguments[index];
+
+ if (nextSource !== null) { // Skip over if undefined or null
+ for (var nextKey in nextSource) {
+ // Avoid bugs when hasOwnProperty is shadowed
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+ to[nextKey] = nextSource[nextKey];
+ }
+ }
+ }
+ }
+ return to;
+ };
+}
diff --git a/src/input/camera_access.js b/src/input/camera_access.js
index b11bb6b..e871dda 100644
--- a/src/input/camera_access.js
+++ b/src/input/camera_access.js
@@ -109,6 +109,11 @@ export function pickConstraints(videoConstraints) {
return Promise.resolve(normalizedConstraints);
}
+function enumerateVideoDevices() {
+ return enumerateDevices()
+ .then(devices => devices.filter(device => device.kind === 'videoinput'));
+}
+
export default {
request: function(video, videoConstraints) {
return pickConstraints(videoConstraints)
@@ -120,5 +125,14 @@ export default {
tracks[0].stop();
}
streamRef = null;
+ },
+ enumerateVideoDevices,
+ getActiveStreamLabel: function() {
+ if (streamRef) {
+ const tracks = streamRef.getVideoTracks();
+ if (tracks && tracks.length) {
+ return tracks[0].label;
+ }
+ }
}
};
diff --git a/src/quagga.js b/src/quagga.js
index 2bfa64d..3af98fa 100644
--- a/src/quagga.js
+++ b/src/quagga.js
@@ -539,5 +539,6 @@ export default {
},
ImageWrapper: ImageWrapper,
ImageDebug: ImageDebug,
- ResultCollector: ResultCollector
+ ResultCollector: ResultCollector,
+ CameraAccess: CameraAccess,
};