Now the CLI can be given alternate dimensions to display images at. This cannot currently be set within a sequence but it's only a matter of time.... (and will).

This commit is contained in:
Matt McWilliams 2026-05-10 21:44:59 -04:00
parent 8547e905da
commit 60cb19787d
7 changed files with 134 additions and 9 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "scad/common"]
path = scad/common
url = https://git.sixteenmillimeter.com/modules/common.git

2
dist/cli/index.d.ts vendored
View File

@ -17,6 +17,7 @@ export declare class CLI {
private port;
private mock;
private displayStr;
private altDimensions;
private lastImage;
constructor();
private main;
@ -27,4 +28,5 @@ export declare class CLI {
private execute;
private expose;
private rgb;
private parseDimensions;
}

54
dist/cli/index.js vendored
View File

@ -31,6 +31,7 @@ class CLI {
constructor() {
this.mock = false;
this.log = (0, log_1.createLog)('fm');
this.log.info('OK');
this.ffprobe = new ffprobe_1.FFPROBE();
this.getSettings();
this.getArgs();
@ -38,13 +39,15 @@ class CLI {
this.image = new image_1.Image(this.fiBin);
this.fd = new fd_1.FD(this.fdBin, this.width, this.height, this.host, this.port, this.displayStr, this.mock);
this.camera = new camera_1.Camera(this.mock);
setTimeout(this.main.bind(this), 4000);
this.log.info('main()');
this.main();
}
async main() {
this.log.info('Starting...');
await (0, delay_1.delay)(10000);
if (typeof this.args.input !== 'undefined') {
this.log.info(`Loading ${(0, path_1.basename)(this.args.input)}`);
await this.parse(this.args.input);
await (0, delay_1.delay)(2000);
}
await (0, delay_1.delay)(5000);
this.fd.exit();
@ -57,12 +60,14 @@ class CLI {
this.width = (0, env_1.envInt)('WIDTH', 0);
this.height = (0, env_1.envInt)('HEIGHT', 0);
this.host = (0, env_1.envString)('FD_HOST', 'localhost');
this.altDimensions = this.parseDimensions((0, env_1.envString)('DIMENSIONS', null));
this.port = (0, env_1.envInt)('FD_PORT', 8082);
}
getArgs() {
const parser = new argparse_1.ArgumentParser({
description: 'Filmout manager CLI application'
});
let parsedDimensions = null;
parser.add_argument('-i', '--input', {
help: 'Path to a script to execute',
type: String,
@ -83,6 +88,11 @@ class CLI {
type: 'int',
required: false
});
parser.add_argument('-d', '--dimensions', {
help: 'Alternate image dimensions from full-scaled to screen',
type: 'str',
required: false
});
parser.add_argument('-v', '--verbose', {
help: 'Enable verbose output',
action: 'store_true'
@ -91,13 +101,19 @@ class CLI {
if (this.args.verbose) {
console.dir(this.args);
}
//overwrite ENV defaults with CLI args
if (typeof this.args.width !== 'undefined') {
this.width = this.args.width;
}
if (typeof this.args.height !== 'undefined') {
this.height = this.args.height;
}
//overwrite defaults
if (typeof this.args.dimensions !== 'undefined') {
parsedDimensions = this.parseDimensions(this.args.dimensions);
if (parsedDimensions !== null) {
this.altDimensions = parsedDimensions;
}
}
}
async parse(filePath) {
let lines = [];
@ -105,6 +121,7 @@ class CLI {
let cmd = null;
try {
file = await (0, promises_1.readFile)(filePath, 'utf8');
this.log.info(`Parsing ${(0, path_1.basename)(filePath)}...`);
}
catch (err) {
this.log.error(`Error reading input file`, err);
@ -254,6 +271,12 @@ class CLI {
img.path = inverted;
}
this.display.setSource(info.width, info.height);
if (this.altDimensions !== null) {
this.display.setOffsetX(this.altDimensions.x);
this.display.setOffsetY(this.altDimensions.y);
this.display.setWidth(this.altDimensions.w);
this.display.setHeight(this.altDimensions.h);
}
dimensions = this.display.getOutgoingPosition();
this.log.info(`${invert ? 'INVERT' : 'EXPOSE'}: [${cmd.time}] ${img.name}`);
try {
@ -298,6 +321,12 @@ class CLI {
const info = await this.ffprobe.info(cmd.file);
let dimensions;
this.display.setSource(info.width, info.height);
if (this.altDimensions !== null) {
this.display.setOffsetX(this.altDimensions.x);
this.display.setOffsetY(this.altDimensions.y);
this.display.setWidth(this.altDimensions.w);
this.display.setHeight(this.altDimensions.h);
}
dimensions = this.display.getOutgoingPosition();
this.log.info(`RGB: ${img.name}`);
try {
@ -358,6 +387,25 @@ class CLI {
}
await this.camera.close();
}
parseDimensions(dimensionsStr) {
if (dimensionsStr === null)
return null;
let parts = dimensionsStr.trim().split(',');
let dim = { x: 0, y: 0, w: 0, h: 0 };
let keys = Object.keys(dim);
if (parts.length !== 4)
return null;
for (let i = 0; i < keys.length; i++) {
try {
dim[keys[i]] = parseInt(parts[i]);
}
catch (err) {
this.log.error(`Error parsing ${parts[i]}`, err);
return null;
}
}
return dim;
}
}
exports.CLI = CLI;
if (require.main === module) {

File diff suppressed because one or more lines are too long

1
scad/common Submodule

@ -0,0 +1 @@
Subproject commit e2eeb27f173d739a174c0d147bcb62a16859e2d9

View File

@ -0,0 +1,18 @@
include <./common/common.scad>;
include <./common/2020_tslot.scad>;
module monitor (pos = [0, 0, 0]) {
translate(pos) {
cube([7 * IN, 12 * IN, 0.39 * IN ], center = true);
}
}
module oxberry (pos = [0, 0, 0]) {
translate(pos) {
translate([0, 0, 100]) cube([200, 200, 200], center = true);
}
}
oxberry([0, 0, 1000]);
monitor();

View File

@ -42,6 +42,7 @@ interface Args {
focus? : boolean;
framing? : boolean;
verbose? : boolean;
dimensions? : string;
}
interface CMD {
@ -52,6 +53,7 @@ interface CMD {
times? : number[];
}
export class CLI {
public log : Logger;
private args : Args;
@ -69,11 +71,13 @@ export class CLI {
private port : number;
private mock : boolean = false;
private displayStr : string | null;
private altDimensions : fdOutgoingPosition | null;
private lastImage : string | null;
constructor () {
this.log = createLog('fm');
this.log.info('OK')
this.ffprobe = new FFPROBE();
this.getSettings();
this.getArgs();
@ -81,17 +85,17 @@ export class CLI {
this.image = new Image(this.fiBin);
this.fd = new FD(this.fdBin, this.width, this.height, this.host, this.port, this.displayStr, this.mock);
this.camera = new Camera(this.mock);
setTimeout(this.main.bind(this), 4000);
this.log.info('main()')
this.main();
}
private async main () {
this.log.info('Starting...')
await delay(10000);
if (typeof this.args.input !== 'undefined') {
this.log.info(`Loading ${basename(this.args.input)}`);
await this.parse(this.args.input);
await delay(2000);
}
await delay(5000);
this.fd.exit();
process.exit(0);
@ -104,6 +108,8 @@ export class CLI {
this.width = envInt('WIDTH', 0);
this.height = envInt('HEIGHT', 0);
this.host = envString('FD_HOST', 'localhost');
this.altDimensions = this.parseDimensions(envString('DIMENSIONS', null));
this.port = envInt('FD_PORT', 8082);
}
@ -112,6 +118,7 @@ export class CLI {
const parser = new ArgumentParser({
description: 'Filmout manager CLI application'
});
let parsedDimensions : fdOutgoingPosition | null = null;
parser.add_argument('-i', '--input', {
help: 'Path to a script to execute',
@ -136,6 +143,12 @@ export class CLI {
type: 'int',
required: false
});
parser.add_argument('-d', '--dimensions', {
help : 'Alternate image dimensions from full-scaled to screen',
type : 'str',
required : false
});
parser.add_argument('-v', '--verbose', {
help: 'Enable verbose output',
@ -148,6 +161,8 @@ export class CLI {
console.dir(this.args);
}
//overwrite ENV defaults with CLI args
if (typeof this.args.width !== 'undefined') {
this.width = this.args.width;
}
@ -155,7 +170,13 @@ export class CLI {
if (typeof this.args.height !== 'undefined') {
this.height = this.args.height;
}
//overwrite defaults
if (typeof this.args.dimensions !== 'undefined') {
parsedDimensions = this.parseDimensions(this.args.dimensions);
if (parsedDimensions !== null) {
this.altDimensions = parsedDimensions;
}
}
}
private async parse (filePath : string) {
@ -165,6 +186,7 @@ export class CLI {
try {
file = await readFile(filePath, 'utf8');
this.log.info(`Parsing ${basename(filePath)}...`)
} catch (err) {
this.log.error(`Error reading input file`, err);
process.exit(1);
@ -318,6 +340,13 @@ export class CLI {
this.display.setSource(info.width, info.height);
if (this.altDimensions !== null) {
this.display.setOffsetX(this.altDimensions.x);
this.display.setOffsetY(this.altDimensions.y);
this.display.setWidth(this.altDimensions.w);
this.display.setHeight(this.altDimensions.h);
}
dimensions = this.display.getOutgoingPosition();
this.log.info(`${invert ? 'INVERT' : 'EXPOSE'}: [${cmd.time}] ${img.name}`);
@ -367,6 +396,13 @@ export class CLI {
this.display.setSource(info.width, info.height);
if (this.altDimensions !== null) {
this.display.setOffsetX(this.altDimensions.x);
this.display.setOffsetY(this.altDimensions.y);
this.display.setWidth(this.altDimensions.w);
this.display.setHeight(this.altDimensions.h);
}
dimensions = this.display.getOutgoingPosition();
this.log.info(`RGB: ${img.name}`);
@ -429,6 +465,23 @@ export class CLI {
await this.camera.close();
}
private parseDimensions (dimensionsStr : string | null) : fdOutgoingPosition | null {
if (dimensionsStr === null) return null;
let parts : string[] = dimensionsStr.trim().split(',');
let dim : fdOutgoingPosition = { x: 0, y: 0, w: 0, h : 0 };
let keys : string[] = Object.keys(dim);
if (parts.length !== 4) return null;
for (let i = 0; i < keys.length; i++) {
try {
(dim as any)[keys[i]] = parseInt(parts[i]);
} catch (err) {
this.log.error(`Error parsing ${parts[i]}`, err);
return null;
}
}
return dim;
}
}
if (require.main === module) {