Added any number of untold features. Saving.

This commit is contained in:
mmcwilliams 2024-08-24 10:23:15 -04:00
parent 0b280ff623
commit c33aaa2bec
17 changed files with 450 additions and 73 deletions

View File

@ -84,7 +84,7 @@ class Display {
this.ctx.stroke();
}
private updateDisplay () {
public updateDisplay () {
if (!this.sequence) {
return;
}
@ -96,13 +96,13 @@ class Display {
this.displayOffsetX = this.screenOffsetX + Math.round(this.offsetX * screenScaleX);
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);
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
this.updateImage();
}
private updateImage() {
public updateImage() {
const img : any = new Image;
img.onload = function () {
this.ctx.drawImage(img, this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
@ -136,16 +136,18 @@ class Client {
private client : WebSocket;
private connected : boolean = false;
private progress : HTMLProgressElement;
private progressText : HTMLElement;
constructor () {
let uri : string = 'ws://localhost:8082';
this.progress = document.getElementById('progress') as HTMLProgressElement;
this.progressText = document.getElementById('progressText');
this.client = new WebSocket(uri);
this.display = new Display();
this.client.onopen = this.onOpen.bind(this);
this.client.onclose = this.onClose.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('manualCtrlForm') as HTMLFormElement ).reset();
this.disableClass('sequenceCtrl');
@ -174,11 +176,19 @@ class Client {
private setSequence(state : State) {
this.setProgress(state.sequence);
this.setFrame(state.sequence);
this.setStatus(state.sequence);
this.setDisplay(state);
(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) {
let status : string;
switch (sequence.status) {
@ -202,10 +212,15 @@ class Client {
private setProgress (sequence : SequenceState) {
const percent : number = sequence.progress * 100.0;
if (this.progress !== null) {
this.progress.value = percent;
this.progress.innerText = `${Math.floor(percent)}%`;
this.progress.value = sequence.progress;
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) {
@ -214,17 +229,18 @@ class Client {
const srcWidthEl : HTMLInputElement = document.getElementById('sourceWidth') as HTMLInputElement;
const srcHeightEl : HTMLInputElement = document.getElementById('sourceHeight') as HTMLInputElement;
widthEl.value = state.display.width as any;
heightEl.value = state.display.height as any;
if (typeof state.display !== 'undefined') {
widthEl.value = state.display.width as any;
heightEl.value = state.display.height as any;
srcWidthEl.value = state.source.width as any;
srcHeightEl.value = state.source.height as any;
widthEl.readOnly = false;
heightEl.readOnly = false;
//console.dir(state);
this.display.set(state);
srcWidthEl.value = state.source.width as any;
srcHeightEl.value = state.source.height as any;
widthEl.readOnly = false;
heightEl.readOnly = false;
//console.dir(state);
this.display.set(state);
}
}
private cmd (msg : Message) {
@ -238,6 +254,9 @@ class Client {
case 'select' :
this.receiveSelect(msg);
break;
case 'update' :
this.receiveUpdate(msg);
break;
default:
console.warn(`No command "${msg.cmd}"`);
break;
@ -280,6 +299,14 @@ class Client {
this.enableClass('manualCtrl');
}
public sendAdvance () {
this.client.send(JSON.stringify({ cmd : 'advance' }));
}
public sendRewind () {
this.client.send(JSON.stringify({ cmd : 'rewind' }));
}
public sendSelect () {
const hash : string = (document.getElementById('sequence') as HTMLSelectElement ).value;
let msg : Message;
@ -294,13 +321,21 @@ class Client {
private receiveSelect (msg : Message) {
console.log('got select');
console.dir(msg);
//console.dir(msg);
this.enableClass('sequenceCtrl');
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 () {

3
dist/fd/index.d.ts vendored
View File

@ -47,7 +47,8 @@ export declare class FD {
private socketAvailable;
private socketConnected;
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 startClient;
private logstd;

46
dist/fd/index.js vendored
View File

@ -25,26 +25,33 @@ var Mode;
Mode[Mode["INVERT_CHANNELS"] = 5] = "INVERT_CHANNELS";
})(Mode || (Mode = {}));
class FD {
constructor(bin, width, height, host, port) {
constructor(bin, width, height, host, port, mock = false) {
this.socketAvailable = false;
this.socketConnected = false;
this.waiting = null;
this.mock = false;
this.bin = bin;
this.width = width;
this.height = height;
this.host = host;
this.port = port;
this.mock = mock;
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.startClient();
this.test();
//this.test();
}
async startDisplay() {
this.log.info(`Launching fd binary ${this.bin}`);
this.shell.execute();
if (!this.mock)
this.shell.execute();
}
async startClient() {
if (this.mock) {
return false;
}
this.client = new net_1.default.Socket();
this.log.info(`Waiting for TCP socket server on ${this.host}:${this.port}...`);
while (!this.socketAvailable) {
@ -65,7 +72,8 @@ class FD {
this.client.on('error', (err) => {
this.log.error('Error in socket client', err);
this.socketConnected = false;
this.shell.kill();
if (!this.mock)
this.shell.kill();
});
}
logstd(data) {
@ -90,7 +98,8 @@ class FD {
send(msg) {
const json = JSON.stringify(msg);
this.log.info(json);
this.client.write(json);
if (!this.mock)
this.client.write(json);
}
receive(json) {
const msg = JSON.parse(json);
@ -112,6 +121,13 @@ class FD {
}
};
const startTime = +new Date();
if (this.mock) {
return {
action: Action.LOAD,
image,
time: (+new Date()) - startTime
};
}
const promise = new Promise(function (resolve, reject) {
this.waiting = function (msg) {
if (msg.action == Action.LOAD && msg.success) {
@ -137,6 +153,16 @@ class FD {
exposure
};
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) {
this.waiting = function (msg) {
if (msg.action == Action.DISPLAY && msg.success) {
@ -161,6 +187,13 @@ class FD {
image
};
const startTime = +new Date();
if (this.mock) {
return {
action: Action.STOP,
image,
time: (+new Date()) - startTime
};
}
const promise = new Promise(function (resolve, reject) {
this.waiting = function (msg) {
if (msg.action == Action.STOP && msg.success) {
@ -194,6 +227,7 @@ class FD {
await this.display(img);
await (0, delay_1.delay)(2000);
await this.stop(img);
this.log.warn('QUITTING!!!!');
process.exit();
}
}

File diff suppressed because one or more lines are too long

29
dist/index.js vendored
View File

@ -35,6 +35,7 @@ const Handlebars = __importStar(require("handlebars"));
const ws_1 = require("ws");
const log_1 = require("./log");
const files_1 = require("./files");
const fd_1 = require("./fd");
const display_1 = require("./display");
const ffmpeg_1 = require("./ffmpeg");
const ffprobe_1 = require("./ffprobe");
@ -175,7 +176,7 @@ function onWssConnection(ws, req) {
ws.ip = ip;
ws.session = (0, uuid_1.v4)();
ws.on('message', function (data) { onClientMessage(data, ws); });
sequence.updateClients();
sequence.updateClientsOnLoad();
}
async function onClientMessage(data, ws) {
let msg = null;
@ -201,6 +202,18 @@ async function cmd(msg) {
case 'select':
await select(msg.state.sequence.hash);
break;
case 'start':
start();
break;
case 'stop':
stop();
break;
case 'advance':
frameAdvance();
break;
case 'rewind':
frameRewind();
break;
default:
log.warn(`No matching command: ${msg.cmd}`);
}
@ -213,6 +226,12 @@ async function cameraClose() {
await camera.close();
send({ cmd: 'close' });
}
function frameAdvance() {
sequence.frameAdvance();
}
function frameRewind() {
sequence.frameRewind();
}
async function select(id) {
const sequencesArr = await files_1.Files.enumerateSequences(sequences);
const seq = sequencesArr.find(el => el.hash === id);
@ -223,6 +242,12 @@ async function select(id) {
await sequence.load(seq);
return true;
}
function start() {
sequence.start();
}
function stop() {
sequence.stop();
}
async function send(msg) {
const msgStr = JSON.stringify(msg);
wss.clients.forEach((client) => {
@ -271,7 +296,7 @@ async function main() {
image = new image_1.Image();
camera = new camera_1.Camera();
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 () => {
log.info(`filmout_manager HTTP server running on port ${port}`);
});

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -28,14 +28,21 @@ export declare class Sequence {
start(): void;
stop(): void;
isRunning(): boolean;
private run;
load(seq: SequenceObject): Promise<void>;
updateClients(): void;
updateClientsOnLoad(): void;
updateClientsOnState(): void;
private enumerate;
unload(): void;
getState(): State;
getUpdateState(): State;
getSequenceState(): SequenceState;
setExposure(ms: number): void;
getStatus(): SequenceStatus;
getCurrent(): ImageObject;
frameAdvance(frames?: number): void;
frameRewind(frames?: number): void;
frameSet(frame: number): void;
private frameRecord;
}
export {};

View File

@ -28,26 +28,54 @@ class Sequence {
this.send = send;
}
start() {
this.running = true;
if (this.current !== null) {
this.running = true;
this.log.info(`Started sequence: ${this.current.name}`);
this.run();
}
}
stop() {
this.running = false;
if (this.running && this.current !== null) {
this.log.info(`Stopped sequence: ${this.current.name}`);
this.running = false;
}
}
isRunning() {
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) {
this.current = seq;
this.frame = 0;
this.progress = 0;
await this.enumerate();
this.updateClients();
this.updateClientsOnLoad();
}
updateClients() {
updateClientsOnLoad() {
if (this.current !== null) {
this.send({ cmd: 'select', state: this.getState() });
}
}
updateClientsOnState() {
if (this.current !== null) {
this.send({ cmd: 'update', state: this.getState() });
}
}
async enumerate() {
let screen;
if (this.current === null) {
@ -105,6 +133,19 @@ class Sequence {
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() {
if (this.current === null) {
return null;
@ -133,6 +174,45 @@ class Sequence {
}
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;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -61,26 +61,31 @@ export class FD {
private socketConnected : boolean = false;
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.width = width;
this.height = height;
this.host = host;
this.port = port;
this.mock = mock;
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.startClient();
this.test();
//this.test();
}
private async startDisplay () {
this.log.info(`Launching fd binary ${this.bin}`);
this.shell.execute();
if (!this.mock) this.shell.execute();
}
private async startClient () {
if (this.mock) {
return false;
}
this.client = new net.Socket();
this.log.info(`Waiting for TCP socket server on ${this.host}:${this.port}...`);
while (!this.socketAvailable) {
@ -104,7 +109,7 @@ export class FD {
this.client.on('error', (err : Error) => {
this.log.error('Error in socket client', err);
this.socketConnected = false;
this.shell.kill();
if (!this.mock) this.shell.kill();
});
}
@ -131,7 +136,7 @@ export class FD {
private send (msg : fdOutgoingMessage) {
const json : string = JSON.stringify(msg);
this.log.info(json);
this.client.write(json);
if (!this.mock) this.client.write(json);
}
private receive (json : string) {
@ -155,6 +160,13 @@ export class FD {
}
};
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) {
this.waiting = function (msg : fdIncomingMessage) {
if (msg.action == Action.LOAD && msg.success) {
@ -180,6 +192,16 @@ export class FD {
exposure
};
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) {
this.waiting = function (msg : fdIncomingMessage) {
if (msg.action == Action.DISPLAY && msg.success) {
@ -204,6 +226,13 @@ export class FD {
image
};
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) {
this.waiting = function (msg : fdIncomingMessage) {
if (msg.action == Action.STOP && msg.success) {
@ -244,6 +273,7 @@ export class FD {
await delay(2000);
await this.stop(img);
this.log.warn('QUITTING!!!!');
process.exit();
}
}

View File

@ -164,7 +164,7 @@ function onWssConnection (ws : WebSocketExtended, req : Request) {
ws.ip = ip;
ws.session = uuid();
ws.on('message', function (data) { onClientMessage(data, ws) });
sequence.updateClients();
sequence.updateClientsOnLoad();
}
async function onClientMessage (data : any, ws : WebSocket) {
@ -191,6 +191,18 @@ async function cmd (msg : Message) {
case 'select' :
await select(msg.state.sequence.hash);
break;
case 'start' :
start();
break;
case 'stop' :
stop();
break;
case 'advance' :
frameAdvance();
break;
case 'rewind' :
frameRewind();
break;
default :
log.warn(`No matching command: ${msg.cmd}`);
}
@ -206,6 +218,14 @@ async function cameraClose () {
send({ cmd : 'close' });
}
function frameAdvance () {
sequence.frameAdvance();
}
function frameRewind () {
sequence.frameRewind();
}
async function select (id : string) : Promise<boolean> {
const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences);
const seq : SequenceObject = sequencesArr.find(el => el.hash === id);
@ -217,6 +237,14 @@ async function select (id : string) : Promise<boolean> {
return true;
}
function start () {
sequence.start();
}
function stop () {
sequence.stop();
}
async function send (msg : Message) {
const msgStr : string = JSON.stringify(msg);
wss.clients.forEach((client : WebSocket ) => {
@ -265,8 +293,7 @@ async function main () {
image = new Image();
camera = new Camera();
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 () => {
log.info(`filmout_manager HTTP server running on port ${port}`);

View File

@ -1,5 +1,6 @@
import { Files } from '../files';
import { createLog } from '../log'
import { createLog } from '../log';
import { delay } from '../delay';
import type { Logger } from 'winston';
import type { SequenceObject, ImageObject } from '../files';
import type { FD, fdOutgoingPosition } from '../fd';
@ -42,31 +43,60 @@ export class Sequence {
}
public start () {
this.running = true;
if (this.current !== null) {
this.running = true;
this.log.info(`Started sequence: ${this.current.name}`);
this.run();
}
}
public stop () {
this.running = false;
if (this.running && this.current !== null) {
this.log.info(`Stopped sequence: ${this.current.name}`);
this.running = false;
}
}
public isRunning () {
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) {
this.current = seq;
this.frame = 0;
this.progress = 0;
await this.enumerate();
this.updateClients();
this.updateClientsOnLoad();
}
public updateClients () {
public updateClientsOnLoad () {
if (this.current !== null) {
this.send({ cmd : 'select', state : this.getState() });
}
}
public updateClientsOnState () {
if (this.current !== null) {
this.send({ cmd : 'update', state : this.getState() });
}
}
private async enumerate () {
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 {
if (this.current === null) {
return null;
@ -161,4 +205,46 @@ export class Sequence {
}
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();
}
}

View File

@ -63,4 +63,11 @@ fieldset.inline .field-row {
fieldset.inline .field-row input {
max-width: 50px;
}
progress {
width: 97vw;
position: absolute;
bottom: 28px;
left: 0.5vw;
}

11
static/js/index.d.ts vendored
View File

@ -31,8 +31,8 @@ declare class Display {
private updateSize;
private clear;
private updateScreen;
private updateDisplay;
private updateImage;
updateDisplay(): void;
updateImage(): void;
update(msg: Message): void;
set(state: State): void;
private onResize;
@ -42,13 +42,16 @@ declare class Client {
private client;
private connected;
private progress;
private progressText;
constructor();
private onMessage;
private onOpen;
private onClose;
private setSequence;
private setUpdate;
private setStatus;
private setProgress;
private setFrame;
private setDisplay;
private cmd;
disableClass(className: string): void;
@ -57,8 +60,12 @@ declare class Client {
private receiveCameraOpen;
sendCameraClose(): void;
private receiveCameraClose;
sendAdvance(): void;
sendRewind(): void;
sendSelect(): void;
private receiveSelect;
sendStart(): void;
sendStop(): void;
private receiveUpdate;
fullscreen(): void;
exitFullscreen(): void;

View File

@ -82,7 +82,7 @@ class Display {
this.displayHeight = Math.round(this.height * screenScaleY);
this.displayOffsetX = this.screenOffsetX + Math.round(this.offsetX * screenScaleX);
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);
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
this.updateImage();
@ -116,12 +116,13 @@ class Client {
this.connected = false;
let uri = 'ws://localhost:8082';
this.progress = document.getElementById('progress');
this.progressText = document.getElementById('progressText');
this.client = new WebSocket(uri);
this.display = new Display();
this.client.onopen = this.onOpen.bind(this);
this.client.onclose = this.onClose.bind(this);
this.client.onmessage = this.onMessage.bind(this);
document.getElementById('sequenceForm').reset();
document.getElementById('sequenceSelectForm').reset();
document.getElementById('sequenceCtrlForm').reset();
document.getElementById('manualCtrlForm').reset();
this.disableClass('sequenceCtrl');
@ -146,10 +147,17 @@ class Client {
}
setSequence(state) {
this.setProgress(state.sequence);
this.setFrame(state.sequence);
this.setStatus(state.sequence);
this.setDisplay(state);
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) {
let status;
switch (sequence.status) {
@ -172,23 +180,29 @@ class Client {
setProgress(sequence) {
const percent = sequence.progress * 100.0;
if (this.progress !== null) {
this.progress.value = percent;
this.progress.innerText = `${Math.floor(percent)}%`;
this.progress.value = sequence.progress;
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) {
const widthEl = document.getElementById('displayWidth');
const heightEl = document.getElementById('displayHeight');
const srcWidthEl = document.getElementById('sourceWidth');
const srcHeightEl = document.getElementById('sourceHeight');
widthEl.value = state.display.width;
heightEl.value = state.display.height;
srcWidthEl.value = state.source.width;
srcHeightEl.value = state.source.height;
widthEl.readOnly = false;
heightEl.readOnly = false;
this.display.set(state);
if (typeof state.display !== 'undefined') {
widthEl.value = state.display.width;
heightEl.value = state.display.height;
srcWidthEl.value = state.source.width;
srcHeightEl.value = state.source.height;
widthEl.readOnly = false;
heightEl.readOnly = false;
this.display.set(state);
}
}
cmd(msg) {
switch (msg.cmd) {
@ -201,6 +215,9 @@ class Client {
case 'select':
this.receiveSelect(msg);
break;
case 'update':
this.receiveUpdate(msg);
break;
default:
console.warn(`No command "${msg.cmd}"`);
break;
@ -236,6 +253,12 @@ class Client {
console.log('got camera close');
this.enableClass('manualCtrl');
}
sendAdvance() {
this.client.send(JSON.stringify({ cmd: 'advance' }));
}
sendRewind() {
this.client.send(JSON.stringify({ cmd: 'rewind' }));
}
sendSelect() {
const hash = document.getElementById('sequence').value;
let msg;
@ -249,11 +272,17 @@ class Client {
}
receiveSelect(msg) {
console.log('got select');
console.dir(msg);
this.enableClass('sequenceCtrl');
this.setSequence(msg.state);
}
sendStart() {
this.client.send(JSON.stringify({ cmd: 'start' }));
}
sendStop() {
this.client.send(JSON.stringify({ cmd: 'stop' }));
}
receiveUpdate(msg) {
this.setUpdate(msg.state);
}
fullscreen() {
if (!document.fullscreenElement) {

File diff suppressed because one or more lines are too long

View File

@ -64,10 +64,10 @@
{{/each}}
</select>
-->
<div>
<fieldset id="sequenceSelect">
<div class="flex">
<fieldset id="sequenceSelect" class="inline half">
<legend>Sequence</legend>
<form id="sequenceForm" onsubmit="return false;">
<form id="sequenceSelectForm" onsubmit="return false;">
<select name="sequence" id="sequence">
<option> - Select Image Sequence - </option>
{{#each sequences}}
@ -77,17 +77,26 @@
<button id="select" onclick="client.sendSelect();">Select</button>
</form>
</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>
<fieldset id="sequenceCtrl">
<legend>Sequence Controls</legend>
<form id="sequenceCtrlForm" onsubmit="return false;">
<button id="start" class="sequenceCtrl" disabled>Start</button>
<button id="stop" class="sequenceCtrl" disabled>Stop</button>
<button id="start" class="sequenceCtrl" onclick="client.sendStart();" disabled>Start</button>
<button id="stop" class="sequenceCtrl" onclick="client.sendStop();" disabled>Stop</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 />
<button id="forward" class="sequenceCtrl" disabled>>></button>
<button id="advance" class="sequenceCtrl" onclick="client.sendAdvance()" disabled>>></button>
</form>
</fieldset>
</div>
@ -108,7 +117,7 @@
<div class="status-bar" id="status">
<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="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>
</div>
</div>