Added any number of untold features. Saving.
This commit is contained in:
parent
0b280ff623
commit
c33aaa2bec
|
@ -84,7 +84,7 @@ class Display {
|
||||||
this.ctx.stroke();
|
this.ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateDisplay () {
|
public updateDisplay () {
|
||||||
if (!this.sequence) {
|
if (!this.sequence) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -96,13 +96,13 @@ class Display {
|
||||||
this.displayOffsetX = this.screenOffsetX + Math.round(this.offsetX * screenScaleX);
|
this.displayOffsetX = this.screenOffsetX + Math.round(this.offsetX * screenScaleX);
|
||||||
this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY);
|
this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY);
|
||||||
|
|
||||||
this.ctx.fillStyle = 'rgb(125, 125, 125)';
|
this.ctx.fillStyle = 'rgb(0, 0, 0)';
|
||||||
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
||||||
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
|
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
|
||||||
this.updateImage();
|
this.updateImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateImage() {
|
public updateImage() {
|
||||||
const img : any = new Image;
|
const img : any = new Image;
|
||||||
img.onload = function () {
|
img.onload = function () {
|
||||||
this.ctx.drawImage(img, this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
this.ctx.drawImage(img, this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
||||||
|
@ -136,16 +136,18 @@ class Client {
|
||||||
private client : WebSocket;
|
private client : WebSocket;
|
||||||
private connected : boolean = false;
|
private connected : boolean = false;
|
||||||
private progress : HTMLProgressElement;
|
private progress : HTMLProgressElement;
|
||||||
|
private progressText : HTMLElement;
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
let uri : string = 'ws://localhost:8082';
|
let uri : string = 'ws://localhost:8082';
|
||||||
this.progress = document.getElementById('progress') as HTMLProgressElement;
|
this.progress = document.getElementById('progress') as HTMLProgressElement;
|
||||||
|
this.progressText = document.getElementById('progressText');
|
||||||
this.client = new WebSocket(uri);
|
this.client = new WebSocket(uri);
|
||||||
this.display = new Display();
|
this.display = new Display();
|
||||||
this.client.onopen = this.onOpen.bind(this);
|
this.client.onopen = this.onOpen.bind(this);
|
||||||
this.client.onclose = this.onClose.bind(this);
|
this.client.onclose = this.onClose.bind(this);
|
||||||
this.client.onmessage = this.onMessage.bind(this);
|
this.client.onmessage = this.onMessage.bind(this);
|
||||||
(document.getElementById('sequenceForm') as HTMLFormElement ).reset();
|
(document.getElementById('sequenceSelectForm') as HTMLFormElement ).reset();
|
||||||
(document.getElementById('sequenceCtrlForm') as HTMLFormElement ).reset();
|
(document.getElementById('sequenceCtrlForm') as HTMLFormElement ).reset();
|
||||||
(document.getElementById('manualCtrlForm') as HTMLFormElement ).reset();
|
(document.getElementById('manualCtrlForm') as HTMLFormElement ).reset();
|
||||||
this.disableClass('sequenceCtrl');
|
this.disableClass('sequenceCtrl');
|
||||||
|
@ -174,11 +176,19 @@ class Client {
|
||||||
|
|
||||||
private setSequence(state : State) {
|
private setSequence(state : State) {
|
||||||
this.setProgress(state.sequence);
|
this.setProgress(state.sequence);
|
||||||
|
this.setFrame(state.sequence);
|
||||||
this.setStatus(state.sequence);
|
this.setStatus(state.sequence);
|
||||||
this.setDisplay(state);
|
this.setDisplay(state);
|
||||||
(document.getElementById('sequence') as HTMLSelectElement ).value = state.sequence.hash;
|
(document.getElementById('sequence') as HTMLSelectElement ).value = state.sequence.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setUpdate(state : State) {
|
||||||
|
this.setProgress(state.sequence);
|
||||||
|
this.setFrame(state.sequence);
|
||||||
|
this.setStatus(state.sequence);
|
||||||
|
this.display.updateImage();
|
||||||
|
}
|
||||||
|
|
||||||
private setStatus (sequence : SequenceState) {
|
private setStatus (sequence : SequenceState) {
|
||||||
let status : string;
|
let status : string;
|
||||||
switch (sequence.status) {
|
switch (sequence.status) {
|
||||||
|
@ -202,10 +212,15 @@ class Client {
|
||||||
private setProgress (sequence : SequenceState) {
|
private setProgress (sequence : SequenceState) {
|
||||||
const percent : number = sequence.progress * 100.0;
|
const percent : number = sequence.progress * 100.0;
|
||||||
if (this.progress !== null) {
|
if (this.progress !== null) {
|
||||||
this.progress.value = percent;
|
this.progress.value = sequence.progress;
|
||||||
this.progress.innerText = `${Math.floor(percent)}%`;
|
this.progressText.innerText = `Progress: ${Math.floor(percent)}%`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFrame (sequence : SequenceState) {
|
||||||
|
if (typeof sequence.current !== 'undefined') {
|
||||||
|
(document.getElementById('frame') as HTMLInputElement).value = `${sequence.current}`.padStart(5, '0');
|
||||||
}
|
}
|
||||||
document.getElementById('sequenceProgress').innerText = `Progress: ${Math.round(sequence.progress)}%`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private setDisplay (state : State) {
|
private setDisplay (state : State) {
|
||||||
|
@ -214,17 +229,18 @@ class Client {
|
||||||
const srcWidthEl : HTMLInputElement = document.getElementById('sourceWidth') as HTMLInputElement;
|
const srcWidthEl : HTMLInputElement = document.getElementById('sourceWidth') as HTMLInputElement;
|
||||||
const srcHeightEl : HTMLInputElement = document.getElementById('sourceHeight') as HTMLInputElement;
|
const srcHeightEl : HTMLInputElement = document.getElementById('sourceHeight') as HTMLInputElement;
|
||||||
|
|
||||||
widthEl.value = state.display.width as any;
|
if (typeof state.display !== 'undefined') {
|
||||||
heightEl.value = state.display.height as any;
|
widthEl.value = state.display.width as any;
|
||||||
|
heightEl.value = state.display.height as any;
|
||||||
|
|
||||||
srcWidthEl.value = state.source.width as any;
|
srcWidthEl.value = state.source.width as any;
|
||||||
srcHeightEl.value = state.source.height as any;
|
srcHeightEl.value = state.source.height as any;
|
||||||
|
|
||||||
widthEl.readOnly = false;
|
|
||||||
heightEl.readOnly = false;
|
|
||||||
//console.dir(state);
|
|
||||||
this.display.set(state);
|
|
||||||
|
|
||||||
|
widthEl.readOnly = false;
|
||||||
|
heightEl.readOnly = false;
|
||||||
|
//console.dir(state);
|
||||||
|
this.display.set(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private cmd (msg : Message) {
|
private cmd (msg : Message) {
|
||||||
|
@ -238,6 +254,9 @@ class Client {
|
||||||
case 'select' :
|
case 'select' :
|
||||||
this.receiveSelect(msg);
|
this.receiveSelect(msg);
|
||||||
break;
|
break;
|
||||||
|
case 'update' :
|
||||||
|
this.receiveUpdate(msg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn(`No command "${msg.cmd}"`);
|
console.warn(`No command "${msg.cmd}"`);
|
||||||
break;
|
break;
|
||||||
|
@ -280,6 +299,14 @@ class Client {
|
||||||
this.enableClass('manualCtrl');
|
this.enableClass('manualCtrl');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sendAdvance () {
|
||||||
|
this.client.send(JSON.stringify({ cmd : 'advance' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendRewind () {
|
||||||
|
this.client.send(JSON.stringify({ cmd : 'rewind' }));
|
||||||
|
}
|
||||||
|
|
||||||
public sendSelect () {
|
public sendSelect () {
|
||||||
const hash : string = (document.getElementById('sequence') as HTMLSelectElement ).value;
|
const hash : string = (document.getElementById('sequence') as HTMLSelectElement ).value;
|
||||||
let msg : Message;
|
let msg : Message;
|
||||||
|
@ -294,13 +321,21 @@ class Client {
|
||||||
|
|
||||||
private receiveSelect (msg : Message) {
|
private receiveSelect (msg : Message) {
|
||||||
console.log('got select');
|
console.log('got select');
|
||||||
console.dir(msg);
|
//console.dir(msg);
|
||||||
this.enableClass('sequenceCtrl');
|
this.enableClass('sequenceCtrl');
|
||||||
this.setSequence(msg.state);
|
this.setSequence(msg.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private receiveUpdate (msg : Message) {
|
public sendStart () {
|
||||||
|
this.client.send(JSON.stringify({ cmd : 'start' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendStop () {
|
||||||
|
this.client.send(JSON.stringify({ cmd : 'stop' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
private receiveUpdate (msg : Message) {
|
||||||
|
this.setUpdate(msg.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public fullscreen () {
|
public fullscreen () {
|
||||||
|
|
|
@ -47,7 +47,8 @@ export declare class FD {
|
||||||
private socketAvailable;
|
private socketAvailable;
|
||||||
private socketConnected;
|
private socketConnected;
|
||||||
private waiting;
|
private waiting;
|
||||||
constructor(bin: string, width: number, height: number, host: string, port: number);
|
private mock;
|
||||||
|
constructor(bin: string, width: number, height: number, host: string, port: number, mock?: boolean);
|
||||||
private startDisplay;
|
private startDisplay;
|
||||||
private startClient;
|
private startClient;
|
||||||
private logstd;
|
private logstd;
|
||||||
|
|
|
@ -25,26 +25,33 @@ var Mode;
|
||||||
Mode[Mode["INVERT_CHANNELS"] = 5] = "INVERT_CHANNELS";
|
Mode[Mode["INVERT_CHANNELS"] = 5] = "INVERT_CHANNELS";
|
||||||
})(Mode || (Mode = {}));
|
})(Mode || (Mode = {}));
|
||||||
class FD {
|
class FD {
|
||||||
constructor(bin, width, height, host, port) {
|
constructor(bin, width, height, host, port, mock = false) {
|
||||||
this.socketAvailable = false;
|
this.socketAvailable = false;
|
||||||
this.socketConnected = false;
|
this.socketConnected = false;
|
||||||
this.waiting = null;
|
this.waiting = null;
|
||||||
|
this.mock = false;
|
||||||
this.bin = bin;
|
this.bin = bin;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
this.mock = mock;
|
||||||
this.log = (0, log_1.createLog)('fd');
|
this.log = (0, log_1.createLog)('fd');
|
||||||
this.shell = new shell_1.Shell([this.bin, `${this.width}`, `${this.height}`, `${this.port}`], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
if (!this.mock)
|
||||||
|
this.shell = new shell_1.Shell([this.bin, `${this.width}`, `${this.height}`, `${this.port}`], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
||||||
this.startDisplay();
|
this.startDisplay();
|
||||||
this.startClient();
|
this.startClient();
|
||||||
this.test();
|
//this.test();
|
||||||
}
|
}
|
||||||
async startDisplay() {
|
async startDisplay() {
|
||||||
this.log.info(`Launching fd binary ${this.bin}`);
|
this.log.info(`Launching fd binary ${this.bin}`);
|
||||||
this.shell.execute();
|
if (!this.mock)
|
||||||
|
this.shell.execute();
|
||||||
}
|
}
|
||||||
async startClient() {
|
async startClient() {
|
||||||
|
if (this.mock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
this.client = new net_1.default.Socket();
|
this.client = new net_1.default.Socket();
|
||||||
this.log.info(`Waiting for TCP socket server on ${this.host}:${this.port}...`);
|
this.log.info(`Waiting for TCP socket server on ${this.host}:${this.port}...`);
|
||||||
while (!this.socketAvailable) {
|
while (!this.socketAvailable) {
|
||||||
|
@ -65,7 +72,8 @@ class FD {
|
||||||
this.client.on('error', (err) => {
|
this.client.on('error', (err) => {
|
||||||
this.log.error('Error in socket client', err);
|
this.log.error('Error in socket client', err);
|
||||||
this.socketConnected = false;
|
this.socketConnected = false;
|
||||||
this.shell.kill();
|
if (!this.mock)
|
||||||
|
this.shell.kill();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
logstd(data) {
|
logstd(data) {
|
||||||
|
@ -90,7 +98,8 @@ class FD {
|
||||||
send(msg) {
|
send(msg) {
|
||||||
const json = JSON.stringify(msg);
|
const json = JSON.stringify(msg);
|
||||||
this.log.info(json);
|
this.log.info(json);
|
||||||
this.client.write(json);
|
if (!this.mock)
|
||||||
|
this.client.write(json);
|
||||||
}
|
}
|
||||||
receive(json) {
|
receive(json) {
|
||||||
const msg = JSON.parse(json);
|
const msg = JSON.parse(json);
|
||||||
|
@ -112,6 +121,13 @@ class FD {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const startTime = +new Date();
|
const startTime = +new Date();
|
||||||
|
if (this.mock) {
|
||||||
|
return {
|
||||||
|
action: Action.LOAD,
|
||||||
|
image,
|
||||||
|
time: (+new Date()) - startTime
|
||||||
|
};
|
||||||
|
}
|
||||||
const promise = new Promise(function (resolve, reject) {
|
const promise = new Promise(function (resolve, reject) {
|
||||||
this.waiting = function (msg) {
|
this.waiting = function (msg) {
|
||||||
if (msg.action == Action.LOAD && msg.success) {
|
if (msg.action == Action.LOAD && msg.success) {
|
||||||
|
@ -137,6 +153,16 @@ class FD {
|
||||||
exposure
|
exposure
|
||||||
};
|
};
|
||||||
const startTime = +new Date();
|
const startTime = +new Date();
|
||||||
|
if (this.mock) {
|
||||||
|
for (let exp of exposure) {
|
||||||
|
await (0, delay_1.delay)(exp);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
action: Action.DISPLAY,
|
||||||
|
image,
|
||||||
|
time: (+new Date()) - startTime
|
||||||
|
};
|
||||||
|
}
|
||||||
const promise = new Promise(function (resolve, reject) {
|
const promise = new Promise(function (resolve, reject) {
|
||||||
this.waiting = function (msg) {
|
this.waiting = function (msg) {
|
||||||
if (msg.action == Action.DISPLAY && msg.success) {
|
if (msg.action == Action.DISPLAY && msg.success) {
|
||||||
|
@ -161,6 +187,13 @@ class FD {
|
||||||
image
|
image
|
||||||
};
|
};
|
||||||
const startTime = +new Date();
|
const startTime = +new Date();
|
||||||
|
if (this.mock) {
|
||||||
|
return {
|
||||||
|
action: Action.STOP,
|
||||||
|
image,
|
||||||
|
time: (+new Date()) - startTime
|
||||||
|
};
|
||||||
|
}
|
||||||
const promise = new Promise(function (resolve, reject) {
|
const promise = new Promise(function (resolve, reject) {
|
||||||
this.waiting = function (msg) {
|
this.waiting = function (msg) {
|
||||||
if (msg.action == Action.STOP && msg.success) {
|
if (msg.action == Action.STOP && msg.success) {
|
||||||
|
@ -194,6 +227,7 @@ class FD {
|
||||||
await this.display(img);
|
await this.display(img);
|
||||||
await (0, delay_1.delay)(2000);
|
await (0, delay_1.delay)(2000);
|
||||||
await this.stop(img);
|
await this.stop(img);
|
||||||
|
this.log.warn('QUITTING!!!!');
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -35,6 +35,7 @@ const Handlebars = __importStar(require("handlebars"));
|
||||||
const ws_1 = require("ws");
|
const ws_1 = require("ws");
|
||||||
const log_1 = require("./log");
|
const log_1 = require("./log");
|
||||||
const files_1 = require("./files");
|
const files_1 = require("./files");
|
||||||
|
const fd_1 = require("./fd");
|
||||||
const display_1 = require("./display");
|
const display_1 = require("./display");
|
||||||
const ffmpeg_1 = require("./ffmpeg");
|
const ffmpeg_1 = require("./ffmpeg");
|
||||||
const ffprobe_1 = require("./ffprobe");
|
const ffprobe_1 = require("./ffprobe");
|
||||||
|
@ -175,7 +176,7 @@ function onWssConnection(ws, req) {
|
||||||
ws.ip = ip;
|
ws.ip = ip;
|
||||||
ws.session = (0, uuid_1.v4)();
|
ws.session = (0, uuid_1.v4)();
|
||||||
ws.on('message', function (data) { onClientMessage(data, ws); });
|
ws.on('message', function (data) { onClientMessage(data, ws); });
|
||||||
sequence.updateClients();
|
sequence.updateClientsOnLoad();
|
||||||
}
|
}
|
||||||
async function onClientMessage(data, ws) {
|
async function onClientMessage(data, ws) {
|
||||||
let msg = null;
|
let msg = null;
|
||||||
|
@ -201,6 +202,18 @@ async function cmd(msg) {
|
||||||
case 'select':
|
case 'select':
|
||||||
await select(msg.state.sequence.hash);
|
await select(msg.state.sequence.hash);
|
||||||
break;
|
break;
|
||||||
|
case 'start':
|
||||||
|
start();
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
case 'advance':
|
||||||
|
frameAdvance();
|
||||||
|
break;
|
||||||
|
case 'rewind':
|
||||||
|
frameRewind();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log.warn(`No matching command: ${msg.cmd}`);
|
log.warn(`No matching command: ${msg.cmd}`);
|
||||||
}
|
}
|
||||||
|
@ -213,6 +226,12 @@ async function cameraClose() {
|
||||||
await camera.close();
|
await camera.close();
|
||||||
send({ cmd: 'close' });
|
send({ cmd: 'close' });
|
||||||
}
|
}
|
||||||
|
function frameAdvance() {
|
||||||
|
sequence.frameAdvance();
|
||||||
|
}
|
||||||
|
function frameRewind() {
|
||||||
|
sequence.frameRewind();
|
||||||
|
}
|
||||||
async function select(id) {
|
async function select(id) {
|
||||||
const sequencesArr = await files_1.Files.enumerateSequences(sequences);
|
const sequencesArr = await files_1.Files.enumerateSequences(sequences);
|
||||||
const seq = sequencesArr.find(el => el.hash === id);
|
const seq = sequencesArr.find(el => el.hash === id);
|
||||||
|
@ -223,6 +242,12 @@ async function select(id) {
|
||||||
await sequence.load(seq);
|
await sequence.load(seq);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
function start() {
|
||||||
|
sequence.start();
|
||||||
|
}
|
||||||
|
function stop() {
|
||||||
|
sequence.stop();
|
||||||
|
}
|
||||||
async function send(msg) {
|
async function send(msg) {
|
||||||
const msgStr = JSON.stringify(msg);
|
const msgStr = JSON.stringify(msg);
|
||||||
wss.clients.forEach((client) => {
|
wss.clients.forEach((client) => {
|
||||||
|
@ -271,7 +296,7 @@ async function main() {
|
||||||
image = new image_1.Image();
|
image = new image_1.Image();
|
||||||
camera = new camera_1.Camera();
|
camera = new camera_1.Camera();
|
||||||
display = new display_1.Display(width, height);
|
display = new display_1.Display(width, height);
|
||||||
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
|
fd = new fd_1.FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']), true);
|
||||||
app.listen(port, async () => {
|
app.listen(port, async () => {
|
||||||
log.info(`filmout_manager HTTP server running on port ${port}`);
|
log.info(`filmout_manager HTTP server running on port ${port}`);
|
||||||
});
|
});
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -28,14 +28,21 @@ export declare class Sequence {
|
||||||
start(): void;
|
start(): void;
|
||||||
stop(): void;
|
stop(): void;
|
||||||
isRunning(): boolean;
|
isRunning(): boolean;
|
||||||
|
private run;
|
||||||
load(seq: SequenceObject): Promise<void>;
|
load(seq: SequenceObject): Promise<void>;
|
||||||
updateClients(): void;
|
updateClientsOnLoad(): void;
|
||||||
|
updateClientsOnState(): void;
|
||||||
private enumerate;
|
private enumerate;
|
||||||
unload(): void;
|
unload(): void;
|
||||||
getState(): State;
|
getState(): State;
|
||||||
|
getUpdateState(): State;
|
||||||
getSequenceState(): SequenceState;
|
getSequenceState(): SequenceState;
|
||||||
setExposure(ms: number): void;
|
setExposure(ms: number): void;
|
||||||
getStatus(): SequenceStatus;
|
getStatus(): SequenceStatus;
|
||||||
getCurrent(): ImageObject;
|
getCurrent(): ImageObject;
|
||||||
|
frameAdvance(frames?: number): void;
|
||||||
|
frameRewind(frames?: number): void;
|
||||||
|
frameSet(frame: number): void;
|
||||||
|
private frameRecord;
|
||||||
}
|
}
|
||||||
export {};
|
export {};
|
||||||
|
|
|
@ -28,26 +28,54 @@ class Sequence {
|
||||||
this.send = send;
|
this.send = send;
|
||||||
}
|
}
|
||||||
start() {
|
start() {
|
||||||
this.running = true;
|
if (this.current !== null) {
|
||||||
|
this.running = true;
|
||||||
|
this.log.info(`Started sequence: ${this.current.name}`);
|
||||||
|
this.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stop() {
|
stop() {
|
||||||
this.running = false;
|
if (this.running && this.current !== null) {
|
||||||
|
this.log.info(`Stopped sequence: ${this.current.name}`);
|
||||||
|
this.running = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isRunning() {
|
isRunning() {
|
||||||
return this.running;
|
return this.running;
|
||||||
}
|
}
|
||||||
|
async run() {
|
||||||
|
//update running
|
||||||
|
for (let i = this.frame; i < this.images.length; i++) {
|
||||||
|
if (!this.running) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.frameRecord();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.log.error(`Error recording frame`, err);
|
||||||
|
}
|
||||||
|
this.frameAdvance();
|
||||||
|
}
|
||||||
|
//complete running
|
||||||
|
}
|
||||||
async load(seq) {
|
async load(seq) {
|
||||||
this.current = seq;
|
this.current = seq;
|
||||||
this.frame = 0;
|
this.frame = 0;
|
||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
await this.enumerate();
|
await this.enumerate();
|
||||||
this.updateClients();
|
this.updateClientsOnLoad();
|
||||||
}
|
}
|
||||||
updateClients() {
|
updateClientsOnLoad() {
|
||||||
if (this.current !== null) {
|
if (this.current !== null) {
|
||||||
this.send({ cmd: 'select', state: this.getState() });
|
this.send({ cmd: 'select', state: this.getState() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateClientsOnState() {
|
||||||
|
if (this.current !== null) {
|
||||||
|
this.send({ cmd: 'update', state: this.getState() });
|
||||||
|
}
|
||||||
|
}
|
||||||
async enumerate() {
|
async enumerate() {
|
||||||
let screen;
|
let screen;
|
||||||
if (this.current === null) {
|
if (this.current === null) {
|
||||||
|
@ -105,6 +133,19 @@ class Sequence {
|
||||||
exposure: this.exposure
|
exposure: this.exposure
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
getUpdateState() {
|
||||||
|
return {
|
||||||
|
sequence: {
|
||||||
|
hash: this.current.hash,
|
||||||
|
name: this.current.name,
|
||||||
|
progress: this.progress,
|
||||||
|
current: this.frame,
|
||||||
|
frames: this.frames,
|
||||||
|
status: this.getStatus()
|
||||||
|
},
|
||||||
|
exposure: this.exposure
|
||||||
|
};
|
||||||
|
}
|
||||||
getSequenceState() {
|
getSequenceState() {
|
||||||
if (this.current === null) {
|
if (this.current === null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -133,6 +174,45 @@ class Sequence {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
frameAdvance(frames = 1) {
|
||||||
|
if (this.frame + frames >= this.images.length) {
|
||||||
|
this.frame = this.images.length - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.frame += frames;
|
||||||
|
}
|
||||||
|
this.progress = this.frame / (this.images.length - 1);
|
||||||
|
this.updateClientsOnState();
|
||||||
|
}
|
||||||
|
frameRewind(frames = 1) {
|
||||||
|
if (this.frame + frames < 0) {
|
||||||
|
this.frame = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.frame -= frames;
|
||||||
|
}
|
||||||
|
this.progress = this.frame > 0 ? this.frame / (this.images.length - 1) : 0;
|
||||||
|
this.updateClientsOnState();
|
||||||
|
}
|
||||||
|
frameSet(frame) {
|
||||||
|
if (frame < 0) {
|
||||||
|
frame = 0;
|
||||||
|
}
|
||||||
|
else if (frame > this.images.length - 1) {
|
||||||
|
frame = this.images.length - 1;
|
||||||
|
}
|
||||||
|
this.progress = this.frame > 0 ? this.frame / (this.images.length - 1) : 0;
|
||||||
|
this.updateClientsOnState();
|
||||||
|
}
|
||||||
|
async frameRecord() {
|
||||||
|
const img = this.images[this.frame];
|
||||||
|
const dimensions = this.display.getDimensions();
|
||||||
|
this.log.info(`Frame: ${this.frame} / ${this.images.length}`);
|
||||||
|
await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
|
||||||
|
await this.camera.open();
|
||||||
|
await this.fd.display(img.path, [this.exposure]);
|
||||||
|
await this.camera.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.Sequence = Sequence;
|
exports.Sequence = Sequence;
|
||||||
//# sourceMappingURL=index.js.map
|
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -61,26 +61,31 @@ export class FD {
|
||||||
private socketConnected : boolean = false;
|
private socketConnected : boolean = false;
|
||||||
|
|
||||||
private waiting : Function = null;
|
private waiting : Function = null;
|
||||||
|
private mock : boolean = false;
|
||||||
|
|
||||||
constructor (bin: string, width : number, height : number, host : string, port : number) {
|
constructor (bin: string, width : number, height : number, host : string, port : number, mock : boolean = false) {
|
||||||
this.bin = bin;
|
this.bin = bin;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
this.mock = mock;
|
||||||
this.log = createLog('fd');
|
this.log = createLog('fd');
|
||||||
this.shell = new Shell([ this.bin, `${this.width}`, `${this.height}`, `${this.port}` ], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
if (!this.mock) this.shell = new Shell([ this.bin, `${this.width}`, `${this.height}`, `${this.port}` ], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
||||||
this.startDisplay();
|
this.startDisplay();
|
||||||
this.startClient();
|
this.startClient();
|
||||||
this.test();
|
//this.test();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async startDisplay () {
|
private async startDisplay () {
|
||||||
this.log.info(`Launching fd binary ${this.bin}`);
|
this.log.info(`Launching fd binary ${this.bin}`);
|
||||||
this.shell.execute();
|
if (!this.mock) this.shell.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async startClient () {
|
private async startClient () {
|
||||||
|
if (this.mock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
this.client = new net.Socket();
|
this.client = new net.Socket();
|
||||||
this.log.info(`Waiting for TCP socket server on ${this.host}:${this.port}...`);
|
this.log.info(`Waiting for TCP socket server on ${this.host}:${this.port}...`);
|
||||||
while (!this.socketAvailable) {
|
while (!this.socketAvailable) {
|
||||||
|
@ -104,7 +109,7 @@ export class FD {
|
||||||
this.client.on('error', (err : Error) => {
|
this.client.on('error', (err : Error) => {
|
||||||
this.log.error('Error in socket client', err);
|
this.log.error('Error in socket client', err);
|
||||||
this.socketConnected = false;
|
this.socketConnected = false;
|
||||||
this.shell.kill();
|
if (!this.mock) this.shell.kill();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +136,7 @@ export class FD {
|
||||||
private send (msg : fdOutgoingMessage) {
|
private send (msg : fdOutgoingMessage) {
|
||||||
const json : string = JSON.stringify(msg);
|
const json : string = JSON.stringify(msg);
|
||||||
this.log.info(json);
|
this.log.info(json);
|
||||||
this.client.write(json);
|
if (!this.mock) this.client.write(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
private receive (json : string) {
|
private receive (json : string) {
|
||||||
|
@ -155,6 +160,13 @@ export class FD {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const startTime : number = +new Date();
|
const startTime : number = +new Date();
|
||||||
|
if (this.mock) {
|
||||||
|
return {
|
||||||
|
action : Action.LOAD,
|
||||||
|
image,
|
||||||
|
time : (+new Date()) - startTime
|
||||||
|
};
|
||||||
|
}
|
||||||
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
||||||
this.waiting = function (msg : fdIncomingMessage) {
|
this.waiting = function (msg : fdIncomingMessage) {
|
||||||
if (msg.action == Action.LOAD && msg.success) {
|
if (msg.action == Action.LOAD && msg.success) {
|
||||||
|
@ -180,6 +192,16 @@ export class FD {
|
||||||
exposure
|
exposure
|
||||||
};
|
};
|
||||||
const startTime : number = +new Date();
|
const startTime : number = +new Date();
|
||||||
|
if (this.mock) {
|
||||||
|
for (let exp of exposure) {
|
||||||
|
await delay(exp);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
action : Action.DISPLAY,
|
||||||
|
image,
|
||||||
|
time : (+new Date()) - startTime
|
||||||
|
};
|
||||||
|
}
|
||||||
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
||||||
this.waiting = function (msg : fdIncomingMessage) {
|
this.waiting = function (msg : fdIncomingMessage) {
|
||||||
if (msg.action == Action.DISPLAY && msg.success) {
|
if (msg.action == Action.DISPLAY && msg.success) {
|
||||||
|
@ -204,6 +226,13 @@ export class FD {
|
||||||
image
|
image
|
||||||
};
|
};
|
||||||
const startTime : number = +new Date();
|
const startTime : number = +new Date();
|
||||||
|
if (this.mock) {
|
||||||
|
return {
|
||||||
|
action : Action.STOP,
|
||||||
|
image,
|
||||||
|
time : (+new Date()) - startTime
|
||||||
|
};
|
||||||
|
}
|
||||||
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
||||||
this.waiting = function (msg : fdIncomingMessage) {
|
this.waiting = function (msg : fdIncomingMessage) {
|
||||||
if (msg.action == Action.STOP && msg.success) {
|
if (msg.action == Action.STOP && msg.success) {
|
||||||
|
@ -244,6 +273,7 @@ export class FD {
|
||||||
await delay(2000);
|
await delay(2000);
|
||||||
await this.stop(img);
|
await this.stop(img);
|
||||||
|
|
||||||
|
this.log.warn('QUITTING!!!!');
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
33
src/index.ts
33
src/index.ts
|
@ -164,7 +164,7 @@ function onWssConnection (ws : WebSocketExtended, req : Request) {
|
||||||
ws.ip = ip;
|
ws.ip = ip;
|
||||||
ws.session = uuid();
|
ws.session = uuid();
|
||||||
ws.on('message', function (data) { onClientMessage(data, ws) });
|
ws.on('message', function (data) { onClientMessage(data, ws) });
|
||||||
sequence.updateClients();
|
sequence.updateClientsOnLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onClientMessage (data : any, ws : WebSocket) {
|
async function onClientMessage (data : any, ws : WebSocket) {
|
||||||
|
@ -191,6 +191,18 @@ async function cmd (msg : Message) {
|
||||||
case 'select' :
|
case 'select' :
|
||||||
await select(msg.state.sequence.hash);
|
await select(msg.state.sequence.hash);
|
||||||
break;
|
break;
|
||||||
|
case 'start' :
|
||||||
|
start();
|
||||||
|
break;
|
||||||
|
case 'stop' :
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
case 'advance' :
|
||||||
|
frameAdvance();
|
||||||
|
break;
|
||||||
|
case 'rewind' :
|
||||||
|
frameRewind();
|
||||||
|
break;
|
||||||
default :
|
default :
|
||||||
log.warn(`No matching command: ${msg.cmd}`);
|
log.warn(`No matching command: ${msg.cmd}`);
|
||||||
}
|
}
|
||||||
|
@ -206,6 +218,14 @@ async function cameraClose () {
|
||||||
send({ cmd : 'close' });
|
send({ cmd : 'close' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function frameAdvance () {
|
||||||
|
sequence.frameAdvance();
|
||||||
|
}
|
||||||
|
|
||||||
|
function frameRewind () {
|
||||||
|
sequence.frameRewind();
|
||||||
|
}
|
||||||
|
|
||||||
async function select (id : string) : Promise<boolean> {
|
async function select (id : string) : Promise<boolean> {
|
||||||
const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences);
|
const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences);
|
||||||
const seq : SequenceObject = sequencesArr.find(el => el.hash === id);
|
const seq : SequenceObject = sequencesArr.find(el => el.hash === id);
|
||||||
|
@ -217,6 +237,14 @@ async function select (id : string) : Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function start () {
|
||||||
|
sequence.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop () {
|
||||||
|
sequence.stop();
|
||||||
|
}
|
||||||
|
|
||||||
async function send (msg : Message) {
|
async function send (msg : Message) {
|
||||||
const msgStr : string = JSON.stringify(msg);
|
const msgStr : string = JSON.stringify(msg);
|
||||||
wss.clients.forEach((client : WebSocket ) => {
|
wss.clients.forEach((client : WebSocket ) => {
|
||||||
|
@ -265,8 +293,7 @@ async function main () {
|
||||||
image = new Image();
|
image = new Image();
|
||||||
camera = new Camera();
|
camera = new Camera();
|
||||||
display = new Display(width, height);
|
display = new Display(width, height);
|
||||||
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
|
fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']), true);
|
||||||
|
|
||||||
|
|
||||||
app.listen(port, async () => {
|
app.listen(port, async () => {
|
||||||
log.info(`filmout_manager HTTP server running on port ${port}`);
|
log.info(`filmout_manager HTTP server running on port ${port}`);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Files } from '../files';
|
import { Files } from '../files';
|
||||||
import { createLog } from '../log'
|
import { createLog } from '../log';
|
||||||
|
import { delay } from '../delay';
|
||||||
import type { Logger } from 'winston';
|
import type { Logger } from 'winston';
|
||||||
import type { SequenceObject, ImageObject } from '../files';
|
import type { SequenceObject, ImageObject } from '../files';
|
||||||
import type { FD, fdOutgoingPosition } from '../fd';
|
import type { FD, fdOutgoingPosition } from '../fd';
|
||||||
|
@ -42,31 +43,60 @@ export class Sequence {
|
||||||
}
|
}
|
||||||
|
|
||||||
public start () {
|
public start () {
|
||||||
this.running = true;
|
if (this.current !== null) {
|
||||||
|
this.running = true;
|
||||||
|
this.log.info(`Started sequence: ${this.current.name}`);
|
||||||
|
this.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop () {
|
public stop () {
|
||||||
this.running = false;
|
if (this.running && this.current !== null) {
|
||||||
|
this.log.info(`Stopped sequence: ${this.current.name}`);
|
||||||
|
this.running = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public isRunning () {
|
public isRunning () {
|
||||||
return this.running;
|
return this.running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async run () {
|
||||||
|
//update running
|
||||||
|
for (let i = this.frame; i < this.images.length; i++) {
|
||||||
|
if (!this.running) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.frameRecord();
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error(`Error recording frame`, err);
|
||||||
|
}
|
||||||
|
this.frameAdvance();
|
||||||
|
}
|
||||||
|
//complete running
|
||||||
|
}
|
||||||
|
|
||||||
public async load (seq : SequenceObject) {
|
public async load (seq : SequenceObject) {
|
||||||
this.current = seq;
|
this.current = seq;
|
||||||
this.frame = 0;
|
this.frame = 0;
|
||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
await this.enumerate();
|
await this.enumerate();
|
||||||
this.updateClients();
|
this.updateClientsOnLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateClients () {
|
public updateClientsOnLoad () {
|
||||||
if (this.current !== null) {
|
if (this.current !== null) {
|
||||||
this.send({ cmd : 'select', state : this.getState() });
|
this.send({ cmd : 'select', state : this.getState() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public updateClientsOnState () {
|
||||||
|
if (this.current !== null) {
|
||||||
|
this.send({ cmd : 'update', state : this.getState() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async enumerate () {
|
private async enumerate () {
|
||||||
let screen : Dimensions;
|
let screen : Dimensions;
|
||||||
|
|
||||||
|
@ -131,6 +161,20 @@ export class Sequence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getUpdateState () : State {
|
||||||
|
return {
|
||||||
|
sequence : {
|
||||||
|
hash : this.current.hash,
|
||||||
|
name : this.current.name,
|
||||||
|
progress : this.progress,
|
||||||
|
current : this.frame,
|
||||||
|
frames : this.frames,
|
||||||
|
status : this.getStatus() as SequenceStatus
|
||||||
|
},
|
||||||
|
exposure : this.exposure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public getSequenceState () : SequenceState {
|
public getSequenceState () : SequenceState {
|
||||||
if (this.current === null) {
|
if (this.current === null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -161,4 +205,46 @@ export class Sequence {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public frameAdvance (frames : number = 1) {
|
||||||
|
if (this.frame + frames >= this.images.length) {
|
||||||
|
this.frame = this.images.length - 1;
|
||||||
|
} else {
|
||||||
|
this.frame += frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.progress = this.frame / (this.images.length - 1);
|
||||||
|
this.updateClientsOnState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public frameRewind (frames : number = 1) {
|
||||||
|
if (this.frame + frames < 0) {
|
||||||
|
this.frame = 0;
|
||||||
|
} else {
|
||||||
|
this.frame -= frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.progress = this.frame > 0 ? this.frame / (this.images.length - 1) : 0;
|
||||||
|
this.updateClientsOnState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public frameSet (frame : number) {
|
||||||
|
if (frame < 0) {
|
||||||
|
frame = 0;
|
||||||
|
} else if (frame > this.images.length - 1) {
|
||||||
|
frame = this.images.length - 1;
|
||||||
|
}
|
||||||
|
this.progress = this.frame > 0 ? this.frame / (this.images.length - 1) : 0;
|
||||||
|
this.updateClientsOnState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async frameRecord () {
|
||||||
|
const img : ImageObject = this.images[this.frame];
|
||||||
|
const dimensions : fdOutgoingPosition = this.display.getDimensions();
|
||||||
|
this.log.info(`Frame: ${this.frame} / ${this.images.length}`);
|
||||||
|
await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
|
||||||
|
await this.camera.open();
|
||||||
|
await this.fd.display(img.path, [ this.exposure ] );
|
||||||
|
await this.camera.close();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -63,4 +63,11 @@ fieldset.inline .field-row {
|
||||||
|
|
||||||
fieldset.inline .field-row input {
|
fieldset.inline .field-row input {
|
||||||
max-width: 50px;
|
max-width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
width: 97vw;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 28px;
|
||||||
|
left: 0.5vw;
|
||||||
}
|
}
|
|
@ -31,8 +31,8 @@ declare class Display {
|
||||||
private updateSize;
|
private updateSize;
|
||||||
private clear;
|
private clear;
|
||||||
private updateScreen;
|
private updateScreen;
|
||||||
private updateDisplay;
|
updateDisplay(): void;
|
||||||
private updateImage;
|
updateImage(): void;
|
||||||
update(msg: Message): void;
|
update(msg: Message): void;
|
||||||
set(state: State): void;
|
set(state: State): void;
|
||||||
private onResize;
|
private onResize;
|
||||||
|
@ -42,13 +42,16 @@ declare class Client {
|
||||||
private client;
|
private client;
|
||||||
private connected;
|
private connected;
|
||||||
private progress;
|
private progress;
|
||||||
|
private progressText;
|
||||||
constructor();
|
constructor();
|
||||||
private onMessage;
|
private onMessage;
|
||||||
private onOpen;
|
private onOpen;
|
||||||
private onClose;
|
private onClose;
|
||||||
private setSequence;
|
private setSequence;
|
||||||
|
private setUpdate;
|
||||||
private setStatus;
|
private setStatus;
|
||||||
private setProgress;
|
private setProgress;
|
||||||
|
private setFrame;
|
||||||
private setDisplay;
|
private setDisplay;
|
||||||
private cmd;
|
private cmd;
|
||||||
disableClass(className: string): void;
|
disableClass(className: string): void;
|
||||||
|
@ -57,8 +60,12 @@ declare class Client {
|
||||||
private receiveCameraOpen;
|
private receiveCameraOpen;
|
||||||
sendCameraClose(): void;
|
sendCameraClose(): void;
|
||||||
private receiveCameraClose;
|
private receiveCameraClose;
|
||||||
|
sendAdvance(): void;
|
||||||
|
sendRewind(): void;
|
||||||
sendSelect(): void;
|
sendSelect(): void;
|
||||||
private receiveSelect;
|
private receiveSelect;
|
||||||
|
sendStart(): void;
|
||||||
|
sendStop(): void;
|
||||||
private receiveUpdate;
|
private receiveUpdate;
|
||||||
fullscreen(): void;
|
fullscreen(): void;
|
||||||
exitFullscreen(): void;
|
exitFullscreen(): void;
|
||||||
|
|
|
@ -82,7 +82,7 @@ class Display {
|
||||||
this.displayHeight = Math.round(this.height * screenScaleY);
|
this.displayHeight = Math.round(this.height * screenScaleY);
|
||||||
this.displayOffsetX = this.screenOffsetX + Math.round(this.offsetX * screenScaleX);
|
this.displayOffsetX = this.screenOffsetX + Math.round(this.offsetX * screenScaleX);
|
||||||
this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY);
|
this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY);
|
||||||
this.ctx.fillStyle = 'rgb(125, 125, 125)';
|
this.ctx.fillStyle = 'rgb(0, 0, 0)';
|
||||||
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
||||||
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
|
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
|
||||||
this.updateImage();
|
this.updateImage();
|
||||||
|
@ -116,12 +116,13 @@ class Client {
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
let uri = 'ws://localhost:8082';
|
let uri = 'ws://localhost:8082';
|
||||||
this.progress = document.getElementById('progress');
|
this.progress = document.getElementById('progress');
|
||||||
|
this.progressText = document.getElementById('progressText');
|
||||||
this.client = new WebSocket(uri);
|
this.client = new WebSocket(uri);
|
||||||
this.display = new Display();
|
this.display = new Display();
|
||||||
this.client.onopen = this.onOpen.bind(this);
|
this.client.onopen = this.onOpen.bind(this);
|
||||||
this.client.onclose = this.onClose.bind(this);
|
this.client.onclose = this.onClose.bind(this);
|
||||||
this.client.onmessage = this.onMessage.bind(this);
|
this.client.onmessage = this.onMessage.bind(this);
|
||||||
document.getElementById('sequenceForm').reset();
|
document.getElementById('sequenceSelectForm').reset();
|
||||||
document.getElementById('sequenceCtrlForm').reset();
|
document.getElementById('sequenceCtrlForm').reset();
|
||||||
document.getElementById('manualCtrlForm').reset();
|
document.getElementById('manualCtrlForm').reset();
|
||||||
this.disableClass('sequenceCtrl');
|
this.disableClass('sequenceCtrl');
|
||||||
|
@ -146,10 +147,17 @@ class Client {
|
||||||
}
|
}
|
||||||
setSequence(state) {
|
setSequence(state) {
|
||||||
this.setProgress(state.sequence);
|
this.setProgress(state.sequence);
|
||||||
|
this.setFrame(state.sequence);
|
||||||
this.setStatus(state.sequence);
|
this.setStatus(state.sequence);
|
||||||
this.setDisplay(state);
|
this.setDisplay(state);
|
||||||
document.getElementById('sequence').value = state.sequence.hash;
|
document.getElementById('sequence').value = state.sequence.hash;
|
||||||
}
|
}
|
||||||
|
setUpdate(state) {
|
||||||
|
this.setProgress(state.sequence);
|
||||||
|
this.setFrame(state.sequence);
|
||||||
|
this.setStatus(state.sequence);
|
||||||
|
this.display.updateImage();
|
||||||
|
}
|
||||||
setStatus(sequence) {
|
setStatus(sequence) {
|
||||||
let status;
|
let status;
|
||||||
switch (sequence.status) {
|
switch (sequence.status) {
|
||||||
|
@ -172,23 +180,29 @@ class Client {
|
||||||
setProgress(sequence) {
|
setProgress(sequence) {
|
||||||
const percent = sequence.progress * 100.0;
|
const percent = sequence.progress * 100.0;
|
||||||
if (this.progress !== null) {
|
if (this.progress !== null) {
|
||||||
this.progress.value = percent;
|
this.progress.value = sequence.progress;
|
||||||
this.progress.innerText = `${Math.floor(percent)}%`;
|
this.progressText.innerText = `Progress: ${Math.floor(percent)}%`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFrame(sequence) {
|
||||||
|
if (typeof sequence.current !== 'undefined') {
|
||||||
|
document.getElementById('frame').value = `${sequence.current}`.padStart(5, '0');
|
||||||
}
|
}
|
||||||
document.getElementById('sequenceProgress').innerText = `Progress: ${Math.round(sequence.progress)}%`;
|
|
||||||
}
|
}
|
||||||
setDisplay(state) {
|
setDisplay(state) {
|
||||||
const widthEl = document.getElementById('displayWidth');
|
const widthEl = document.getElementById('displayWidth');
|
||||||
const heightEl = document.getElementById('displayHeight');
|
const heightEl = document.getElementById('displayHeight');
|
||||||
const srcWidthEl = document.getElementById('sourceWidth');
|
const srcWidthEl = document.getElementById('sourceWidth');
|
||||||
const srcHeightEl = document.getElementById('sourceHeight');
|
const srcHeightEl = document.getElementById('sourceHeight');
|
||||||
widthEl.value = state.display.width;
|
if (typeof state.display !== 'undefined') {
|
||||||
heightEl.value = state.display.height;
|
widthEl.value = state.display.width;
|
||||||
srcWidthEl.value = state.source.width;
|
heightEl.value = state.display.height;
|
||||||
srcHeightEl.value = state.source.height;
|
srcWidthEl.value = state.source.width;
|
||||||
widthEl.readOnly = false;
|
srcHeightEl.value = state.source.height;
|
||||||
heightEl.readOnly = false;
|
widthEl.readOnly = false;
|
||||||
this.display.set(state);
|
heightEl.readOnly = false;
|
||||||
|
this.display.set(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cmd(msg) {
|
cmd(msg) {
|
||||||
switch (msg.cmd) {
|
switch (msg.cmd) {
|
||||||
|
@ -201,6 +215,9 @@ class Client {
|
||||||
case 'select':
|
case 'select':
|
||||||
this.receiveSelect(msg);
|
this.receiveSelect(msg);
|
||||||
break;
|
break;
|
||||||
|
case 'update':
|
||||||
|
this.receiveUpdate(msg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn(`No command "${msg.cmd}"`);
|
console.warn(`No command "${msg.cmd}"`);
|
||||||
break;
|
break;
|
||||||
|
@ -236,6 +253,12 @@ class Client {
|
||||||
console.log('got camera close');
|
console.log('got camera close');
|
||||||
this.enableClass('manualCtrl');
|
this.enableClass('manualCtrl');
|
||||||
}
|
}
|
||||||
|
sendAdvance() {
|
||||||
|
this.client.send(JSON.stringify({ cmd: 'advance' }));
|
||||||
|
}
|
||||||
|
sendRewind() {
|
||||||
|
this.client.send(JSON.stringify({ cmd: 'rewind' }));
|
||||||
|
}
|
||||||
sendSelect() {
|
sendSelect() {
|
||||||
const hash = document.getElementById('sequence').value;
|
const hash = document.getElementById('sequence').value;
|
||||||
let msg;
|
let msg;
|
||||||
|
@ -249,11 +272,17 @@ class Client {
|
||||||
}
|
}
|
||||||
receiveSelect(msg) {
|
receiveSelect(msg) {
|
||||||
console.log('got select');
|
console.log('got select');
|
||||||
console.dir(msg);
|
|
||||||
this.enableClass('sequenceCtrl');
|
this.enableClass('sequenceCtrl');
|
||||||
this.setSequence(msg.state);
|
this.setSequence(msg.state);
|
||||||
}
|
}
|
||||||
|
sendStart() {
|
||||||
|
this.client.send(JSON.stringify({ cmd: 'start' }));
|
||||||
|
}
|
||||||
|
sendStop() {
|
||||||
|
this.client.send(JSON.stringify({ cmd: 'stop' }));
|
||||||
|
}
|
||||||
receiveUpdate(msg) {
|
receiveUpdate(msg) {
|
||||||
|
this.setUpdate(msg.state);
|
||||||
}
|
}
|
||||||
fullscreen() {
|
fullscreen() {
|
||||||
if (!document.fullscreenElement) {
|
if (!document.fullscreenElement) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -64,10 +64,10 @@
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
-->
|
-->
|
||||||
<div>
|
<div class="flex">
|
||||||
<fieldset id="sequenceSelect">
|
<fieldset id="sequenceSelect" class="inline half">
|
||||||
<legend>Sequence</legend>
|
<legend>Sequence</legend>
|
||||||
<form id="sequenceForm" onsubmit="return false;">
|
<form id="sequenceSelectForm" onsubmit="return false;">
|
||||||
<select name="sequence" id="sequence">
|
<select name="sequence" id="sequence">
|
||||||
<option> - Select Image Sequence - </option>
|
<option> - Select Image Sequence - </option>
|
||||||
{{#each sequences}}
|
{{#each sequences}}
|
||||||
|
@ -77,17 +77,26 @@
|
||||||
<button id="select" onclick="client.sendSelect();">Select</button>
|
<button id="select" onclick="client.sendSelect();">Select</button>
|
||||||
</form>
|
</form>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<fieldset id="displayAdjust" class="inline half">
|
||||||
|
<legend>Display Adjust</legend>
|
||||||
|
<form id="displayAdjustForm" onsubmit="return false;">
|
||||||
|
<button id="offsetXPlus">X +</button>
|
||||||
|
<button id="offsetXMinus">X -</button>
|
||||||
|
<button id="offsetYPlus">Y +</button>
|
||||||
|
<button id="offsetYMinus">Y -</button>
|
||||||
|
</form>
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<fieldset id="sequenceCtrl">
|
<fieldset id="sequenceCtrl">
|
||||||
<legend>Sequence Controls</legend>
|
<legend>Sequence Controls</legend>
|
||||||
<form id="sequenceCtrlForm" onsubmit="return false;">
|
<form id="sequenceCtrlForm" onsubmit="return false;">
|
||||||
<button id="start" class="sequenceCtrl" disabled>Start</button>
|
<button id="start" class="sequenceCtrl" onclick="client.sendStart();" disabled>Start</button>
|
||||||
<button id="stop" class="sequenceCtrl" disabled>Stop</button>
|
<button id="stop" class="sequenceCtrl" onclick="client.sendStop();" disabled>Stop</button>
|
||||||
<button id="pause" class="sequenceCtrl" disabled>Pause</button>
|
<button id="pause" class="sequenceCtrl" disabled>Pause</button>
|
||||||
<button id="rewind" class="sequenceCtrl" disabled><<</button>
|
<button id="rewind" class="sequenceCtrl" onclick="client.sendRewind();" disabled><<</button>
|
||||||
<input id="frame" value="00000" class="sequenceCtrl" disabled />
|
<input id="frame" value="00000" class="sequenceCtrl" disabled />
|
||||||
<button id="forward" class="sequenceCtrl" disabled>>></button>
|
<button id="advance" class="sequenceCtrl" onclick="client.sendAdvance()" disabled>>></button>
|
||||||
</form>
|
</form>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
@ -108,7 +117,7 @@
|
||||||
<div class="status-bar" id="status">
|
<div class="status-bar" id="status">
|
||||||
<p class="status-bar-field" id="sequenceStatus">Idle</p>
|
<p class="status-bar-field" id="sequenceStatus">Idle</p>
|
||||||
<p class="status-bar-field" id="sequenceName">Not Set</p>
|
<p class="status-bar-field" id="sequenceName">Not Set</p>
|
||||||
<p class="status-bar-field" id="sequenceProgress">Progress: 0%</p>
|
<p class="status-bar-field" id="progressText">Progress: 0%</p>
|
||||||
<p class="status-bar-field" id="sequenceLength">Sequence Length: 0</p>
|
<p class="status-bar-field" id="sequenceLength">Sequence Length: 0</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue