iAdd vtv-viewer. - vtv-tools - virtual terminal video tools Err bitreich.org 70 1Log /scm/vtv-tools/log.gph bitreich.org 70 1Files /scm/vtv-tools/files.gph bitreich.org 70 1Refs /scm/vtv-tools/refs.gph bitreich.org 70 1Tags /scm/vtv-tools/tag bitreich.org 70 1README /scm/vtv-tools/file/README.md.gph bitreich.org 70 1LICENSE /scm/vtv-tools/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 991a6f94bb058979f28763ecd33b5920cad034d5 /scm/vtv-tools/commit/991a6f94bb058979f28763ecd33b5920cad034d5.gph bitreich.org 70 1parent 121db131a875338f494bb1ab98e6dd7245cea1f6 /scm/vtv-tools/commit/121db131a875338f494bb1ab98e6dd7245cea1f6.gph bitreich.org 70 hAuthor: Troels Henriksen URL:mailto:athas@sigkill.dk bitreich.org 70 iDate: Tue, 22 Aug 2023 18:30:18 +0200 Err bitreich.org 70 i Err bitreich.org 70 iAdd vtv-viewer. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M .gitignore | 1 + Err bitreich.org 70 i M Makefile | 2 +- Err bitreich.org 70 i M man/vtv-player.1 | 2 +- Err bitreich.org 70 i A man/vtv-viewer.1 | 41 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A src/vtv-viewer.c | 147 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i Err bitreich.org 70 i5 files changed, 191 insertions(+), 2 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/.gitignore b/.gitignore /scm/vtv-tools/file/.gitignore.gph bitreich.org 70 i@@ -1 +1,2 @@ Err bitreich.org 70 i bin/vtv-from-ff Err bitreich.org 70 i+bin/vtv-viewer Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/vtv-tools/file/Makefile.gph bitreich.org 70 i@@ -4,7 +4,7 @@ MANPREFIX ?= ${PREFIX}/share/man Err bitreich.org 70 i CFLAGS?=-O -Wall -Wextra -pedantic Err bitreich.org 70 i CC?=cc Err bitreich.org 70 i Err bitreich.org 70 i-all: bin/vtv-from-ff Err bitreich.org 70 i+all: bin/vtv-from-ff bin/vtv-viewer Err bitreich.org 70 i Err bitreich.org 70 i bin/%: src/%.c Err bitreich.org 70 i $(CC) -o $@ $< $(CFLAGS) Err bitreich.org 70 1diff --git a/man/vtv-player.1 b/man/vtv-player.1 /scm/vtv-tools/file/man/vtv-player.1.gph bitreich.org 70 i@@ -16,7 +16,7 @@ Err bitreich.org 70 i .Sh DESCRIPTION Err bitreich.org 70 i .Bd -filled Err bitreich.org 70 i .Nm Err bitreich.org 70 i-plays a VTV file in the terminal. Loops until manually terminated. Err bitreich.org 70 i+Plays a VTV file in the terminal. Loops until manually terminated. Err bitreich.org 70 i . Err bitreich.org 70 i .Sh OPTIONS Err bitreich.org 70 i .Bl -tag -width Ds Err bitreich.org 70 1diff --git a/man/vtv-viewer.1 b/man/vtv-viewer.1 /scm/vtv-tools/file/man/vtv-viewer.1.gph bitreich.org 70 i@@ -0,0 +1,41 @@ Err bitreich.org 70 i+.Dd August 22, 2023 Err bitreich.org 70 i+.Dt VTV-VIEWER 1 Err bitreich.org 70 i+.OS Err bitreich.org 70 i+. Err bitreich.org 70 i+.sh NAME Err bitreich.org 70 i+.Nm vtv-viewer Err bitreich.org 70 i+.Nd Interactively view frames of VTV file. Err bitreich.org 70 i+. Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+.Bk Err bitreich.org 70 i+.Ar FILE Err bitreich.org 70 i+.Ek Err bitreich.org 70 i+. Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Bd -filled Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+Interactively shows frames of a VTV file in the terminal. This can be Err bitreich.org 70 i+useful for trying to figure out the intended frame size of a VTV. Err bitreich.org 70 i+. Err bitreich.org 70 i+.Sh COMMANDS Err bitreich.org 70 i+. Err bitreich.org 70 i+The following keyboard commands are supported. Err bitreich.org 70 i+.Bl -tag -width Ds Err bitreich.org 70 i+.It h Err bitreich.org 70 i+Go to previous frame. Err bitreich.org 70 i+.It l Err bitreich.org 70 i+Go to next frame. Err bitreich.org 70 i+.It j Err bitreich.org 70 i+Decrease frame size by one line. Err bitreich.org 70 i+.It k Err bitreich.org 70 i+Increase frame size by one line. Err bitreich.org 70 i+.El Err bitreich.org 70 i+. Err bitreich.org 70 i+.Sh BUGS Err bitreich.org 70 i+The VTV frame is emitted directly to the terminal, which can cause Err bitreich.org 70 i+user interface corruption if it writes to the parts of the screen used Err bitreich.org 70 i+by vtv-viewer itself. Err bitreich.org 70 i+. Err bitreich.org 70 i+.Sh LICENSE Err bitreich.org 70 i+The vtv-tools are released under the GPLv3 or later. Err bitreich.org 70 1diff --git a/src/vtv-viewer.c b/src/vtv-viewer.c /scm/vtv-tools/file/src/vtv-viewer.c.gph bitreich.org 70 i@@ -0,0 +1,147 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+struct termios orig_termios; Err bitreich.org 70 i+ Err bitreich.org 70 i+void cooked_mode() { Err bitreich.org 70 i+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios); Err bitreich.org 70 i+ printf("\033[?25h"); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void raw_mode() { Err bitreich.org 70 i+ printf("\033[?25l"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ tcgetattr(STDIN_FILENO, &orig_termios); Err bitreich.org 70 i+ atexit(cooked_mode); Err bitreich.org 70 i+ Err bitreich.org 70 i+ struct termios raw = orig_termios; Err bitreich.org 70 i+ raw.c_iflag &= ~(IXON); Err bitreich.org 70 i+ raw.c_lflag &= ~(ECHO | ICANON); Err bitreich.org 70 i+ raw.c_cc[VMIN] = 1; Err bitreich.org 70 i+ raw.c_cc[VTIME] = 0; Err bitreich.org 70 i+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void move(int x, int y) { printf("\033[%d;%dH", y, x); } Err bitreich.org 70 i+void home() { printf("\033[;H"); } Err bitreich.org 70 i+void clear_screen() { printf("\033[2J"); } Err bitreich.org 70 i+void clear_line() { printf("\033[2K"); } Err bitreich.org 70 i+void def() { printf("\033[0m"); } Err bitreich.org 70 i+ Err bitreich.org 70 i+void fg_rgb(uint8_t r, uint8_t g, uint8_t b) { Err bitreich.org 70 i+ printf("\033[38;2;%d;%d;%dm", r, g, b); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void bg_rgb(uint8_t r, uint8_t g, uint8_t b) { Err bitreich.org 70 i+ printf("\033[48;2;%d;%d;%dm", r, g, b); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int read_lines(FILE* f, char*** lines_out, size_t *num_lines_out) { Err bitreich.org 70 i+ size_t n, num_lines = 0, capacity = 10; Err bitreich.org 70 i+ char** lines = calloc(capacity, sizeof(char*)); Err bitreich.org 70 i+ ssize_t len; Err bitreich.org 70 i+ Err bitreich.org 70 i+ while ((len = getline(&lines[num_lines], &n, f)) > 0) { Err bitreich.org 70 i+ lines[num_lines][len-1] = 0; // Strip newline. Err bitreich.org 70 i+ if (++num_lines == capacity) { Err bitreich.org 70 i+ capacity *= 2; Err bitreich.org 70 i+ lines = reallocarray(lines, capacity, sizeof(char*)); Err bitreich.org 70 i+ for (unsigned int i = num_lines; i < capacity; i++) { Err bitreich.org 70 i+ lines[i] = NULL; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ *lines_out = lines; Err bitreich.org 70 i+ *num_lines_out = num_lines; Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+struct { Err bitreich.org 70 i+ int frame; Err bitreich.org 70 i+ int lines_per_frame; Err bitreich.org 70 i+ char** lines; Err bitreich.org 70 i+ int num_lines; Err bitreich.org 70 i+} state; Err bitreich.org 70 i+ Err bitreich.org 70 i+void show_status() { Err bitreich.org 70 i+ printf("Frame (h/l): %5d Framesize (j/k): %5d\n", Err bitreich.org 70 i+ state.frame, state.lines_per_frame); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void show_frame() { Err bitreich.org 70 i+ for (int i = 0; i < state.lines_per_frame; i++) { Err bitreich.org 70 i+ int j = state.frame*state.lines_per_frame + i; Err bitreich.org 70 i+ if (j < state.num_lines) { Err bitreich.org 70 i+ puts(state.lines[j]); Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ puts(" MISSING LINE"); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int view(char** lines, size_t num_lines) { Err bitreich.org 70 i+ raw_mode(); Err bitreich.org 70 i+ Err bitreich.org 70 i+ state.frame = 0; Err bitreich.org 70 i+ state.lines_per_frame = 25; Err bitreich.org 70 i+ state.lines = lines; Err bitreich.org 70 i+ state.num_lines = num_lines; Err bitreich.org 70 i+ Err bitreich.org 70 i+ while (1) { Err bitreich.org 70 i+ home(); Err bitreich.org 70 i+ def(); Err bitreich.org 70 i+ clear_screen(); Err bitreich.org 70 i+ show_frame(); Err bitreich.org 70 i+ move(0, state.lines_per_frame+1); Err bitreich.org 70 i+ def(); Err bitreich.org 70 i+ // It is intentional that the status is at the bottom, as VTV Err bitreich.org 70 i+ // files may assume that they are drawn from line 0. Err bitreich.org 70 i+ show_status(); Err bitreich.org 70 i+ switch(getchar()) { Err bitreich.org 70 i+ case 'q': Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ case 'h': Err bitreich.org 70 i+ if (state.frame != 0) { state.frame--; } Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 'l': Err bitreich.org 70 i+ state.frame = (state.frame+1); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 'j': Err bitreich.org 70 i+ if (state.lines_per_frame != 0) {state.lines_per_frame--; } Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 'k': Err bitreich.org 70 i+ state.lines_per_frame++; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int main(int argc, char** argv) { Err bitreich.org 70 i+ if (argc != 2) { Err bitreich.org 70 i+ fprintf(stderr, "Usage: %s FILE\n", argv[0]); Err bitreich.org 70 i+ return 1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ FILE* f = fopen(argv[1], "r"); Err bitreich.org 70 i+ if (f == NULL) { Err bitreich.org 70 i+ fprintf(stderr, "%s: cannot open %s: %s\n", Err bitreich.org 70 i+ argv[0], argv[1], strerror(errno)); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ char** lines; Err bitreich.org 70 i+ size_t num_lines; Err bitreich.org 70 i+ if (read_lines(f, &lines, &num_lines) != 0) { Err bitreich.org 70 i+ fprintf(stderr, "%s: failed to read from %s: %s\n", Err bitreich.org 70 i+ argv[0], argv[1], strerror(errno)); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ return view(lines, num_lines); Err bitreich.org 70 i+} Err bitreich.org 70 .