1//Webcam funcs 2var SayCheese = (function () { 3 4 var SayCheese; 5 6 navigator.getUserMedia = (navigator.getUserMedia || 7 navigator.webkitGetUserMedia || 8 navigator.mozGetUserMedia || 9 navigator.msGetUserMedia || 10 false); 11 12 window.AudioContext = (window.AudioContext || 13 window.webkitAudioContext); 14 15 window.URL = (window.URL || 16 window.webkitURL); 17 18 var ERRORS = { 19 NOT_SUPPORTED: 'NOT_SUPPORTED', 20 AUDIO_NOT_SUPPORTED: 'AUDIO_NOT_SUPPORTED' 21 } 22 23 SayCheese = function SayCheese(element, options) { 24 this.snapshots = [], 25 this.video = null, 26 this.events = {}, 27 this.stream = null, 28 this.options = { 29 videoSource: null, 30 snapshots: true, 31 audio: false, 32 width: 320 33 }; 34 35 this.setOptions(options); 36 this.element = document.querySelector(element); 37 return this; 38 }; 39 40 SayCheese.prototype.on = function on(evt, handler) { 41 if (this.events.hasOwnProperty(evt) === false) { 42 this.events[evt] = []; 43 } 44 45 this.events[evt].push(handler) 46 }; 47 48 SayCheese.prototype.off = function off(evt, handler) { 49 this.events[evt] = this.events[evt].filter(function (h) { 50 return h !== handler; 51 }); 52 }; 53 54 SayCheese.prototype.trigger = function trigger(evt, data) { 55 if (this.events.hasOwnProperty(evt) === false) { 56 return false; 57 } 58 59 this.events[evt].forEach(function (handler) { 60 handler.call(this, data); 61 }.bind(this)); 62 }; 63 64 SayCheese.prototype.setOptions = function setOptions(options) { 65 // just use naïve, shallow cloning 66 for (var opt in options) { 67 this.options[opt] = options[opt]; 68 } 69 } 70 71 SayCheese.prototype.getStreamUrl = function getStreamUrl() { 72 if (window.URL && window.URL.createObjectURL) { 73 return window.URL.createObjectURL(this.stream); 74 } else { 75 return this.stream; 76 } 77 }; 78 79 SayCheese.prototype.createVideo = function createVideo() { 80 var width = this.options.width, 81 height = 0, 82 streaming = false; 83 84 this.video = document.createElement('video'); 85 this.video.autoplay = true; 86 87 this.video.addEventListener('canplay', function () { 88 if (!streaming) { 89 height = this.video.videoHeight / (this.video.videoWidth / width); 90 this.video.width = width; 91 this.video.height = height; 92 streaming = true; 93 return this.trigger('start'); 94 } 95 }.bind(this), false); 96 }; 97 98 SayCheese.prototype.linkAudio = function linkAudio() { 99 this.audioCtx = new window.AudioContext(); 100 this.audioStream = this.audioCtx.createMediaStreamSource(this.stream); 101 102 var biquadFilter = this.audioCtx.createBiquadFilter(); 103 104 this.audioStream.connect(biquadFilter); 105 biquadFilter.connect(this.audioCtx.destination); 106 }; 107 108 SayCheese.prototype.takeSnapshot = function takeSnapshot(width, height) { 109 if (this.options.snapshots === false) { 110 return false; 111 } 112 113 width = width || this.video.videoWidth; 114 height = height || this.video.videoHeight; 115 116 var snapshot = document.createElement('canvas'), 117 ctx = snapshot.getContext('2d'); 118 119 snapshot.width = width; 120 snapshot.height = height; 121 122 ctx.drawImage(this.video, 0, 0, width, height); 123 124 this.snapshots.push(snapshot); 125 this.trigger('snapshot', snapshot); 126 127 ctx = null; 128 }; 129 130 /* Start up the stream, if possible */ 131 SayCheese.prototype.start = function start() { 132 133 // fail fast and softly if browser not supported 134 if (navigator.getUserMedia === false) { 135 this.trigger('error', ERRORS.NOT_SUPPORTED); 136 return false; 137 } 138 139 var success = function success(stream) { 140 this.stream = stream; 141 this.createVideo(); 142 143 if (navigator.mozGetUserMedia) { 144 this.video.mozSrcObject = stream; 145 } else {
146 this.video.src = this.getStreamUrl(); 147 } 148 149 if (this.options.audio === true) { 150 try { 151 this.linkAudio(); 152 } catch (e) { 153 this.trigger('error', ERRORS.AUDIO_NOT_SUPPORTED); 154 } 155 } 156 157 this.element.appendChild(this.video); 158 this.video.play(); 159 160 this.trigger('success'); 161 }.bind(this); 162 163 /* error is also called when someone denies access */ 164 var error = function error(error) { 165 this.trigger('error', error); 166 }.bind(this); 167 168 return navigator.getUserMedia({ 169 video: { 170 optional: [{ 171 sourceId: this.options.videoSource 172 }] 173 }, audio: this.options.audio 174 }, success, error); 175 }; 176 177 SayCheese.prototype.stop = function stop() { 178 this.stream.stop(); 179 180 if (window.URL && window.URL.revokeObjectURL) { 181 window.URL.revokeObjectURL(this.video.src); 182 } 183 184 return this.trigger('stop'); 185 }; 186 187 return SayCheese; 188 189})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.