Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide a way to get access to photo content and to call closeAndCall… #107

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 122 additions & 36 deletions packages/mdg:camera/photo-browser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
var stream;
var closeAndCallback;
// merge defaults settings with Meteor settings if exists
var settings = (function(defaults) {
var settings =
{
camera: {
type: "back",
width: 640,
height: 480
},
quality: 80,
viewFinder: {
width: 320,
height: 240
}
};

if (!defaults) return settings;

if (defaults.camera) {
settings.camera = _.extend(settings.camera, defaults.camera);
}

if (defaults.quality && check(defaults.quality, Number)) {
settings.quality = defaults.quality;
}

if (defaults.viewFinder) {
settings.viewFinder = _.extend(settings.viewFinder, defaults.viewFinder);
}

return settings;
})(Meteor.settings.public.MeteorCamera);

var photo = new ReactiveVar(null);
var error = new ReactiveVar(null);
Expand All @@ -8,9 +38,7 @@ var waitingForPermission = new ReactiveVar(null);
var canvasWidth = 0;
var canvasHeight = 0;

var quality = 80;

Template.viewfinder.rendered = function() {
Template.viewfinder.onRendered(function() {
var template = this;

waitingForPermission.set(true);
Expand All @@ -19,13 +47,13 @@ Template.viewfinder.rendered = function() {

// stream webcam video to the <video> element
var success = function(newStream) {
stream = newStream;
MeteorCamera.setStream(newStream);

if (navigator.mozGetUserMedia) {
video.mozSrcObject = stream;
video.mozSrcObject = MeteorCamera.getStream();
} else {
var vendorURL = window.URL || window.webkitURL;
video.src = vendorURL.createObjectURL(stream);
video.src = vendorURL.createObjectURL(MeteorCamera.getStream());
}
video.play();

Expand All @@ -51,25 +79,71 @@ Template.viewfinder.rendered = function() {
return;
}

// initiate request for webcam
navigator.getUserMedia({
/**
* Hack to force Wished camera
*/
var wishedCameraSource;
var gotWishedCameraSource = function (sourceInfos) {
for (var i = 0; i < sourceInfos.length; ++i) {
var sourceInfo = sourceInfos[i];
var option = document.createElement('option');
option.value = sourceInfo.id;

console.log("sourceInfo", i, sourceInfo, sourceInfo.kind);

if (sourceInfo.kind == 'video') {
wishedCameraSource = sourceInfo;
var isWished = sourceInfo.label.match(settings.camera.type);
console.log("source id", wishedCameraSource, isWished);

if (isWished) {
console.log("wished found, break loop", wishedCameraSource, isWished);
i = sourceInfos.length;
return;
}
}
}

if (!wishedCameraSource) {
failure("VIDEO_NOT_SUPPORTED");
return;
}

// initiate request for webcam
var userMediaConfig = {
video: {
optional: [{
sourceId: wishedCameraSource.id
}]
},
audio: false
};

navigator.getUserMedia(userMediaConfig, success, failure);
};

// @TODO : be compliant with mobile IE/Safari/Other and not only Chrome
if (MediaStreamTrack) {
MediaStreamTrack.getSources(gotWishedCameraSource);
} else {
// initiate request for webcam
navigator.getUserMedia({
video: true,
audio: false
}, success, failure);
}, success, failure);
}

// resize viewfinder to a reasonable size, not necessarily photo size
var viewfinderWidth = 320;
var viewfinderHeight = 240;
var resized = false;

video.addEventListener('canplay', function() {
if (! resized) {
viewfinderHeight = video.videoHeight / (video.videoWidth / viewfinderWidth);
video.setAttribute('width', viewfinderWidth);
video.setAttribute('height', viewfinderHeight);
video.setAttribute('width', settings.viewFinder.width);
video.setAttribute('height', (video.videoHeight / (video.videoWidth / settings.viewFinder.width)));
resized = true;
}
}, false);
};
});

// is the current error a permission denied error?
var permissionDeniedError = function () {
Expand All @@ -81,7 +155,8 @@ var permissionDeniedError = function () {

// is the current error a browser not supported error?
var browserNotSupportedError = function () {
return error.get() && error.get() === "BROWSER_NOT_SUPPORTED";
return error.get() && error.get() === "BROWSER_NOT_SUPPORTED" ||
error.get() === "VIDEO_NOT_SUPPORTED"; // HTML5 feature ok, but no camera available on device
};

Template.camera.helpers({
Expand All @@ -97,24 +172,38 @@ Template.camera.helpers({

Template.camera.events({
"click .use-photo": function () {
closeAndCallback(null, photo.get());
MeteorCamera.closeAndCallback(null, photo.get());
},
"click .new-photo": function () {
photo.set(null);
},
"click .cancel": function () {
if (permissionDeniedError()) {
closeAndCallback(new Meteor.Error("permissionDenied", "Camera permissions were denied."));
MeteorCamera.closeAndCallback(new Meteor.Error("permissionDenied", "Camera permissions were denied."));
} else if (browserNotSupportedError()) {
closeAndCallback(new Meteor.Error("browserNotSupported", "This browser isn't supported."));
MeteorCamera.closeAndCallback(new Meteor.Error("browserNotSupported", "This browser isn't supported."));
} else if (error.get()) {
closeAndCallback(new Meteor.Error("unknownError", "There was an error while accessing the camera."));
MeteorCamera.closeAndCallback(new Meteor.Error("unknownError", "There was an error while accessing the camera."));
} else {
closeAndCallback(new Meteor.Error("cancel", "Photo taking was cancelled."));
MeteorCamera.closeAndCallback(new Meteor.Error("cancel", "Photo taking was cancelled."));
}

if (stream) {
stream.stop();
},

// This part could be moved outside this package and each dev could add its own logic, because with MeteorCamera object he gets all he needs
"change #videofallback": function(ev, tpl) {
var files = ev.currentTarget.files; // FileList
if(!files.length){
error.set("Please, click on browse button to select a file.");
return;
}

var reader = new FileReader();
reader.addEventListener("load", function () {
MeteorCamera.getPhoto().set(reader.result);
}, false);

if (files[0]) {
reader.readAsDataURL(files[0]);
}
}
});
Expand All @@ -127,9 +216,9 @@ Template.viewfinder.events({
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.getContext('2d').drawImage(video, 0, 0, canvasWidth, canvasHeight);
var data = canvas.toDataURL('image/jpeg', quality);
var data = canvas.toDataURL('image/jpeg', settings.quality);
photo.set(data);
stream.stop();
MeteorCamera.stopStream();
}
});

Expand Down Expand Up @@ -176,14 +265,11 @@ MeteorCamera.getPicture = function (options, callback) {
canvasHeight = Math.round(canvasHeight);

var view;

closeAndCallback = function () {
var originalArgs = arguments;
UI.remove(view);
photo.set(null);
callback.apply(null, originalArgs);
};


view = UI.renderWithData(Template.camera);
UI.insert(view, document.body);
MeteorCamera
.setView(view)
.setPhoto(photo)
.setCallback(callback);
};
Loading