Numbered, fixed-width lines let us read a printer's actual page length
and line width limits straight off the paper, instead of guessing them
from A4 geometry - needed to nail down the real constants for the
PRINTER_A4 landscape math.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
a4_landscape_chars() was sizing the capture/preview to the *final*
landscape look (assuming the physical page gets fed sideways), but
txt2printr.sh actually rotates the ascii art 90 degrees in software on
a normally-fed page. Combining both produced ~107 printed lines,
overflowing the printer's page-length capacity onto a second sheet.
Since the software rotation is cancelled out by the reader turning the
finished page 90 degrees, the capture buffer's own dimensions equal
the final visual result, but its width becomes the printed line count
post-rotation - so it must be capped by the page's line capacity along
the long edge, with height derived from the target landscape aspect
ratio (corrected for non-square character cells) instead of just
filling the available character budget.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dot-matrix printers have no hardware page-rotation, so when PRINTER_A4
is enabled in the new printer.conf, txt2printr.sh rotates the ascii art
90 degrees in software before sending it, and photobooth.py caps its
live-preview viewfinder to an A4-landscape character grid (sized from
configurable PRINTER_CPI/PRINTER_LPI) instead of just filling the
terminal, so the preview matches what actually gets printed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Missing '!' meant the kernel couldn't recognize the interpreter
directive, causing ENOEXEC (errno 8) when executed directly, e.g.
via subprocess.run() from photobooth.py.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-f only matches regular files, so it never matched the /dev/lp0 or
/dev/usb/lp0 character device nodes, leaving dev unset and always
failing. Use -e existence checks in proper if/elif priority order
(lp0 > usb/lp0 > stdout), with PRINTER_DEV as an unconditional override.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces per-frame fswebcam process spawns with a persistent OpenCV/v4l2
capture handle for the highest achievable refresh rate, while still
shelling out to ascii-image-converter for conversion and txt2printr.sh
for printing. Renders a bordered live preview with a status/keybind-help
bar via curses, works on a plain TTY with no graphical environment.
Reuses webcam.conf/ascii.conf/keybinds.conf, parsed as plain key=value
(not sourced, so a config file can no longer execute arbitrary code).
Brightness/exposure now go through v4l2-ctl with percentage mapped onto
each control's actual min/max range; added DEVICE/BRIGHTNESS_CTRL_ID/
EXPOSURE_CTRL_ID to webcam.conf and KEY_QUIT to keybinds.conf for this,
kept separate from the bash-oriented keys so the existing bash scripts
are unaffected. Bash scripts are left in place as a fallback.
New deps: python-opencv, v4l-utils.
ascii.conf exposes ascii-image-converter's dimension/complexity/map/
grayscale/negative/flip options (color and braille stay out since they
rely on ANSI/multi-byte Unicode that txt2printr.sh's raw print path
can't render). keybinds.conf lets exec-cycle.sh's capture/brightness/
exposure/reset keys be rebound instead of hardcoded, matched
case-insensitively; the on-screen hint bar renders from the same
config so it never drifts out of sync with the actual bindings.
exec-cycle.sh's live preview now shows brightness/exposure and lets
+/-, ./, adjust them per-frame via fswebcam --set, with r to reset;
webcam.conf centralizes the starting values, step size, capture
resolution/quality, and the v4l2 control names (which vary by camera)
so hardware-specific tuning doesn't require editing the scripts.
txt2printr.sh writes directly to /dev/lp0, which needs the lp kernel
driver loaded (via parport/parport_pc) and lp group membership for
non-root write access; wire both up during dependency install.
writes raw bytes to /dev/lp0 (overridable via PRINTER_DEV): resets the
printer with ESC @, converts LF to CRLF to avoid staircasing on raw
device writes, then form-feeds to eject the page.
replaced the guvcview+keypress capture flow with a continuous
capture/convert/display loop so the terminal shows a live ascii
preview; pressing c saves the frame and triggers the new
txt2printr.sh hook (currently a blank template).