New Python screen monitor uses Allwinner /dev/disp ioctls to turn off
the display after 15s of no input and toggle it with a short power
button press. Launched by the wrapper alongside sdlamp2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The in-app shutdown visual didn't work because SDL cleanup wiped the
framebuffer. Instead of hacking around that, move the shutdown display
to the device wrapper where it belongs. The wrapper now decodes the
stock firmware's goodbye.png with Python3+PIL and writes raw BGRA
pixels directly to /dev/fb0 before calling poweroff.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sdlamp2 now catches SIGTERM and SIGINT via a sig_atomic_t flag checked
in the main loop, ensuring position and volume are saved before exit.
Previously, a kill signal would terminate instantly without saving.
New tools/rg35xx-wrapper.sh replaces sdlamp2 as the dmenu_ln CMD on
the RG35XX Plus. Skeleton includes placeholders for WiFi hotspot and
power button monitoring (TBD after on-device investigation).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The spritesheet is compiled in as a C byte array. An external
controls.png in cwd still takes precedence for skinning. Includes
tools/embed_png.py to regenerate the header if the asset changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The m4a muxer doesn't support mjpeg as a regular video stream, causing
concatenation to fail when inputs contain album art. Extract art separately
and re-attach it with attached_pic disposition. Also strip leading track
numbers (e.g. "01 ") from chapter titles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shell script to recombine individual story m4a files back into
per-cassette files using ffmpeg concat demuxer (stream copy, no
re-encoding). Generates chapter markers from input filenames and
preserves album art.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>