diff --git a/.gitignore b/.gitignore
index 0e06d079c..c84fe43db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,6 @@ frontend/DEV/*
.DS_Store
*/.DS_Store
segfault.log/*
+.idea
+work
+logs
diff --git a/README.md b/README.md
index 74d63bd42..a0ed3cdb4 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,33 @@
+This fork aims to enhance the stability and predictability of the VIEW intervalometer, refine its ramping algorithms, and eliminate bugs. I can only provide support for Sony cameras as I have tested it solely on the Sony A6300 and A6600.
+
+Currently, I have a general understanding of how VIEW operates, the algorithms involved, and why it may sometimes produce extreme light or dark exposures. At present, it appears that the estimated ramping needs adjustment, and issues with the histogram and luminance calculations are causing inaccuracies. Highlight protection calculations may result in underexposure, so it's advisable to disable this feature. Further investigation is necessary.
+
+Please note that the releases are provided 'AS IS.' During development, I inadvertently caused a soft brick on my VIEW and spent several anxious nights trying to recover it. The provided releases have been tested on my own device. Simply download the archive onto your SD card and install the update via the 'Firmware Update' menu. In case of any issues, consult the troubleshooting section in the official documentation to revert to previous versions. Feel free to reach out to discuss ideas, VIEW development, and future enhancements.
+## Changes
+### 1.8.52
+* Implemented a new method for calculating the histogram. Past experiences highlighted many overexposed timelapses due to incorrect histogram calculations, leading to failures in actual highlights protection algorithms. Day and night luminance calculations are now more precise, based on the YUV colorspace formula. Adjust your luminance references accordingly for `day` and `night`.
+* Revised the `sunrise ramping algorithm`. Previously, the algorithm sometimes hesitated to adjust to the increasing light levels in the mornings. It has been modified to ramp faster towards brighter conditions.
+* Enhanced camera exposure values in balance mode (`S=A=I`). If previous change in one direction was of the same parameter, then the opposite direction change will be of the same parameter. Except iso in up direction, we want it to ramp as quickly as possible.
+For instance, transitioning to darkness with the previous algorithm: `6s 5.6f`, `8s 5.6f`(s), `8s 4f`(a), `10s 4f`(s) -> transitioning light -> `10s 5.6f`(a) -> transitioning dark -> `12s 5.6f`(s). Notice that the shutter and aperture change sequentially, which can lead to a peculiar situation where you may end up with a longer shutter speed instead of a wider aperture at night.
+ The new algorithm will maintain the adjusted parameter sequence: `6s 5.6f`, `8s 5.6f`(s), `8s 4f`(a), `10s 4f`(s) -> transitioning light -> `8s 4f`(s) -> transitioning dark -> `10s 4f`(s). Notice that the `aperture remains unchanged` as the EV decreases and increases.
+* In balance mode (`S=A=I`), ISO will consistently be the last parameter to change when transitioning to darker settings and the first parameter to adjust when transitioning to brighter settings.
+
+
+## TODO:
+* video advance in clips via knob
+* histogram and luminance in capture and exposure screen
+* new mobile app
+* new cameras?
+* make aperture changes not so quick as it is now, but scaled to the number of shutter changes
+
+------------------------------------------
-# Timelapse+ VIEW Intervalometer
+### Timelapse+ VIEW Intervalometer
📷 Innovative solutions for time-lapse.
-## Docs
+### Docs
**[Official VIEW documentation](http://docs.view.tl/)**
diff --git a/camera/camera.js b/camera/camera.js
index 212c3ff32..545593cb3 100644
--- a/camera/camera.js
+++ b/camera/camera.js
@@ -286,7 +286,7 @@ camera.setEv = function(ev, options, cb) {
if (!options) options = {};
var doSet = function(settings) {
var shutter = settings.details ? settings.details.shutter : settings.shutter;
- var aperture = settings.details ? settings.details.aperture : settings.sperture;
+ var aperture = settings.details ? settings.details.aperture : settings.aperture;
var iso = settings.details ? settings.details.iso : settings.iso;
var apertureEnabled = false;
diff --git a/camera/image/image.js b/camera/image/image.js
index 40e03e070..1314d23e4 100644
--- a/camera/image/image.js
+++ b/camera/image/image.js
@@ -83,7 +83,7 @@ exports.writeXMP = function(fileName, exposureCompensation, description, name, l
\n\
\n\
';
-
+
var gpsData = "";
if(lat != null && lat != null) {
if(lat < 0) {
@@ -215,7 +215,7 @@ exports.downsizeJpeg = function(jpeg, size, crop, callback) {
exports.downsizeJpegSharp = function(jpeg, size, crop, exposureCompensation, callback) {
return exports.downsizeJpeg(jpeg, size, crop, callback);
-
+
console.log("IMAGE: (sharp) Resizing photo...");
@@ -329,7 +329,7 @@ exports.histogramArray = function(jpegBuffer, callback) {
fs.writeFile(TMP_IMAGE_THUMB, new Buffer(jpegBuffer), function() {
luminance.read(TMP_IMAGE_THUMB, function(err, res) {
var histArray = null;
- if(!err && res && res.histogram) histArray = res.histogram;
+ if(!err && res && res.histogram) histArray = res.histogram;
if (callback) callback(err, histArray);
});
/*pixelr.read(TMP_IMAGE_THUMB, "jpeg", function(err, data) {
@@ -358,10 +358,10 @@ exports.exposureValue = function(jpegBuffer, callback) {
var lum = 0;
if(!err && res && res.luminance) {
lum = res.luminance;
- if(res.clipped && highlightProtection) {
+ /* if(res.clipped && highlightProtection) {
console.log("IMAGE: Compensating for clipped highlights: ", res.clipped * highlightProtection);
lum += res.clipped * highlightProtection;
- }
+ }*/
}
if (callback) callback(err, lum, res.histogram);
});
@@ -384,4 +384,4 @@ exports.faceDetection = function(jpegBuffer, callback) {
}
});
});
-}
\ No newline at end of file
+}
diff --git a/camera/ptpjs/api.js b/camera/ptpjs/api.js
index b12105d1e..47dd46063 100644
--- a/camera/ptpjs/api.js
+++ b/camera/ptpjs/api.js
@@ -13,6 +13,7 @@ var fs = require('fs');
var path = require('path');
var async = require('async');
var test = require('./test');
+var api_util = require('./api_util');
var api = new EventEmitter();
@@ -124,12 +125,12 @@ while (us < 1000000 * 60 * 10) {
util.inherits(CameraAPI, EventEmitter);
-usb.on('attach', function(device) {
+usb.on('attach', function(device) {
//console.log("device attached", device);
if(api.enabled) tryConnectDevice(device);
});
-usb.on('detach', function(device) {
+usb.on('detach', function(device) {
//console.log("DETACHED:", device);
var port = device.busNumber + ':' + device.deviceAddress;
var camIndex = null;
@@ -149,7 +150,7 @@ usb.on('detach', function(device) {
api.emit('disconnect', name); // had been connected
break;
}
- }
+ }
});
@@ -323,7 +324,7 @@ function ensurePrimary() {
if(api.cameras.length > 0) {
if(primaryIndex == -1) {
primaryIndex = 0;
- api.cameras[primaryIndex].primary = true;
+ api.cameras[primaryIndex].primary = true;
}
api.available = true;
api.model = api.cameras[primaryIndex].model;
@@ -377,7 +378,7 @@ api.cameraList = function(callback) {
api.switchPrimary = function(cameraObject, callback) {
//if(camera.lvOn) camera.lvOff();
if(cameraObject._port) {
- console.log("switching primary camera to ", cameraObject.model);
+ console.log("switching primary camera to ", cameraObject.model);
var index = null;
for(var j = 0; j < api.cameras.length; j++) {
if(api.cameras[j].camera._port == cameraObject._port) {
@@ -506,71 +507,6 @@ api.lvZoom = function(zoom, callback) {
primaryCamera.camera.lvZoom(zoom, callback);
}
-function listEvs(param, minEv, maxEv) { // returns a sorted list of EV's from a camera available list
- var base = api.cameras[0].camera.exposure;
- //console.log("API:", param, "base", base);
- if(!base || !base[param] || !base[param].list) return null;
- var list = base[param].list;
- //console.log("API:", param, "base list", list);
-
- return list.map(function(item) {
- return item.ev;
- }).filter(function(ev, index, self) {
- if(ev == null) return false;
- if(minEv != null && ev < minEv) return false;
- if(maxEv != null && ev > maxEv) return false;
- return self.indexOf(ev) === index; // ensure unique
- }).sort(function(a, b){return a-b});
-}
-
-function evIndexOf(ev, evList) {
- var i = evList.indexOf(ev);
- if(i != -1) return i;
- for(i = 0; i < evList.length; i++) {
- if(ev <= evList[i]) {
- if(i == 0) return i;
- if(Math.abs(ev - evList[i]) > Math.abs(ev - evList[i - 1])) {
- return i - 1;
- } else {
- return i;
- }
- }
- }
- return -1;
-}
-
-function incEv(ev, evList) {
- //console.log("incEv: index", i, "ev", ev, "list", evList);
- if(!evList) return null;
- var i = evIndexOf(ev, evList);
- if(i != -1 && i < evList.length - 1 && evList[i + 1] != null) return evList[i + 1];
- if(ev != null && evList && evList.length > 0) {
- var min = Math.min.apply(null, evList),
- max = Math.max.apply(null, evList);
- if(ev < min) return min;
- if(ev > max) return max;
- }
- return ev;
-}
-
-function decEv(ev, evList) {
- if(!evList) return null;
- var i = evIndexOf(ev, evList);
- if(i > 0 && evList[i - 1] != null) return evList[i - 1];
- if(ev != null && evList && evList.length > 0) {
- var min = Math.min.apply(null, evList),
- max = Math.max.apply(null, evList);
- if(ev < min) return min;
- if(ev > max) return max;
- }
- return ev;
-}
-
-function equalEv(ev1, ev2) {
- if(ev1 == null || ev2 == null) return true; // equal means ignore
- return Math.abs(ev1 - ev2) < 0.25;
-}
-
api.getEv = function(shutterEv, apertureEv, isoEv) {
if(shutterEv == null) shutterEv = api.cameras.length > 0 && api.cameras[0].camera.exposure.shutter ? api.cameras[0].camera.exposure.shutter.ev : null;
if(apertureEv == null) apertureEv = api.cameras.length > 0 && api.cameras[0].camera.exposure.aperture ? api.cameras[0].camera.exposure.aperture.ev : null;
@@ -588,8 +524,7 @@ api.getSecondsFromEv = function(ev) { // only accurate to 1/3 stop
return 0.1;
}
-var lastParam = null;
-api.setEv = function(ev, options, callback) {
+api.setEv = function(targetEv, options, callback) {
if (!options) options = {};
var returnData = {
@@ -599,7 +534,7 @@ api.setEv = function(ev, options, callback) {
iso: {}
}
- if(ev == null) return callback && callback("invalid ev", returnData);
+ if(targetEv == null) return callback && callback("invalid targetEv", returnData);
if(api.cameras.length == 0) return callback && callback("camera not connected", returnData);
var exposure = api.cameras[0].camera.exposure;
@@ -631,7 +566,7 @@ api.setEv = function(ev, options, callback) {
}
var origEv = currentEv;
- if(equalEv(ev, currentEv)) {
+ if(api_util.equalEv(targetEv, currentEv)) {
return callback && callback(null, {
ev: currentEv,
shutter: {ev: shutterEv},
@@ -640,9 +575,10 @@ api.setEv = function(ev, options, callback) {
});
}
- var shutterList = listEvs('shutter', options.shutterMax, null);
- var apertureList = listEvs('aperture', options.apertureMin, options.apertureMax);
- var isoList = listEvs('iso', options.isoMax, options.isoMin);
+ var base = api.cameras[0].camera.exposure;
+ var shutterList = api_util.listEvs(base, 'shutter', options.shutterMax, null);
+ var apertureList = api_util.listEvs(base, 'aperture', options.apertureMin, options.apertureMax);
+ var isoList = api_util.listEvs(base, 'iso', options.isoMax, options.isoMin);
console.log("API setEv: shutterList.length", shutterList && shutterList.length, "max =", options.shutterMax);
console.log("API setEv: apertureList.length", apertureList && apertureList.length);
@@ -656,63 +592,29 @@ api.setEv = function(ev, options, callback) {
});
}
- if(!options.blendParams) lastParam = null;
-
- for (var trys = 0; trys < 3; trys++) {
- while (ev < currentEv - 1 / 4) {
- //console.log("ev < currentEv");
- var s = decEv(shutterEv, shutterList);
- if (apertureEnabled) var a = decEv(apertureEv, apertureList);
- var i = decEv(isoEv, isoList);
-
- if (!equalEv(shutterEv, s) && lastParam != 's') {
- shutterEv = s;
- if(options.blendParams) lastParam = 's';
- } else if (apertureEnabled && !equalEv(apertureEv, a) && lastParam != 'a') {
- apertureEv = a;
- if(options.blendParams) lastParam = 'a';
- } else if (!equalEv(isoEv, i) && lastParam != 'i') {
- isoEv = i;
- if(options.blendParams) lastParam = 'i';
- } else {
- lastParam = null;
- currentEv = api.getEv(shutterEv, apertureEv, isoEv);
- break;
- }
- currentEv = api.getEv(shutterEv, apertureEv, isoEv);
- //console.log(" update: ", currentEv);
- }
-
- while (ev > currentEv + 1 / 4) {
- //console.log("ev > currentEv");
- var s = incEv(shutterEv, shutterList);
- if (apertureEnabled) var a = incEv(apertureEv, apertureList);
- var i = incEv(isoEv, isoList);
-
- if (!equalEv(isoEv, i) && lastParam != 'i') {
- isoEv = i;
- if(options.blendParams) lastParam = 'i';
- } else if (apertureEnabled && !equalEv(apertureEv, a) && lastParam != 'a') {
- apertureEv = a;
- if(options.blendParams) lastParam = 'a';
- } else if (!equalEv(shutterEv, s) && lastParam != 's') {
- shutterEv = s;
- if(options.blendParams) lastParam = 's';
- } else {
- lastParam = null;
- currentEv = api.getEv(shutterEv, apertureEv, isoEv);
- break;
- }
- currentEv = api.getEv(shutterEv, apertureEv, isoEv);
- //console.log(" update: ", currentEv);
- }
-
- if (Math.abs(ev - currentEv) <= 1 / 4) break;
-
- }
-
-
- console.log("API setEv: current:", origEv, "target:", ev, "new:", currentEv);
+ if(!options.blendParams) api_util.setZeros()
+ const result = api_util.adjustCameraExposure(targetEv, currentEv,
+ shutterEv, shutterList,
+ apertureEnabled, apertureEv, apertureList,
+ isoEv, isoList,
+ options,
+ api.getEv
+ );
+ currentEv = result.currentEv;
+ shutterEv = result.shutterEv;
+ apertureEv = result.apertureEv;
+ isoEv = result.isoEv;
+
+ console.log("API setEv: current:", origEv, "target:", targetEv, "new:", currentEv);
+ console.log("API setEv: current:",
+ api_util.findEvName(exposure, 'shutter', result.shutterEv), " ",
+ api_util.findEvName(exposure, 'aperture', result.apertureEv), " ",
+ api_util.findEvName(exposure, 'iso', result.isoEv), " ",
+ result.direction, " ",
+ result.lastParam, " ",
+ targetEv.toFixed(2), " ",
+ result.currentEv.toFixed(2)
+ );
function runQueue(queue, callback) {
console.log("API: runQueue length", queue.length);
diff --git a/camera/ptpjs/api_util.js b/camera/ptpjs/api_util.js
new file mode 100644
index 000000000..3194b42af
--- /dev/null
+++ b/camera/ptpjs/api_util.js
@@ -0,0 +1,203 @@
+// noinspection JSDuplicatedDeclaration,ES6ConvertVarToLetConst
+
+var lastParam = null;
+var lastParamUp = null;
+var lastParamDown = null;
+var lastDirection = null;
+var isoDownChanges = 0
+
+exports.setZeros = function () {
+ lastParam = null;
+ lastParamUp = null;
+ lastParamDown = null;
+ lastDirection = null;
+ isoDownChanges = 0
+}
+
+exports.adjustCameraExposure = function (targetEv, currentEv,
+ shutterEv, shutterList,
+ apertureEnabled, apertureEv, apertureList,
+ isoEv, isoList,
+ options,
+ getEv) {
+ if (!options.blendParams) lastParam = null;
+
+ var direction = targetEv < currentEv ? '↓' : '↑';
+ var directionChanged = direction != lastDirection;
+
+ for (var trys = 0; trys < 3; trys++) {
+ while (targetEv < currentEv - 1 / 4) {
+
+ var s = decEv(shutterEv, shutterList);
+ if (apertureEnabled) var a = decEv(apertureEv, apertureList);
+ var i = decEv(isoEv, isoList);
+ var changeShutterInsteadOfIso = apertureEv == a;
+
+ if (!equalEv(shutterEv, s) && (lastParamDown != 's' || changeShutterInsteadOfIso || directionChanged && lastParamUp == 's')) {
+ shutterEv = s;
+ if (changeShutterInsteadOfIso)
+ isoDownChanges++;
+ if (options.blendParams) lastParamDown = 's';
+ } else if (apertureEnabled && !equalEv(apertureEv, a) && (lastParamDown != 'a' || directionChanged && lastParamUp == 'a')) {
+ apertureEv = a;
+ if (options.blendParams) lastParamDown = 'a';
+ } else if (!equalEv(isoEv, i) && (lastParamDown != 'i' || directionChanged && lastParamUp == 'i')) {
+ isoEv = i;
+ isoDownChanges++;
+ if (options.blendParams) lastParamDown = 'i';
+ } else {
+ lastParamDown = null;
+ currentEv = getEv(shutterEv, apertureEv, isoEv);
+ break;
+ }
+ currentEv = getEv(shutterEv, apertureEv, isoEv);
+ //console.log(" update: ", currentEv, " ", lastParam);
+ }
+
+ while (targetEv > currentEv + 1 / 4) {
+
+ var s = incEv(shutterEv, shutterList);
+ if (apertureEnabled) var a = incEv(apertureEv, apertureList);
+ var i = incEv(isoEv, isoList);
+
+ if (!equalEv(isoEv, i) /*&& (lastParamUp != 'i' || directionChanged && lastParamDown == 'i')*/) {
+ isoEv = i;
+ if (options.blendParams) lastParamUp = 'i';
+ } else if (!equalEv(shutterEv, s) && (lastParamUp != 's' || directionChanged && lastParamDown == 's')) {
+ shutterEv = s;
+ if (options.blendParams) lastParamUp = 's';
+ } else if (apertureEnabled && !equalEv(apertureEv, a) && (lastParamUp != 'a' || directionChanged && lastParamDown == 'a')) {
+ apertureEv = a;
+ if (options.blendParams) lastParamUp = 'a';
+ } else {
+ lastParamUp = null;
+ currentEv = getEv(shutterEv, apertureEv, isoEv);
+ break;
+ }
+ currentEv = getEv(shutterEv, apertureEv, isoEv);
+ //console.log(" update: ", currentEv, " ", lastParam);
+ }
+
+ if (Math.abs(targetEv - currentEv) <= 1 / 4) break;
+
+ }
+ lastParam = (lastParamDown + " " + lastParamUp);
+ lastDirection = direction;
+ return {
+ currentEv: currentEv,
+ shutterEv: shutterEv,
+ apertureEv: apertureEv,
+ isoEv: isoEv,
+ direction: direction,
+ lastParam: lastParam
+ };
+}
+
+exports.listEvs = function (param, minEv, maxEv) { // returns a sorted list of EV's from a camera available list
+ var base = api.cameras[0].camera.exposure;
+ //console.log("API:", param, "base", base);
+ if (!base || !base[param] || !base[param].list) return null;
+ var list = base[param].list;
+ //console.log("API:", param, "base list", list);
+
+ return list.map(function (item) {
+ return item.ev;
+ }).filter(function (ev, index, self) {
+ if (ev == null) return false;
+ if (minEv != null && ev < minEv) return false;
+ if (maxEv != null && ev > maxEv) return false;
+ return self.indexOf(ev) === index; // ensure unique
+ }).sort(function (a, b) {
+ return a - b
+ });
+}
+
+exports.findEvName = function (base, param, targetEv) { // returns a sorted list of EV's from a camera available list
+ //console.log("API:", param, "base", base);
+ if (!base || !base[param] || !base[param].list) return null;
+ var list = base[param].list;
+ //console.log("API:", param, "base list", list);
+
+ return find(list, function (ev) {
+ return targetEv == ev.ev;
+ }).name;
+}
+
+function find(list, callback) {
+ for (var i = 0; i < list.length; i++) {
+ if (callback(list[i])) {
+ return list[i];
+ }
+ }
+ return undefined;
+}
+
+function incEv(ev, evList) {
+ //console.log("incEv: index", i, "ev", ev, "list", evList);
+ if (!evList) return null;
+ var i = evIndexOf(ev, evList);
+ if (i != -1 && i < evList.length - 1 && evList[i + 1] != null) return evList[i + 1];
+ if (ev != null && evList && evList.length > 0) {
+ var min = Math.min.apply(null, evList),
+ max = Math.max.apply(null, evList);
+ if (ev < min) return min;
+ if (ev > max) return max;
+ }
+ return ev;
+}
+
+function decEv(ev, evList) {
+ if (!evList) return null;
+ var i = evIndexOf(ev, evList);
+ if (i > 0 && evList[i - 1] != null) return evList[i - 1];
+ if (ev != null && evList && evList.length > 0) {
+ var min = Math.min.apply(null, evList),
+ max = Math.max.apply(null, evList);
+ if (ev < min) return min;
+ if (ev > max) return max;
+ }
+ return ev;
+}
+
+function equalEv(ev1, ev2) {
+ if (ev1 == null || ev2 == null) return true; // equal means ignore
+ return Math.abs(ev1 - ev2) < 0.25;
+}
+
+exports.equalEv = equalEv
+
+function evIndexOf(ev, evList) {
+ var i = evList.indexOf(ev);
+ if (i != -1) return i;
+ for (i = 0; i < evList.length; i++) {
+ if (ev <= evList[i]) {
+ if (i == 0) return i;
+ if (Math.abs(ev - evList[i]) > Math.abs(ev - evList[i - 1])) {
+ return i - 1;
+ } else {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+function listEvs(base, param, minEv, maxEv) { // returns a sorted list of EV's from a camera available list
+ //console.log("API:", param, "base", base);
+ if (!base || !base[param] || !base[param].list) return null;
+ var list = base[param].list;
+ //console.log("API:", param, "base list", list);
+
+ return list.map(function (item) {
+ return item.ev;
+ }).filter(function (ev, index, self) {
+ if (ev == null) return false;
+ if (minEv != null && ev < minEv) return false;
+ if (maxEv != null && ev > maxEv) return false;
+ return self.indexOf(ev) === index; // ensure unique
+ }).sort(function (a, b) {
+ return a - b
+ });
+}
+
+exports.listEvs = listEvs
diff --git a/camera/ptpjs/drivers/sony.js b/camera/ptpjs/drivers/sony.js
index 5989cd615..e29e8d0e3 100644
--- a/camera/ptpjs/drivers/sony.js
+++ b/camera/ptpjs/drivers/sony.js
@@ -159,7 +159,6 @@ var properties = {
{ name: "1.2", ev: -7 - 1 / 3, code: 120 },
{ name: "1.4", ev: -7, code: 140 },
{ name: "1.6", ev: -6 - 2 / 3, code: 160 },
- { name: "1.7", ev: -6 - 1 / 2, code: 170 },
{ name: "1.8", ev: -6 - 1 / 3, code: 180 },
{ name: "2.0", ev: -6, code: 200 },
{ name: "2.2", ev: -5 - 2 / 3, code: 220 },
diff --git a/currentDetails.bat b/currentDetails.bat
new file mode 100644
index 000000000..f3411df68
--- /dev/null
+++ b/currentDetails.bat
@@ -0,0 +1,2 @@
+scp root@192.168.31.21:"$(ssh root@192.168.31.21 'ls -td /root/time-lapse/*/ | head -n 1')"details.csv ./logs
+scp root@192.168.31.21:"$(ssh root@192.168.31.21 'ls -td /root/time-lapse/*/ | head -n 1')"data.js ./logs
diff --git a/currentLog.bat b/currentLog.bat
new file mode 100644
index 000000000..d06fb0cb2
--- /dev/null
+++ b/currentLog.bat
@@ -0,0 +1 @@
+scp -r root@192.168.31.21:/home/view/current/logs/ .
diff --git a/frontend/www/build/main.js b/frontend/www/build/main.js
index ed0e51f8b..a62c7c73c 100644
--- a/frontend/www/build/main.js
+++ b/frontend/www/build/main.js
@@ -859,6 +859,10 @@ var RampingModalContentPage = (function () {
{ label: '-1 stop', value: -1 },
{ label: '-0.5 stops', value: -0.5 },
{ label: '0 stops', value: 0 },
+ { label: '0.5 stops', value: 0.5 },
+ { label: '1 stop', value: 1 },
+ { label: '1.5 stops', value: 1.5 },
+ { label: '2 stops', value: 2 },
],
dayLuminance: [
{ label: '-1.5 stops', value: -1.5 },
diff --git a/hardware/oled.js b/hardware/oled.js
index 8cd1bc44b..65d27f2aa 100644
--- a/hardware/oled.js
+++ b/hardware/oled.js
@@ -158,7 +158,7 @@ function textInitPos(setMode) {
for(var i = 0; i < TEXT_MODES.length; i++) {
mode = textGetMode(TEXT_MODES[i]);
var list = TEXT_LIST[mode];
- if(TEXT_MODES[i] == 'lcase') list = list.toLowerCase();
+ if(TEXT_MODES[i] == 'lcase') list = list.toLowerCase();
if(list.indexOf(textValue.charAt(oled.selected)) !== -1) {
textMode = TEXT_MODES[i];
console.log("set text mode to", textMode);
@@ -183,7 +183,7 @@ function textUpdateCurrent() {
oled.textMoveForward = function() {
if(oled.mode == 'text' || oled.mode == 'number') {
- if(oled.selected < TEXT_MAX_CHARS) oled.selected++;
+ if(oled.selected < TEXT_MAX_CHARS) oled.selected++;
if(textMode == 'number') {
var textLength = textValue.length;
textValue = textValue.replace(/ /g, '');
@@ -191,7 +191,7 @@ oled.textMoveForward = function() {
}
textInitPos(true);
} else if(oled.mode == 'time' || oled.mode == "date") {
- if(oled.selected < 2) oled.selected++; else oled.selected = 0;
+ if(oled.selected < 2) oled.selected++; else oled.selected = 0;
}
oled.writeMenu();
oled.update();
@@ -213,7 +213,7 @@ oled.textMoveBackward = function() {
function textGetMode(currentMode) {
if(!currentMode) currentMode = textMode;
var mode;
- if(currentMode == 'ucase' || currentMode == 'lcase') mode = 'alpha'; else mode = currentMode == 'number' ? 'num' : currentMode;
+ if(currentMode == 'ucase' || currentMode == 'lcase') mode = 'alpha'; else mode = currentMode == 'number' ? 'num' : currentMode;
return mode;
}
@@ -236,7 +236,7 @@ function getTextList() {
return TEXT_LIST['num'].concat(['.']);
} else {
return TEXT_LIST['num'];
- }
+ }
} else {
return TEXT_LIST[textGetMode()];
}
@@ -274,7 +274,7 @@ function drawTimeLapseStatus(status) {
fb.text(upperTextStart, 37, status.apertureText || "---");
fb.text(upperTextStart, 50, status.shutterText || "---");
fb.text(upperTextStart, 63, status.evText || "---");
- fb.text(upperTextStart, 76, status.rampModeText);
+ fb.text(upperTextStart, 76, status.lastPhotoLum || "---");
var m = Math.round(status.durationSeconds / 60);
var hours = Math.floor(m / 60);
@@ -284,7 +284,7 @@ function drawTimeLapseStatus(status) {
fb.text(0, 100, "Interval: " + (Math.round(status.intervalSeconds * 10) / 10).toString() + "s (" + status.intervalModeText + ")");
fb.text(0, 113, "Frames: " + (status.frames || 0).toString() + "/" + status.remaining.toString());
- fb.text(0, 126, "Duration: " + hours.toString() + "h" + minutes.toString() + "m");
+ fb.text(0, 126, "Dur: " + hours.toString() + "h" + minutes.toString() + "m " + status.rampModeText);
// ramp chart window
//color("background");
@@ -305,7 +305,7 @@ function drawTimeLapseStatus(status) {
fb.line(x, histY + 1 + histH - h, x, histY + 1 + histH, 1);
}
} else {
- fb.rect(histX, histY, histW, histH, false);
+ fb.rect(histX, histY, histW, histH, false);
}
// interval/exposure status line
@@ -324,9 +324,9 @@ function drawTimeLapseStatus(status) {
var bufferLineEnd = shutterLineEnd + Math.ceil(status.bufferSeconds * secondsRatio);
color("background");
- fb.line(4, 84.5, lw, 84.5, 1);
+ fb.line(4, 84.5, lw, 84.5, 1);
color("alert");
- fb.line(shutterLineStart, 84.5, shutterLineEnd, 84.5, 1);
+ fb.line(shutterLineStart, 84.5, shutterLineEnd, 84.5, 1);
color("secondary");
fb.line(bufferLineStart, 84.5, bufferLineEnd, 84.5, 1);
@@ -349,7 +349,7 @@ oled.updateTimelapseStatus = function(status) {
if(status) {
oled.timelapseStatus = status;
if(status.running) {
- if(oled.mode == 'timelapse') statusIntervalHandle = setInterval(function(){drawTimeLapseStatus(status);}, 150);
+ if(oled.mode == 'timelapse') statusIntervalHandle = setInterval(function(){drawTimeLapseStatus(status);}, 150);
} else {
statusDetails = {};
}
@@ -365,6 +365,10 @@ oled.updateHistogram = function(histogram) {
statusDetails.histogram = histogram;
}, 100);
}
+oled.setEvHistogram = function (ev, histogram) {
+ statusDetails.histogram = histogram;
+ statusDetails.ev = ev;
+}
oled.setTimelapseMode = function(set) {
if(set) {
@@ -545,7 +549,7 @@ oled.writeMenu = function() {
color("primary");
} else {
color("secondary");
- }
+ }
fb.text(160 - 48 + i * xAdvance, 125, modes[i]);
}
@@ -767,7 +771,7 @@ oled.writeMenu = function() {
var parts = list[i].split('~');
var textSize = fb.text(MENU_XOFFSET, MENU_YOFFSET + i * MENU_LINE_HEIGHT, parts[0]);
-
+
if(parts[1]) { // menu item value
color("secondary");
fb.text(MENU_XOFFSET + textSize.width, MENU_YOFFSET + i * MENU_LINE_HEIGHT, ' ' + parts[1]);
@@ -1055,12 +1059,28 @@ oled.exposure = function(jpegFile, textArray, highlightTextIndex) {
} else {
fb.rect(0, 15, 160, 128 - 15, true);
}
- fb.font(MENU_STATUS_FONT_SIZE, false, FONT_DEFAULT);
+
+ var histX = 110;
+ var histY = 76;
+ var histH = 37;
+ var histW = 50;
+ if(statusDetails.histogram) {
+ color("background");
+ fb.rect(histX, histY, histW, histH, false);
+ color("primary");
+ for(var i = 0; i < 256; i++) {
+ var x = histX + 1 + (histW - 2) * (i/255);
+ var h = statusDetails.histogram[i] ? (histH - 2) * (statusDetails.histogram[i]/256) : 0;
+ fb.line(x, histY + 1 + histH - h, x, histY + 1 + histH, 1);
+ }
+ }
+
+ fb.font(MENU_STATUS_FONT_SIZE, false, FONT_DEFAULT); fb.font(MENU_STATUS_FONT_SIZE, false, FONT_DEFAULT);
color("primary");
var sectionSize = 160 / textArray.length;
for(var i = 0; i < textArray.length; i++) {
var textSize = fb.textSize(textArray[i]);
- var x = sectionSize * i + sectionSize / 2 - textSize.width / 2;
+ var x = sectionSize * i + sectionSize / 2 - textSize.width / 2;
//console.log("OLED: writing", textArray[i], "at x =", x, "textSize =", textSize.width);
fb.text(x, 126, textArray[i]);
if(highlightTextIndex === i) {
@@ -1069,6 +1089,15 @@ oled.exposure = function(jpegFile, textArray, highlightTextIndex) {
color("primary");
}
}
+ if (statusDetails.ev) {
+ var textSize = fb.textSize(statusDetails.ev);
+ var x = 160 - textSize.width - 4;
+ fb.color(0, 0, 0);
+ var y = 76 - 12;
+ fb.rect(x - 2, y - textSize.height, textSize.width + 4, textSize.height + 4, true);
+ color("primary");
+ fb.text(x, y, statusDetails.ev);
+ }
oled.update(true);
}
@@ -1105,6 +1134,7 @@ oled.batteryPercentage = function(percentage) {
var videoIntervalHandle = null;
var videoCallback = null;
var skipFrames = 0;
+var fpsMultiplier = 0;
oled.video = function(videoPathFormat, frames, fps, callback) {
console.log("playing video, mode=", typeof frames);
if(oled.videoRunning) return callback && setTimeout(callback);
@@ -1124,7 +1154,7 @@ oled.video = function(videoPathFormat, frames, fps, callback) {
var indexString, paddingLength;
var frameComplete = true;
var frameLineFactor = (160 - 6) / frames;
-
+ fb.font(MENU_STATUS_FONT_SIZE, false, FONT_DEFAULT); fb.font(MENU_STATUS_FONT_SIZE, false, FONT_DEFAULT);
videoIntervalHandle = setInterval(function(){
if(!frameComplete) {
console.log("dropping frame #" + index);
@@ -1133,6 +1163,8 @@ oled.video = function(videoPathFormat, frames, fps, callback) {
frameComplete = false;
frameIndex += skipFrames;
skipFrames = 0;
+ if (fpsMultiplier > 0)
+ frameIndex += fpsMultiplier;
if(frameIndex > frames) oled.stopVideo();
if(frameArray) {
@@ -1153,6 +1185,16 @@ oled.video = function(videoPathFormat, frames, fps, callback) {
fb.line(3, 127 - 3, 159 - 3, 127 - 3, 2);
color("primary");
fb.line(3, 127 - 3, frameIndex * frameLineFactor, 127 - 3, 2);
+
+ var s = "x" + (fpsMultiplier + 1);
+ var textSize = fb.textSize(s);
+ var x = 160 - textSize.width - 4;
+ fb.color(0, 0, 0);
+ var y = 50;
+ fb.rect(x - 2, y - textSize.height, textSize.width + 4, textSize.height + 4, true);
+ color("primary");
+ fb.text(x, y, s);
+
fb.blit();
frameComplete = true;
}, 1000 / (fps||24));
@@ -1169,4 +1211,12 @@ oled.videoSkipFrames = function(frames) {
skipFrames = frames;
}
}
-module.exports = oled;
\ No newline at end of file
+oled.increaseVideoSpeed = function () {
+ fpsMultiplier++;
+ if (fpsMultiplier > 15) fpsMultiplier = 15;
+}
+oled.decreaseVideoSpeed = function () {
+ fpsMultiplier--;
+ if (fpsMultiplier <=0) fpsMultiplier = 0;
+}
+module.exports = oled;
diff --git a/intervalometer/exposure.js b/intervalometer/exposure.js
index b6bc2fe55..42a029654 100644
--- a/intervalometer/exposure.js
+++ b/intervalometer/exposure.js
@@ -1,5 +1,7 @@
-var tv = require('intervalometer/time-value.js');
-var interpolate = require('intervalometer/interpolate.js');
+var tv = require('./time-value.js');
+var interpolate = require('./interpolate.js');
+var fs = require('fs');
+
var exp = {};
var local = {};
@@ -8,9 +10,9 @@ exp.config = {};
//exp.init = function(minEv, maxEv, nightCompensation, highlightProtection) {
-exp.init = function(minEv, maxEv, nightLuminance, dayLuminance, highlightProtection) {
- if(nightLuminance == null) nightLuminance = -1.5;
- if(dayLuminance == null) dayLuminance = 0;
+exp.init = function (minEv, maxEv, nightLuminance, dayLuminance, highlightProtection, datajs) {
+ if (nightLuminance == null) nightLuminance = -1.5;
+ if (dayLuminance == null) dayLuminance = 0;
local = {
lumArray: [],
@@ -20,7 +22,8 @@ exp.init = function(minEv, maxEv, nightLuminance, dayLuminance, highlightProtect
rateHistoryArray: [],
targetHighlights: null,
targetLum: null,
- first: true
+ first: true,
+ datajs: datajs
};
exp.status = {
@@ -33,11 +36,11 @@ exp.init = function(minEv, maxEv, nightLuminance, dayLuminance, highlightProtect
exp.config = {
sunrise: {
- p: 0.9,
- i: 0.4,
+ p: 0.97,
+ i: 0.5,
d: 0.6,
- targetTimeSeconds: 300,
- evIntegrationSeconds: 300,
+ targetTimeSeconds: 360,
+ evIntegrationSeconds: 360,
historyIntegrationSeconds: 480,
highlightIntegrationFrames: 3,
},
@@ -48,38 +51,54 @@ exp.init = function(minEv, maxEv, nightLuminance, dayLuminance, highlightProtect
targetTimeSeconds: 480,
evIntegrationSeconds: 480,
historyIntegrationSeconds: 480,
- highlightIntegrationFrames: 5,
+ highlightIntegrationFrames: 3,
},
maxEv: maxEv,
minEv: minEv,
maxRate: 30,
hysteresis: 0.4,
nightCompensationDayEv: 10,
- nightCompensationNightEv: -2,
+ nightCompensationNightEv: -1,
nightCompensation: 'auto',
nightLuminance: nightLuminance,
dayLuminance: dayLuminance,
highlightProtection: highlightProtection,
highlightProtectionLimit: 1
};
-
+ fs.writeFileSync(datajs, "var datajs = {}\n" +
+ "module.exports = datajs\n" +
+ "\n" +
+ "datajs.data = [ ");
return exp.config;
}
-exp.calculate = function(algorithm, direction, currentEv, lastPhotoLum, lastPhotoHistogram, minEv, maxEv) {
- if(minEv != null) exp.config.minEv = minEv;
- if(maxEv != null) exp.config.maxEv = maxEv;
- lastPhotoHistogram = normalizeHistogram(lastPhotoHistogram);
+exp.calculate = function (algorithm, direction, currentEv, lastPhotoLum, lastPhotoHistogram, minEv, maxEv, frame) {
+ if (minEv != null) exp.config.minEv = minEv;
+ if (maxEv != null) exp.config.maxEv = maxEv;
+ //// lastPhotoHistogram = normalizeHistogram(lastPhotoHistogram);
- if(['auto', 'sunset', 'sunrise'].indexOf(direction) === -1) direction = 'auto';
+ if (['auto', 'sunset', 'sunrise'].indexOf(direction) === -1) direction = 'auto';
+
+ console.log("lastPhotoHistogram = ", JSON.stringify(lastPhotoHistogram));
+ fs.appendFileSync(local.datajs, "{ \n" +
+ "frame: " + frame + ", \n" +
+ "lastPhotoHistogram: " + JSON.stringify(lastPhotoHistogram) + ", \n" +
+ "currentEv: " + currentEv + ", \n" +
+ "lastPhotoLum: " + lastPhotoLum + ", \n" +
+ "minEv: " + minEv + ", \n" +
+ "maxEv: " + maxEv + ", \n" +
+ "},"
+ );
//if(algorithm == "lrt") {
// return exp.calculate_LRTtimelapse(currentEv, direction, lastPhotoLum, lastPhotoHistogram, minEv, maxEv);
//} else {
- return exp.calculate_TLPAuto(currentEv, lastPhotoLum, lastPhotoHistogram, minEv, maxEv);
+ var rampEv = exp.calculate_TLPAuto(currentEv, lastPhotoLum, lastPhotoHistogram, minEv, maxEv);
+ return rampEv;
//}
}
+/*
exp.calculate_LRTtimelapse = function(currentEv, direction, lastPhotoLum, lastPhotoHistogram, minEv, maxEv) {
var lum = 0;
for(var i = 0; i < 256; i++) {
@@ -96,7 +115,7 @@ exp.calculate_LRTtimelapse = function(currentEv, direction, lastPhotoLum, lastPh
exp.status.rampEv = currentEv;
local.lrtLumArray = [];
local.targetLum = lum;
-
+
if(direction == 'sunrise') {
local.direction = 1;
} else if(direction == 'sunset') {
@@ -132,15 +151,33 @@ exp.calculate_LRTtimelapse = function(currentEv, direction, lastPhotoLum, lastPh
console.log("LRT Lum:", lum, local.direction, local.targetLum, " currentEv:", currentEv, ", newEv:", exp.status.rampEv, ", Dir:", direction);
return exp.status.rampEv;
+}*/
+
+function highlightsF(histogram, size) {
+ return histogram.slice(size * 0.75, size).reduce(function (acc, val) {
+ return acc + val;
+ }, 0);
+}
+
+function underexposedF(histogram, size) {
+ return histogram.slice(0, size / 2).reduce(function (acc, val) {
+ return acc + val;
+ }, 0);
+}
+
+function overexposedF(histogram, size) {
+ return histogram.slice(size / 2, size).reduce(function (acc, val) {
+ return acc + val;
+ }, 0);
}
-exp.calculate_TLPAuto = function(currentEv, lastPhotoLum, lastPhotoHistogram, minEv, maxEv) {
+exp.calculate_TLPAuto = function (currentEv, lastPhotoLum, lastPhotoHistogram, minEv, maxEv) {
// measure the interval
exp.status.intervalSeconds = 0;
var thisPhotoTime = new Date();
if (local.lastPhotoTime) {
var intervalSeconds = (thisPhotoTime - local.lastPhotoTime) / 1000;
- if(intervalSeconds > 0) {
+ if (intervalSeconds > 0) {
exp.status.intervalSeconds = intervalSeconds; // in case the time changes while running, make sure this is never negative
}
}
@@ -160,8 +197,8 @@ exp.calculate_TLPAuto = function(currentEv, lastPhotoLum, lastPhotoHistogram, mi
if (Math.abs(exp.status.rate) < exp.config.hysteresis) exp.status.rate = 0;
// limit to max rate
- if(exp.status.rate > exp.config.maxRate) exp.status.rate = exp.config.maxRate;
- if(exp.status.rate < -exp.config.maxRate) exp.status.rate = -exp.config.maxRate;
+ if (exp.status.rate > exp.config.maxRate) exp.status.rate = exp.config.maxRate;
+ if (exp.status.rate < -exp.config.maxRate) exp.status.rate = -exp.config.maxRate;
// don't swing quickly past zero (stops oscillation)
if (exp.status.rate > 3 && exp.status.direction < -0.5) exp.status.rate = 0;
@@ -170,24 +207,51 @@ exp.calculate_TLPAuto = function(currentEv, lastPhotoLum, lastPhotoHistogram, mi
// adjust exposure according to rate in stops/hour
exp.status.rampEv += (exp.status.rate / 3600) * exp.status.intervalSeconds;
- if(exp.config.highlightProtection) {
- var highlights = lastPhotoHistogram[255] + lastPhotoHistogram[254] / 2;
+ if (exp.config.highlightProtection) {
+
+ const maxHist = Math.max.apply(null, lastPhotoHistogram);
+ const u = underexposedF(lastPhotoHistogram, lastPhotoHistogram.length);
+ const o = overexposedF(lastPhotoHistogram, lastPhotoHistogram.length);
+ const h = highlightsF(lastPhotoHistogram, lastPhotoHistogram.length);
+ const overexposed = 100 * o / (u + o);
+ const underexposed = 100 * u / (u + o);
+ const highlights = 100 * h / (u + o);
+ const shouldProtect = (highlights > 30 && underexposed <= 51) // this check is for overexposed highlights. blacks and half midtones should be less 51%
+ || (lastPhotoHistogram[lastPhotoHistogram.size - 1] == maxHist && underexposed < 70); // when highlights are clipped but that is a hdr scene, don't clip. 70 backs and midtones enough for hdr
// highlight protection
- local.highlightArray.unshift(highlights);
+ local.highlightArray.unshift(shouldProtect);
local.highlightArray = local.highlightArray.slice(0, config.highlightIntegrationFrames);
- var tempArray = local.highlightArray.slice(0).sort(function (a, b) { return a - b; }).slice(local.highlightArray.length > 2 ? 1 : 0, local.highlightArray.length > 2 ? local.highlightArray.length - 1 : local.highlightArray.length);
- exp.status.highlights = tempArray.reduce(function(sum, val) { return sum + val}) / tempArray.length;
- if(local.targetHighlights === null) local.targetHighlights = Math.max(exp.status.highlights, 2);
+ var saturatedFrames = local.highlightArray.filter(function (i) {
+ return i;
+ }).length
+
+
+ // var tempArray = local.highlightArray.slice(0).sort(function (a, b) { return a - b; }).slice(local.highlightArray.length > 2 ? 1 : 0, local.highlightArray.length > 2 ? local.highlightArray.length - 1 : local.highlightArray.length);
+ // exp.status.highlights = tempArray.reduce(function(sum, val) { return sum + val}) / tempArray.length;
+ // // if(local.targetHighlights === null) local.targetHighlights = Math.max(exp.status.highlights, 2);
+
- if(exp.status.highlights > local.targetHighlights * 2 && lastPhotoHistogram[255] > local.targetHighlights && exp.status.highlightProtection < exp.config.highlightProtectionLimit) {
+ console.log("HIGHLIGHTS: maxHist = ", maxHist);
+ console.log("HIGHLIGHTS: u = ", u);
+ console.log("HIGHLIGHTS: o = ", o);
+ console.log("HIGHLIGHTS: h = ", h);
+ console.log("HIGHLIGHTS: over = ", overexposed);
+ console.log("HIGHLIGHTS: under = ", underexposed);
+ console.log("HIGHLIGHTS: hi = ", highlights);
+ console.log("HIGHLIGHTS: local.highlightArray = ", local.highlightArray);
+ console.log("HIGHLIGHTS: saturatedFrames = ", saturatedFrames);
+
+
+ if (saturatedFrames >= config.highlightIntegrationFrames - 1) { // 2 >= 3 - 1
exp.status.highlightProtection += 0.333;
exp.status.manualOffsetEv -= 0.333;
exp.status.rampEv += 0.333;
- } else if(exp.status.highlights < local.targetHighlights / 2 && exp.status.highlightProtection > 0.3) {
+ console.log("HIGHLIGHTS: protecting", exp.status.highlightProtection);
+ } else if ((saturatedFrames < config.highlightIntegrationFrames - 1) && (exp.status.highlightProtection > 0.3)) {
exp.status.highlightProtection -= 0.333;
exp.status.manualOffsetEv += 0.333;
- exp.status.rampEv -= 0.333;
+ console.log("HIGHLIGHTS: restoring", exp.status.highlightProtection);
}
exp.status.highlightProtection = Math.round(exp.status.highlightProtection * 1000) / 1000;
}
@@ -199,7 +263,6 @@ exp.calculate_TLPAuto = function(currentEv, lastPhotoLum, lastPhotoHistogram, mi
}
-
// ******* Private Functions ******* //
function filteredMean(tvArr, trim) {
@@ -231,12 +294,19 @@ function calculateRate(currentEv, lastPhotoLum, config) {
exp.status.iComponent = exp.status.pastError * config.i;
exp.status.dComponent = exp.status.evSlope * config.d;
+ console.log("currentEv = ", currentEv, " lastPhotoLum = ", lastPhotoLum, " diff = ", diff, " delta = ", delta);
+
delta *= config.p;
delta += exp.status.pastError * config.i;
delta += exp.status.evSlope * config.d;
var rate = delta * (3600 / config.targetTimeSeconds);
+ console.log(" deltaNew = ", delta, " delta*3600", delta * 3600,
+ "exp.status.pastError", exp.status.pastError,
+ "exp.status.evSlope = ", exp.status.evSlope);
+
+
local.rateHistoryArray.push({
val: rate,
time: new Date()
@@ -266,17 +336,25 @@ function calculateDelta(currentEv, lastPhotoLum, config) {
y: 0
}]
exp.status.nightRatio = interpolate.linear(evScale, currentEv);
-
if (local.first) {
+
// exp.status.nightRefEv = lastPhotoLum * exp.status.nightRatio + -1.5 * (1 - exp.status.nightRatio);
// exp.status.dayRefEv = lastPhotoLum * (1 - exp.status.nightRatio);
- exp.status.nightRefEv = lastPhotoLum * exp.status.nightRatio + exp.config.nightLuminance * (1 - exp.status.nightRatio);
- exp.status.dayRefEv = lastPhotoLum * (1 - exp.status.nightRatio) + exp.config.dayLuminance * exp.status.nightRatio;
+ var duration = (exp.config.dayLuminance - exp.config.nightLuminance)
+
+ exp.status.nightRefEv = lastPhotoLum - duration * (1 - exp.status.nightRatio);
+ exp.status.dayRefEv = lastPhotoLum + duration * (exp.status.nightRatio);
exp.status.fixedRefEv = lastPhotoLum;
- exp.status.manualOffsetEv = lastPhotoLum - getEvOffsetScale(currentEv, lastPhotoLum);
+ exp.status.manualOffsetEv = lastPhotoLum - getEvOffsetScale(currentEv);
console.log("EXPOSURE: lastPhotoLum =", lastPhotoLum);
+ console.log("EXPOSURE: currentEv =", currentEv);
+ console.log("EXPOSURE: exp.status.nightRefEv =", exp.status.nightRefEv);
+ console.log("EXPOSURE: exp.status.dayRefEv =", exp.status.dayRefEv);
+ console.log("EXPOSURE: exp.status.nightRatio =", exp.status.nightRatio);
+ console.log("EXPOSURE: exp.config.nightLuminance =", exp.config.nightLuminance);
+ console.log("EXPOSURE: exp.config.dayLuminance =", exp.config.dayLuminance);
console.log("EXPOSURE: exp.status.manualOffsetEv =", exp.status.manualOffsetEv);
- console.log("EXPOSURE: getEvOffsetScale(currentEv, lastPhotoLum) =", getEvOffsetScale(currentEv, lastPhotoLum));
+ console.log("EXPOSURE: getEvOffsetScale(currentEv, lastPhotoLum) =", getEvOffsetScale(currentEv));
//exp.status.offsetEv = getEvOffsetScale(currentEv, lastPhotoLum) + exp.status.manualOffsetEv;
console.log("EXPOSURE: lastPhotoLum - exp.status.manualOffsetEv =", lastPhotoLum - exp.status.manualOffsetEv);
local.first = false;
@@ -284,6 +362,12 @@ function calculateDelta(currentEv, lastPhotoLum, config) {
local.lumArray = tv.purgeArray(local.lumArray, config.evIntegrationSeconds);
local.evArray = tv.purgeArray(local.evArray, config.evIntegrationSeconds);
+ // console.log("local.lumArray = ", local.lumArray.map(function (item) {
+ // return item.val;
+ // }));
+ // console.log("local.evArray = ", local.evArray.map(function (item) {
+ // return item.val;
+ // }));
var trim = 1;
if (exp.status.intervalSeconds) {
@@ -293,30 +377,26 @@ function calculateDelta(currentEv, lastPhotoLum, config) {
exp.status.evMean = filteredMean(local.lumArray, trim);
exp.status.evSlope = filteredSlope(local.evArray, trim) * config.targetTimeSeconds;
- return lastPhotoLum - (getEvOffsetScale(currentEv, lastPhotoLum) + exp.status.manualOffsetEv);
+ var evOffsetScale = getEvOffsetScale(currentEv);
+ console.log("lastPhotoLum - ", lastPhotoLum, "getEvOffsetScale = ", (evOffsetScale),
+ " + manual(", exp.status.manualOffsetEv, ")",
+ "currentEv= ", currentEv);
+
+ return lastPhotoLum - (evOffsetScale + exp.status.manualOffsetEv);
}
-function getEvOffsetScale(ev, lastPhotoLum, noAuto) {
+function getEvOffsetScale(ev, noAuto) {
var evScale
- if(exp.config.nightCompensation == 'auto') {
- if(noAuto) { // for LRT algorithm
- evScale = [{
- ev: exp.config.nightCompensationNightEv,
- offset: -1.333333
- }, {
- ev: exp.config.nightCompensationDayEv,
- offset: 0
- }]
- } else { // auto calculate night exposure
- evScale = [{
- ev: exp.config.nightCompensationNightEv,
- offset: exp.status.nightRefEv
- }, {
- ev: exp.config.nightCompensationDayEv,
- offset: exp.status.dayRefEv
- }]
- }
+ if (exp.config.nightCompensation == 'auto') {
+ // auto calculate night exposure
+ evScale = [{
+ ev: exp.config.nightCompensationNightEv,
+ offset: exp.status.nightRefEv
+ }, {
+ ev: exp.config.nightCompensationDayEv,
+ offset: exp.status.dayRefEv
+ }]
} else {
evScale = [{
ev: exp.config.nightCompensationNightEv,
@@ -327,25 +407,32 @@ function getEvOffsetScale(ev, lastPhotoLum, noAuto) {
}]
}
- var values = evScale.map(function(item) {
+ var values = evScale.map(function (item) {
return {
x: item.ev,
y: item.offset
}
});
- return interpolate.linear(values, ev);
+
+ var result = interpolate.linear(values, ev);
+ console.log("getEvOffsetScale() values= ", values);
+ console.log("getEvOffsetScale() interpolate.linear(values, ev) ", result, " ev = ", ev);
+
+ return result;
}
function normalizeHistogram(histogramArray) {
var lum = 0, sum = 0;
- for(var i = 0; i < 256; i++) {
+ for (var i = 0; i < 256; i++) {
sum += histogramArray[i];
}
sum /= 256;
- for(var i = 0; i < 256; i++) {
+ for (var i = 0; i < 256; i++) {
histogramArray[i] = histogramArray[i] / sum;
}
return histogramArray;
}
-module.exports = exp;
\ No newline at end of file
+exp.normalizeHistogram = normalizeHistogram
+
+module.exports = exp;
diff --git a/intervalometer/interpolate.js b/intervalometer/interpolate.js
index 07325a9be..238366322 100644
--- a/intervalometer/interpolate.js
+++ b/intervalometer/interpolate.js
@@ -5,7 +5,7 @@ exports.linear = function(xyPoints, xVal) {
}).sort(function(a, b) {
if(a.x < b.x) return -1;
if(a.x > b.x) return 1;
- return 0;
+ return 0;
});
if(typeof p != 'object' || !p.length) return null;
@@ -46,8 +46,6 @@ exports.linear = function(xyPoints, xVal) {
if(res > limits.max) res = limits.max;
if(res < limits.min) res = limits.min;
- //console.log("Interpolated result:", res);
-
return res;
}
@@ -130,17 +128,17 @@ exports.catmullRomSpline = function(xyPoints, xVal) {
}).sort(function(a, b) {
if(a.x < b.x) return -1;
if(a.x > b.x) return 1;
- return 0;
+ return 0;
});
if (!xyPoints || xyPoints.length == 0) {
return null;
} else if(xVal <= xyPoints[0].x) {
- return xyPoints[0].y;
-
+ return xyPoints[0].y;
+
} else if(xVal >= xyPoints[xyPoints.length - 1].x) {
- return xyPoints[xyPoints.length - 1].y;
+ return xyPoints[xyPoints.length - 1].y;
} else if(xyPoints.length == 1) {
return xyPoints[0].y;
@@ -218,12 +216,12 @@ exports.smooth = function(xyPoints, xVal) {
}
}
if(nextIndex == null) nextIndex = xyPoints.length - 1;
-
+
var tSpan = (xyPoints[nextIndex].x - xyPoints[lastIndex].x);
if(tSpan == 0) return xyPoints[lastIndex].y;
var t = (xVal - xyPoints[lastIndex].x) / tSpan;
var tS = smoothStep(t);
-
+
var lastSlope = pointSlope(lastIndex, xyPoints);
var nextSlope = pointSlope(nextIndex, xyPoints);
@@ -235,14 +233,14 @@ exports.smooth = function(xyPoints, xVal) {
if(Math.abs(nextVal - lastVal) > 0 && nextSlope > 0) d2 = (nextSlope * tSpan) / Math.abs(nextVal - lastVal);
var y1 = lastVal + (lastSlope * t*tSpan) / (1+d1*t);
var y2 = nextVal - (nextSlope * (1-t) * tSpan) / (1+d2*(1-t));
-
+
if(y1 > Math.max(lastVal, nextVal)) y1 = Math.max(lastVal, nextVal);
if(y2 > Math.max(lastVal, nextVal)) y2 = Math.max(lastVal, nextVal);
if(y1 < Math.min(lastVal, nextVal)) y1 = Math.min(lastVal, nextVal);
if(y2 < Math.min(lastVal, nextVal)) y2 = Math.min(lastVal, nextVal);
-
+
var y = (y1 * (1-tS)) + (y2 * tS);
-
+
return y;
}
@@ -257,7 +255,7 @@ exports.smoothStep = function(xyPoints, xVal) {
}
}
if(nextIndex == null) nextIndex = xyPoints.length - 1;
-
+
var tSpan = (xyPoints[nextIndex].x - xyPoints[lastIndex].x);
if(tSpan == 0) return xyPoints[lastIndex].y;
var t = (xVal - xyPoints[lastIndex].x) / tSpan;
@@ -265,9 +263,9 @@ exports.smoothStep = function(xyPoints, xVal) {
var lastVal = xyPoints[lastIndex].y;
var nextVal = xyPoints[nextIndex].y;
-
+
var y = (lastVal * (1-tS)) + (nextVal * tS);
-
+
return y;
}
diff --git a/intervalometer/intervalometer-server.js b/intervalometer/intervalometer-server.js
index 8743b5151..6ff305a60 100644
--- a/intervalometer/intervalometer-server.js
+++ b/intervalometer/intervalometer-server.js
@@ -23,9 +23,9 @@ message args response
'camera-liveview' enable (bool) camera_status (obj)
-event payload
+event payload
--------------------------------------------------
-'error' message (str)
+'error' message (str)
'status' intervalometerStatus (obj)
'motion-status' motionStatus (obj)
'camera-status' cameraStatus (obj)
@@ -512,11 +512,30 @@ function runCommand(type, args, callback, client) {
camera.ptp.new.liveviewImage(function(err, img) {
cameraCallback(err);
if(!err && img) {
- var obj = {
- base64: new Buffer(img).toString('base64'),
- type: 'preview'
- };
- sendEvent('camera.photo', obj);
+
+ var size = {
+ x: 160,
+ q: 128-15
+ }
+ image.downsizeJpeg(img, size, null, function (err, lowResJpg) {
+ var img2;
+ if (!err && lowResJpg) {
+ img2 = lowResJpg;
+ } else {
+ im2g = img;
+ }
+ var photoRes = {
+ base64: new Buffer(img2).toString('base64'),
+ type: 'preview',
+ ev: null
+ }
+ image.exposureValue(img2, function (err, ev, histogram) {
+ photoRes.ev = ev;
+ photoRes.histogram = histogram;
+ sendEvent('camera.photo', photoRes);
+ callback && callback(err, photoRes);
+ });
+ });
} else {
console.log("PREVIEW: err:", err);
}
@@ -588,7 +607,7 @@ function runCommand(type, args, callback, client) {
camera.ptp.new.switchPrimary(args.cameraObject, callback);
} else {
camera.ptp.switchPrimary(args.cameraObject, callback);
- }
+ }
break;
case 'camera.ptp.capture':
remap('camera.ptp.capture')(args.options, cameraCallback);
@@ -723,7 +742,7 @@ function getNewSettings(settings, status) {
shutter: settings.shutter && settings.shutter.list,
aperture: settings.aperture && settings.aperture.list,
iso: settings.iso && settings.iso.list
- },
+ },
details: {
shutter: settings.shutter,
aperture: settings.aperture,
diff --git a/intervalometer/intervalometer.js b/intervalometer/intervalometer.js
index b486aedfb..7c1712981 100644
--- a/intervalometer/intervalometer.js
+++ b/intervalometer/intervalometer.js
@@ -24,75 +24,77 @@ var AUXRING_OUT = 110;
var HOTSHOE_IN = 34;
function remap(method) { // remaps camera.ptp methods to use new driver if possible
- switch(method) {
+ switch (method) {
case 'camera.setEv':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
return camera.ptp.new.setEv;
} else {
return camera.setEv;
}
case 'camera.setExposure':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
return camera.ptp.new.setExposure;
} else {
return camera.setExposure;
}
case 'camera.ptp.settings.format':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
return camera.ptp.new.cameras[0].camera.config.format && camera.ptp.new.cameras[0].camera.config.format.value && camera.ptp.new.cameras[0].camera.config.format.value.toUpperCase();
} else {
return camera.ptp.settings.format;
}
case 'camera.ptp.model':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
return camera.ptp.new.model;
} else {
return camera.ptp.model;
}
case 'camera.ptp.supports.destination':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
return camera.ptp.new.supports.destination;
} else {
return camera.ptp.supports.destination;
}
case 'camera.ptp.connected':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
return camera.ptp.new.available;
} else {
return camera.ptp.connected;
}
case 'camera.ptp.getSettings':
- if(camera.ptp.new.available) {
- return function(callback) {callback && callback()};
+ if (camera.ptp.new.available) {
+ return function (callback) {
+ callback && callback()
+ };
} else {
return camera.ptp.getSettings;
}
case 'camera.ptp.capture':
- if(camera.ptp.new.available) {
- return function(captureOptions, callback) {
+ if (camera.ptp.new.available) {
+ return function (captureOptions, callback) {
var options = {
destination: (intervalometer.currentProgram.destination == 'sd' && camera.ptp.sdPresent && camera.ptp.sdMounted) ? 'sd' : 'camera',
}
- if(captureOptions && captureOptions.mode == 'test') {
+ if (captureOptions && captureOptions.mode == 'test') {
options.destination = "VIEW";
}
- if(camera.ptp.new.cameras[0].camera.supportsNativeHDR && captureOptions && captureOptions.hdrCount && captureOptions.hdrCount > 1 && captureOptions.hdrStops > 0) {
+ if (camera.ptp.new.cameras[0].camera.supportsNativeHDR && captureOptions && captureOptions.hdrCount && captureOptions.hdrCount > 1 && captureOptions.hdrStops > 0) {
options.hdrStops = captureOptions.hdrStops;
options.hdrCount = captureOptions.hdrCount;
}
logEvent("initiating capture...");
- return camera.ptp.new.capture(options.destination, options, function(err, thumb, filename, raw) {
- if(err) {
+ return camera.ptp.new.capture(options.destination, options, function (err, thumb, filename, raw) {
+ if (err) {
logErr("capture failed:", err);
return callback && callback(err);
}
- if(captureOptions && captureOptions.mode == "test") {
+ if (captureOptions && captureOptions.mode == "test") {
var size = {
x: 120,
q: 80
}
logEvent("capture complete, downsizing image...");
- image.downsizeJpeg(thumb, size, null, function(err, lowResJpg) {
+ image.downsizeJpeg(thumb, size, null, function (err, lowResJpg) {
var img;
if (!err && lowResJpg) {
img = lowResJpg;
@@ -100,7 +102,7 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
img = thumb;
}
logEvent("analyzing test image exposure...");
- image.exposureValue(img, function(err, ev, histogram) {
+ image.exposureValue(img, function (err, ev, histogram) {
var photoRes = {};
photoRes.ev = ev;
photoRes.histogram = histogram;
@@ -117,26 +119,26 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
thumbnailPath: thumbnailFileFromIndex(captureOptions ? captureOptions.index : 1),
ev: null
}
- if(captureOptions && captureOptions.noDownload) {
+ if (captureOptions && captureOptions.noDownload) {
logEvent("...capture complete.");
return callback && callback(err, photoRes);
}
- if(!thumb) {
+ if (!thumb) {
logEvent("capture complete, invalid thumbnail! Using chached...");
thumb = intervalometer.lastThumb;
}
intervalometer.lastThumb = thumb;
- setTimeout(function() {
+ setTimeout(function () {
saveThumbnail(thumb, captureOptions ? captureOptions.index : 1, cameraIndex, 0);
}, 10);
- var completeCapture = function() {
+ var completeCapture = function () {
var size = {
x: 120,
q: 80
}
logEvent("capture complete, downsizing image...");
- image.downsizeJpeg(thumb, size, null, function(err, lowResJpg) {
+ image.downsizeJpeg(thumb, size, null, function (err, lowResJpg) {
var img;
if (!err && lowResJpg) {
img = lowResJpg;
@@ -145,9 +147,9 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
}
intervalometer.lastImage = img;
intervalometer.emit("photo");
- if(captureOptions.calculateEv) {
+ if (captureOptions.calculateEv) {
logEvent("capture complete, analyzing image...");
- image.exposureValue(img, function(err, ev, histogram) {
+ image.exposureValue(img, function (err, ev, histogram) {
photoRes.ev = ev;
photoRes.histogram = histogram;
logEvent("...processing complete, image ev", ev);
@@ -160,19 +162,19 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
}
});
}
- if(options.destination == 'sd' && captureOptions.saveRaw) {
- if(raw && filename) {
+ if (options.destination == 'sd' && captureOptions.saveRaw) {
+ if (raw && filename) {
var file = captureOptions.saveRaw + filename.slice(-4);
var cameraIndex = 1;
- var writeSD = function() {
- if(intervalometer.status.writing) return setTimeout(writeSD, 100);
- if(!intervalometer.status.running) return;
+ var writeSD = function () {
+ if (intervalometer.status.writing) return setTimeout(writeSD, 100);
+ if (!intervalometer.status.running) return;
intervalometer.status.writing = true;
- logEvent("Writing", raw ? raw.length : -1, "bytes to SD card...");
- fs.writeFile(file, raw, function(err) {
+ logEvent("Writing", raw ? raw.length : -1, "bytes to SD card...");
+ fs.writeFile(file, raw, function (err) {
raw = null;
intervalometer.status.writing = false;
- if(err) {
+ if (err) {
logErr("Error writing to SD:", err);
intervalometer.cancel('err');
error("Failed to save RAW image to SD card!\nTime-lapse has been stopped.\nPlease verify that the camera is set to RAW (not RAW+JPEG) and that the SD card is formatted and fully inserted into the VIEW.\nSystem message: " + err);
@@ -197,7 +199,7 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
return camera.ptp.capture;
}
case 'camera.ptp.settings':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
var base = camera.ptp.new.cameras[0].camera.exposure;
return {
shutter: base.shutter,
@@ -213,7 +215,7 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
return camera.ptp.settings;
}
case 'camera.ptp.settings-camera':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
var base = camera.ptp.new.cameras[0].camera.exposure;
return {
shutter: base.shutter && base.shutter.name,
@@ -229,7 +231,7 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
return camera.ptp.settings;
}
case 'camera.ptp.settings.details':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
var base = camera.ptp.new.cameras[0].camera.exposure;
return {
shutter: base.shutter,
@@ -245,30 +247,30 @@ function remap(method) { // remaps camera.ptp methods to use new driver if possi
return camera.ptp.settings.details;
}
case 'camera.ptp.settings.focusPos':
- if(camera.ptp.new.available) {
+ if (camera.ptp.new.available) {
return camera.ptp.new.cameras[0].camera.status.focusPos || 0;
} else {
return camera.ptp.settings.focusPos;
}
case 'camera.ptp.focus':
- if(camera.ptp.new.available) {
- return function(dir, steps, callback, absPos) {
+ if (camera.ptp.new.available) {
+ return function (dir, steps, callback, absPos) {
camera.ptp.new.moveFocus(dir * steps, 1, callback, absPos);
}
} else {
return camera.ptp.focus;
}
case 'camera.ptp.lvOff':
- if(camera.ptp.new.available) {
- return function(callback) {
+ if (camera.ptp.new.available) {
+ return function (callback) {
return camera.ptp.new.liveviewMode(false, callback);
}
} else {
return camera.ptp.lvOff;
}
case 'camera.ptp.preview':
- if(camera.ptp.new.available) {
- return function(callback) {
+ if (camera.ptp.new.available) {
+ return function (callback) {
return camera.ptp.new.liveviewMode(true, callback);
}
} else {
@@ -283,32 +285,32 @@ function thumbnailFileFromIndex(index, cameraIndex, hqVersion) {
while (indexStr.length < 5) {
indexStr = '0' + indexStr;
}
- if(!cameraIndex) cameraIndex = 1;
+ if (!cameraIndex) cameraIndex = 1;
return intervalometer.timelapseFolder + "/cam-" + cameraIndex + "-" + indexStr + (hqVersion ? "q" : "") + ".jpg"
}
function saveThumbnail(jpgBuffer, index, cameraIndex, exposureCompensation) {
var indexStr = (index + 1).toString();
- logEvent("saving thumbnails...");
- fs.writeFile(intervalometer.timelapseFolder + "/count.txt", indexStr, function() {
+ logEvent("saving thumbnails...");
+ fs.writeFile(intervalometer.timelapseFolder + "/count.txt", indexStr, function () {
//image.downsizeJpeg(jpgBuffer, {x: 320, q: 80}, null, function(err1, jpgHQBuf) {
// if (!err1 && jpgHQBuf) {
-
- //image.downsizeJpegSharp(jpgHQBuf, {x: 160, q: 80}, null, exposureCompensation, function(err2, jpgBuf) {
- try {
- image.downsizeJpeg(jpgBuffer, {x: 160, q: 80}, null, function(err2, jpgBuf) {
- if (!err2 && jpgBuf) {
- fs.writeFile(thumbnailFileFromIndex(index, cameraIndex, false), jpgBuf, function() {
- logEvent("...completed save thumbnails.");
- });
- } else {
- logErr("error saving thumbnail jpeg:", err2);
- }
+
+ //image.downsizeJpegSharp(jpgHQBuf, {x: 160, q: 80}, null, exposureCompensation, function(err2, jpgBuf) {
+ try {
+ image.downsizeJpeg(jpgBuffer, {x: 160, q: 80}, null, function (err2, jpgBuf) {
+ if (!err2 && jpgBuf) {
+ fs.writeFile(thumbnailFileFromIndex(index, cameraIndex, false), jpgBuf, function () {
+ logEvent("...completed save thumbnails.");
});
- } catch(e) {
- logErr("error while saving thumbnail jpeg:", e);
+ } else {
+ logErr("error saving thumbnail jpeg:", err2);
}
+ });
+ } catch (e) {
+ logErr("error while saving thumbnail jpeg:", e);
+ }
// fs.writeFile(thumbnailFileFromIndex(index, cameraIndex, true), jpgHQBuf, function() {
// });
@@ -318,7 +320,6 @@ function saveThumbnail(jpgBuffer, index, cameraIndex, exposureCompensation) {
}
-
gpio.setMode(gpio.MODE_RAW);
//gpio.setup(AUXTIP_OUT, gpio.DIR_OUT, function(err){
@@ -331,33 +332,33 @@ gpio.setMode(gpio.MODE_RAW);
// gpio.write(AUXRING_OUT, 1);
//});
-gpio.setup(HOTSHOE_IN, gpio.DIR_IN, function(err){
- if(err) logErr("GPIO error: ", err);
+gpio.setup(HOTSHOE_IN, gpio.DIR_IN, function (err) {
+ if (err) logErr("GPIO error: ", err);
});
var intervalometer = new EventEmitter();
intervalometer.db = db;
-intervalometer.enableLogging = false;
+intervalometer.enableLogging = true;
function log() {
- if(!intervalometer.enableLogging) return;
- if(arguments.length > 0) {
+ if (!intervalometer.enableLogging) return;
+ if (arguments.length > 0) {
arguments[0] = "INTERVALOMETER: (trace) " + arguments[0];
}
console.log.apply(console, arguments);
}
function logErr() {
- if(arguments.length > 0) {
+ if (arguments.length > 0) {
arguments[0] = "INTERVALOMETER: (error) " + arguments[0];
}
console.log.apply(console, arguments);
}
function logEvent() {
- if(arguments.length > 0) {
+ if (arguments.length > 0) {
arguments[0] = "INTERVALOMETER: " + arguments[0];
}
console.log.apply(console, arguments);
@@ -400,8 +401,8 @@ intervalometer.status = {
intervalometer.internal = {};
-setInterval(function() {
- if(!intervalometer.status.running) {
+setInterval(function () {
+ if (!intervalometer.status.running) {
intervalometer.emit("intervalometer.status", intervalometer.status);
}
}, 30000);
@@ -416,34 +417,39 @@ var retryHandle = null;
var referencePhotoRes = null;
var retryCounter = 0;
-auxTrigger.on('press', function() {
+auxTrigger.on('press', function () {
if (intervalometer.status.running && intervalometer.currentProgram.intervalMode == 'aux' && !pendingPhoto && !intervalometer.status.waitForStartup) {
logEvent("AUX2 trigger!");
- if(timerHandle) clearTimeout(timerHandle);
+ if (timerHandle) clearTimeout(timerHandle);
timerHandle = setTimeout(runPhoto, 0);
} else {
logEvent("AUX2 trigger! (ignoring)");
}
});
-auxTrigger.on('error', function(err) {
+auxTrigger.on('error', function (err) {
logErr("AUX2 error: ", err);
});
function motionSyncSetup() {
- aux2out({lengthMs: 0, invert: (auxMotionConfig.inverted && intervalometer.currentProgram && intervalometer.currentProgram.intervalMode != 'aux')}, function(){});
+ aux2out({
+ lengthMs: 0,
+ invert: (auxMotionConfig.inverted && intervalometer.currentProgram && intervalometer.currentProgram.intervalMode != 'aux')
+ }, function () {
+ });
}
+
motionSyncSetup();
function motionSyncPulse(callback) {
if (intervalometer.status.running && intervalometer.currentProgram.intervalMode != 'aux') {
- gpio.read(HOTSHOE_IN, function(err, shutterClosed) {
+ gpio.read(HOTSHOE_IN, function (err, shutterClosed) {
log("hotshoe:", shutterClosed);
- if(shutterClosed) {
+ if (shutterClosed) {
log("=> AUX Pulse");
busyAuxPulse = true;
- aux2out({lengthMs: auxMotionConfig.lengthMs, invert: auxMotionConfig.inverted}, function(){
+ aux2out({lengthMs: auxMotionConfig.lengthMs, invert: auxMotionConfig.inverted}, function () {
busyAuxPulse = false;
log("=> AUX Pulse Complete");
callback && callback();
@@ -452,15 +458,31 @@ function motionSyncPulse(callback) {
setTimeout(motionSyncPulse, 100);
}
});
- }
+ }
}
function fileInit() {
- fs.writeFileSync(intervalometer.status.timelapseFolder + "/details.csv", "frame, error, target, setting, rate, interval, timestamp, file, p, i, d\n");
+ // fs.writeFileSync(intervalometer.status.timelapseFolder + "/details.csv", "frame, error, target, setting, rate, interval, timestamp, file, p, i, d, direction\n");
+ fs.writeFileSync(intervalometer.status.timelapseFolder + "/details.csv",
+ "frame, evDiff, targetEv, rampEv, rate, lastPhotoLum, intervalMs, lastPhotoTime, file, pComponent, iComponent, dComponent, direction\n");
+
}
function writeFile() {
- fs.appendFileSync(intervalometer.status.timelapseFolder + "/details.csv", intervalometer.status.frames + ", " + intervalometer.status.evDiff + "," + exp.status.targetEv + "," + intervalometer.status.rampEv + "," + exp.status.rate + "," + (intervalometer.status.intervalMs / 1000) + "," + intervalometer.status.lastPhotoTime + "," + intervalometer.status.path + "," + exp.status.pComponent + "," + exp.status.iComponent + "," + exp.status.dComponent + "\n");
+ fs.appendFileSync(intervalometer.status.timelapseFolder + "/details.csv",
+ intervalometer.status.frames + ", " +
+ intervalometer.status.evDiff + "," +
+ exp.status.targetEv + "," +
+ intervalometer.status.rampEv + "," +
+ exp.status.rate + "," +
+ intervalometer.status.lastPhotoLum + "," +
+ (intervalometer.status.intervalMs / 1000) + "," +
+ intervalometer.status.lastPhotoTime + "," +
+ intervalometer.status.path + "," +
+ exp.status.pComponent + "," +
+ exp.status.iComponent + "," +
+ exp.status.dComponent + "," +
+ exp.status.direction + "\n");
//image.writeXMP(name, intervalometer.status.evDiff);
}
@@ -479,7 +501,7 @@ function getDetails(file) {
i: exp.status.iComponent,
d: exp.status.dComponent,
};
- if(intervalometer.gpsData) {
+ if (intervalometer.gpsData) {
d.latitude = intervalometer.gpsData.lat;
d.longitude = intervalometer.gpsData.lon;
@@ -501,8 +523,8 @@ function getDetails(file) {
}
function calculateIntervalMs(interval, currentEv) {
- var dayEv = 8;
- var nightEv = -2;
+ var dayEv = exp.config.nightCompensationDayEv;
+ var nightEv = exp.config.nightCompensationNightEv;
if (intervalometer.currentProgram.intervalMode == 'fixed') {
return interval * 1000;
} else {
@@ -518,7 +540,7 @@ function calculateIntervalMs(interval, currentEv) {
}
function doKeyframeAxis(axisName, keyframes, setupFirst, interpolationMethod, position, motionFunction) {
- if(interpolationMethod != 'smooth') interpolationMethod = 'linear';
+ if (interpolationMethod != 'smooth') interpolationMethod = 'linear';
if (intervalometer.status.running && keyframes && keyframes.length > 0 && keyframes[0].position != null) {
var kfSet = null;
var kfCurrent = null;
@@ -531,7 +553,7 @@ function doKeyframeAxis(axisName, keyframes, setupFirst, interpolationMethod, po
} else {
var secondsSinceStart = intervalometer.status.lastPhotoTime + (intervalometer.status.intervalMs / 1000);
- if(intervalometer.status.frames > intervalometer.status.keyframesFrames) {
+ if (intervalometer.status.frames > intervalometer.status.keyframesFrames) {
intervalometer.status.keyframesFrames = intervalometer.status.frames;
intervalometer.status.keyframeSeconds += (intervalometer.status.intervalMs / 1000);
var diff = secondsSinceStart - intervalometer.status.keyframeSeconds;
@@ -541,15 +563,15 @@ function doKeyframeAxis(axisName, keyframes, setupFirst, interpolationMethod, po
}
var totalSeconds = 0;
- var kfPoints = keyframes.map(function(kf) {
+ var kfPoints = keyframes.map(function (kf) {
return {
x: kf.seconds,
y: kf.position || 0
}
- }).sort(function(a, b) {
- if(a.x < b.x) return -1;
- if(a.x > b.x) return 1;
- return 0;
+ }).sort(function (a, b) {
+ if (a.x < b.x) return -1;
+ if (a.x > b.x) return 1;
+ return 0;
});
kfSet = interpolate[interpolationMethod](kfPoints, intervalometer.status.keyframeSeconds);
log("KF: " + axisName + " target: " + kfSet, "points:", kfPoints);
@@ -581,8 +603,8 @@ function calculateCelestialDistance(startPos, currentPos, trackBelowHorizon) {
var easeStartDegrees = 15;
var easeEndDegrees = -5;
- if(!trackBelowHorizon && altDeg < easeStartDegrees) {
- if(altDeg < easeEndDegrees) {
+ if (!trackBelowHorizon && altDeg < easeStartDegrees) {
+ if (altDeg < easeEndDegrees) {
ease = 0;
} else {
ease = (altDeg - easeEndDegrees) / (easeStartDegrees - easeEndDegrees);
@@ -597,11 +619,11 @@ function calculateCelestialDistance(startPos, currentPos, trackBelowHorizon) {
function getTrackingMotor(trackingMotor) {
logEvent("getTrackingMotor: no motor info found for " + trackingMotor);
- if(trackingMotor && trackingMotor != 'none') {
+ if (trackingMotor && trackingMotor != 'none') {
var parts = trackingMotor.match(/^([A-Z]+)-([0-9]+)(r?)$/);
- if(parts && parts.length > 2) {
+ if (parts && parts.length > 2) {
var stepsPerDegree = 1;
- if(parts[1] == 'NMX') stepsPerDegree = 550.81967213;
+ if (parts[1] == 'NMX') stepsPerDegree = 550.81967213;
return {
driver: parts[1],
motor: parts[2],
@@ -620,9 +642,9 @@ function processKeyframes(setupFirst, callback) {
var numAxes = 1;
var axesDone = 0;
- if(intervalometer.currentProgram.scheduled) return callback();
+ if (intervalometer.currentProgram.scheduled) return callback();
- var checkDone = function(item) {
+ var checkDone = function (item) {
axesDone++;
log("KF: " + item + "completed");
log("KF: " + axesDone + " of " + numAxes + " keyframe items complete");
@@ -632,7 +654,7 @@ function processKeyframes(setupFirst, callback) {
}
}
- if(intervalometer.currentProgram.coords && intervalometer.currentProgram.coords.lat != null && intervalometer.currentProgram.coords.lon != null && !isNaN(intervalometer.currentProgram.coords.lat) && !isNaN(intervalometer.currentProgram.coords.lon)) {
+ if (intervalometer.currentProgram.coords && intervalometer.currentProgram.coords.lat != null && intervalometer.currentProgram.coords.lon != null && !isNaN(intervalometer.currentProgram.coords.lat) && !isNaN(intervalometer.currentProgram.coords.lon)) {
var sunmoon = meeus.sunmoon(new Date(), intervalometer.currentProgram.coords.lat, intervalometer.currentProgram.coords.lon, intervalometer.currentProgram.coords.alt);
var sunPos = {
azimuth: sunmoon.sunpos.az,
@@ -644,27 +666,27 @@ function processKeyframes(setupFirst, callback) {
}
}
- var eachAxis = function(axis) {
+ var eachAxis = function (axis) {
numAxes++;
log("Intervalometer: KF: running axis", m);
- if(axis.type == 'keyframe') {
- if(m == 'focus') {
- doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'linear', remap('camera.ptp.settings.focusPos'), function(focus, axisName, absFocus) {
- var doFocus = function() {
+ if (axis.type == 'keyframe') {
+ if (m == 'focus') {
+ doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'linear', remap('camera.ptp.settings.focusPos'), function (focus, axisName, absFocus) {
+ var doFocus = function () {
logEvent("KF: Moving focus by " + focus + " steps (currentPos=" + remap('camera.ptp.settings.focusPos') + ")");
var dir = focus > 0 ? 1 : -1;
var steps = Math.abs(focus);
- remap('camera.ptp.focus')(dir, steps, function() {
+ remap('camera.ptp.focus')(dir, steps, function () {
var model = remap('camera.ptp.model');
- if((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
+ if ((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
checkDone('focus');
} else {
- setTimeout(function(){
- remap('camera.ptp.lvOff')(function(){
- setTimeout(function(){
+ setTimeout(function () {
+ remap('camera.ptp.lvOff')(function () {
+ setTimeout(function () {
checkDone('focus');
- }, 500);
+ }, 500);
});
}, 500);
}
@@ -672,12 +694,12 @@ function processKeyframes(setupFirst, callback) {
}
focus += intervalometer.status.focusDiffNew;
intervalometer.status.focusDiffNew = 0;
- if(focus) {
+ if (focus) {
var model = remap('camera.ptp.model');
- if((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
+ if ((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
doFocus();
} else {
- remap('camera.ptp.preview')(function() {
+ remap('camera.ptp.preview')(function () {
setTimeout(doFocus, 1000);
});
}
@@ -685,13 +707,13 @@ function processKeyframes(setupFirst, callback) {
checkDone('focus');
}
});
- } else if(m == 'ev') {
- doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'linear', null, function(ev) {
+ } else if (m == 'ev') {
+ doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'linear', null, function (ev) {
//if (ev != null && camera.settings.ev != ev) remap('camera.setEv')(ev);
checkDone('ev');
});
- } else if(m == 'interval') {
- doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'linear', null, function(interval) {
+ } else if (m == 'interval') {
+ doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'linear', null, function (interval) {
//intervalometer.status.intervalMs = interval * 1000;
checkDone('interval');
});
@@ -699,7 +721,7 @@ function processKeyframes(setupFirst, callback) {
var parts = m.split('-');
var driver = parts[0];
var motor = parseInt(parts[1]);
- doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'smooth', motion.getPosition(driver, motor), function(move, axisName) {
+ doKeyframeAxis(m, axis.kf, setupFirst, axis.interpolation || 'smooth', motion.getPosition(driver, motor), function (move, axisName) {
var parts = axisName.split('-');
if (move && parts.length == 2) {
var driver = parts[0];
@@ -707,15 +729,15 @@ function processKeyframes(setupFirst, callback) {
log("KF: Moving " + axisName + " by " + move + " steps");
if (motion.status.available) {
var connected = false;
- for(var index = 0; index < motion.status.motors.length; index++) {
+ for (var index = 0; index < motion.status.motors.length; index++) {
var mo = motion.status.motors[index];
- if(mo.driver == driver && mo.motor == motor) {
+ if (mo.driver == driver && mo.motor == motor) {
connected = mo.connected;
break;
}
}
- if(connected) {
- motion.move(driver, motor, move, function() {
+ if (connected) {
+ motion.move(driver, motor, move, function () {
checkDone(axisName);
});
} else {
@@ -731,28 +753,28 @@ function processKeyframes(setupFirst, callback) {
}
});
}
- } else if(axis.type == 'tracking' || axis.type == 'constant') {
+ } else if (axis.type == 'tracking' || axis.type == 'constant') {
var trackingTarget = null;
- if(axis.type == 'tracking' && !intervalometer.currentProgram.coords) {
+ if (axis.type == 'tracking' && !intervalometer.currentProgram.coords) {
axis.type = 'disabled';
logErr("No GPS/coordinates available for tracking calculations");
intervalometer.emit('error', "No GPS/coordinates available for tracking calculations. Time-lapse will continue with tracking disabled on axis " + m + ".");
} else {
- if(axis.type == 'tracking' && intervalometer.currentProgram.trackingTarget == 'sun' && sunPos) {
+ if (axis.type == 'tracking' && intervalometer.currentProgram.trackingTarget == 'sun' && sunPos) {
trackingTarget = calculateCelestialDistance(intervalometer.status.sunPos, sunPos, axis.trackBelowHorizon);
- } else if(axis.type == 'tracking' && intervalometer.currentProgram.trackingTarget == 'moon' && moonPos) {
+ } else if (axis.type == 'tracking' && intervalometer.currentProgram.trackingTarget == 'moon' && moonPos) {
trackingTarget = calculateCelestialDistance(intervalometer.status.moonPos, moonPos, axis.trackBelowHorizon);
- } else if(axis.type == 'constant') {
- if(axis.rate == null) axis.rate = 15;
- if(axis.orientation == 'pan') {
+ } else if (axis.type == 'constant') {
+ if (axis.rate == null) axis.rate = 15;
+ if (axis.orientation == 'pan') {
trackingTarget = {
pan: (((new Date() / 1000) - intervalometer.status.startTime) / 3600) * parseFloat(axis.rate),
tilt: 0,
ease: 1
}
}
- if(axis.orientation == 'tilt') {
+ if (axis.orientation == 'tilt') {
trackingTarget = {
tilt: (((new Date() / 1000) - intervalometer.status.startTime) / 3600) * parseFloat(axis.rate),
pan: 0,
@@ -761,65 +783,65 @@ function processKeyframes(setupFirst, callback) {
}
}
var motor = null;
- if(axis.motor) {
+ if (axis.motor) {
motor = axis.motor;
motor.stepsPerDegree = motor.unitSteps || 1;
} else {
motor = getTrackingMotor(m);
}
var rev = axis.orientation == 'tilt' ? !axis.reverse : axis.reverse; // tilt axis is naturally reversed
- if(axis.motor && axis.motor.reverse) rev = !rev;
+ if (axis.motor && axis.motor.reverse) rev = !rev;
motor.direction = rev ? -1 : 1;
}
- if(trackingTarget) {
- if(axis.orientation == 'pan') {
+ if (trackingTarget) {
+ if (axis.orientation == 'pan') {
var panDegrees = trackingTarget.pan - intervalometer.status.trackingPan;
- if(axis.type == 'tracking') { // in case it crosses zero
- if(panDegrees > 180) panDegrees -= 360;
- if(panDegrees < -180) panDegrees += 360;
+ if (axis.type == 'tracking') { // in case it crosses zero
+ if (panDegrees > 180) panDegrees -= 360;
+ if (panDegrees < -180) panDegrees += 360;
}
var addSkippedDegrees = panDegrees;
panDegrees *= trackingTarget.ease;
addSkippedDegrees -= panDegrees;
intervalometer.status.trackingPan += addSkippedDegrees;
- if(intervalometer.status.panDiff != intervalometer.status.panDiffNew) {
+ if (intervalometer.status.panDiff != intervalometer.status.panDiffNew) {
intervalometer.status.panDiff = intervalometer.status.panDiffNew;
}
panDegrees += intervalometer.status.panDiff;
intervalometer.status.trackingPanEnabled = true;
- if(panDegrees != 0) {
+ if (panDegrees != 0) {
var panSteps = panDegrees * motor.stepsPerDegree;
- if(motor.stepsPerDegree > 100) {
+ if (motor.stepsPerDegree > 100) {
panSteps = Math.round(panSteps);
}
log("Intervalometer: tracking pan", panDegrees, intervalometer.status.trackingPan, panSteps, intervalometer.status.frames);
- motion.move(motor.driver, motor.motor, panSteps * motor.direction, function() {
+ motion.move(motor.driver, motor.motor, panSteps * motor.direction, function () {
intervalometer.status.trackingPan += panSteps / motor.stepsPerDegree;
checkDone('tracking');
});
} else {
checkDone('tracking');
}
- } else if(axis.orientation == 'tilt') {
+ } else if (axis.orientation == 'tilt') {
var tiltDegrees = trackingTarget.tilt - intervalometer.status.trackingTilt;
var addSkippedDegrees = tiltDegrees;
tiltDegrees *= trackingTarget.ease;
addSkippedDegrees -= tiltDegrees;
intervalometer.status.trackingTilt += addSkippedDegrees;
- if(intervalometer.status.tiltDiff != intervalometer.status.tiltDiffNew) {
+ if (intervalometer.status.tiltDiff != intervalometer.status.tiltDiffNew) {
intervalometer.status.tiltDiff = intervalometer.status.tiltDiffNew;
}
tiltDegrees += intervalometer.status.tiltDiff;
intervalometer.status.trackingTiltEnabled = true;
- if(tiltDegrees != 0 && axis.orientation == 'tilt') {
+ if (tiltDegrees != 0 && axis.orientation == 'tilt') {
var tiltSteps = tiltDegrees * motor.stepsPerDegree;
- if(motor.stepsPerDegree > 100) {
+ if (motor.stepsPerDegree > 100) {
tiltSteps = Math.round(tiltSteps);
}
log("Intervalometer: tracking tilt", tiltDegrees, intervalometer.status.trackingTilt, tiltSteps, intervalometer.status.frames);
- motion.move(motor.driver, motor.motor, tiltSteps * motor.direction, function() {
+ motion.move(motor.driver, motor.motor, tiltSteps * motor.direction, function () {
intervalometer.status.trackingTilt += tiltSteps / motor.stepsPerDegree;
checkDone('tracking');
});
@@ -832,9 +854,9 @@ function processKeyframes(setupFirst, callback) {
} else {
checkDone('tracking');
}
- } else if(axis.type == 'polar') {
+ } else if (axis.type == 'polar') {
var motor = null;
- if(axis.motor) {
+ if (axis.motor) {
motor = axis.motor;
motor.stepsPerDegree = motor.unitSteps || 1;
} else {
@@ -842,49 +864,49 @@ function processKeyframes(setupFirst, callback) {
}
log("Intervalometer: polar: motor.stepsPerDegree =", motor.stepsPerDegree);
var rev = axis.reverse;
- if(axis.motor && axis.motor.reverse) rev = !rev;
+ if (axis.motor && axis.motor.reverse) rev = !rev;
var polarDirection = rev ? -1 : 1;
var currentPolarPos = motion.getPosition(motor.driver, motor.motor);
- if(intervalometer.internal.polarStart == null) intervalometer.internal.polarStart = currentPolarPos;
+ if (intervalometer.internal.polarStart == null) intervalometer.internal.polarStart = currentPolarPos;
var backlashAmount = 1 * motor.stepsPerDegree;
- var degressPerHour = 15;
+ var degressPerHour = 15;
var stepsPerSecond = ((motor.stepsPerDegree * degressPerHour) / 3600) * polarDirection;
- var setupTracking = function(speed, _motor) {
- var moveBack = function(cb) {
+ var setupTracking = function (speed, _motor) {
+ var moveBack = function (cb) {
log("Intervalometer: polar: moving back", "(motor", _motor.motor, ")");
- motion.move(_motor.driver, _motor.motor, (intervalometer.internal.polarStart - currentPolarPos) + (backlashAmount * -polarDirection), function(err) {
- if(err) logErr("Intervalometer: polar: err:", err);
+ motion.move(_motor.driver, _motor.motor, (intervalometer.internal.polarStart - currentPolarPos) + (backlashAmount * -polarDirection), function (err) {
+ if (err) logErr("Intervalometer: polar: err:", err);
setTimeout(cb);
});
}
- var moveStart = function(cb) {
+ var moveStart = function (cb) {
log("Intervalometer: polar: moving to start");
- motion.move(_motor.driver, _motor.motor, backlashAmount * polarDirection, function(err) {
- if(err) logErr("Intervalometer: polar: err:", err);
+ motion.move(_motor.driver, _motor.motor, backlashAmount * polarDirection, function (err) {
+ if (err) logErr("Intervalometer: polar: err:", err);
setTimeout(cb);
});
}
- var startTracking = function() {
+ var startTracking = function () {
log("Intervalometer: polar: moving tracking...");
- if(intervalometer.status.running) intervalometer.internal.polarTrackIntervalHandle = setInterval(function(){
+ if (intervalometer.status.running) intervalometer.internal.polarTrackIntervalHandle = setInterval(function () {
log("Intervalometer: polar: continuing tracking...");
motion.joystick(_motor.driver, _motor.motor, speed + 1000);
}, 1000);
- setTimeout(function(){
+ setTimeout(function () {
checkDone('polar');
}, 100);
}
- if(remap('camera.ptp.settings.details').shutter.ev < -2) { // only for shutter speeds longer than 1/15
- moveBack(function(){
- moveStart(function(){
+ if (remap('camera.ptp.settings.details').shutter.ev < -2) { // only for shutter speeds longer than 1/15
+ moveBack(function () {
+ moveStart(function () {
startTracking();
});
});
- } else if(intervalometer.status.frames == 0) { // take up backlash on first frame
- moveBack(function(){
- moveStart(function(){
+ } else if (intervalometer.status.frames == 0) { // take up backlash on first frame
+ moveBack(function () {
+ moveStart(function () {
checkDone('polar');
});
});
@@ -892,54 +914,54 @@ function processKeyframes(setupFirst, callback) {
checkDone('polar');
}
}
- if(intervalometer.internal.polarTrackIntervalHandle) {
+ if (intervalometer.internal.polarTrackIntervalHandle) {
clearInterval(intervalometer.internal.polarTrackIntervalHandle);
intervalometer.internal.polarTrackIntervalHandle = null;
- motion.joystick(motor.driver, motor.motor, 0, function(){
+ motion.joystick(motor.driver, motor.motor, 0, function () {
setupTracking(stepsPerSecond * polarDirection, motor);
});
} else {
- motion.getBacklash(motor.driver, motor.motor, function(backlash) {
+ motion.getBacklash(motor.driver, motor.motor, function (backlash) {
log("Intervalometer: polar: backlash was", backlash);
intervalometer.internal.polarMotorBacklash = {
backlash: backlash,
driver: motor.driver,
motor: motor.motor
}
- motion.setBacklash(motor.driver, motor.motor, 0, function() {
+ motion.setBacklash(motor.driver, motor.motor, 0, function () {
setupTracking(stepsPerSecond * polarDirection, motor);
});
});
}
} else {
- if(m == 'focus') {
- var doFocus = function(focus) {
+ if (m == 'focus') {
+ var doFocus = function (focus) {
log("KF: Moving focus by " + focus + " steps");
var dir = focus > 0 ? 1 : -1;
var steps = Math.abs(focus);
- remap('camera.ptp.focus')(dir, steps, function() {
+ remap('camera.ptp.focus')(dir, steps, function () {
var model = remap('camera.ptp.model');
- if((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
+ if ((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
checkDone('focus-update');
} else {
- setTimeout(function(){
- remap('camera.ptp.lvOff')(function(){
- setTimeout(function(){
+ setTimeout(function () {
+ remap('camera.ptp.lvOff')(function () {
+ setTimeout(function () {
checkDone('focus-update');
- }, 500);
+ }, 500);
});
}, 500);
}
});
}
- if(intervalometer.status.focusDiffNew) {
+ if (intervalometer.status.focusDiffNew) {
intervalometer.status.focusDiffNew = 0;
var model = remap('camera.ptp.model');
- if((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
+ if ((model && model.match(/fuji/i)) || intervalometer.status.useLiveview) {
doFocus(intervalometer.status.focusDiffNew);
} else {
- remap('camera.ptp.preview')(function() {
- setTimeout(function(){
+ remap('camera.ptp.preview')(function () {
+ setTimeout(function () {
doFocus(intervalometer.status.focusDiffNew);
}, 1000);
});
@@ -954,7 +976,7 @@ function processKeyframes(setupFirst, callback) {
}
- for(var m in intervalometer.currentProgram.axes) {
+ for (var m in intervalometer.currentProgram.axes) {
eachAxis(intervalometer.currentProgram.axes[m]);
}
checkDone('function');
@@ -963,13 +985,13 @@ function processKeyframes(setupFirst, callback) {
function getEvOptions() {
var neededPadMs = intervalometer.autoSettings.paddingTimeMs;
- if(intervalometer.currentProgram.intervalMode == 'aux') {
- if(auxMotionConfig.externalIntervalPaddingMs > neededPadMs) neededPadMs = auxMotionConfig.externalIntervalPaddingMs; // add an extra padding for external motion
+ if (intervalometer.currentProgram.intervalMode == 'aux') {
+ if (auxMotionConfig.externalIntervalPaddingMs > neededPadMs) neededPadMs = auxMotionConfig.externalIntervalPaddingMs; // add an extra padding for external motion
} else {
- if(auxMotionConfig.lengthMs > neededPadMs) neededPadMs = auxMotionConfig.lengthMs;
+ if (auxMotionConfig.lengthMs > neededPadMs) neededPadMs = auxMotionConfig.lengthMs;
}
var maxShutterLengthMs = (intervalometer.status.intervalMs - neededPadMs);
- if(maxShutterLengthMs < 500) maxShutterLengthMs = 500; // warn on this condition?
+ if (maxShutterLengthMs < 500) maxShutterLengthMs = 500; // warn on this condition?
logEvent("\n\nIntervalometer: total padding ms:", neededPadMs, "= max shutter ms: ", maxShutterLengthMs);
return {
cameraSettings: remap('camera.ptp.settings'),
@@ -991,17 +1013,17 @@ function setupExposure(cb) {
var expSetupStartTime = new Date() / 1000;
var oldDriverEnableLv = intervalometer.status.useLiveview && !busyExposure && camera.ptp.settings && camera.ptp.settings.viewfinder == "off";
var newDriverEnableLv = intervalometer.status.useLiveview && !busyExposure && camera.ptp.new.available;
- if(oldDriverEnableLv) {
+ if (oldDriverEnableLv) {
log("\n\nEXP: setupExposure (enabling LV)");
busyExposure = true;
- return camera.ptp.liveview(function(){
+ return camera.ptp.liveview(function () {
setupExposure(cb);
});
}
- if(newDriverEnableLv) {
+ if (newDriverEnableLv) {
logEvent("\n\nEXP: setupExposure (enabling LV)");
busyExposure = true;
- return camera.ptp.new.liveviewMode(true, function(){
+ return camera.ptp.new.liveviewMode(true, function () {
setupExposure(cb);
});
}
@@ -1010,9 +1032,9 @@ function setupExposure(cb) {
log("\n\nEXP: setupExposure");
var diff = 0;
- if(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
- if(!intervalometer.status.hdrIndex) intervalometer.status.hdrIndex = 0;
- if(intervalometer.status.hdrIndex < intervalometer.status.hdrSet.length) {
+ if (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
+ if (!intervalometer.status.hdrIndex) intervalometer.status.hdrIndex = 0;
+ if (intervalometer.status.hdrIndex < intervalometer.status.hdrSet.length) {
diff = intervalometer.status.hdrSet[intervalometer.status.hdrIndex];
intervalometer.status.hdrIndex++;
} else {
@@ -1021,62 +1043,63 @@ function setupExposure(cb) {
logEvent("HDR adjustment:", diff, intervalometer.status.hdrIndex);
}
- var doSetup = function() {
- if(intervalometer.status.stopping) return cb && cb();
+ var doSetup = function () {
+ if (intervalometer.status.stopping) return cb && cb();
log("EXP: current interval: ", intervalometer.status.intervalMs, " (took ", (new Date() / 1000 - expSetupStartTime), "seconds from setup start");
- if(intervalometer.status.rampEv == null) {
+ if (intervalometer.status.rampEv == null) {
intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
+ console.log("EXP: setting default rampEV", intervalometer.status.rampEv);
}
dynamicChangeUpdate();
- if(intervalometer.status.rampMode == 'preset') {
- remap('camera.setExposure')(intervalometer.status.shutterPreset + diff, intervalometer.status.aperturePreset, intervalometer.status.isoPreset, function(err, ev) {
- if(ev != null) {
+ if (intervalometer.status.rampMode == 'preset') {
+ remap('camera.setExposure')(intervalometer.status.shutterPreset + diff, intervalometer.status.aperturePreset, intervalometer.status.isoPreset, function (err, ev) {
+ if (ev != null) {
intervalometer.status.cameraEv = ev;
- }
+ }
intervalometer.status.cameraSettings = remap('camera.ptp.settings-camera');
intervalometer.status.evDiff = intervalometer.status.cameraEv - intervalometer.status.rampEv;
log("EXP: program (preset):", "capture", " (took ", (new Date() / 1000 - expSetupStartTime), "seconds from setup start");
busyExposure = false;
- setTimeout(function(){
+ setTimeout(function () {
cb && cb(err);
}, 100)
});
} else {
- if(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
+ if (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
var options = getEvOptions();
options.doNotSet = true;
- remap('camera.setEv')(intervalometer.status.rampEv + intervalometer.status.hdrMax, options, function(err, res) {
- if(intervalometer.status.stopping) return cb && cb();
- remap('camera.setExposure')(res.shutter.ev + diff - intervalometer.status.hdrMax, res.aperture.ev, res.iso.ev, function(err, ev) {
- if(ev != null) {
+ remap('camera.setEv')(intervalometer.status.rampEv + intervalometer.status.hdrMax, options, function (err, res) {
+ if (intervalometer.status.stopping) return cb && cb();
+ remap('camera.setExposure')(res.shutter.ev + diff - intervalometer.status.hdrMax, res.aperture.ev, res.iso.ev, function (err, ev) {
+ if (ev != null) {
intervalometer.status.cameraEv = ev;
- }
+ }
intervalometer.status.cameraSettings = remap('camera.ptp.settings-camera');
intervalometer.status.evDiff = intervalometer.status.cameraEv - intervalometer.status.rampEv;
log("EXP: program (preset):", "capture", " (took ", (new Date() / 1000 - expSetupStartTime), "seconds from setup start");
busyExposure = false;
- setTimeout(function(){
+ setTimeout(function () {
cb && cb(err);
}, 100)
});
});
} else {
- remap('camera.setEv')(intervalometer.status.rampEv + diff, getEvOptions(), function(err, res) {
- if(res.ev != null) {
+ remap('camera.setEv')(intervalometer.status.rampEv + diff, getEvOptions(), function (err, res) {
+ if (res.ev != null) {
intervalometer.status.cameraEv = res.ev;
- }
+ }
intervalometer.status.cameraSettings = remap('camera.ptp.settings-camera');
intervalometer.status.evDiff = intervalometer.status.cameraEv - intervalometer.status.rampEv;
log("EXP: program:", "capture", " (took ", (new Date() / 1000 - expSetupStartTime), "seconds from setup start");
busyExposure = false;
- setTimeout(function(){
+ setTimeout(function () {
cb && cb(err);
}, 100)
});
}
}
}
- if(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0 && diff != 0) { // speed HDR performance by not refreshing settings from camera
+ if (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0 && diff != 0) { // speed HDR performance by not refreshing settings from camera
doSetup();
} else {
remap('camera.ptp.getSettings')(doSetup);
@@ -1084,8 +1107,8 @@ function setupExposure(cb) {
}
function planHdr(hdrCount, hdrStops) {
- if(!hdrStops || hdrStops < 1/3) hdrStops = 1/3;
- if(!hdrCount || hdrCount < 1) hdrCount = 1;
+ if (!hdrStops || hdrStops < 1 / 3) hdrStops = 1 / 3;
+ if (!hdrCount || hdrCount < 1) hdrCount = 1;
var totalHdr = Math.floor(hdrCount) - 1;
var overHdr = Math.floor(totalHdr / 2);
var underHdr = totalHdr - overHdr;
@@ -1093,11 +1116,11 @@ function planHdr(hdrCount, hdrStops) {
var overSet = [];
var underSet = [];
- for(var i = 0; i < overHdr; i++) {
- overSet.push(hdrStops * (i + 1));
+ for (var i = 0; i < overHdr; i++) {
+ overSet.push(hdrStops * (i + 1));
}
- for(var i = 0; i < underHdr; i++) {
- underSet.push(hdrStops * -(i + 1));
+ for (var i = 0; i < underHdr; i++) {
+ underSet.push(hdrStops * -(i + 1));
}
intervalometer.status.hdrIndex = 0;
@@ -1106,30 +1129,30 @@ function planHdr(hdrCount, hdrStops) {
intervalometer.status.hdrCount = hdrCount > 1 ? hdrCount : 0;
intervalometer.status.hdrStops = hdrCount > 1 ? hdrStops : 0;
-
- if(!camera.ptp.new.available || !(camera.ptp.new.cameras && camera.ptp.new.cameras[0] && camera.ptp.new.cameras[0].camera && camera.ptp.new.cameras[0].camera.supportsNativeHDR)) {
- while(overSet.length || underSet.length) {
- if(overSet.length) intervalometer.status.hdrSet.push(overSet.shift());
- if(underSet.length) intervalometer.status.hdrSet.push(underSet.shift());
+
+ if (!camera.ptp.new.available || !(camera.ptp.new.cameras && camera.ptp.new.cameras[0] && camera.ptp.new.cameras[0].camera && camera.ptp.new.cameras[0].camera.supportsNativeHDR)) {
+ while (overSet.length || underSet.length) {
+ if (overSet.length) intervalometer.status.hdrSet.push(overSet.shift());
+ if (underSet.length) intervalometer.status.hdrSet.push(underSet.shift());
}
log("planHdr:", intervalometer.status.hdrSet)
}
}
function checkCurrentPlan(restart) {
- if(intervalometer.currentProgram.exposurePlans && intervalometer.currentProgram.exposurePlans.length > 0) {
- var planIndex = null;
+ if (intervalometer.currentProgram.exposurePlans && intervalometer.currentProgram.exposurePlans.length > 0) {
+ var planIndex = null;
var now = (new Date()).getTime();
- for(var i = 0; i < intervalometer.currentProgram.exposurePlans.length; i++) {
+ for (var i = 0; i < intervalometer.currentProgram.exposurePlans.length; i++) {
//log("PLAN: now", now, "plan.start", new Date(intervalometer.currentProgram.exposurePlans[i].start).getTime());
- if((new Date(intervalometer.currentProgram.exposurePlans[i].start)).getTime() < now) {
+ if ((new Date(intervalometer.currentProgram.exposurePlans[i].start)).getTime() < now) {
planIndex = i;
} else {
break;
}
}
//log("PLAN: checking plans...", planIndex);
- if(intervalometer.status.currentPlanIndex !== planIndex) {
+ if (intervalometer.status.currentPlanIndex !== planIndex) {
intervalometer.status.currentPlanIndex = planIndex;
intervalometer.status.framesRemaining = Infinity;
var plan = intervalometer.currentProgram.exposurePlans[planIndex];
@@ -1145,34 +1168,33 @@ function checkCurrentPlan(restart) {
.dayInterval
.nightIntervl
*/
- if(plan.mode == 'auto') {
+ if (plan.mode == 'auto') {
intervalometer.status.rampMode = 'auto';
- if(intervalometer.status.rampEv == null) intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
+ if (intervalometer.status.rampEv == null) intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
}
- if(plan.mode == 'lock') {
- if(intervalometer.status.rampEv == null) intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
+ if (plan.mode == 'lock') {
+ if (intervalometer.status.rampEv == null) intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
intervalometer.status.rampMode = 'fixed';
}
- if(plan.mode == 'preset') {
+ if (plan.mode == 'preset') {
intervalometer.status.rampMode = 'preset';
intervalometer.status.shutterPreset = plan.shutter;
intervalometer.status.aperturePreset = plan.aperture;
intervalometer.status.isoPreset = plan.iso;
intervalometer.status.rampEv = camera.lists.getEv(intervalometer.status.shutterPreset, intervalometer.status.aperturePreset, intervalometer.status.isoPreset);
}
- if(intervalometer.currentProgram.intervalMode != 'aux') {
+ if (intervalometer.currentProgram.intervalMode != 'aux') {
intervalometer.currentProgram.intervalMode = plan.intervalMode;
- if(plan.intervalMode == 'fixed') {
+ if (plan.intervalMode == 'fixed') {
intervalometer.currentProgram.interval = plan.interval;
- }
- else if(plan.intervalMode == 'auto') {
+ } else if (plan.intervalMode == 'auto') {
intervalometer.currentProgram.dayInterval = plan.dayInterval;
intervalometer.currentProgram.nightInterval = plan.nightInterval;
}
}
planHdr(plan.hdrCount, plan.hdrStops);
- if(restart) {
+ if (restart) {
if (timerHandle) clearTimeout(timerHandle);
setupExposure(runPhoto);
}
@@ -1183,7 +1205,7 @@ function checkCurrentPlan(restart) {
}
function checkDay(m) {
- switch(m.day()) {
+ switch (m.day()) {
case 0:
return intervalometer.currentProgram.schedSunday;
case 1:
@@ -1202,17 +1224,17 @@ function checkDay(m) {
}
function checkTime(m) {
- if(intervalometer.currentProgram.schedStart == intervalometer.currentProgram.schedStop) return true;
+ if (intervalometer.currentProgram.schedStart == intervalometer.currentProgram.schedStop) return true;
- if(!intervalometer.currentProgram.schedStart || typeof intervalometer.currentProgram.schedStart != "string") return true;
- if(!intervalometer.currentProgram.schedStop || typeof intervalometer.currentProgram.schedStop != "string") return true;
+ if (!intervalometer.currentProgram.schedStart || typeof intervalometer.currentProgram.schedStart != "string") return true;
+ if (!intervalometer.currentProgram.schedStop || typeof intervalometer.currentProgram.schedStop != "string") return true;
var parts = intervalometer.currentProgram.schedStart.split(':');
- if(parts.length < 2) return true;
+ if (parts.length < 2) return true;
var startHour = parseInt(parts[0]);
var startMinute = parseInt(parts[1]);
parts = intervalometer.currentProgram.schedStop.split(':');
- if(parts.length < 2) return true;
+ if (parts.length < 2) return true;
var stopHour = parseInt(parts[0]);
var stopMinute = parseInt(parts[1]);
@@ -1223,7 +1245,7 @@ function checkTime(m) {
log("Intervalometer: mNow", mNow, "mStart", mStart, "mStop", mStop);
intervalometer.status.minutesUntilStart = Math.round(mStart - mNow);
- if(mStart < mStop) { // day only
+ if (mStart < mStop) { // day only
return (mNow >= mStart && mNow < mStop);
} else { // night only
return (mNow >= mStart || mNow < mStop);
@@ -1231,76 +1253,80 @@ function checkTime(m) {
}
var scheduleHandle = null;
+
function waitForSchedule() {
- scheduleHandle = setTimeout(function(){
- if(scheduled(true)) {
- if(intervalometer.status.running) {
+ scheduleHandle = setTimeout(function () {
+ if (scheduled(true)) {
+ if (intervalometer.status.running) {
logEvent("scheduled start beginning...");
- if(intervalometer.status.frames > 0) {
- intervalometer.cancel('scheduled', function(){ // each day a new clip is generated
- setTimeout(function(){
+ if (intervalometer.status.frames > 0) {
+ intervalometer.cancel('scheduled', function () { // each day a new clip is generated
+ setTimeout(function () {
logEvent("running scheduled start...");
intervalometer.run(intervalometer.currentProgram, null, intervalometer.status.timeOffsetSeconds, intervalometer.status.exposureReferenceEv);
});
});
} else {
- setTimeout(function(){
+ setTimeout(function () {
logEvent("running scheduled start...");
intervalometer.run(intervalometer.currentProgram, null, intervalometer.status.timeOffsetSeconds, intervalometer.status.exposureReferenceEv || 0);
});
}
- } else {
+ } else {
logEvent("scheduled start canceled because time-lapse is no longer running.");
- }
+ }
} else {
waitForSchedule();
}
}, 60000);
}
+
var wasDelayed = false;
+
function scheduled(noResume) {
- if(intervalometer.currentProgram && intervalometer.currentProgram.scheduled) {
+ if (intervalometer.currentProgram && intervalometer.currentProgram.scheduled) {
var m = moment().add(intervalometer.status.timeOffsetSeconds, 'seconds');
- if(checkDay(m)) {
- if(checkTime(m)) {
- if(wasDelayed) {
+ if (checkDay(m)) {
+ if (checkTime(m)) {
+ if (wasDelayed) {
logEvent("scheduled start ready");
}
return true;
} else {
wasDelayed = true;
- if(intervalometer.status.minutesUntilStart < 0 && intervalometer.status.frames > 0) {
+ if (intervalometer.status.minutesUntilStart < 0 && intervalometer.status.frames > 0) {
intervalometer.status.message = "done for today, rebooting...";
logEvent("schedule complete, rebooting system and resuming...");
intervalometer.status.autoRestart = true;
- return intervalometer.cancel('scheduled', function(){ // each day a new clip is generated
- setTimeout(function() {
- exec('nohup /bin/sh -c "killall node; sleep 2; killall -s 9 node; init 6"', function() {}); // restarting system
+ return intervalometer.cancel('scheduled', function () { // each day a new clip is generated
+ setTimeout(function () {
+ exec('nohup /bin/sh -c "killall node; sleep 2; killall -s 9 node; init 6"', function () {
+ }); // restarting system
}, 3000);
});
} else {
- if(intervalometer.status.minutesUntilStart < 0) {
+ if (intervalometer.status.minutesUntilStart < 0) {
intervalometer.status.message = "today's schedule complete, waiting...";
} else {
var minutes = intervalometer.status.minutesUntilStart % 60;
var hours = (intervalometer.status.minutesUntilStart - minutes) / 60;
- if(hours > 0) {
- intervalometer.status.message = "starting in " + hours + "hour" + (hours > 1 ? "s, ":", ") + minutes + " minute" + (minutes > 1 ? "s...":"...");
+ if (hours > 0) {
+ intervalometer.status.message = "starting in " + hours + "hour" + (hours > 1 ? "s, " : ", ") + minutes + " minute" + (minutes > 1 ? "s..." : "...");
} else {
- intervalometer.status.message = "starting in " + minutes + " minute" + (minutes > 1 ? "s...":"...");
+ intervalometer.status.message = "starting in " + minutes + " minute" + (minutes > 1 ? "s..." : "...");
}
}
}
intervalometer.emit("intervalometer.status", intervalometer.status);
- if(!noResume) waitForSchedule();
+ if (!noResume) waitForSchedule();
return false;
}
} else {
wasDelayed = true;
intervalometer.status.message = "not scheduled today, waiting...";
intervalometer.emit("intervalometer.status", intervalometer.status);
- if(!noResume) waitForSchedule();
+ if (!noResume) waitForSchedule();
return false;
}
} else {
@@ -1310,7 +1336,7 @@ function scheduled(noResume) {
function runPhoto(isRetry) {
//log("#############################");
- if(!intervalometer.status.running) {
+ if (!intervalometer.status.running) {
busyPhoto = false;
busyExposure = false;
pendingPhoto = false;
@@ -1319,38 +1345,40 @@ function runPhoto(isRetry) {
return;
}
- if(busyAuxPulse) return setTimeout(runPhoto, 100);
-
- if((busyPhoto || busyExposure) && pendingPhoto && !isRetry) {
+ if (busyAuxPulse) return setTimeout(runPhoto, 100);
+
+ if ((busyPhoto || busyExposure) && pendingPhoto && !isRetry) {
logEvent("dropping frame!");
return; // drop frame if backed up
}
if ((busyPhoto || busyExposure || busyKeyframes) && intervalometer.currentProgram.rampMode != "fixed") {
- if(retryCounter == 0) {
- if(busyPhoto) log("P");
- if(busyExposure) log("E");
- if(busyKeyframes) log("K");
+ if (retryCounter == 0) {
+ if (busyPhoto) log("P");
+ if (busyExposure) log("E");
+ if (busyKeyframes) log("K");
}
retryCounter++;
- if(retryCounter >= 20) retryCounter = 0;
- if (intervalometer.status.running) retryHandle = setTimeout(function(){runPhoto(true);}, 100);
+ if (retryCounter >= 20) retryCounter = 0;
+ if (intervalometer.status.running) retryHandle = setTimeout(function () {
+ runPhoto(true);
+ }, 100);
return;
}
- if(!intervalometer.status.running) return;
- if(intervalometer.status.first) {
+ if (!intervalometer.status.running) return;
+ if (intervalometer.status.first) {
intervalometer.status.first = false;
- return setTimeout(function() {
+ return setTimeout(function () {
setupExposure(runPhoto);
});
}
- if(busyPhoto || busyExposure) pendingPhoto = true; else pendingPhoto = false;
+ if (busyPhoto || busyExposure) pendingPhoto = true; else pendingPhoto = false;
busyPhoto = true;
if (remap('camera.ptp.connected')) {
//console.trace("Starting Photo...");
- if(intervalometer.status.useLiveview && !camera.ptp.new.available && !camera.ptp.lvOn) camera.ptp.liveview();
- if(intervalometer.status.useLiveview && camera.ptp.new.available && !camera.ptp.new.cameras[0].camera.status.liveview) camera.ptp.new.liveviewMode(true);
- if(!(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) || intervalometer.status.hdrIndex == 1) {
+ if (intervalometer.status.useLiveview && !camera.ptp.new.available && !camera.ptp.lvOn) camera.ptp.liveview();
+ if (intervalometer.status.useLiveview && camera.ptp.new.available && !camera.ptp.new.cameras[0].camera.status.liveview) camera.ptp.new.liveviewMode(true);
+ if (!(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) || intervalometer.status.hdrIndex == 1) {
intervalometer.status.captureStartTime = new Date() / 1000;
}
intervalometer.emit("intervalometer.status", intervalometer.status);
@@ -1358,8 +1386,8 @@ function runPhoto(isRetry) {
thumbnail: true,
index: intervalometer.status.frames,
noDownload: (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0 && intervalometer.status.hdrIndex > 0) // only fetch thumbnail for the reference photo in the HDR set
- //saveTiff: "/mnt/sd/test" + intervalometer.status.frames + ".tiff",
- //saveRaw: "/mnt/sd/test" + intervalometer.status.frames + ".cr2",
+ //saveTiff: "/mnt/sd/test" + intervalometer.status.frames + ".tiff",
+ //saveRaw: "/mnt/sd/test" + intervalometer.status.frames + ".cr2",
}
if (intervalometer.currentProgram.destination == 'sd' && camera.ptp.sdPresent && camera.ptp.sdMounted) {
log("CAPT: Saving timelapse to SD card");
@@ -1377,21 +1405,21 @@ function runPhoto(isRetry) {
if (intervalometer.status.running && scheduled()) timerHandle = setTimeout(runPhoto, intervalometer.status.intervalMs);
var details = remap('camera.ptp.settings.details');
var delayMs = intervalometer.status.intervalMs / 2;
- if(details && details.shutter) {
+ if (details && details.shutter) {
delayMs = camera.lists.getSecondsFromEv(details.shutter.ev) * 1000;
}
setTimeout(motionSyncPulse, delayMs + 1000);
captureOptions.calculateEv = false;
intervalometer.status.lastPhotoTime = new Date() / 1000 - intervalometer.status.startTime;
- if(intervalometer.status.hdrCount && intervalometer.status.hdrCount > 1 && intervalometer.status.hdrStops > 0) {
+ if (intervalometer.status.hdrCount && intervalometer.status.hdrCount > 1 && intervalometer.status.hdrStops > 0) {
captureOptions.hdrCount = intervalometer.status.hdrCount;
captureOptions.hdrStops = intervalometer.status.hdrStops;
}
- remap('camera.ptp.capture')(captureOptions, function(err, photoRes) {
+ remap('camera.ptp.capture')(captureOptions, function (err, photoRes) {
if (!err && photoRes) {
intervalometer.status.path = photoRes.file;
- if(photoRes.cameraCount > 1) {
- for(var i = 0; i < photoRes.cameraResults.length; i++) {
+ if (photoRes.cameraCount > 1) {
+ for (var i = 0; i < photoRes.cameraResults.length; i++) {
log("photoRes.cameraResults[" + i + "]:", photoRes.cameraResults[i].file, photoRes.cameraResults[i].cameraIndex, photoRes.cameraResults[i].thumbnailPath);
db.setTimelapseFrame(intervalometer.status.id, 0, getDetails(photoRes.cameraResults[i].file), photoRes.cameraResults[i].cameraIndex, photoRes.cameraResults[i].thumbnailPath);
}
@@ -1403,7 +1431,7 @@ function runPhoto(isRetry) {
intervalometer.status.frames++;
//writeFile();
intervalometer.emit("intervalometer.status", intervalometer.status);
- log("TL: program intervalometer.status:", JSON.stringify(intervalometer.status));
+ // log("TL: program intervalometer.status:", intervalometer.status);
} else {
logErr("error occurred during capture", err);
intervalometer.emit('error', "An error occurred during capture. This could mean that the camera body is not supported or possibly an issue with the cable disconnecting.\nThe time-lapse will attempt to continue anyway.\nSystem message: ", err);
@@ -1417,25 +1445,27 @@ function runPhoto(isRetry) {
dynamicChangeUpdate();
busyKeyframes = true;
busyPhoto = false;
- processKeyframes(false, function() {
+ processKeyframes(false, function () {
busyKeyframes = false;
pendingPhoto = false;
});
try {
- if (global.gc) {global.gc();}
+ if (global.gc) {
+ global.gc();
+ }
} catch (e) {
- logEvent("garbage collection failed:", e);
+ logEvent("garbage collection failed:", e);
}
});
} else {
if (intervalometer.status.rampEv === null) {
- intervalometer.status.cameraEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
+ intervalometer.status.cameraEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
intervalometer.status.rampEv = intervalometer.status.cameraEv;
}
captureOptions.exposureCompensation = intervalometer.status.evDiff || 0;
- if(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
- if(intervalometer.status.hdrIndex == 0) {
+ if (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
+ if (intervalometer.status.hdrIndex == 0) {
captureOptions.calculateEv = true;
} else {
captureOptions.calculateEv = false;
@@ -1444,15 +1474,15 @@ function runPhoto(isRetry) {
captureOptions.calculateEv = true;
}
- if(intervalometer.currentProgram.intervalMode == 'aux') {
- if(intervalometer.status.intervalStartTime) intervalometer.status.intervalMs = ((new Date() / 1000) - intervalometer.status.intervalStartTime) * 1000;
+ if (intervalometer.currentProgram.intervalMode == 'aux') {
+ if (intervalometer.status.intervalStartTime) intervalometer.status.intervalMs = ((new Date() / 1000) - intervalometer.status.intervalStartTime) * 1000;
intervalometer.status.intervalStartTime = new Date() / 1000;
- } else if(!(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) || intervalometer.status.hdrIndex == 1) { // only start interval timer at first HDR exposure
- intervalometer.status.intervalMs = calculateIntervalMs(intervalometer.currentProgram.interval, intervalometer.status.rampEv);
+ } else if (!(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) || intervalometer.status.hdrIndex == 1) { // only start interval timer at first HDR exposure
+ intervalometer.status.intervalMs = calculateIntervalMs(intervalometer.currentProgram.interval, intervalometer.status.rampEv);
log("TL: Setting timer for interval at ", intervalometer.status.intervalMs);
if (timerHandle) clearTimeout(timerHandle);
- var runIntervalHdrCheck = function() {
- if(!(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) || intervalometer.status.hdrIndex == 1) {
+ var runIntervalHdrCheck = function () {
+ if (!(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) || intervalometer.status.hdrIndex == 1) {
runPhoto();
} else {
log("HDR: delaying interval for HDR set");
@@ -1460,24 +1490,24 @@ function runPhoto(isRetry) {
}
}
if (intervalometer.status.running && scheduled()) timerHandle = setTimeout(runIntervalHdrCheck, intervalometer.status.intervalMs);
- }
+ }
intervalometer.emit("intervalometer.status", intervalometer.status);
var shutterEv;
- if(remap('camera.ptp.settings.details') && remap('camera.ptp.settings.details').shutter) shutterEv = remap('camera.ptp.settings.details').shutter.ev; else shutterEv = 0;
+ if (remap('camera.ptp.settings.details') && remap('camera.ptp.settings.details').shutter) shutterEv = remap('camera.ptp.settings.details').shutter.ev; else shutterEv = 0;
- if(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0 && intervalometer.status.hdrIndex > 0 && intervalometer.status.rampEv + intervalometer.status.hdrMax >= camera.maxEv(remap('camera.ptp.settings'), getEvOptions())) {
+ if (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0 && intervalometer.status.hdrIndex > 0 && intervalometer.status.rampEv + intervalometer.status.hdrMax >= camera.maxEv(remap('camera.ptp.settings'), getEvOptions())) {
intervalometer.status.hdrIndex = 0; // disable HDR is the exposure is at the maximum
}
- if(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0 && intervalometer.status.hdrIndex > 0) {
- if(checkCurrentPlan(true)) {
+ if (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0 && intervalometer.status.hdrIndex > 0) {
+ if (checkCurrentPlan(true)) {
busyPhoto = false;
return;
}
//var nextHDRms = 100 + camera.lists.getSecondsFromEv(shutterEv) * 1000;
//log("running next in HDR sequence", intervalometer.status.hdrIndex, nextHDRms);
- remap('camera.ptp.capture')(captureOptions, function(err, res) {
- setupExposure(function(){
+ remap('camera.ptp.capture')(captureOptions, function (err, res) {
+ setupExposure(function () {
busyPhoto = false;
runPhoto()
});
@@ -1494,23 +1524,23 @@ function runPhoto(isRetry) {
setTimeout(motionSyncPulse, msDelayPulse);
intervalometer.status.lastPhotoTime = new Date() / 1000 - intervalometer.status.startTime;
}
- if(intervalometer.status.hdrCount && intervalometer.status.hdrCount > 1 && intervalometer.status.hdrStops > 0) {
+ if (intervalometer.status.hdrCount && intervalometer.status.hdrCount > 1 && intervalometer.status.hdrStops > 0) {
captureOptions.hdrCount = intervalometer.status.hdrCount;
captureOptions.hdrStops = intervalometer.status.hdrStops;
}
- remap('camera.ptp.capture')(captureOptions, function(err, photoRes) {
+ remap('camera.ptp.capture')(captureOptions, function (err, photoRes) {
if (!err && photoRes) {
- if(!intervalometer.status.hdrIndex) referencePhotoRes = photoRes;
+ if (!intervalometer.status.hdrIndex) referencePhotoRes = photoRes;
var bufferTime = (new Date() / 1000) - intervalometer.status.captureStartTime - camera.lists.getSecondsFromEv(remap('camera.ptp.settings.details').shutter.ev);
- if(!intervalometer.status.bufferSeconds) {
+ if (!intervalometer.status.bufferSeconds) {
intervalometer.status.bufferSeconds = bufferTime;
- } else if(bufferTime != intervalometer.status.bufferSeconds) {
+ } else if (bufferTime != intervalometer.status.bufferSeconds) {
intervalometer.status.bufferSeconds = (intervalometer.status.bufferSeconds + bufferTime) / 2;
}
intervalometer.status.path = referencePhotoRes.file;
- if(referencePhotoRes.cameraCount > 1) {
- for(var i = 0; i < referencePhotoRes.cameraResults.length; i++) {
+ if (referencePhotoRes.cameraCount > 1) {
+ for (var i = 0; i < referencePhotoRes.cameraResults.length; i++) {
db.setTimelapseFrame(intervalometer.status.id, intervalometer.status.evDiff, getDetails(referencePhotoRes.cameraResults[i].file), referencePhotoRes.cameraResults[i].cameraIndex, referencePhotoRes.cameraResults[i].thumbnailPath);
}
} else {
@@ -1519,31 +1549,35 @@ function runPhoto(isRetry) {
intervalometer.autoSettings.paddingTimeMs = intervalometer.status.bufferSeconds * 1000 + 500; // add a half second for setting exposure
var model = remap('camera.ptp.model');
- if(model && model.match(/5DS/i)) intervalometer.autoSettings.paddingTimeMs += 1000; // add one second for 5DS
+ if (model && model.match(/5DS/i)) intervalometer.autoSettings.paddingTimeMs += 1000; // add one second for 5DS
- if(intervalometer.status.rampMode == "auto") {
- intervalometer.status.rampEv = exp.calculate(intervalometer.currentProgram.rampAlgorithm, intervalometer.currentProgram.lrtDirection, intervalometer.status.rampEv, referencePhotoRes.ev, referencePhotoRes.histogram, camera.minEv(remap('camera.ptp.settings'), getEvOptions()), camera.maxEv(remap('camera.ptp.settings'), getEvOptions()));
+ if (intervalometer.status.rampMode == "auto") {
+ intervalometer.status.rampEv = exp.calculate(intervalometer.currentProgram.rampAlgorithm, intervalometer.currentProgram.lrtDirection, intervalometer.status.rampEv, referencePhotoRes.ev, referencePhotoRes.histogram,
+ camera.minEv(remap('camera.ptp.settings'), getEvOptions()), camera.maxEv(remap('camera.ptp.settings'), getEvOptions()),
+ intervalometer.status.frames
+ );
intervalometer.status.rampRate = exp.status.rate;
- } else if(intervalometer.status.rampMode == "fixed") {
+ } else if (intervalometer.status.rampMode == "fixed") {
intervalometer.status.rampRate = 0;
}
intervalometer.status.path = referencePhotoRes.file;
- intervalometer.status.message = "running";
- if(!checkCurrentPlan(true)) setupExposure();
+ intervalometer.status.lastPhotoLum = referencePhotoRes.ev;
+ intervalometer.status.message = "running";
+ if (!checkCurrentPlan(true)) setupExposure();
if (intervalometer.status.framesRemaining > 0) intervalometer.status.framesRemaining--;
intervalometer.status.frames++;
writeFile();
- if(intervalometer.currentProgram.intervalMode == 'aux') intervalometer.status.message = "waiting for AUX2...";
+ if (intervalometer.currentProgram.intervalMode == 'aux') intervalometer.status.message = "waiting for AUX2...";
intervalometer.emit("intervalometer.status", intervalometer.status);
- log("TL: program intervalometer.status:", JSON.stringify(intervalometer.status));
- if(intervalometer.status.frames == 1 && intervalometer.status.exposureReferenceEv == null) {
+ //log("TL: program intervalometer.status:", JSON.stringify(intervalometer.status));
+ if (intervalometer.status.frames == 1 && intervalometer.status.exposureReferenceEv == null) {
brightWarning(photoRes.ev);
}
} else {
- if(!err) err = "unknown";
+ if (!err) err = "unknown";
error("An error occurred during capture. This could mean that the camera body is not supported or possibly an issue with the cable disconnecting.\nThe time-lapse will attempt to continue anyway.\nSystem message: " + err);
logErr("capture error:", err);
}
@@ -1556,16 +1590,18 @@ function runPhoto(isRetry) {
}
busyKeyframes = true;
busyPhoto = false;
- processKeyframes(false, function() {
+ processKeyframes(false, function () {
busyKeyframes = false;
pendingPhoto = false;
log("INTERVALOMETER: KF completed.");
});
try {
- if (global.gc) {global.gc();}
+ if (global.gc) {
+ global.gc();
+ }
} catch (e) {
- logEvent("garbage collection failed:", e);
+ logEvent("garbage collection failed:", e);
}
});
}
@@ -1573,7 +1609,7 @@ function runPhoto(isRetry) {
}
function brightWarning(ev) {
- if(ev > 2.5) {
+ if (ev > 2.5) {
logErr("warn exposure too high")
error("WARNING: the exposure is too high for reliable ramping. It will attempt to continue, but it's strongly recommended to stop the time-lapse, descrease the exposure to expose for the highlights and then start again.");
}
@@ -1581,22 +1617,22 @@ function brightWarning(ev) {
function error(msg, callback) {
log("INTERVALOMETER: error:", msg);
- setTimeout(function(){
+ setTimeout(function () {
intervalometer.emit("error", msg);
}, 50);
- setTimeout(function(){
+ setTimeout(function () {
return callback && callback(msg);
}, 100);
}
-camera.ptp.on('saveError', function(msg) {
+camera.ptp.on('saveError', function (msg) {
if (intervalometer.status.running) {
intervalometer.cancel('err');
logErr("failed saving to SD card:", msg);
error("Failed to save RAW image to SD card!\nTime-lapse has been stopped.\nPlease verify that the camera is set to RAW (not RAW+JPEG) and that the SD card is formatted and fully inserted into the VIEW.\nSystem message: " + msg);
}
});
-camera.ptp.on('saveErrorCardFull', function(msg) {
+camera.ptp.on('saveErrorCardFull', function (msg) {
if (intervalometer.status.running) {
intervalometer.cancel('err');
logErr("SD card full, save failed:", msg);
@@ -1605,18 +1641,19 @@ camera.ptp.on('saveErrorCardFull', function(msg) {
});
function autoSetExposure(offset, callback) {
- if(!offset) offset = 0;
+ if (!offset) offset = 0;
+
function captureTestEv() {
logEvent("Auto Setting Exposure...");
- remap('camera.ptp.capture')({mode:'test'}, function(err, res) {
- if(!err && res && res.ev != null) {
+ remap('camera.ptp.capture')({mode: 'test'}, function (err, res) {
+ if (!err && res && res.ev != null) {
intervalometer.status.message = "checking/setting exposure...";
intervalometer.emit("intervalometer.status", intervalometer.status);
var evChange = res.ev - offset;
- remap('camera.ptp.getSettings')(function() {
+ remap('camera.ptp.getSettings')(function () {
var currentEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
- remap('camera.setEv')(currentEv + evChange, getEvOptions(), function(err, res) {
- if(Math.abs(evChange) < 2) {
+ remap('camera.setEv')(currentEv + evChange, getEvOptions(), function (err, res) {
+ if (Math.abs(evChange) < 2) {
callback && callback(null);
} else {
captureTestEv();
@@ -1624,90 +1661,109 @@ function autoSetExposure(offset, callback) {
})
});
} else {
- callback && callback(err||"invalid exposure");
+ callback && callback(err || "invalid exposure");
}
});
}
+
captureTestEv();
}
-intervalometer.validate = function(program) {
+intervalometer.validate = function (program) {
var results = {
errors: []
};
- if(program.frames === null) program.frames = Infinity;
-
+ if (program.frames === null) program.frames = Infinity;
+
if (parseInt(program.delay) < 1) program.delay = 1;
- if(program.scheduled) program.delay = 0;
- if(program.rampMode == 'fixed' && !program.scheduled) {
- if (parseInt(program.frames) < 1) results.errors.push({param:'frames', reason: 'frame count not set'});
+ if (program.scheduled) program.delay = 0;
+ if (program.rampMode == 'fixed' && !program.scheduled) {
+ if (parseInt(program.frames) < 1) results.errors.push({param: 'frames', reason: 'frame count not set'});
} else {
- if(program.intervalMode == 'fixed' || program.rampMode == 'fixed') {
- if (parseInt(program.interval) < 1) results.errors.push({param:'interval', reason: 'interval not set or too short'});
+ if (program.intervalMode == 'fixed' || program.rampMode == 'fixed') {
+ if (parseInt(program.interval) < 1) results.errors.push({
+ param: 'interval',
+ reason: 'interval not set or too short'
+ });
} else {
- if (parseInt(program.dayInterval) < 2) results.errors.push({param:'dayInterval', reason: 'dayInterval must be at least 2 seconds'});
- if (parseInt(program.nightInterval) < program.dayInterval) results.errors.push({param:'nightInterval', reason: 'nightInterval shorter than dayInterval'});
- }
+ if (parseInt(program.dayInterval) < 2) results.errors.push({
+ param: 'dayInterval',
+ reason: 'dayInterval must be at least 2 seconds'
+ });
+ if (parseInt(program.nightInterval) < program.dayInterval) results.errors.push({
+ param: 'nightInterval',
+ reason: 'nightInterval shorter than dayInterval'
+ });
+ }
}
- if(!remap('camera.ptp.supports.destination') && (program.destination != 'sd' || !camera.ptp.sdPresent)) {
+ if (!remap('camera.ptp.supports.destination') && (program.destination != 'sd' || !camera.ptp.sdPresent)) {
log("VAL: Error: SD card required");
- results.errors.push({param:false, reason: "SD card required. The connected camera (" + remap('camera.ptp.model') + ") does not support saving images to the camera. Please insert an SD card into the VIEW and set the Destination to 'SD Card' so images can be saved to the card."});
+ results.errors.push({
+ param: false,
+ reason: "SD card required. The connected camera (" + remap('camera.ptp.model') + ") does not support saving images to the camera. Please insert an SD card into the VIEW and set the Destination to 'SD Card' so images can be saved to the card."
+ });
}
var settingsDetails = remap('camera.ptp.settings.details');
- if(!settingsDetails) {
+ if (!settingsDetails) {
log("VAL: Error: invalid cameras settings", settingsDetails);
- results.errors.push({param:false, reason: "unable to read camera settings."});
+ results.errors.push({param: false, reason: "unable to read camera settings."});
} else {
-
- if((!settingsDetails.iso || settingsDetails.iso.ev == null) && program.rampMode != 'fixed') {
+
+ if ((!settingsDetails.iso || settingsDetails.iso.ev == null) && program.rampMode != 'fixed') {
log("VAL: Error: invalid ISO setting", settingsDetails.iso);
- results.errors.push({param:false, reason: "invalid ISO setting on camera."});
+ results.errors.push({param: false, reason: "invalid ISO setting on camera."});
}
- if((!settingsDetails.shutter || settingsDetails.shutter.ev == null) && program.rampMode != 'fixed') {
+ if ((!settingsDetails.shutter || settingsDetails.shutter.ev == null) && program.rampMode != 'fixed') {
log("VAL: Error: invalid shutter setting", settingsDetails.shutter);
- results.errors.push({param:false, reason: "invalid shutter setting on camera."});
+ results.errors.push({param: false, reason: "invalid shutter setting on camera."});
}
- if(remap('camera.ptp.settings') && remap('camera.ptp.settings.format') != 'RAW' && program.destination == 'sd' && camera.ptp.sdPresent) {
- if(remap('camera.ptp.model') == 'SonyWifi') {
+ if (remap('camera.ptp.settings') && remap('camera.ptp.settings.format') != 'RAW' && program.destination == 'sd' && camera.ptp.sdPresent) {
+ if (remap('camera.ptp.model') == 'SonyWifi') {
log("VAL: Error: SonyWifi doesn't support Destination='SD'");
- results.errors.push({param:false, reason: "Destination must be set to 'Camera' when connected to Sony cameras via Wifi"});
+ results.errors.push({
+ param: false,
+ reason: "Destination must be set to 'Camera' when connected to Sony cameras via Wifi"
+ });
} else {
log("VAL: Error: camera not set to save in RAW");
- results.errors.push({param:false, reason: "camera must be set to save in RAW. The VIEW expects RAW files when processing images to the SD card (RAW+JPEG does not work)"});
+ results.errors.push({
+ param: false,
+ reason: "camera must be set to save in RAW. The VIEW expects RAW files when processing images to the SD card (RAW+JPEG does not work)"
+ });
}
}
}
- if(!program.axes) program.axes = {};
- if(!program.axes.focus) program.axes.focus = {type:'disabled'}; // make focus adjustment available
+ if (!program.axes) program.axes = {};
+ if (!program.axes.focus) program.axes.focus = {type: 'disabled'}; // make focus adjustment available
log("VAL: validating program:", results);
return results;
}
-intervalometer.cancel = function(reason, callback) {
- if(!callback && typeof reason == 'function') {
+intervalometer.cancel = function (reason, callback) {
+ if (!callback && typeof reason == 'function') {
callback = reason;
reason = null;
}
log("Cancelling time-lapse, reason =", reason);
- if(!reason) reason = 'stopped';
- if(intervalometer.internal.polarTrackIntervalHandle) {
+ if (!reason) reason = 'stopped';
+ if (intervalometer.internal.polarTrackIntervalHandle) {
log("polar: stopping tracking motion");
clearInterval(intervalometer.internal.polarTrackIntervalHandle);
intervalometer.internal.polarTrackIntervalHandle = null;
motion.joystick(intervalometer.internal.polarMotorBacklash.driver, intervalometer.internal.polarMotorBacklash.motor, 0);
}
- if(intervalometer.internal.polarMotorBacklash) {
- setTimeout(function(){
+ if (intervalometer.internal.polarMotorBacklash) {
+ setTimeout(function () {
log("Intervalometer: polar: resetting backlash to", intervalometer.internal.polarMotorBacklash.backlash);
- motion.setBacklash(intervalometer.internal.polarMotorBacklash.driver, intervalometer.internal.polarMotorBacklash.motor, intervalometer.internal.polarMotorBacklash.backlash, function(){
+ motion.setBacklash(intervalometer.internal.polarMotorBacklash.driver, intervalometer.internal.polarMotorBacklash.motor, intervalometer.internal.polarMotorBacklash.backlash, function () {
intervalometer.internal.polarMotorBacklash = null;
});
}, 2000);
@@ -1716,21 +1772,21 @@ intervalometer.cancel = function(reason, callback) {
clearTimeout(timerHandle);
clearTimeout(delayHandle);
intervalometer.status.stopping = true;
- if(reason == 'err') intervalometer.status.message = "stopped due to error";
- else if(reason == 'done') intervalometer.status.message = "time-lapse complete";
- else if(reason == 'schedule') intervalometer.status.message = "time-lapse stopped on schedule";
+ if (reason == 'err') intervalometer.status.message = "stopped due to error";
+ else if (reason == 'done') intervalometer.status.message = "time-lapse complete";
+ else if (reason == 'schedule') intervalometer.status.message = "time-lapse stopped on schedule";
else intervalometer.status.message = "time-lapse canceled";
intervalometer.status.framesRemaining = 0;
intervalometer.emit("intervalometer.status", intervalometer.status);
- camera.ptp.completeWrites(function() {
- var finalize = function() {
- if(intervalometer.status.writing) {
+ camera.ptp.completeWrites(function () {
+ var finalize = function () {
+ if (intervalometer.status.writing) {
console.log("INTERVALOMETER: writing...");
return setTimeout(finalize, 100);
}
- setTimeout(function(){
- if(intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
- remap('camera.ptp.getSettings')(function() {
+ setTimeout(function () {
+ if (intervalometer.status.hdrSet && intervalometer.status.hdrSet.length > 0) {
+ remap('camera.ptp.getSettings')(function () {
var options = getEvOptions();
remap('camera.setEv')(intervalometer.status.rampEv, options);
});
@@ -1742,7 +1798,7 @@ intervalometer.cancel = function(reason, callback) {
intervalometer.timelapseFolder = false;
camera.ptp.saveThumbnails(intervalometer.timelapseFolder);
camera.ptp.unmountSd();
- if(intervalometer.status.useLiveview) remap('camera.ptp.lvOff');
+ if (intervalometer.status.useLiveview) remap('camera.ptp.lvOff');
intervalometer.emit("intervalometer.status", intervalometer.status);
logEvent("==========> END TIMELAPSE", intervalometer.status.tlName, "(", reason, ")");
callback && callback();
@@ -1751,12 +1807,12 @@ intervalometer.cancel = function(reason, callback) {
finalize();
});
} else {
- if(reason != "scheduled") intervalometer.emit("intervalometer.status", intervalometer.status);
- }
+ if (reason != "scheduled") intervalometer.emit("intervalometer.status", intervalometer.status);
+ }
}
-intervalometer.resume = function() {
- if(!intervalometer.status.running) return;
+intervalometer.resume = function () {
+ if (!intervalometer.status.running) return;
logEvent("resuming time-lapse...")
camera.ptp.cancelCallbacks();
busyPhoto = false;
@@ -1765,18 +1821,18 @@ intervalometer.resume = function() {
clearTimeout(delayHandle);
clearTimeout(retryHandle);
clearTimeout(scheduleHandle);
- if(intervalometer.internal.polarTrackIntervalHandle && intervalometer.internal.polarMotorBacklash) {
+ if (intervalometer.internal.polarTrackIntervalHandle && intervalometer.internal.polarMotorBacklash) {
log("Intervalometer: polar: stopping tracking motion for resume");
clearInterval(intervalometer.internal.polarTrackIntervalHandle);
intervalometer.internal.polarTrackIntervalHandle = null;
motion.joystick(intervalometer.internal.polarMotorBacklash.driver, intervalometer.internal.polarMotorBacklash.motor, 0);
}
- if(intervalometer.status.rampMode != 'fixed' && intervalometer.status.rampEv != null && intervalometer.status.running) {
+ if (intervalometer.status.rampMode != 'fixed' && intervalometer.status.rampEv != null && intervalometer.status.running) {
camera.setEv(intervalometer.status.rampEv, getEvOptions());
}
var ms = intervalometer.status.intervalMs - ((new Date() / 1000) - (intervalometer.status.startTime + intervalometer.status.lastPhotoTime)) * 1000;
- if(ms < 0) ms = 0;
- if(scheduled() && intervalometer.status.running) setTimeout(runPhoto, ms);
+ if (ms < 0) ms = 0;
+ if (scheduled() && intervalometer.status.running) setTimeout(runPhoto, ms);
}
function getReferenceExposure(callback, tries) {
@@ -1784,15 +1840,15 @@ function getReferenceExposure(callback, tries) {
logEvent("Getting reference exposure...");
intervalometer.status.message = "capturing reference image";
intervalometer.emit("intervalometer.status", intervalometer.status);
- remap('camera.ptp.capture')({mode:'test'}, function(err, res){
+ remap('camera.ptp.capture')({mode: 'test'}, function (err, res) {
logEvent("reference exposure result:", err, res);
- if(!err && res && res.ev != null) {
+ if (!err && res && res.ev != null) {
callback && callback(null, res.ev);
} else {
- if(!tries) tries = 0;
+ if (!tries) tries = 0;
tries++;
- if(tries < 3) {
- setTimeout(function() {
+ if (tries < 3) {
+ setTimeout(function () {
getReferenceExposure(callback, tries);
}, 5000);
} else {
@@ -1802,13 +1858,13 @@ function getReferenceExposure(callback, tries) {
});
}
-intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarget, callback) {
+intervalometer.run = function (program, date, timeOffsetSeconds, autoExposureTarget, callback) {
if (intervalometer.status.running && autoExposureTarget == null) return;
intervalometer.status.stopping = false;
log("loading time-lapse program:", program);
db.set('intervalometer.currentProgram', program);
- if(date != null) { // sync time with phone app local time
+ if (date != null) { // sync time with phone app local time
var mD = moment(date);
var mN = moment();
logEvent("Intervalometer: App time:", mD.format(), "VIEW time:", mN.format());
@@ -1818,32 +1874,32 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
var secondsDiff = mD.seconds() - mN.seconds();
intervalometer.status.timeOffsetSeconds = daysDiff * 86400 + hoursDiff * 3600 + minutesDiff * 60 + secondsDiff;
logEvent("date difference (seconds):", intervalometer.status.timeOffsetSeconds);
- } else if(timeOffsetSeconds != null) { // cached timeOffsetSeconds from restart
+ } else if (timeOffsetSeconds != null) { // cached timeOffsetSeconds from restart
intervalometer.status.timeOffsetSeconds = parseInt(timeOffsetSeconds);
}
- if(!intervalometer.status.timeOffsetSeconds) intervalometer.status.timeOffsetSeconds = 0;
- if(autoExposureTarget != null && program.rampMode == 'auto') {
+ if (!intervalometer.status.timeOffsetSeconds) intervalometer.status.timeOffsetSeconds = 0;
+ if (autoExposureTarget != null && program.rampMode == 'auto') {
logEvent("using referenceEv from argument:", autoExposureTarget);
intervalometer.status.exposureReferenceEv = autoExposureTarget;
} else {
intervalometer.status.exposureReferenceEv = null;
}
- if(program.manualAperture != null) {
+ if (program.manualAperture != null) {
camera.fixedApertureEv = program.manualAperture;
- camera.lists.fixedApertureEv = program.manualAperture;
+ camera.lists.fixedApertureEv = program.manualAperture;
}
if (remap('camera.ptp.connected')) {
- remap('camera.ptp.getSettings')(function(){
+ remap('camera.ptp.getSettings')(function () {
var validationResults = intervalometer.validate(program);
if (validationResults.errors.length == 0) {
- db.getTimelapseIndex(function(err, tlIndex){
+ db.getTimelapseIndex(function (err, tlIndex) {
if (!tlIndex) {
tlIndex = 0;
}
- if(tlIndex < 99) tlIndex += 99;
+ if (tlIndex < 99) tlIndex += 99;
var list = fs.readdirSync(TLROOT);
//log("Intervalometer: time-lapse list:", list);
@@ -1851,7 +1907,7 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
do {
tlIndex++;
name = "tl-" + tlIndex;
- } while(list.indexOf(name) !== -1);
+ } while (list.indexOf(name) !== -1);
intervalometer.status.tlName = "tl-" + tlIndex;
logEvent("==========> TIMELAPSE START", intervalometer.status.tlName);
@@ -1894,21 +1950,21 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
intervalometer.internal.polarStart = null;
intervalometer.internal.polarTrackIntervalHandle = null;
- if(program.hdrCount && program.hdrCount > 1 && program.hdrStops) {
+ if (program.hdrCount && program.hdrCount > 1 && program.hdrStops) {
planHdr(program.hdrCount, program.hdrStops);
}
- if(intervalometer.status.rampMode != 'fixed') {
+ if (intervalometer.status.rampMode != 'fixed') {
checkCurrentPlan();
}
motionSyncSetup();
- if(intervalometer.currentProgram.coords && intervalometer.currentProgram.coords.lat != null && intervalometer.currentProgram.coords.lon != null && !isNaN(intervalometer.currentProgram.coords.lat) && !isNaN(intervalometer.currentProgram.coords.lon)) {
+ if (intervalometer.currentProgram.coords && intervalometer.currentProgram.coords.lat != null && intervalometer.currentProgram.coords.lon != null && !isNaN(intervalometer.currentProgram.coords.lat) && !isNaN(intervalometer.currentProgram.coords.lon)) {
intervalometer.status.latitude = intervalometer.currentProgram.coords.lat;
intervalometer.status.longitude = intervalometer.currentProgram.coords.lon;
intervalometer.status.altitude = intervalometer.currentProgram.coords.alt;
-
+
var sunmoon = meeus.sunmoon(new Date(), intervalometer.currentProgram.coords.lat, intervalometer.currentProgram.coords.lon, intervalometer.currentProgram.coords.alt || 0);
intervalometer.status.sunPos = {
azimuth: sunmoon.sunpos.az,
@@ -1919,7 +1975,10 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
altitude: sunmoon.moonpos.alt,
}
}
- exp.init(camera.minEv(remap('camera.ptp.settings'), getEvOptions()), camera.maxEv(remap('camera.ptp.settings'), getEvOptions()), program.nightLuminance, program.dayLuminance, program.highlightProtection);
+ exp.init(camera.minEv(remap('camera.ptp.settings'), getEvOptions()), camera.maxEv(remap('camera.ptp.settings'), getEvOptions()),
+ program.nightLuminance, program.dayLuminance, program.highlightProtection,
+ intervalometer.status.timelapseFolder + "/data.js"
+ );
intervalometer.status.running = true;
intervalometer.emit("intervalometer.status", intervalometer.status);
logEvent("program:", "starting", program);
@@ -1936,15 +1995,15 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
function start() {
intervalometer.emit("intervalometer.currentProgram", intervalometer.currentProgram);
intervalometer.status.useLiveview = false;
- var oldDriverUseLiveview = (camera.ptp.model && camera.ptp.model.match(/nikon/i) &&
- !camera.ptp.model.match(/ Z /i)) &&
- (((camera.ptp.settings.afmode && camera.ptp.settings.afmode != "manual") || camera.ptp.model.match(/D850/i)) ||
- (camera.ptp.settings.viewfinder && camera.ptp.settings.viewfinder != "off"));
- var newDriverUseLiveview = (camera.ptp.new.available && camera.ptp.new.model && camera.ptp.new.model.match(/nikon/i) && !camera.ptp.new.model.match(/ Z /i)) &&
- (((camera.ptp.new.cameras[0].camera.config.focusMode && camera.ptp.new.cameras[0].camera.config.focusMode.value != "mf") || camera.ptp.new.model.match(/D850/i)) ||
- (camera.ptp.new.cameras[0].camera.status.liveview));
- if(oldDriverUseLiveview || newDriverUseLiveview) {
- if(oldDriverUseLiveview) {
+ var oldDriverUseLiveview = (camera.ptp.model && camera.ptp.model.match(/nikon/i) &&
+ !camera.ptp.model.match(/ Z /i)) &&
+ (((camera.ptp.settings.afmode && camera.ptp.settings.afmode != "manual") || camera.ptp.model.match(/D850/i)) ||
+ (camera.ptp.settings.viewfinder && camera.ptp.settings.viewfinder != "off"));
+ var newDriverUseLiveview = (camera.ptp.new.available && camera.ptp.new.model && camera.ptp.new.model.match(/nikon/i) && !camera.ptp.new.model.match(/ Z /i)) &&
+ (((camera.ptp.new.cameras[0].camera.config.focusMode && camera.ptp.new.cameras[0].camera.config.focusMode.value != "mf") || camera.ptp.new.model.match(/D850/i)) ||
+ (camera.ptp.new.cameras[0].camera.status.liveview));
+ if (oldDriverUseLiveview || newDriverUseLiveview) {
+ if (oldDriverUseLiveview) {
logEvent("Intervalometer: using Nikon liveview for capture (old driver)");
camera.ptp.liveview(start2);
} else {
@@ -1959,17 +2018,17 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
}
function start2() {
- if(program.scheduled && autoExposureTarget != null) {
+ if (program.scheduled && autoExposureTarget != null) {
//if(scheduled(true)) {
// autoSetExposure(intervalometer.status.exposureReferenceEv, function(err) {
// start3();
// });
//} else {
- start3();
+ start3();
//}
} else {
- if(camera.ptp.model && camera.ptp.model.match(/nikon/i) && !camera.ptp.captureInitiated() && intervalometer.currentProgram.intervalMode == 'aux') { // only applies to old driver
- remap('camera.ptp.capture')({mode:"test"}, start3);
+ if (camera.ptp.model && camera.ptp.model.match(/nikon/i) && !camera.ptp.captureInitiated() && intervalometer.currentProgram.intervalMode == 'aux') { // only applies to old driver
+ remap('camera.ptp.capture')({mode: "test"}, start3);
} else {
start3();
}
@@ -1978,13 +2037,13 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
function start3() {
var cameras = 1, primary = 1;
- if(camera.ptp.synchronized || (camera.ptp.new.available && camera.ptp.new.cameras.length > 1)) {
- if(camera.ptp.new.available) {
+ if (camera.ptp.synchronized || (camera.ptp.new.available && camera.ptp.new.cameras.length > 1)) {
+ if (camera.ptp.new.available) {
cameras = camera.ptp.new.cameras.length;
primary = camera.ptp.new.primaryIndex;
try {
camera.ptp.new.setExposure(camera.ptp.new.cameras[primary].camera.exposure.shutter.ev, camera.ptp.new.cameras[primary].camera.exposure.aperture && camera.ptp.new.cameras[primary].camera.exposure.aperture.ev, camera.ptp.new.cameras[primary].camera.exposure.iso.ev);
- } catch(e) {
+ } catch (e) {
var sh_err = camera.ptp.new.cameras[primary] && camera.ptp.new.cameras[primary].camera && camera.ptp.new.cameras[primary].camera.exposure && camera.ptp.new.cameras[primary].camera.exposure.shutter ? camera.ptp.new.cameras[primary].camera.exposure.shutter.ev : "NULL";
var iso_err = camera.ptp.new.cameras[primary] && camera.ptp.new.cameras[primary].camera && camera.ptp.new.cameras[primary].camera.exposure && camera.ptp.new.cameras[primary].camera.exposure.iso ? camera.ptp.new.cameras[primary].camera.exposure.iso.ev : "NULL";
logErr("sync: error setting exposure:", e, e.stack, "\n\tcamera.ptp.new.cameras[primary].camera.exposure.shutter.ev: " + sh_err + "\n\tcamera.ptp.new.cameras[primary].camera.exposure.iso.ev: " + iso_err);
@@ -1994,30 +2053,31 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
primary = camera.ptp.getPrimaryCameraIndex();
}
}
- db.setTimelapse(intervalometer.status.tlName, program, cameras, primary, intervalometer.status, function(err, timelapseId) {
+ db.setTimelapse(intervalometer.status.tlName, program, cameras, primary, intervalometer.status, function (err, timelapseId) {
intervalometer.status.id = timelapseId;
- processKeyframes(true, function() {
- setTimeout(function() {
+ processKeyframes(true, function () {
+ setTimeout(function () {
busyPhoto = false;
- if(intervalometer.currentProgram.intervalMode != 'aux' || intervalometer.currentProgram.rampMode == 'fixed') {
- if(scheduled(true)) {
+ if (intervalometer.currentProgram.intervalMode != 'aux' || intervalometer.currentProgram.rampMode == 'fixed') {
+ if (scheduled(true)) {
var delayedMinutes = 0;
+
function delayed() {
- if(program.delay > 5) {
+ if (program.delay > 5) {
var minutes = (Math.round(program.delay / 60) - delayedMinutes);
intervalometer.status.message = "delaying start for " + minutes.toString() + " minute" + (minutes > 1 ? 's' : '') + "...";
intervalometer.emit("intervalometer.status", intervalometer.status);
}
var delay = 60;
- if(program.delay - delayedMinutes * 60 < 60) delay = program.delay - delayedMinutes * 60;
- if(delay < 0 || program.scheduled) delay = 0;
+ if (program.delay - delayedMinutes * 60 < 60) delay = program.delay - delayedMinutes * 60;
+ if (delay < 0 || program.scheduled) delay = 0;
delayedMinutes++;
- delayHandle = setTimeout(function() {
- if(delayedMinutes * 60 >= program.delay) {
- if(intervalometer.status.exposureReferenceEv != null && (!program.scheduled || autoExposureTarget != null)) {
- autoSetExposure(intervalometer.status.exposureReferenceEv, function(err) {
+ delayHandle = setTimeout(function () {
+ if (delayedMinutes * 60 >= program.delay) {
+ if (intervalometer.status.exposureReferenceEv != null && (!program.scheduled || autoExposureTarget != null)) {
+ autoSetExposure(intervalometer.status.exposureReferenceEv, function (err) {
intervalometer.status.startTime = new Date() / 1000; // update start time to now (important for keyframes)
- if(err) {
+ if (err) {
error("Failed to verify reference exposure after delayed start, will try to continue anyway...");
logErr("failed to verify reference exposure after delayed start")
runPhoto();
@@ -2035,9 +2095,10 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
}, delay * 1000);
}
- if((program.delay > 60 || program.scheduled) && intervalometer.status.exposureReferenceEv == null && program.rampMode == 'auto') {
- getReferenceExposure(function(err, ev) {
- if(err) {
+
+ if ((program.delay > 60 || program.scheduled) && intervalometer.status.exposureReferenceEv == null && program.rampMode == 'auto') {
+ getReferenceExposure(function (err, ev) {
+ if (err) {
intervalometer.cancel('err');
error(err);
} else {
@@ -2052,10 +2113,10 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
delayed();
}
} else {
- if(program.rampMode == 'auto') {
- if(intervalometer.status.exposureReferenceEv == null) {
- getReferenceExposure(function(err, ev) {
- if(err) {
+ if (program.rampMode == 'auto') {
+ if (intervalometer.status.exposureReferenceEv == null) {
+ getReferenceExposure(function (err, ev) {
+ if (err) {
intervalometer.cancel('err');
error(err);
} else {
@@ -2063,23 +2124,23 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
intervalometer.status.exposureReferenceEv = ev;
intervalometer.emit("intervalometer.status", intervalometer.status);
logEvent("reference EV:", intervalometer.status.exposureReferenceEv);
- if(scheduled()) runPhoto();
+ if (scheduled()) runPhoto();
}
});
} else {
- autoSetExposure(intervalometer.status.exposureReferenceEv, function(err) {
- if(err) {
+ autoSetExposure(intervalometer.status.exposureReferenceEv, function (err) {
+ if (err) {
error("Failed to verify reference exposure after delayed start, will try to continue anyway...");
}
- if(scheduled()) runPhoto();
+ if (scheduled()) runPhoto();
});
}
} else {
- if(scheduled()) runPhoto();
+ if (scheduled()) runPhoto();
}
}
}
- if(intervalometer.currentProgram.intervalMode == 'aux') {
+ if (intervalometer.currentProgram.intervalMode == 'aux') {
intervalometer.status.message = "waiting for AUX2...";
logEvent("ready and waiting for AUX2...");
intervalometer.emit("intervalometer.status", intervalometer.status);
@@ -2091,15 +2152,15 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
}
if (program.destination && program.destination == 'sd' && camera.ptp.sdPresent) {
- camera.ptp.mountSd(function(mountErr) {
- if(mountErr) {
+ camera.ptp.mountSd(function (mountErr) {
+ if (mountErr) {
logErr("failed to mount SD card");
intervalometer.cancel('err');
error("Error mounting SD card. \nVerify the SD card is formatted and fully inserted in the VIEW, then try starting the time-lapse again.\nMessage from system: " + mountErr, callback);
} else {
intervalometer.status.mediaFolder = "/media/" + intervalometer.status.tlName;
- fs.mkdir(intervalometer.status.mediaFolder, function(folderErr) {
- if(folderErr) {
+ fs.mkdir(intervalometer.status.mediaFolder, function (folderErr) {
+ if (folderErr) {
logErr("error creating folder", intervalometer.status.mediaFolder);
intervalometer.cancel('err');
error("Error creating folder on SD card: /" + intervalometer.status.tlName + ".\nVerify the card is present and not write-protected, then try starting the time-lapse again.\nAlternatively, set the Destination to Camera instead (if supported)", callback);
@@ -2117,8 +2178,8 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
} else {
var errorList = "";
var val = "";
- for(var i = 0; i < validationResults.errors.length; i++) {
- if(program.hasOwnProperty([validationResults.errors[i].param])) {
+ for (var i = 0; i < validationResults.errors.length; i++) {
+ if (program.hasOwnProperty([validationResults.errors[i].param])) {
val = " (" + program[validationResults.errors[i].param] + ")";
} else {
val = "";
@@ -2136,31 +2197,31 @@ intervalometer.run = function(program, date, timeOffsetSeconds, autoExposureTarg
}
-intervalometer.moveTracking = function(axis, degrees, callback) {
- if(axis == 'Pan') {
+intervalometer.moveTracking = function (axis, degrees, callback) {
+ if (axis == 'Pan') {
intervalometer.status.panDiffNew += degrees;
}
- if(axis == 'Tilt') {
+ if (axis == 'Tilt') {
intervalometer.status.tiltDiffNew += degrees;
}
callback && callback();
}
-intervalometer.moveFocus = function(steps, callback) {
+intervalometer.moveFocus = function (steps, callback) {
intervalometer.status.focusDiffNew += steps;
callback && callback();
}
-intervalometer.addGpsData = function(gpsData, callback) {
+intervalometer.addGpsData = function (gpsData, callback) {
intervalometer.gpsData = gpsData;
callback && callback();
}
function dynamicChangeUpdate() {
- if(intervalometer.status.dynamicChange) {
+ if (intervalometer.status.dynamicChange) {
var change = false;
- for(var param in intervalometer.status.dynamicChange) {
- if(intervalometer.status.dynamicChange.hasOwnProperty(param) && intervalometer.status.dynamicChange[param]) {
+ for (var param in intervalometer.status.dynamicChange) {
+ if (intervalometer.status.dynamicChange.hasOwnProperty(param) && intervalometer.status.dynamicChange[param]) {
var item = intervalometer.status.dynamicChange[param];
var newVal = interpolate.linear([{
x: item.startFrame,
@@ -2169,7 +2230,7 @@ function dynamicChangeUpdate() {
x: item.endFrame,
y: item.endVal
}], intervalometer.status.frames);
- switch(param) {
+ switch (param) {
case 'manualOffsetEv':
intervalometer.status.exposure.status.rampEv -= newVal - item.lastVal; // this makes for an immediate change without destabilizing the PID loop
case 'nightRefEv':
@@ -2182,14 +2243,16 @@ function dynamicChangeUpdate() {
default:
intervalometer.currentProgram[param] = newVal;
}
+ logEvent("LIVE UPDATE:", "dynamicChangeUpdate", "param", param, "newVal", newVal, "item", item, intervalometer.status.exposure.status[param]);
+
item.lastVal = newVal;
- if(item.endFrame < intervalometer.status.frames) {
+ if (item.endFrame < intervalometer.status.frames) {
delete intervalometer.status.dynamicChange[param];
}
change = true;
}
}
- if(change) {
+ if (change) {
intervalometer.emit("intervalometer.status", intervalometer.status);
intervalometer.emit("intervalometer.currentProgram", intervalometer.currentProgram);
}
@@ -2198,13 +2261,13 @@ function dynamicChangeUpdate() {
// changes 'parameter' to 'newValue' across 'frames'
// parameter can be: interval, dayInterval, nightInterval, exposureOffset, mode (immediate)
-intervalometer.dynamicChange = function(parameter, newValue, frames, callback) {
+intervalometer.dynamicChange = function (parameter, newValue, frames, callback) {
var rampableChange = ['interval', 'dayInterval', 'nightInterval'];
var specialChange = ['rampMode', 'hdrCount', 'hdrStops', 'intervalMode', 'manualOffsetEv', 'dayRefEv', 'nightRefEv', 'rampEv', 'frames'];
- if(rampableChange.indexOf(parameter) !== -1) {
+ if (rampableChange.indexOf(parameter) !== -1) {
frames = parseInt(frames);
- if(!frames || frames < 1) frames = 1;
+ if (!frames || frames < 1) frames = 1;
logEvent("LIVE UPDATE:", parameter, "set to", newValue, "across", frames, "frames");
intervalometer.status.dynamicChange[parameter] = {
startVal: parseFloat(intervalometer.currentProgram[parameter]),
@@ -2214,17 +2277,17 @@ intervalometer.dynamicChange = function(parameter, newValue, frames, callback) {
endFrame: intervalometer.status.frames + frames
};
callback && callback();
- } else if(specialChange.indexOf(parameter) !== -1) {
- switch(parameter) {
+ } else if (specialChange.indexOf(parameter) !== -1) {
+ switch (parameter) {
case 'intervalMode':
var newInt = intervalometer.status.intervalMs / 1000;
- if(newValue == 'auto' && intervalometer.currentProgram.intervalMode == 'fixed') {
+ if (newValue == 'auto' && intervalometer.currentProgram.intervalMode == 'fixed') {
intervalometer.currentProgram.dayInterval = newInt;
intervalometer.currentProgram.nightInterval = newInt;
intervalometer.currentProgram.intervalMode = 'auto';
intervalometer.emit("intervalometer.currentProgram", intervalometer.currentProgram);
}
- if(newValue == 'fixed' && intervalometer.currentProgram.intervalMode == 'auto') {
+ if (newValue == 'fixed' && intervalometer.currentProgram.intervalMode == 'auto') {
intervalometer.currentProgram.frames = Math.ceil(intervalometer.status.frames / 100) * 100 + 500;
intervalometer.status.framesRemaining = intervalometer.currentProgram.frames - intervalometer.status.frames;
intervalometer.currentProgram.interval = newInt;
@@ -2235,14 +2298,19 @@ intervalometer.dynamicChange = function(parameter, newValue, frames, callback) {
break
case 'rampMode':
- if(newValue == 'auto' && intervalometer.status.rampMode != 'auto') { // restart ramping based on current exposure
+ if (newValue == 'auto' && intervalometer.status.rampMode != 'auto') { // restart ramping based on current exposure
intervalometer.status.rampMode = 'auto';
intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
- exp.init(camera.minEv(remap('camera.ptp.settings'), getEvOptions()), camera.maxEv(remap('camera.ptp.settings'), getEvOptions()), intervalometer.currentProgram.nightLuminance, intervalometer.currentProgram.dayLuminance, intervalometer.currentProgram.highlightProtection);
+ exp.init(camera.minEv(remap('camera.ptp.settings'), getEvOptions()),
+ camera.maxEv(remap('camera.ptp.settings'), getEvOptions()),
+ intervalometer.currentProgram.nightLuminance, intervalometer.currentProgram.dayLuminance,
+ intervalometer.currentProgram.highlightProtection,
+ intervalometer.status.timelapseFolder + "/data.js"
+ );
intervalometer.emit("intervalometer.status", intervalometer.status);
}
- if(newValue == 'fixed') {
- if(intervalometer.status.rampEv == null) intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
+ if (newValue == 'fixed') {
+ if (intervalometer.status.rampEv == null) intervalometer.status.rampEv = camera.lists.getEvFromSettings(remap('camera.ptp.settings'));
intervalometer.status.rampMode = 'fixed';
intervalometer.emit("intervalometer.status", intervalometer.status);
}
@@ -2252,7 +2320,7 @@ intervalometer.dynamicChange = function(parameter, newValue, frames, callback) {
case 'nightRefEv':
case 'dayRefEv':
frames = parseInt(frames);
- if(!frames || frames < 1) frames = 1;
+ if (!frames || frames < 1) frames = 1;
logEvent("LIVE UPDATE:", parameter, "set to", newValue, "across", frames, "frames");
intervalometer.status.dynamicChange[parameter] = {
startVal: parseFloat(intervalometer.status.exposure.status[parameter]),
@@ -2266,7 +2334,7 @@ intervalometer.dynamicChange = function(parameter, newValue, frames, callback) {
case 'rampEv':
frames = parseInt(frames);
- if(!frames || frames < 1) frames = 1;
+ if (!frames || frames < 1) frames = 1;
logEvent("LIVE UPDATE:", parameter, "set to", newValue, "across", frames, "frames");
intervalometer.status.dynamicChange[parameter] = {
startVal: intervalometer.status.rampEv,
@@ -2278,7 +2346,7 @@ intervalometer.dynamicChange = function(parameter, newValue, frames, callback) {
break;
case 'frames':
- if(parseInt(newValue) > intervalometer.status.frames) {
+ if (parseInt(newValue) > intervalometer.status.frames) {
intervalometer.currentProgram.frames = parseInt(newValue);
intervalometer.status.framesRemaining = intervalometer.currentProgram.frames - intervalometer.status.frames;
intervalometer.emit("intervalometer.currentProgram", intervalometer.currentProgram);
@@ -2301,32 +2369,31 @@ intervalometer.dynamicChange = function(parameter, newValue, frames, callback) {
}
}
-intervalometer.updateProgram = function(updates, callback) {
+intervalometer.updateProgram = function (updates, callback) {
log("Intervalometer: updateProgram:", updates);
- for(var key in updates) {
- if(updates.hasOwnProperty(key)) {
+ for (var key in updates) {
+ if (updates.hasOwnProperty(key)) {
intervalometer.currentProgram[key] = updates[key];
}
}
callback && callback();
}
-intervalometer.setAuxPulseLength = function(lengthMs, callback) {
+intervalometer.setAuxPulseLength = function (lengthMs, callback) {
auxMotionConfig.lengthMs = lengthMs;
log("INTERVALOMETER: set aux lengthMs to", auxMotionConfig.lengthMs);
}
-intervalometer.setAuxPulseInvert = function(invert, callback) {
+intervalometer.setAuxPulseInvert = function (invert, callback) {
auxMotionConfig.inverted = !!invert;
motionSyncSetup();
log("INTERVALOMETER: set aux invert to", auxMotionConfig.inverted);
}
-intervalometer.setAuxExternalPad = function(padMs, callback) {
+intervalometer.setAuxExternalPad = function (padMs, callback) {
auxMotionConfig.externalIntervalPaddingMs = padMs;
log("INTERVALOMETER: set aux externalIntervalPaddingMs to", auxMotionConfig.externalIntervalPaddingMs);
}
-
-module.exports = intervalometer;
\ No newline at end of file
+module.exports = intervalometer;
diff --git a/main.js b/main.js
index 9adfc626e..ff0ae43e4 100644
--- a/main.js
+++ b/main.js
@@ -889,7 +889,7 @@ if (VIEW_HARDWARE) {
var intervalPlan = function(planIndex) {
if(!core.currentProgram.exposurePlans[planIndex]) core.currentProgram.exposurePlans[planIndex] = {};
if(!core.currentProgram.exposurePlans[planIndex].interval) core.currentProgram.exposurePlans[planIndex].interval = 6;
-
+
var res = {
name: "interval",
type: "options",
@@ -1356,7 +1356,7 @@ if (VIEW_HARDWARE) {
action: ui.set(core.currentProgram.exposurePlans[planIndex], 'hdrCount', 15)
}]
}
- }
+ }
var hdrCountOptions = {
name: "HDR Exposures",
@@ -1445,7 +1445,7 @@ if (VIEW_HARDWARE) {
action: ui.set(core.currentProgram.exposurePlans[planIndex], 'hdrStops', 2)
}]
}
- }
+ }
var hdrStopsOptions = {
name: "HDR Bracket Step",
@@ -1636,6 +1636,8 @@ if (VIEW_HARDWARE) {
inputs.removeListener('D', captureDialHandler);
setTimeout(cb, 500);
ui.status("liveview error");
+ } else {
+ showLiveViewScreen();
}
});
lists.fixedApertureEv = core.currentProgram.manualAperture;
@@ -1690,7 +1692,7 @@ if (VIEW_HARDWARE) {
core.getCurrentTimelapseFrames(null, function(err, framesPaths) {
if(framesPaths) {
oled.video(null, framesPaths, 30, cb);
- }
+ }
});
}
}
@@ -1711,7 +1713,7 @@ if (VIEW_HARDWARE) {
// oled.video(null, framesPaths, 30, cb);
// }
// });
- // }
+ // }
// });
// }
// },
@@ -1735,7 +1737,7 @@ if (VIEW_HARDWARE) {
oled.video(null, framesPaths, 30, function(){
ui.reload();
});
- }
+ }
});
},
button3: function(){
@@ -1871,7 +1873,7 @@ if (VIEW_HARDWARE) {
var getMotor = function(motorName, callback) {
db.get('motion-'+motorName, callback);
- }
+ }
var exposurePlansReview = function() {
var info = "";
@@ -1881,11 +1883,11 @@ if (VIEW_HARDWARE) {
var plan = core.currentProgram.exposurePlans[i];
info += plan.name + '\t';
if(i < core.currentProgram.exposurePlans.length - 1 && core.currentProgram.exposurePlans[i + 1].start < now) {
- info += pad + "(skipping)\n";
+ info += pad + "(skipping)\n";
continue;
}
if(i > 0) info += pad + moment(plan.start).fromNow() + '\t';
- info += pad;
+ info += pad;
if(plan.mode == 'preset') {
info += lists.getNameFromEv(lists.shutter, plan.shutter) + ', ';
info += 'f/' + lists.getNameFromEv(lists.aperture, plan.aperture) + ', ';
@@ -1926,7 +1928,7 @@ if (VIEW_HARDWARE) {
var motorOrientationKnown = function() {
if(!core.motionStatus.motors) return false;
- var motors = [];
+ var motors = [];
for(var i = 0; i < core.motionStatus.motors.length; i++) {
if(core.motionStatus.motors[i].connected) motors.push(core.motionStatus.motors[i]);
}
@@ -2368,7 +2370,7 @@ if (VIEW_HARDWARE) {
});
checkDone();
});
-
+
})(clips[i]);
} else {
checkDone();
@@ -2765,7 +2767,7 @@ if (VIEW_HARDWARE) {
}
});
}
- },
+ },
condition: function() {
return core.sdPresent;
}
@@ -2888,7 +2890,7 @@ if (VIEW_HARDWARE) {
// }
//});
}
- }
+ }
var wifiScanWait = function() {
if(wifi.list.length > 0) {
@@ -2918,7 +2920,7 @@ if (VIEW_HARDWARE) {
type: "menu"
}
m.items = wifi.list.map(function(item){return {
- name:item.ssid + ((wifi.connected && wifi.connected.address == item.address) ? "~connected" : ""),
+ name:item.ssid + ((wifi.connected && wifi.connected.address == item.address) ? "~connected" : ""),
help: help.wifiConnect,
action: {
type: 'function',
@@ -2974,7 +2976,7 @@ if (VIEW_HARDWARE) {
details += "Encryption: WPA2\t";
} else {
details += "Encryption: NONE\t";
- }
+ }
details += "BSSID: " + w.address + "\t";
details += "Channel: " + w.channel + "\t";
ui.alert('Wifi details', details);
@@ -4357,8 +4359,8 @@ if (VIEW_HARDWARE) {
info += "Moon sets at " + moonset.format("h:mm:ss A") + "\t (" + moonset.fromNow() + ")\t";
var phase = "unknown";
var phaseNumber = (sunmoon.mooninfo.phase * 180 / Math.PI) / 180 + 0.5
- if(phaseNumber == 0 || phaseNumber == 1) phase = "New Moon";
- else if(phaseNumber < 0.25) phase = "Waxing Crescent";
+ if(phaseNumber == 0 || phaseNumber == 1) phase = "New Moon";
+ else if(phaseNumber < 0.25) phase = "Waxing Crescent";
else if(phaseNumber == 0.25) phase = "First Quarter";
else if(phaseNumber > 0.25 && phaseNumber < 0.5) phase = "Waxing Gibbous";
else if(phaseNumber == 0.5) phase = "Full Moon";
@@ -4414,10 +4416,10 @@ if (VIEW_HARDWARE) {
info += "This is a partial eclipse with " + Math.round(data.coverage * 100) + "% coverage observable from the current location " + currentLocation + ".";
}
} else {
- info += "No upcoming eclipses were found for the current location " + currentLocation + ".";
+ info += "No upcoming eclipses were found for the current location " + currentLocation + ".";
}
} else {
- info += "No upcoming eclipses were found for the current location " + currentLocation + ".";
+ info += "No upcoming eclipses were found for the current location " + currentLocation + ".";
}
} else {
info = "GPS position info unavailable\t";
@@ -4692,7 +4694,15 @@ if (VIEW_HARDWARE) {
inputs.on('D', function(move) {
power.activity();
- if(oled.videoRunning) return;
+ if(oled.videoRunning) {
+ if (move == "U") {
+ oled.increaseVideoSpeed();
+ }
+ if (move == "D") {
+ oled.decreaseVideoSpeed();
+ }
+ return;
+ }
blockGestureTimer();
if (blockInputs) return;
@@ -4757,7 +4767,7 @@ if (VIEW_HARDWARE) {
} else {
cb();
}
- });
+ });
} else {
ui.back();
//cb();
@@ -4780,7 +4790,7 @@ if (VIEW_HARDWARE) {
} else {
cb();
}
- });
+ });
} else {
ui.back();
//cb();
@@ -4875,7 +4885,7 @@ if (VIEW_HARDWARE) {
});
app.on('logs-uploaded', function(count) {
- ui.alert('Success', help.logFilesUploaded);
+ ui.alert('Success', help.logFilesUploaded);
})
core.on('media.insert', function(type) {
@@ -4986,8 +4996,8 @@ if (VIEW_HARDWARE) {
} else {
gestureVideoPlaying = false;
gestureModeTimer();
- }
- })
+ }
+ })
}
}
});
@@ -5286,7 +5296,7 @@ app.on('message', function(msg) {
});
break;
- case 'motion':
+ case 'motion':
if (msg.key == "move" && msg.motor && msg.driver) {
console.log("moving motor " + msg.motor);
(function(driver, motor, steps, reply) {
@@ -5426,7 +5436,7 @@ app.on('message', function(msg) {
});
})(liveviewOn);
break;
-
+
case 'capture-test':
core.captureTest(function(err){
if(err) {
@@ -5553,7 +5563,7 @@ app.on('message', function(msg) {
};
sendFragment(msg.start);
}
- }
+ }
});
break;
@@ -5872,6 +5882,11 @@ core.on('camera.photo', function() {
} else {
//app.addJpegFrame(core.photo.jpeg);
//app.addJpegFrame(core.photo.jpeg);
+ var lastPhotoLum
+ if (core.photo.ev)
+ lastPhotoLum = (Math.round(core.photo.ev * 10) / 10).toString() + " L";
+ oled.setEvHistogram(lastPhotoLum, core.photo.histogram);
+
var size = {
x: 160,
q: 80
@@ -5891,7 +5906,6 @@ core.on('camera.photo', function() {
}
}
}
-
previewImage = {
jpeg: core.photo.base64,
zoomed: core.photo.zoomed,
@@ -5967,7 +5981,7 @@ ui.defaultStatus(defaultStatus);
ui.status(defaultStatus);
console.log("Setting default status to '" + defaultStatus + "'")
-core.on('camera.exiting', function() {
+core.on('camera.exiting', function() {
if(btBlockedForSony) {
wifi.unblockBt();
wifi.noReset = false;
@@ -6041,13 +6055,15 @@ core.on('intervalometer.status', function(msg) {
}
//img116x70, isoText, apertureText, shutterText, intervalSeconds, intervalModeChar, hist60, ramp30, frames, remaining, durationSeconds, bufferSeconds, shutterSeconds
-
+
var evText = (Math.round(lists.getEvFromSettings(msg.cameraSettings) * 10) / 10).toString();
+ var lastPhotoLum = (Math.round(msg.lastPhotoLum * 10) / 10).toString();
var statusScreen = {
isoText: msg.cameraSettings ? ((typeof msg.cameraSettings.iso == 'object') ? msg.cameraSettings.iso.name : msg.cameraSettings.iso) : "--",
shutterText: msg.cameraSettings ? ((typeof msg.cameraSettings.shutter == 'object') ? msg.cameraSettings.shutter.name : msg.cameraSettings.shutter) : "--",
apertureText: msg.cameraSettings ? (((msg.cameraSettings.aperture && msg.cameraSettings.aperture.ev != null) || (msg.cameraSettings.details && msg.cameraSettings.details.aperture && msg.cameraSettings.details.aperture.ev != null)) ? ("f/" + (msg.cameraSettings.details ? msg.cameraSettings.details.aperture.name : msg.cameraSettings.aperture.name)) : ("f/" + lists.getNameFromEv(lists.aperture, core.currentProgram.manualAperture) + ' (m)')) : "--",
evText: evText + " EV",
+ lastPhotoLum: lastPhotoLum + " L",
intervalSeconds: msg.intervalMs / 1000,
bufferSeconds: msg.autoSettings ? msg.autoSettings.paddingTimeMs / 1000 : 5,
rampModeText: core.currentProgram.rampMode,
diff --git a/node_modules/jpeg-lum/CMakeLists.txt b/node_modules/jpeg-lum/CMakeLists.txt
new file mode 100644
index 000000000..17710bb2c
--- /dev/null
+++ b/node_modules/jpeg-lum/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.22)
+project(jpeg-lum-test)
+
+set(CMAKE_C_STANDARD 99)
+
+include_directories(
+ /opt/libjpeg-turbo/include
+)
+
+add_executable(jpeg-lum-test
+ lib/test.cpp
+ lib/lib.cc
+)
+
+target_link_directories(jpeg-lum-test PUBLIC
+ /opt/libjpeg-turbo/lib64
+)
+
+target_link_libraries(jpeg-lum-test PUBLIC jpeg )
diff --git a/node_modules/jpeg-lum/binding.gyp b/node_modules/jpeg-lum/binding.gyp
index e774e8b37..40fdf1e84 100644
--- a/node_modules/jpeg-lum/binding.gyp
+++ b/node_modules/jpeg-lum/binding.gyp
@@ -2,7 +2,7 @@
"targets": [
{
"target_name": "jpeglum",
- "sources": [ "./lib/jpeg-lum.cc" ],
+ "sources": [ "./lib/jpeg-lum.cc", "./lib/lib.cc" ],
"link_settings": {
"libraries": [
"-ljpeg"
diff --git a/node_modules/jpeg-lum/build/Makefile b/node_modules/jpeg-lum/build/Makefile
index 5981ced92..b4f017aeb 100644
--- a/node_modules/jpeg-lum/build/Makefile
+++ b/node_modules/jpeg-lum/build/Makefile
@@ -41,22 +41,30 @@ all_deps :=
CC.target ?= $(CC)
-CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS)
+CFLAGS.target ?= $(CFLAGS)
CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS)
+CXXFLAGS.target ?= $(CXXFLAGS)
LINK.target ?= $(LINK)
LDFLAGS.target ?= $(LDFLAGS)
AR.target ?= $(AR)
# C++ apps need to be linked with g++.
-LINK ?= $(CXX.target)
+#
+# Note: flock is used to seralize linking. Linking is a memory-intensive
+# process so running parallel links can often lead to thrashing. To disable
+# the serialization, override LINK via an envrionment variable as follows:
+#
+# export LINK=g++
+#
+# This will allow make to invoke N linker processes as specified in -jN.
+LINK ?= flock $(builddir)/linker.lock $(CXX.target)
# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
# to replicate this environment fallback in make as well.
CC.host ?= gcc
-CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host)
+CFLAGS.host ?=
CXX.host ?= g++
-CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host)
+CXXFLAGS.host ?=
LINK.host ?= $(CXX.host)
LDFLAGS.host ?=
AR.host ?= ar
@@ -308,8 +316,8 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
endif
quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/root/VIEW/node_modules/jpeg-lum/build/config.gypi -I/usr/local/lib/node_modules/node-gyp/addon.gypi -I/root/.node-gyp/0.10.40/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/root/.node-gyp/0.10.40" "-Dnode_gyp_dir=/usr/local/lib/node_modules/node-gyp" "-Dnode_lib_file=node.lib" "-Dmodule_root_dir=/root/VIEW/node_modules/jpeg-lum" binding.gyp
-Makefile: $(srcdir)/../../../.node-gyp/0.10.40/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../usr/local/lib/node_modules/node-gyp/addon.gypi
+cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/home/view/v1.8.50-beta/node_modules/jpeg-lum/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/root/.node-gyp/0.10.40/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/root/.node-gyp/0.10.40" "-Dmodule_root_dir=/home/view/v1.8.50-beta/node_modules/jpeg-lum" binding.gyp
+Makefile: $(srcdir)/../../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../root/.node-gyp/0.10.40/common.gypi
$(call do_cmd,regen_makefile)
# "all" is a concatenation of the "all" targets from all the included
diff --git a/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum.node.d b/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum.node.d
index 33b32b03e..fb9f3c5ff 100644
--- a/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum.node.d
+++ b/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum.node.d
@@ -1 +1 @@
-cmd_Release/obj.target/jpeglum.node := g++ -shared -pthread -rdynamic -Wl,-soname=jpeglum.node -o Release/obj.target/jpeglum.node -Wl,--start-group Release/obj.target/jpeglum/lib/jpeg-lum.o -Wl,--end-group -ljpeg
+cmd_Release/obj.target/jpeglum.node := flock ./Release/linker.lock g++ -shared -pthread -rdynamic -Wl,-soname=jpeglum.node -o Release/obj.target/jpeglum.node -Wl,--start-group Release/obj.target/jpeglum/lib/jpeg-lum.o Release/obj.target/jpeglum/lib/lib.o -Wl,--end-group -ljpeg
diff --git a/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum/lib/jpeg-lum.o.d b/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum/lib/jpeg-lum.o.d
index a5f746916..b93497b8a 100644
--- a/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum/lib/jpeg-lum.o.d
+++ b/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum/lib/jpeg-lum.o.d
@@ -1,6 +1,6 @@
-cmd_Release/obj.target/jpeglum/lib/jpeg-lum.o := g++ '-DNODE_GYP_MODULE_NAME=jpeglum' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/root/.node-gyp/0.10.40/include/node -I/root/.node-gyp/0.10.40/src -I/root/.node-gyp/0.10.40/deps/uv/include -I/root/.node-gyp/0.10.40/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/jpeglum/lib/jpeg-lum.o.d.raw -c -o Release/obj.target/jpeglum/lib/jpeg-lum.o ../lib/jpeg-lum.cc
+cmd_Release/obj.target/jpeglum/lib/jpeg-lum.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/root/.node-gyp/0.10.40/src -I/root/.node-gyp/0.10.40/deps/uv/include -I/root/.node-gyp/0.10.40/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/jpeglum/lib/jpeg-lum.o.d.raw -c -o Release/obj.target/jpeglum/lib/jpeg-lum.o ../lib/jpeg-lum.cc
Release/obj.target/jpeglum/lib/jpeg-lum.o: ../lib/jpeg-lum.cc \
- /root/.node-gyp/0.10.40/src/node.h \
+ ../lib/lib.h /root/.node-gyp/0.10.40/src/node.h \
/root/.node-gyp/0.10.40/deps/uv/include/uv.h \
/root/.node-gyp/0.10.40/deps/uv/include/uv-private/uv-unix.h \
/root/.node-gyp/0.10.40/deps/uv/include/uv-private/ngx-queue.h \
@@ -10,6 +10,7 @@ Release/obj.target/jpeglum/lib/jpeg-lum.o: ../lib/jpeg-lum.cc \
/root/.node-gyp/0.10.40/src/node_object_wrap.h \
/root/.node-gyp/0.10.40/src/node.h
../lib/jpeg-lum.cc:
+../lib/lib.h:
/root/.node-gyp/0.10.40/src/node.h:
/root/.node-gyp/0.10.40/deps/uv/include/uv.h:
/root/.node-gyp/0.10.40/deps/uv/include/uv-private/uv-unix.h:
diff --git a/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum/lib/lib.o.d b/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum/lib/lib.o.d
new file mode 100644
index 000000000..45a5e64e4
--- /dev/null
+++ b/node_modules/jpeg-lum/build/Release/.deps/Release/obj.target/jpeglum/lib/lib.o.d
@@ -0,0 +1,4 @@
+cmd_Release/obj.target/jpeglum/lib/lib.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/root/.node-gyp/0.10.40/src -I/root/.node-gyp/0.10.40/deps/uv/include -I/root/.node-gyp/0.10.40/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/jpeglum/lib/lib.o.d.raw -c -o Release/obj.target/jpeglum/lib/lib.o ../lib/lib.cc
+Release/obj.target/jpeglum/lib/lib.o: ../lib/lib.cc ../lib/lib.h
+../lib/lib.cc:
+../lib/lib.h:
diff --git a/node_modules/jpeg-lum/build/Release/jpeglum.node b/node_modules/jpeg-lum/build/Release/jpeglum.node
index 76ff9805e..ced26dc3c 100755
Binary files a/node_modules/jpeg-lum/build/Release/jpeglum.node and b/node_modules/jpeg-lum/build/Release/jpeglum.node differ
diff --git a/node_modules/jpeg-lum/build/Release/linker.lock b/node_modules/jpeg-lum/build/Release/linker.lock
new file mode 100644
index 000000000..e69de29bb
diff --git a/node_modules/jpeg-lum/build/Release/obj.target/jpeglum.node b/node_modules/jpeg-lum/build/Release/obj.target/jpeglum.node
index 76ff9805e..ced26dc3c 100755
Binary files a/node_modules/jpeg-lum/build/Release/obj.target/jpeglum.node and b/node_modules/jpeg-lum/build/Release/obj.target/jpeglum.node differ
diff --git a/node_modules/jpeg-lum/build/Release/obj.target/jpeglum/lib/jpeg-lum.o b/node_modules/jpeg-lum/build/Release/obj.target/jpeglum/lib/jpeg-lum.o
index 119a1d8a6..e91e1f40d 100644
Binary files a/node_modules/jpeg-lum/build/Release/obj.target/jpeglum/lib/jpeg-lum.o and b/node_modules/jpeg-lum/build/Release/obj.target/jpeglum/lib/jpeg-lum.o differ
diff --git a/node_modules/jpeg-lum/build/Release/obj.target/jpeglum/lib/lib.o b/node_modules/jpeg-lum/build/Release/obj.target/jpeglum/lib/lib.o
new file mode 100644
index 000000000..a27276d8e
Binary files /dev/null and b/node_modules/jpeg-lum/build/Release/obj.target/jpeglum/lib/lib.o differ
diff --git a/node_modules/jpeg-lum/build/config.gypi b/node_modules/jpeg-lum/build/config.gypi
index c27ddab24..7f8867ef7 100644
--- a/node_modules/jpeg-lum/build/config.gypi
+++ b/node_modules/jpeg-lum/build/config.gypi
@@ -39,6 +39,88 @@
"want_separate_host_toolset": 0,
"nodedir": "/root/.node-gyp/0.10.40",
"copy_dev_lib": "true",
- "standalone_static_library": 1
+ "standalone_static_library": 1,
+ "cache_lock_stale": "60000",
+ "sign_git_tag": "",
+ "user_agent": "npm/1.4.28 node/v0.10.40 linux arm",
+ "always_auth": "",
+ "bin_links": "true",
+ "key": "",
+ "description": "true",
+ "fetch_retries": "2",
+ "heading": "npm",
+ "user": "",
+ "force": "",
+ "cache_min": "10",
+ "init_license": "ISC",
+ "editor": "vi",
+ "rollback": "true",
+ "cache_max": "Infinity",
+ "userconfig": "/root/.npmrc",
+ "engine_strict": "",
+ "init_author_name": "",
+ "init_author_url": "",
+ "tmp": "/tmp",
+ "depth": "Infinity",
+ "save_dev": "",
+ "usage": "",
+ "cafile": "",
+ "https_proxy": "",
+ "onload_script": "",
+ "rebuild_bundle": "true",
+ "save_bundle": "",
+ "shell": "/bin/bash",
+ "prefix": "/usr/local",
+ "registry": "https://registry.npmjs.org/",
+ "browser": "",
+ "cache_lock_wait": "10000",
+ "save_optional": "",
+ "searchopts": "",
+ "versions": "",
+ "cache": "/root/.npm",
+ "ignore_scripts": "",
+ "searchsort": "name",
+ "version": "",
+ "local_address": "",
+ "viewer": "man",
+ "color": "true",
+ "fetch_retry_mintimeout": "10000",
+ "umask": "18",
+ "fetch_retry_maxtimeout": "60000",
+ "message": "%s",
+ "ca": "",
+ "cert": "",
+ "global": "",
+ "link": "",
+ "save": "",
+ "unicode": "true",
+ "long": "",
+ "production": "",
+ "unsafe_perm": "",
+ "node_version": "0.10.40",
+ "tag": "latest",
+ "git_tag_version": "true",
+ "shrinkwrap": "true",
+ "fetch_retry_factor": "10",
+ "npat": "",
+ "proprietary_attribs": "true",
+ "save_exact": "",
+ "strict_ssl": "true",
+ "username": "",
+ "dev": "",
+ "globalconfig": "/usr/local/etc/npmrc",
+ "init_module": "/root/.npm-init.js",
+ "parseable": "",
+ "globalignorefile": "/usr/local/etc/npmignore",
+ "cache_lock_retries": "10",
+ "save_prefix": "^",
+ "group": "",
+ "init_author_email": "",
+ "searchexclude": "",
+ "git": "git",
+ "optional": "true",
+ "email": "",
+ "json": "",
+ "spin": "true"
}
}
diff --git a/node_modules/jpeg-lum/build/jpeglum.target.mk b/node_modules/jpeg-lum/build/jpeglum.target.mk
index f0aacce24..679acccec 100644
--- a/node_modules/jpeg-lum/build/jpeglum.target.mk
+++ b/node_modules/jpeg-lum/build/jpeglum.target.mk
@@ -3,10 +3,6 @@
TOOLSET := target
TARGET := jpeglum
DEFS_Debug := \
- '-DNODE_GYP_MODULE_NAME=jpeglum' \
- '-DUSING_UV_SHARED=1' \
- '-DUSING_V8_SHARED=1' \
- '-DV8_DEPRECATION_WARNINGS=1' \
'-D_LARGEFILE_SOURCE' \
'-D_FILE_OFFSET_BITS=64' \
'-DBUILDING_NODE_EXTENSION' \
@@ -32,16 +28,11 @@ CFLAGS_CC_Debug := \
-fno-exceptions
INCS_Debug := \
- -I/root/.node-gyp/0.10.40/include/node \
-I/root/.node-gyp/0.10.40/src \
-I/root/.node-gyp/0.10.40/deps/uv/include \
-I/root/.node-gyp/0.10.40/deps/v8/include
DEFS_Release := \
- '-DNODE_GYP_MODULE_NAME=jpeglum' \
- '-DUSING_UV_SHARED=1' \
- '-DUSING_V8_SHARED=1' \
- '-DV8_DEPRECATION_WARNINGS=1' \
'-D_LARGEFILE_SOURCE' \
'-D_FILE_OFFSET_BITS=64' \
'-DBUILDING_NODE_EXTENSION'
@@ -67,13 +58,13 @@ CFLAGS_CC_Release := \
-fno-exceptions
INCS_Release := \
- -I/root/.node-gyp/0.10.40/include/node \
-I/root/.node-gyp/0.10.40/src \
-I/root/.node-gyp/0.10.40/deps/uv/include \
-I/root/.node-gyp/0.10.40/deps/v8/include
OBJS := \
- $(obj).target/$(TARGET)/lib/jpeg-lum.o
+ $(obj).target/$(TARGET)/lib/jpeg-lum.o \
+ $(obj).target/$(TARGET)/lib/lib.o
# Add to the list of files we specially track dependencies for.
all_deps += $(OBJS)
diff --git a/node_modules/jpeg-lum/lib/jpeg-lum.cc b/node_modules/jpeg-lum/lib/jpeg-lum.cc
index d06a405f5..09df8b479 100644
--- a/node_modules/jpeg-lum/lib/jpeg-lum.cc
+++ b/node_modules/jpeg-lum/lib/jpeg-lum.cc
@@ -4,152 +4,10 @@
#include
#include
#include
-
-unsigned int size;
-unsigned int histogram[256];
-unsigned int hist_max = 0;
-unsigned int width;
-unsigned int height;
-double luminance;
-double clipped;
-
-#define LUT_LENGTH 33
-struct lut_t {
- double x;
- double y;
-};
-lut_t lut[LUT_LENGTH] =
-{
- {4.793865/4, -7},
- {4.793865/2, -6},
- {4.793865, -5},
- {6.056875, -4.66666666666667},
- {7.697362, -4.33333333333333},
- {9.780035, -4},
- {12.092661, -3.66666666666667},
- {15.089602, -3.33333333333333},
- {18.683953, -3},
- {23.421734, -2.66666666666667},
- {28.643862, -2.33333333333333},
- {35.019192, -2},
- {42.607219, -1.66666666666667},
- {52.126612, -1.33333333333333},
- {63.956853, -1},
- {76.885797, -0.666666666666667},
- {89.6882, -0.333333333333333},
- {103.382354, 0},
- {118.336503, 0.333333333333333},
- {135.244366, 0.666666666666667},
- {147.969053, 1},
- {162.615242, 1.33333333333333},
- {182.654258, 1.66666666666667},
- {194.224312, 2},
- {206.764022, 2.33333333333333},
- {213.891809, 2.66666666666667},
- {230.007117, 3},
- {238.483315, 3.33333333333333},
- {246.258409, 3.66666666666667},
- {249.447248, 4},
- {249.495413, 4.33333333333333},
- {252, 5},
- {253, 6}
-};
-
-double lum(double x)
-{
- int i;
-
- if(x < lut[0].x) return lut[0].y - 1;
- if(x > lut[LUT_LENGTH-1].x) return lut[LUT_LENGTH-1].y + 1;
-
- for( i = 0; i < LUT_LENGTH-1; i++ )
- {
- if ( lut[i].x <= x && lut[i+1].x >= x )
- {
- double diffx = x - lut[i].x;
- double diffn = lut[i+1].x - lut[i].x;
-
- return lut[i].y + ( lut[i+1].y - lut[i].y ) * diffx / diffn;
- }
- }
- printf("error - not found\n");
- return 0; // Not in Range
-}
-
-int read_jpeg_file(char *filename)
-{
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1];
- FILE *infile = fopen(filename, "rb");
- unsigned int i = 0, component = 0;
- if (!infile) {
- printf("Error opening jpeg file %s\n!", filename);
- return -1;
- }
- cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_decompress(&cinfo);
- jpeg_stdio_src(&cinfo, infile);
- jpeg_read_header(&cinfo, TRUE);
- jpeg_start_decompress(&cinfo);
-
- width = cinfo.output_width;
- height = cinfo.output_height;
- luminance = 0.0;
- size = cinfo.output_width*cinfo.output_height*cinfo.num_components*sizeof(unsigned int);
- memset(histogram, 0, sizeof(int)*256);
- row_pointer[0] = (unsigned char *)malloc(cinfo.output_width*cinfo.num_components);
- unsigned long total_count = 0;
-
- unsigned int row_number = 0;
- int skip_rows = 0;
- float ratio = (float)width / (float)height;
- if(ratio < 1.75) {
- skip_rows = (height-((float)width)/1.75)/2;
- //printf("skipping %d rows on top and bottom", skip_rows);
- }
-
- while (cinfo.output_scanline < cinfo.image_height) {
- row_number++;
- jpeg_read_scanlines( &cinfo, row_pointer, 1 );
- if(row_number <= skip_rows) continue;
- if(row_number > height - skip_rows) continue;
- for (i=0; i m) m = p;
- }
- }
- if(m > 255) m = 255;
- histogram[m]++;
- total_count++;
- }
- }
-
- unsigned long count = 0, sum = 0;
- luminance = 0.0;
- hist_max = 0;
- for(int i = 0; i < 256; i++) {
- sum += histogram[i];
- if(histogram[i] > hist_max) hist_max = histogram[i];
- if(sum < total_count / 2) continue; // only look at the upper 50%
- luminance += lum((float)i) * (float) histogram[i];
- count += histogram[i];
- }
-
- clipped = (double)histogram[255] / (double)count;
- luminance /= (double)count;
- jpeg_finish_decompress(&cinfo);
- jpeg_destroy_decompress(&cinfo);
- free(row_pointer[0]);
- fclose(infile);
- return 1;
-}
+#include "lib.h"
#ifndef BUILDING_NODE_EXTENSION
- #define BUILDING_NODE_EXTENSION
+#define BUILDING_NODE_EXTENSION
#endif
#include
@@ -157,65 +15,64 @@ int read_jpeg_file(char *filename)
using namespace v8;
Handle CreateObject(const Arguments& args) {
- HandleScope scope;
+ HandleScope scope;
- Local