Verbatim engine copy (fluid.js + effects.js + visualizer.js) plus the
fluid.js script tag in output.html. 102 new audio-reactive ink-in-water
presets. Not yet deployed to the device (offline at commit time).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add POST /api/power/:action (reboot|shutdown) that runs `sudo systemctl
reboot|poweroff` (sudo is passwordless on the appliance), replying before the
host tears down. Two red buttons in the Output tab use a two-tap confirm to
avoid accidental power-offs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expose the engine's live-input mode on the remote: an "Sorgente audio"
selector in the Audio tab lists the input devices the output reports and
switches between File/Playlist and a live USB capture (useInput); picking
File again stops the input. Grant the kiosk getUserMedia access with
--use-fake-ui-for-media-stream so device enumeration/labels work without a
prompt. Make reportDevices resilient (per-probe timeout, always report even
an empty list) so the UI gets feedback when no input is connected yet.
The Pi 5 has no audio input — a USB (line) sound card is required; visuals
react to the source while the audio stays on the mixer.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Port the Mac app's scene system to the phone control. Each queue entry is
now an independent clone carrying a `cues` list of timed elements (effect /
text / image), each with its own appearance time and visible duration; the
three channels are driven independently from playback progress (advanceCues).
Add visual-only "Intermezzo" queue items (silence audio, run their scene for
a set duration) and make the inter-track gap keep the scene running. New
mobile scene editor lives in the queue card detail (⚙). The queue (with
scenes) is persisted via saveState so it survives a phone reload.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Android/iOS Chrome grey out audio files when the document provider reports
a generic MIME (e.g. application/octet-stream for mp3 in Downloads), so
accept="audio/*,video/*" alone hid them. Add explicit extension tokens
(.mp3, .m4a, …) which mobile pickers honour by filename, un-greying them.
Also surface upload success/failure on the button instead of silently
resetting.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Pi 5 vc4hdmi exposes only IEC958 and has no hardware mixing, so raw
ALSA is exclusive: once Chromium's Web Audio stream holds the HDMI device,
the media-element audio (the actual track) can't open it and stays silent
even though the analyser sees the signal. Install PipeWire + pipewire-pulse
as a software mixer (it also handles the IEC958 conversion) so every
Chromium stream mixes onto HDMI. Enable lingering so the user services
start at boot; set the HDMI sink to full volume.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root cause of 'track does not start': the server re-broadcast incoming frames as
binary (Buffer), so the browser output page received Blobs, JSON.parse failed,
and every command (playTrack, etc.) was silently dropped — only the text-encoded
lastEffect sync got through. Broadcast as text now; net.js also handles Blob
defensively. Also: no-store for app assets + kiosk --disk-cache-size=1 so
redeploys always take effect; /api/clients debug endpoint; /api/peaks duration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Queue cards expand to a detail panel with the waveform, elapsed/total/remaining
times, draggable in/out handles, scrub-to-seek and a 'pausa dopo' gap.
- /api/peaks now also returns exact duration (samples/8000) so non-playing tracks
have correct times/trim without relying on the output media probe.
- Service worker switched to network-first (+v2) so UI updates aren't masked by
a stale cache; output.js probeDurations hardened (load()+timeout fallback).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Drop --use-gl=egl (disabled the GPU on Chromium 149) and let Chromium pick the
default ANGLE/GLES backend with --ignore-gpu-blocklist -> hardware WebGL2.
- Launch kiosk via 'cage -- bash kiosk.sh' so a non-executable bit after rsync
no longer breaks startup.
- output.js reports gpuInfo (webgl2 + renderer) on load for remote diagnostics.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New separate project (the Electron Mac app stays untouched). Reuses the visual
engine (WebGL shaders, effect catalog, Web Audio) verbatim and replaces Electron
IPC with a Node HTTP+WebSocket server:
- server.js: serves the kiosk output page + mobile control PWA, relays the same
ctl/rpt JSON protocol over WebSocket, plus REST for media library/upload,
JSON state (pads), waveform peaks and MP4 recording (ffmpeg).
- public/js/net.js: window.djv shim over WebSocket+HTTP so output.js runs intact.
- public/index.html + control.js: touch-first mobile remote (effects, media/queue,
ticker, pads, audio/EQ, fullscreen + recording).
- PWA (manifest + service worker + generated icons).
- scripts/: Chromium kiosk launcher + install-pi.sh (systemd units for Pi 5).
Verified: REST endpoints, WebSocket relay both directions, control PWA loads the
2958-effect catalog and renders. (Headless WebGL output not testable without GPU.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>