Merge all work on server with filmout features #77
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1.7.7",
|
||||
"version": "1.7.18",
|
||||
"ext_port": 1111,
|
||||
"profiles": {
|
||||
"mcopy": {
|
||||
|
|
|
@ -13,6 +13,16 @@
|
|||
body.meter {
|
||||
background: rgb(117, 117, 117);
|
||||
}
|
||||
body.meter #img,
|
||||
body.meter #can {
|
||||
display: none;
|
||||
}
|
||||
body.image #can{
|
||||
display: none;
|
||||
}
|
||||
body.image #img {
|
||||
display: block;
|
||||
}
|
||||
#img {
|
||||
position: absolute;
|
||||
/*background-image: url(".../img/background.jpg");*/
|
||||
|
@ -46,16 +56,16 @@
|
|||
</canvas>
|
||||
<script>
|
||||
'use strict';
|
||||
const { remote, ipcRenderer } = require('electron')
|
||||
const { ipcRenderer } = require('electron')
|
||||
const remote = require('@electron/remote')
|
||||
let imgTmp;
|
||||
async function setImage (src) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
imgTmp = new Image()
|
||||
let img = document.getElementById('img')
|
||||
let body = document.querySelector('body')
|
||||
if (body.classList.contains('meter')) {
|
||||
body.classList.remove('meter')
|
||||
}
|
||||
body.className = ''
|
||||
body.classList.add('image')
|
||||
imgTmp.onload = function () {
|
||||
img.style.backgroundImage = `url('${src}')`;
|
||||
return resolve(src);
|
||||
|
@ -66,15 +76,16 @@
|
|||
async function onMeter () {
|
||||
console.log('meter')
|
||||
const body = document.querySelector('body')
|
||||
if (!body.classList.contains('meter')) {
|
||||
body.classList.add('meter')
|
||||
}
|
||||
body.className = ''
|
||||
body.classList.add('meter')
|
||||
}
|
||||
async function onFocus () {
|
||||
console.log('focus')
|
||||
const can = document.getElementById('can')
|
||||
const dpr = window.devicePixelRatio || 1
|
||||
const body = document.querySelector('body')
|
||||
let ctx;
|
||||
body.className = ''
|
||||
if (!can.classList.contains('show')) {
|
||||
can.classList.add('show')
|
||||
}
|
||||
|
@ -122,7 +133,9 @@
|
|||
const can = document.getElementById('can')
|
||||
const dpr = window.devicePixelRatio || 1
|
||||
const screen = window.outerWidth / window.outerHeight
|
||||
const body = document.querySelector('body')
|
||||
let ctx;
|
||||
body.className = ''
|
||||
if (!can.classList.contains('show')) {
|
||||
can.classList.add('show')
|
||||
}
|
||||
|
@ -145,7 +158,7 @@
|
|||
can.style.width = `${window.innerHeight * arg.ratio}px`
|
||||
can.style.height = `${window.innerHeight}px`
|
||||
} else {
|
||||
can.style.width = `${window.inneWidth}px`
|
||||
can.style.width = `${window.innerWidth}px`
|
||||
can.style.height = `${window.innerWidth / arg.ratio}px`
|
||||
}
|
||||
} else {
|
||||
|
@ -209,7 +222,7 @@
|
|||
async function onDigital (event, arg) {
|
||||
if (arg.src) {
|
||||
try {
|
||||
await setImage(arg.src)
|
||||
await setImage(arg.src)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
|
@ -217,9 +230,11 @@
|
|||
}
|
||||
return event.returnValue = true
|
||||
}
|
||||
|
||||
async function onEscape (evt) {
|
||||
let isEscape = false
|
||||
let win
|
||||
|
||||
evt = evt || window.event
|
||||
|
||||
if ('key' in evt) {
|
||||
|
@ -227,6 +242,7 @@
|
|||
} else {
|
||||
isEscape = (evt.keyCode == 27)
|
||||
}
|
||||
|
||||
if (isEscape) {
|
||||
win = remote.getCurrentWindow()
|
||||
win.close()
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Delay in an async/await function
|
||||
*
|
||||
* @param {integer} ms Milliseconds to delay for
|
||||
*
|
||||
* @returns {Promise} Promise to resolve after timeout
|
||||
**/
|
||||
declare function delay(ms: number): Promise<unknown>;
|
|
@ -17,7 +17,8 @@ class WebView {
|
|||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
allowRunningInsecureContent: false,
|
||||
enableRemoteModule: true
|
||||
enableRemoteModule: true,
|
||||
contextIsolation: false
|
||||
},
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
@ -35,6 +36,7 @@ class WebView {
|
|||
prefs.y = display.y + 50;
|
||||
}
|
||||
this.digitalWindow = new BrowserWindow(prefs);
|
||||
require('@electron/remote/main').enable(this.digitalWindow.webContents);
|
||||
this.digitalWindow.loadURL(pageUrl);
|
||||
if (process.argv.indexOf('-d') !== -1 || process.argv.indexOf('--dev') !== -1) {
|
||||
this.digitalWindow.webContents.openDevTools();
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -23,7 +23,7 @@ class FilmOut {
|
|||
* @param {object} ui Electron ui object
|
||||
* @param {object} light Light device object
|
||||
**/
|
||||
constructor(display, ffmpeg, ffprobe, ui, light) {
|
||||
constructor(display, server, ffmpeg, ffprobe, ui, light) {
|
||||
this.id = 'filmout';
|
||||
this.videoExtensions = ['.mpg', '.mpeg', '.mov', '.mkv', '.avi', '.mp4'];
|
||||
this.stillExtensions = ['.tif', '.tiff', '.png', '.jpg', '.jpeg', '.bmp'];
|
||||
|
@ -42,6 +42,7 @@ class FilmOut {
|
|||
files: []
|
||||
};
|
||||
this.display = display;
|
||||
this.server = server;
|
||||
this.ffmpeg = ffmpeg;
|
||||
this.ffprobe = ffprobe;
|
||||
this.ui = ui;
|
||||
|
@ -123,6 +124,10 @@ class FilmOut {
|
|||
this.log.error(err, 'FILMOUT', true, true);
|
||||
throw err;
|
||||
}
|
||||
if (this.server.displayImage(path)) {
|
||||
await delay_1.delay(20);
|
||||
return;
|
||||
}
|
||||
await this.display.show(path);
|
||||
await delay_1.delay(20);
|
||||
}
|
||||
|
@ -411,6 +416,9 @@ class FilmOut {
|
|||
throw err;
|
||||
}
|
||||
try {
|
||||
if (await this.server.displayImage(path)) {
|
||||
return;
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.show(path);
|
||||
}
|
||||
|
@ -424,6 +432,9 @@ class FilmOut {
|
|||
async focus(evt, arg) {
|
||||
this.log.info(`Showing focus screen`);
|
||||
try {
|
||||
if (await this.server.cmdAll('focus')) {
|
||||
return;
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.focus();
|
||||
}
|
||||
|
@ -438,6 +449,9 @@ class FilmOut {
|
|||
const ratio = arg.ratio;
|
||||
this.log.info(`Showing field guide screen`);
|
||||
try {
|
||||
if (await this.server.cmdAll('field', { ratio })) {
|
||||
return;
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.field(ratio);
|
||||
}
|
||||
|
@ -451,6 +465,9 @@ class FilmOut {
|
|||
async meter(evt, arg) {
|
||||
this.log.info(`Showing meter screen`);
|
||||
try {
|
||||
if (await this.server.cmdAll('meter')) {
|
||||
return;
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.meter();
|
||||
}
|
||||
|
@ -463,6 +480,9 @@ class FilmOut {
|
|||
**/
|
||||
async close(evt, arg) {
|
||||
try {
|
||||
if (await this.server.cmdAll('blank')) {
|
||||
return;
|
||||
}
|
||||
await this.display.hide();
|
||||
await this.display.close();
|
||||
}
|
||||
|
@ -478,7 +498,7 @@ class FilmOut {
|
|||
this.log.info(`Changing the display to ${arg.display}`);
|
||||
}
|
||||
}
|
||||
module.exports = (display, ffmpeg, ffprobe, ui, light) => {
|
||||
return new FilmOut(display, ffmpeg, ffprobe, ui, light);
|
||||
module.exports = (display, server, ffmpeg, ffprobe, ui, light) => {
|
||||
return new FilmOut(display, server, ffmpeg, ffprobe, ui, light);
|
||||
};
|
||||
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -50,7 +50,7 @@ async function logFile() {
|
|||
*
|
||||
* @returns {object} Logger transport
|
||||
**/
|
||||
module.exports = async function (arg) {
|
||||
module.exports = async function Log(arg) {
|
||||
let consoleFormat = {
|
||||
colorize: true
|
||||
};
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/log/index.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/log/index.ts"],"names":[],"mappings":"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"}
|
File diff suppressed because one or more lines are too long
|
@ -146,7 +146,7 @@ class Sequencer {
|
|||
//start sequence
|
||||
this.log.info(`Starting sequence...`);
|
||||
this.ui.send(this.id, { start: true });
|
||||
if (this.cmd.proj.filmout.state.enabled === true) {
|
||||
if (this.cmd.proj.filmout.state.enabled === true && !this.cmd.proj.filmout.server.useServer()) {
|
||||
await this.cmd.proj.filmout.display.open();
|
||||
}
|
||||
for (let x = 0; x < this.loops; x++) {
|
||||
|
@ -179,7 +179,7 @@ class Sequencer {
|
|||
this.log.info(`Ended loop ${x + 1}`);
|
||||
this.ui.send(this.id, { loop: x, stop: true });
|
||||
}
|
||||
if (this.cmd.proj.filmout.state.enabled === true) {
|
||||
if (this.cmd.proj.filmout.state.enabled === true && !this.cmd.proj.filmout.server.useServer()) {
|
||||
await this.cmd.proj.filmout.display.close();
|
||||
}
|
||||
electron_1.powerSaveBlocker.stop(psbId);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
export {};
|
|
@ -1,90 +1,197 @@
|
|||
'use script'
|
||||
|
||||
let os
|
||||
let restify
|
||||
let app
|
||||
|
||||
let cam
|
||||
let proj
|
||||
let light
|
||||
|
||||
const PACKAGE = require('../../package.json')
|
||||
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const ws_1 = require("ws");
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const promises_1 = require("fs/promises");
|
||||
const path_1 = require("path");
|
||||
const uuid_1 = require("uuid");
|
||||
const Log = require("log");
|
||||
class Server {
|
||||
constructor (camera, projector, light) {
|
||||
restify = require('restify')
|
||||
os = require('os')
|
||||
app = restify.createServer({
|
||||
name: 'mcopy-server',
|
||||
version: PACKAGE.version
|
||||
})
|
||||
|
||||
this.ip = this.getIp()
|
||||
|
||||
/*app.get('/', function (req, res) {
|
||||
mcopy.mobile.log('Device connected');
|
||||
res.send(fs.readFileSync('tmpl/mcopy_index.html', 'utf8'));
|
||||
})
|
||||
app.get('/js/mcopy_mobile.js', function (req, res) {
|
||||
res.send(fs.readFileSync('js/mcopy_mobile.js', 'utf8'));
|
||||
});
|
||||
app.get('/js/jquery.js', function (req, res) {
|
||||
res.send(fs.readFileSync('js/jquery.js', 'utf8'));
|
||||
});
|
||||
app.get('/cmd/:cmd', function (req, res) {
|
||||
var cmd,
|
||||
success = function (res) {
|
||||
var obj = {
|
||||
success: true,
|
||||
cmd : cmd,
|
||||
cam: {
|
||||
dir : cam.dir,
|
||||
pos : cam.pos
|
||||
},
|
||||
proj: {
|
||||
dir : proj.dir,
|
||||
pos : proj.pos
|
||||
}
|
||||
}
|
||||
res.json(obj);
|
||||
};
|
||||
if (typeof req.params.cmd !== 'undefined') {
|
||||
mcopy.log('Receiving command from mobile: ' + req.params.cmd);
|
||||
cmd = req.params.cmd;
|
||||
if (cmd === 'CF'){
|
||||
mcopy.cmd.camera_forward(success);
|
||||
} else if (cmd === 'CB') {
|
||||
mcopy.cmd.camera_backward(success);
|
||||
} else if (cmd === 'PF') {
|
||||
mcopy.cmd.projector_forward(success);
|
||||
} else if (cmd === 'PB') {
|
||||
mcopy.cmd.projector_backward(success);
|
||||
} else {
|
||||
mcopy.mobile.fail(res, 'Command ' + cmd + ' not found');
|
||||
}
|
||||
} else {
|
||||
mcopy.mobile.fail(res, 'No command provided');
|
||||
}
|
||||
});
|
||||
app.get('/state', function (req, res) {
|
||||
res.json({
|
||||
cam: {
|
||||
dir : cam.dir,
|
||||
pos : cam.pos
|
||||
},
|
||||
proj: {
|
||||
dir : proj.dir,
|
||||
pos : proj.pos
|
||||
}
|
||||
});
|
||||
});*/
|
||||
|
||||
|
||||
}
|
||||
end () {
|
||||
app.close()
|
||||
app = null
|
||||
}
|
||||
constructor() {
|
||||
this.id = 'server';
|
||||
this.isActive = false;
|
||||
this.templates = [
|
||||
{
|
||||
name: 'index',
|
||||
path: 'server.html'
|
||||
},
|
||||
{
|
||||
name: 'script',
|
||||
path: 'lib/client/index.js'
|
||||
}
|
||||
];
|
||||
this.port = 9900;
|
||||
this.wsPort = 9901;
|
||||
this.proxy = {};
|
||||
this.queue = {};
|
||||
this.intervalPeriod = 10000; //10 sec
|
||||
this.init();
|
||||
}
|
||||
async init() {
|
||||
this.log = await Log({ label: this.id });
|
||||
await this.load();
|
||||
await this.start();
|
||||
}
|
||||
async load() {
|
||||
this.http = express_1.default();
|
||||
for (let tmpl of this.templates) {
|
||||
tmpl.data = await promises_1.readFile(tmpl.path, 'utf8');
|
||||
}
|
||||
this.http.get('/', this.index.bind(this));
|
||||
this.http.get('/image/:key', this.image.bind(this));
|
||||
this.log.info("Server assets loaded");
|
||||
}
|
||||
template(name, data) {
|
||||
let html = this.templates.find(el => el.name === name).data;
|
||||
for (let key of Object.keys(data)) {
|
||||
html = html.replace(`{{${key}}}`, data[key]);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
async startWss() {
|
||||
try {
|
||||
this.wss = new ws_1.WebSocketServer({ port: this.wsPort });
|
||||
}
|
||||
catch (err) {
|
||||
this.log.error(err);
|
||||
return;
|
||||
}
|
||||
this.wss.on('connection', async function (ws) {
|
||||
ws.on("message", function (data) {
|
||||
let obj = JSON.parse(data);
|
||||
//this.log.info(data)
|
||||
if (obj.id && this.queue[obj.id]) {
|
||||
this.queue[obj.id](obj);
|
||||
delete this.queue[obj.id];
|
||||
if (obj.action !== 'ping') {
|
||||
this.log.info(`${obj.action} ACK`);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
ws.on('close', function () {
|
||||
this.log.info('Client disconnected');
|
||||
}.bind(this));
|
||||
await this.cmd(ws, 'mcopy');
|
||||
this.log.info('Client connected');
|
||||
}.bind(this));
|
||||
this.log.info(`Websocket server started!`);
|
||||
this.log.info(`WSS [ ws://localhost:${this.wsPort} ]`);
|
||||
}
|
||||
async startHttp() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
this.httpd = this.http.listen(this.port, function () {
|
||||
this.log.info(`HTTP server started!`);
|
||||
this.log.info(`URL [ http://localhost:${this.port} ]`);
|
||||
return resolve(true);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
async start() {
|
||||
await this.startHttp();
|
||||
await this.startWss();
|
||||
this.interval = setInterval(async function () {
|
||||
await this.cmdAll('ping');
|
||||
}.bind(this), this.intervalPeriod);
|
||||
this.isActive = true;
|
||||
}
|
||||
async stopHttp() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
return this.httpd.close(function () {
|
||||
this.log.info(`HTTP server stopped :(`);
|
||||
return resolve(false);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
async stop() {
|
||||
await this.stopHttp();
|
||||
clearInterval(this.interval);
|
||||
this.isActive = false;
|
||||
}
|
||||
index(req, res, next) {
|
||||
const SCRIPT = this.template('script', { PORT: `${this.wsPort}` });
|
||||
const html = this.template('index', { SCRIPT });
|
||||
this.log.info('GET /');
|
||||
return res.send(html);
|
||||
}
|
||||
async image(req, res, next) {
|
||||
let filePath;
|
||||
if (req.params && req.params.key) {
|
||||
if (this.proxy[req.params.key]) {
|
||||
filePath = this.proxy[req.params.key].path;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
return res.sendFile(filePath, function (err) {
|
||||
if (err) {
|
||||
res.status(err.status).end();
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(true);
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
addProxy(key, filePath) {
|
||||
//wipe every time
|
||||
this.proxy = {};
|
||||
this.proxy[key] = {
|
||||
path: filePath
|
||||
};
|
||||
this.log.info(`Added proxy image [${key}]`);
|
||||
}
|
||||
async cmdAll(action, options = {}) {
|
||||
const cmds = [];
|
||||
if (this.useServer()) {
|
||||
this.wss.clients.forEach(function (ws) {
|
||||
cmds.push(this.cmd(ws, action, options));
|
||||
}.bind(this));
|
||||
await Promise.all(cmds);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
async displayImage(src) {
|
||||
let key;
|
||||
if (this.useServer()) {
|
||||
key = path_1.basename(src);
|
||||
this.addProxy(key, src);
|
||||
await this.cmdAll('image', { image: `/image/${key}` });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
useServer() {
|
||||
return this.isActive && this.wss.clients.size > 0;
|
||||
}
|
||||
/**
|
||||
* WSS
|
||||
**/
|
||||
async cmd(ws, action, options = {}) {
|
||||
const id = uuid_1.v4();
|
||||
let obj = {
|
||||
id, action
|
||||
};
|
||||
let str;
|
||||
obj = Object.assign(obj, options);
|
||||
str = JSON.stringify(obj);
|
||||
ws.send(str);
|
||||
return new Promise(function (resolve, reject) {
|
||||
this.queue[id] = function (obj) {
|
||||
return resolve(obj);
|
||||
};
|
||||
//setTimeout() ?
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Server
|
||||
module.exports = function () {
|
||||
return new Server();
|
||||
};
|
||||
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -39,6 +39,7 @@ let cmd;
|
|||
let seq;
|
||||
let capper;
|
||||
let alert;
|
||||
let server;
|
||||
|
||||
const cfg = require('./data/cfg.json')
|
||||
|
||||
|
@ -116,8 +117,9 @@ var init = async function () {
|
|||
log.error('Error enumerating connected devices', err)
|
||||
}
|
||||
|
||||
server = require('server')()
|
||||
light = require('light')(arduino, cfg, mainWindow.webContents)
|
||||
filmout = require('filmout')(display, ffmpeg, ffprobe, mainWindow.webContents, light)
|
||||
filmout = require('filmout')(display, server, ffmpeg, ffprobe, mainWindow.webContents, light)
|
||||
cam = require('cam')(arduino, cfg, mainWindow.webContents, filmout)
|
||||
proj = require('proj')(arduino, cfg, mainWindow.webContents, filmout)
|
||||
alert = require('alert')(mainWindow.webContents)
|
||||
|
@ -135,7 +137,6 @@ var init = async function () {
|
|||
|
||||
cmd = require('cmd')(cfg, proj, cam, light, alert, cam2, proj2, capper)
|
||||
seq = require('sequencer')(cfg, cmd, mainWindow.webContents)
|
||||
|
||||
}
|
||||
|
||||
app.on('ready', init)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mcopy-app",
|
||||
"version": "1.7.7",
|
||||
"version": "1.7.18",
|
||||
"description": "GUI for the mcopy small gauge film optical printer platform",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
@ -64,6 +64,7 @@
|
|||
"display": "file:lib/display",
|
||||
"exec": "file:lib/exec",
|
||||
"exit": "file:lib/exit",
|
||||
"express": "^4.18.2",
|
||||
"ffmpeg": "file:lib/ffmpeg",
|
||||
"ffmpeg-static": "^5.0.0",
|
||||
"ffprobe": "file:lib/ffprobe",
|
||||
|
@ -89,7 +90,8 @@
|
|||
"spawn": "file:lib/spawn",
|
||||
"system": "file:lib/system",
|
||||
"uuid": "^8.3.2",
|
||||
"winston": "^3.7.2"
|
||||
"winston": "^3.7.2",
|
||||
"ws": "^8.12.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"electron-installer-debian": "^3.1.0"
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
html, body{ background: #000; padding: 0; margin: 0; width: 100vw; height: 100vh; overflow: hidden; }
|
||||
body.meter { background: rgb(117, 117, 117); }
|
||||
body.blank { background: #000; }
|
||||
body.blank #img, body.blank #can, body.meter #img, body.meter #can, body.image #can { display: none; }
|
||||
body.image #img, #can.show { display: block; }
|
||||
#nosleep { color: #fff; margin: 50px auto; text-align: center; }
|
||||
#img {
|
||||
position: absolute;
|
||||
background-repeat:no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
#can{
|
||||
margin: 0;
|
||||
background: #fff;
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
</style>
|
||||
<div id="nosleep">Click to full screen and prevent sleep</div>
|
||||
<div id="img">
|
||||
</div>
|
||||
<canvas id="can">
|
||||
</canvas>
|
||||
<script>
|
||||
{{SCRIPT}}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1.7.7",
|
||||
"version": "1.7.18",
|
||||
"ext_port": 1111,
|
||||
"profiles": {
|
||||
"mcopy": {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "mcopy",
|
||||
"version": "1.7.7",
|
||||
"version": "1.7.18",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mcopy",
|
||||
"version": "1.7.7",
|
||||
"version": "1.7.18",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"arduino": "file:app/lib/arduino",
|
||||
|
@ -28,12 +28,14 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/electron": "^1.6.10",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/fs-extra": "^9.0.7",
|
||||
"@types/jimp": "^0.2.28",
|
||||
"@types/node": "^14.14.31",
|
||||
"@types/request": "^2.48.5",
|
||||
"@types/sharp": "^0.27.1",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/ws": "^8.5.4",
|
||||
"jsdoc-to-markdown": "^6.0.1",
|
||||
"typescript": "^4.1.5"
|
||||
}
|
||||
|
@ -596,12 +598,31 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
|
||||
"integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/connect": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/caseless": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/connect": {
|
||||
"version": "3.4.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
|
||||
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/electron": {
|
||||
"version": "1.6.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/electron/-/electron-1.6.10.tgz",
|
||||
|
@ -611,6 +632,29 @@
|
|||
"electron": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express": {
|
||||
"version": "4.17.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
|
||||
"integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "^4.17.33",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express-serve-static-core": {
|
||||
"version": "4.17.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz",
|
||||
"integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/range-parser": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/fs-extra": {
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.7.tgz",
|
||||
|
@ -629,12 +673,30 @@
|
|||
"jimp": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mime": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
|
||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "14.14.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz",
|
||||
"integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/range-parser": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
|
||||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/request": {
|
||||
"version": "2.48.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz",
|
||||
|
@ -647,6 +709,16 @@
|
|||
"form-data": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/serve-static": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz",
|
||||
"integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/mime": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/sharp": {
|
||||
"version": "0.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.27.1.tgz",
|
||||
|
@ -668,6 +740,15 @@
|
|||
"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
|
||||
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escape-sequences": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz",
|
||||
|
@ -3284,12 +3365,31 @@
|
|||
"defer-to-connect": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@types/body-parser": {
|
||||
"version": "1.19.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
|
||||
"integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/connect": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/caseless": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
|
||||
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/electron": {
|
||||
"version": "1.6.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/electron/-/electron-1.6.10.tgz",
|
||||
|
@ -3299,6 +3399,29 @@
|
|||
"electron": "*"
|
||||
}
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
|
||||
"integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "^4.17.33",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"@types/express-serve-static-core": {
|
||||
"version": "4.17.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz",
|
||||
"integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/range-parser": "*"
|
||||
}
|
||||
},
|
||||
"@types/fs-extra": {
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.7.tgz",
|
||||
|
@ -3317,12 +3440,30 @@
|
|||
"jimp": "*"
|
||||
}
|
||||
},
|
||||
"@types/mime": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
|
||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.14.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz",
|
||||
"integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/range-parser": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
|
||||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/request": {
|
||||
"version": "2.48.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz",
|
||||
|
@ -3335,6 +3476,16 @@
|
|||
"form-data": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"@types/serve-static": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz",
|
||||
"integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/mime": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/sharp": {
|
||||
"version": "0.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.27.1.tgz",
|
||||
|
@ -3356,6 +3507,15 @@
|
|||
"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "8.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
|
||||
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"ansi-escape-sequences": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mcopy",
|
||||
"version": "1.7.7",
|
||||
"version": "1.7.18",
|
||||
"description": "Small gauge film optical printer platform",
|
||||
"main": "build.js",
|
||||
"directories": {
|
||||
|
@ -26,12 +26,14 @@
|
|||
"homepage": "https://github.com/sixteenmillimeter/mcopy#readme",
|
||||
"devDependencies": {
|
||||
"@types/electron": "^1.6.10",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/fs-extra": "^9.0.7",
|
||||
"@types/jimp": "^0.2.28",
|
||||
"@types/node": "^14.14.31",
|
||||
"@types/request": "^2.48.5",
|
||||
"@types/sharp": "^0.27.1",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/ws": "^8.5.4",
|
||||
"jsdoc-to-markdown": "^6.0.1",
|
||||
"typescript": "^4.1.5"
|
||||
},
|
||||
|
@ -47,8 +49,8 @@
|
|||
"light": "file:app/lib/light",
|
||||
"log": "file:app/lib/log",
|
||||
"mscript": "file:app/lib/mscript",
|
||||
"proj": "file:app/lib/proj",
|
||||
"processing": "file:app/lib/processing",
|
||||
"proj": "file:app/lib/proj",
|
||||
"sequencer": "file:app/lib/sequencer",
|
||||
"settings": "file:app/lib/settings",
|
||||
"system": "file:app/lib/system"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1.7.7",
|
||||
"version": "1.7.18",
|
||||
"ext_port": 1111,
|
||||
"profiles": {
|
||||
"mcopy": {
|
||||
|
|
|
@ -8,7 +8,7 @@ echo "VERSION: $version"
|
|||
|
||||
git add ./package.json
|
||||
|
||||
declare -a fileArr=("./package-lock.json" "./data/cfg.json" "./app/package.json" "./app/package-lock.json" "./processing/mcopy/cfg.json")
|
||||
declare -a fileArr=("./package-lock.json" "./data/cfg.json" "./app/package.json" "./app/package-lock.json" "./app/data/cfg.json" "./processing/mcopy/cfg.json")
|
||||
|
||||
for i in "${fileArr[@]}"
|
||||
do
|
||||
|
|
|
@ -25,7 +25,8 @@ class WebView {
|
|||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
allowRunningInsecureContent: false,
|
||||
enableRemoteModule: true
|
||||
enableRemoteModule: true,
|
||||
contextIsolation: false
|
||||
},
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
@ -43,6 +44,7 @@ class WebView {
|
|||
prefs.y = display.y + 50;
|
||||
}
|
||||
this.digitalWindow = new BrowserWindow(prefs);
|
||||
require('@electron/remote/main').enable(this.digitalWindow.webContents)
|
||||
this.digitalWindow.loadURL(pageUrl);
|
||||
if (process.argv.indexOf('-d') !== -1 || process.argv.indexOf('--dev') !== -1) {
|
||||
this.digitalWindow.webContents.openDevTools();
|
||||
|
|
|
@ -37,6 +37,7 @@ class FilmOut {
|
|||
private ipc : any;
|
||||
private ui : any;
|
||||
private log : any;
|
||||
private server : any;
|
||||
/**
|
||||
* @constructor
|
||||
* Builds FilmOut class with display, ffmpeg, ffprobe, ui and light as internal properties.
|
||||
|
@ -47,8 +48,9 @@ class FilmOut {
|
|||
* @param {object} ui Electron ui object
|
||||
* @param {object} light Light device object
|
||||
**/
|
||||
constructor (display : any, ffmpeg : any, ffprobe : any, ui : any, light : any) {
|
||||
constructor (display : any, server : any, ffmpeg : any, ffprobe : any, ui : any, light : any) {
|
||||
this.display = display;
|
||||
this.server = server;
|
||||
this.ffmpeg = ffmpeg;
|
||||
this.ffprobe = ffprobe;
|
||||
this.ui = ui;
|
||||
|
@ -133,6 +135,11 @@ class FilmOut {
|
|||
throw err;
|
||||
}
|
||||
|
||||
if (this.server.displayImage(path)) {
|
||||
await delay(20)
|
||||
return
|
||||
}
|
||||
|
||||
await this.display.show(path);
|
||||
await delay(20);
|
||||
}
|
||||
|
@ -430,6 +437,9 @@ class FilmOut {
|
|||
}
|
||||
|
||||
try {
|
||||
if (await this.server.displayImage(path)) {
|
||||
return
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.show(path);
|
||||
} catch (err) {
|
||||
|
@ -442,6 +452,9 @@ class FilmOut {
|
|||
async focus (evt : any, arg : any) {
|
||||
this.log.info(`Showing focus screen`);
|
||||
try {
|
||||
if (await this.server.cmdAll('focus')) {
|
||||
return
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.focus();
|
||||
} catch (err) {
|
||||
|
@ -455,8 +468,12 @@ class FilmOut {
|
|||
const ratio : number = arg.ratio;
|
||||
this.log.info(`Showing field guide screen`);
|
||||
try {
|
||||
if (await this.server.cmdAll('field', { ratio })) {
|
||||
return
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.field(ratio);
|
||||
|
||||
} catch (err) {
|
||||
this.log.error(err, 'FILMOUT', true, true);
|
||||
}
|
||||
|
@ -467,6 +484,9 @@ class FilmOut {
|
|||
async meter (evt : any, arg : any) {
|
||||
this.log.info(`Showing meter screen`);
|
||||
try {
|
||||
if (await this.server.cmdAll('meter')) {
|
||||
return
|
||||
}
|
||||
await this.display.open();
|
||||
await this.display.meter();
|
||||
} catch (err) {
|
||||
|
@ -478,8 +498,12 @@ class FilmOut {
|
|||
**/
|
||||
async close (evt : any, arg : any) {
|
||||
try {
|
||||
if (await this.server.cmdAll('blank')) {
|
||||
return
|
||||
}
|
||||
await this.display.hide();
|
||||
await this.display.close();
|
||||
|
||||
} catch (err) {
|
||||
this.log.error(err, 'FILMOUT', true, true);
|
||||
}
|
||||
|
@ -493,6 +517,6 @@ class FilmOut {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = (display : any, ffmpeg : any, ffprobe : any, ui : any, light : any) => {
|
||||
return new FilmOut(display, ffmpeg, ffprobe, ui, light);
|
||||
module.exports = (display : any, server : any, ffmpeg : any, ffprobe : any, ui : any, light : any) => {
|
||||
return new FilmOut(display, server, ffmpeg, ffprobe, ui, light);
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ async function logFile () {
|
|||
*
|
||||
* @returns {object} Logger transport
|
||||
**/
|
||||
module.exports = async function (arg : any) {
|
||||
module.exports = async function Log (arg : any) {
|
||||
let consoleFormat : any = {
|
||||
colorize : true
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ class Projector {
|
|||
}
|
||||
message += ' 1 frame'
|
||||
} else if (cmd === this.cfg.arduino.cmd.projectors) {
|
||||
message += 'Projectors both MOVED 1 frame each';
|
||||
message += 'Projectors both MOVED 1 frame each'
|
||||
}
|
||||
message += ` ${ms}ms`
|
||||
this.log.info(message, 'PROJECTOR')
|
||||
|
@ -164,5 +164,5 @@ class Projector {
|
|||
}
|
||||
|
||||
module.exports = function (arduino : Arduino, cfg : any, ui : any, filmout : any, second : boolean) {
|
||||
return new Projector(arduino, cfg, ui, filmout, second);
|
||||
return new Projector(arduino, cfg, ui, filmout, second)
|
||||
}
|
|
@ -168,7 +168,7 @@ class Sequencer {
|
|||
this.log.info(`Starting sequence...`);
|
||||
this.ui.send(this.id, { start : true });
|
||||
|
||||
if (this.cmd.proj.filmout.state.enabled === true) {
|
||||
if (this.cmd.proj.filmout.state.enabled === true && !this.cmd.proj.filmout.server.useServer()) {
|
||||
await this.cmd.proj.filmout.display.open();
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ class Sequencer {
|
|||
this.ui.send(this.id, { loop : x, stop : true });
|
||||
}
|
||||
|
||||
if (this.cmd.proj.filmout.state.enabled === true) {
|
||||
if (this.cmd.proj.filmout.state.enabled === true && !this.cmd.proj.filmout.server.useServer()) {
|
||||
await this.cmd.proj.filmout.display.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
import WebSocket, { WebSocketServer } from 'ws'
|
||||
import express, { Express, Request, Response, Application } from 'express'
|
||||
import { readFile } from 'fs/promises'
|
||||
import { basename } from 'path'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import Log = require('log')
|
||||
import { delay } from 'delay'
|
||||
|
||||
interface ServerData {
|
||||
[key: string]: string;
|
||||
PORT? : string;
|
||||
SCRIPT? : string;
|
||||
}
|
||||
|
||||
interface ServerTemplate {
|
||||
name : string;
|
||||
path : string;
|
||||
data? : string;
|
||||
}
|
||||
|
||||
interface ServerProxy {
|
||||
path : string;
|
||||
}
|
||||
|
||||
interface ServerProxyList {
|
||||
[key: string]: ServerProxy;
|
||||
}
|
||||
|
||||
interface ServerQueue {
|
||||
[key: string]: Function;
|
||||
}
|
||||
|
||||
class Server {
|
||||
private id : string = 'server'
|
||||
public isActive : boolean = false
|
||||
private log : any
|
||||
private templates : ServerTemplate[] = [
|
||||
{
|
||||
name :'index',
|
||||
path : 'server.html'
|
||||
},
|
||||
{
|
||||
name : 'script',
|
||||
path : 'lib/client/index.js'
|
||||
}
|
||||
]
|
||||
private http : Application
|
||||
private httpd : Server
|
||||
private wss : WebSocketServer
|
||||
private port : number = 9900
|
||||
private wsPort : number = 9901
|
||||
private proxy : ServerProxyList = {}
|
||||
private queue : ServerQueue = {}
|
||||
private interval : ReturnType<typeof setInterval>
|
||||
private intervalPeriod : number = 10000 //10 sec
|
||||
|
||||
constructor () {
|
||||
this.init()
|
||||
}
|
||||
|
||||
async init () {
|
||||
this.log = await Log({ label : this.id });
|
||||
await this.load()
|
||||
await this.start()
|
||||
}
|
||||
|
||||
async load () {
|
||||
this.http = express()
|
||||
for (let tmpl of this.templates) {
|
||||
tmpl.data = await readFile(tmpl.path, 'utf8')
|
||||
}
|
||||
|
||||
this.http.get('/', this.index.bind(this))
|
||||
this.http.get('/image/:key', this.image.bind(this))
|
||||
|
||||
this.log.info("Server assets loaded")
|
||||
}
|
||||
|
||||
template (name: string, data : ServerData) {
|
||||
let html : string = this.templates.find(el => el.name === name).data
|
||||
for (let key of Object.keys(data)) {
|
||||
html = html.replace(`{{${key}}}`, data[key])
|
||||
}
|
||||
return html
|
||||
}
|
||||
|
||||
async startWss () {
|
||||
try {
|
||||
this.wss = new WebSocketServer({ port: this.wsPort })
|
||||
} catch (err) {
|
||||
this.log.error(err)
|
||||
return
|
||||
}
|
||||
this.wss.on('connection', async function (ws : WebSocket) {
|
||||
ws.on("message", function (data : string ) {
|
||||
let obj : any = JSON.parse(data)
|
||||
//this.log.info(data)
|
||||
if (obj.id && this.queue[obj.id]) {
|
||||
this.queue[obj.id](obj)
|
||||
delete this.queue[obj.id]
|
||||
if (obj.action !== 'ping') {
|
||||
this.log.info(`${obj.action} ACK`)
|
||||
}
|
||||
}
|
||||
}.bind(this))
|
||||
|
||||
ws.on('close', function () {
|
||||
this.log.info('Client disconnected')
|
||||
}.bind(this))
|
||||
|
||||
await this.cmd(ws, 'mcopy')
|
||||
this.log.info('Client connected')
|
||||
|
||||
}.bind(this))
|
||||
this.log.info(`Websocket server started!`)
|
||||
this.log.info(`WSS [ ws://localhost:${this.wsPort} ]`)
|
||||
}
|
||||
|
||||
async startHttp () {
|
||||
return new Promise(function (resolve : Function, reject : Function) {
|
||||
this.httpd = this.http.listen(this.port, function () {
|
||||
this.log.info(`HTTP server started!`)
|
||||
this.log.info(`URL [ http://localhost:${this.port} ]`)
|
||||
return resolve(true)
|
||||
}.bind(this))
|
||||
}.bind(this))
|
||||
}
|
||||
|
||||
async start () {
|
||||
await this.startHttp()
|
||||
await this.startWss()
|
||||
this.interval = setInterval(async function () {
|
||||
await this.cmdAll('ping');
|
||||
}.bind(this), this.intervalPeriod)
|
||||
this.isActive = true
|
||||
}
|
||||
|
||||
async stopHttp() {
|
||||
return new Promise(function (resolve : Function, reject : Function) {
|
||||
return this.httpd.close(function () {
|
||||
this.log.info(`HTTP server stopped :(`)
|
||||
return resolve(false)
|
||||
}.bind(this))
|
||||
}.bind(this))
|
||||
}
|
||||
|
||||
async stop () {
|
||||
await this.stopHttp()
|
||||
clearInterval(this.interval)
|
||||
this.isActive = false
|
||||
}
|
||||
|
||||
index (req : Request, res : Response, next : Function) {
|
||||
const SCRIPT = this.template('script', { PORT : `${this.wsPort}` })
|
||||
const html : string = this.template('index', { SCRIPT })
|
||||
this.log.info('GET /')
|
||||
return res.send(html)
|
||||
}
|
||||
|
||||
async image (req : Request, res : Response, next : Function) {
|
||||
let filePath : string
|
||||
if (req.params && req.params.key) {
|
||||
if (this.proxy[req.params.key]) {
|
||||
filePath = this.proxy[req.params.key].path
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return new Promise(function (resolve : Function, reject: Function) {
|
||||
return res.sendFile(filePath, function (err : any) {
|
||||
if (err) {
|
||||
res.status(err.status).end()
|
||||
return reject(err)
|
||||
}
|
||||
return resolve(true)
|
||||
})
|
||||
}.bind(this))
|
||||
}
|
||||
|
||||
public addProxy (key : string, filePath : string) {
|
||||
//wipe every time
|
||||
this.proxy = {}
|
||||
this.proxy[key] = {
|
||||
path : filePath
|
||||
}
|
||||
this.log.info(`Added proxy image [${key}]`)
|
||||
}
|
||||
|
||||
public async cmdAll (action : string, options : any = {}) {
|
||||
const cmds : any[] = []
|
||||
if (this.useServer()) {
|
||||
this.wss.clients.forEach(function (ws : WebSocket) {
|
||||
cmds.push(this.cmd(ws, action, options))
|
||||
}.bind(this))
|
||||
await Promise.all(cmds)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public async displayImage (src : string) {
|
||||
let key
|
||||
if (this.useServer()) {
|
||||
key = basename(src)
|
||||
this.addProxy(key, src)
|
||||
await this.cmdAll('image', { image : `/image/${key}` })
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public useServer () : boolean {
|
||||
return this.isActive && this.wss.clients.size > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* WSS
|
||||
**/
|
||||
|
||||
public async cmd (ws : WebSocket, action : string, options : any = {}) {
|
||||
const id : string = uuidv4()
|
||||
let obj = {
|
||||
id, action
|
||||
}
|
||||
let str : string
|
||||
|
||||
obj = Object.assign(obj, options)
|
||||
str = JSON.stringify(obj)
|
||||
ws.send(str)
|
||||
|
||||
return new Promise(function (resolve : Function, reject: Function) {
|
||||
this.queue[id] = function (obj : any) {
|
||||
return resolve(obj)
|
||||
}
|
||||
//setTimeout() ?
|
||||
}.bind(this))
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
return new Server()
|
||||
}
|
Loading…
Reference in New Issue