remote-server.js: http + ws server (off by default, started from the panel,
port 8787 or next free), every request gated by a secret key embedded in a
QR code; the key persists in userData/remote.json so a phone's home-screen
shortcut survives restarts, 'Nuovo codice' revokes it. Phones send commands
that the panel executes through its own functions (transport, track pick,
effect next/prev/random/family/sequence, Auto VJ, pads, mapping on + visible
zones, blackout, freeze) and the panel pushes a compact live state at ~6 Hz
while a phone is connected (track + progress, effect, sequence, pads,
zones, meters, BPM). New panic controls in output and aux windows: blackout
(fade to black above every layer) and freeze (hold the last frame); also
available as panel buttons. src/remote.{html,css,js} is the touch UI in the
Neon Grid style, installable to the home screen, auto-reconnecting.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVMQ2JhsJ77pGKqcvvFHqc
Mappatura = where (zone geometry + default content), playlist = what.
Text and image scene elements get the 'Su' destination (main output or a
zone), and a new 🎞 Video element plays a looping clip inside a zone. Each
destination is its own cue channel; text/image/video clear when their
element ends, effects stay (apply-once). On the output, zoneOv holds the
per-zone base content (effect/image/video, via a new 'media' source type
in the mapping engine) plus an animated text overlay (zonetext.js: canvas
sized to the zone's aspect, marquee/vertical, letter effects, audio glow)
warped into the zone with alpha. New track or live scene edit sends
mapZoneReset, so zones fall back to their Mappatura content; the saved
mapping is never touched (edit reports return original src/srcRect/opacity).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVMQ2JhsJ77pGKqcvvFHqc
New scene element 🗺 Mappatura (➕🗺): at its time it switches mapping on or
off and, via 'Mostra su' checkboxes, picks which zones show content — the
others go black (opacity 0 on the output only). Effect elements can target
a single zone ('🗺 Zona: …') to run their own preset there; 'no effect'
gives the zone back. Both are live overrides on the output: the saved
mapping is never modified, and edit reports from the output return the
original src/opacity. Manual 'Attiva' toggle shows every zone again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVMQ2JhsJ77pGKqcvvFHqc
Edges are evaluated in output pixels (top/bottom vs horizontal, left/right
vs vertical): under half a pixel of deviation the edge draws green; on the
selected zone crooked edges carry an orange degree badge and the status
line lists all four (degrees + pixels). 'Raddrizza zona' button / R key
squares the zone to the closest axis-aligned rectangle. Dragging a single
corner now also snaps to the other corners of its own zone, so an edge
locks straight. Grid select no longer stretched by the global select rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVMQ2JhsJ77pGKqcvvFHqc
'Aggancia' toggle + grid step (5%, 10%, 2.5%, 1/8, 1/16), persisted. While
dragging a corner or a whole zone the delta is shifted so the closest
moving point lands exactly on a grid line or on another zone's corner coordinate
(per axis, 9 css px capture radius) — adjacent LED panels butt together to
the pixel. Hold Alt to drag freely; keyboard nudge stays unsnapped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVMQ2JhsJ77pGKqcvvFHqc
Editing corners with handles on the output is unmanageable on a large LED
wall (7x4 m): the hand has to work on the giant screen. The Mappatura tab
now has a scaled replica of the output (aspect from the output display or
the LED area) where zones are dragged by corner or whole, with live sync
to the output (one IPC per frame). Keyboard on the focused editor: arrows
nudge 1 output pixel, Shift 10 px, Tab cycles corners, Esc = whole zone;
keys never leak to the global hotkeys. Selection is shared with the zone
list and highlighted on the output handles; a status line shows pixel
coordinates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVMQ2JhsJ77pGKqcvvFHqc
New controls in the Registra tab: a 'Posizione taglio' slider choosing WHICH
strip of the screen survives the cover-crop when the format differs from the
display (ffmpeg crop x/y driven by cropX 0..1), and a guide checkbox. The
guide is a dashed frame + dimmed surroundings drawn on the output window
(outside #stage, last in DOM, overlay only — composeFrame never captures
it), live-updated from slider/format and hidden when no crop applies.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVMQ2JhsJ77pGKqcvvFHqc
A cue aimed at a connected display whose aux window was off landed nowhere
and the monitor stayed black. The cue now switches that output on (persisted,
row updates in the panel) and 'auxReady' re-sends the scene effect once the
freshly created window has loaded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The per-monitor overlay text now reuses the main output's ticker wholesale
(same DOM structure and style.css classes): direction h/vertical/side-edges,
letter effects (wave/zoom/flash/rotate/updown), the 8 fonts, position, size,
weight, color, speed, and the audio-reactive glow — the complete Testo tab
option set. Scene 'effect' elements gain a 'Su' selector (main output / one
aux display / all screens); each target is an independent cue channel so
same-time cues aimed at different monitors all fire, and aux windows in
follow mode ignore the all-screens broadcast (they already follow).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each aux row gets a 🔤 toggle opening a sub-row: text, position
(top/middle/bottom), static or marquee, size, speed, color, bold. The text
renders as an overlay above whatever the window shows — effect, image or
plain black — so a monitor can be a dedicated message board. Scroll duration
scales with text length for constant apparent speed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New 'Uscite multiple' section in the Schermo tab: every display that hosts
neither the panel nor the main output gets a row with an on/off toggle and a
content mode — follow the main effect, a dedicated effect (family+preset,
camera/3D families excluded), a fullscreen image, or black. Aux windows are
lightweight visual-only renderers (aux.html/aux.js) fed with the audio
analysis relayed from the main output at ~30 Hz over the new 'afr' channel,
with a drift-corrected clock. Display hot-plug is now detected (list refresh
+ stale aux windows dropped); config persists per display id in localStorage.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every 400ms progress tick rebuilt the whole list (now heavy with per-track
waveforms), so nodes were replaced between mousedown and mouseup and row
buttons never received their click while a track was playing. renderPlaylist
now computes a skeleton signature and, when unchanged, refreshes times,
progress bar and waveforms on the existing nodes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A lost dragend (dragged node removed from the DOM) left dragFrom/cueDragging
stuck, permanently deferring renderPlaylist: the list stopped redrawing and
row buttons acted on stale indexes (delete/play appeared dead). The guard now
unlocks itself when no .dragging element exists, and row actions resolve the
track index at click time by object identity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
'Disattiva' in the Animazioni 3D tab restores the last non-3D preset
(tracked by applyEffect), answering 'how do I turn the 3D output off'
without hunting through the effect library.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New 'Zona Effetto': each zone runs its own preset on an independent
offscreen Visualizer (960x540, own WebGL context), stepped with the
shared clock and audio so every panel dances to the same music with a
different effect (fluid presets included; interactive/3D excluded).
Zone row gains family/preset selectors; engines are created/destroyed
as zones change and their canvases uploaded as zone textures each
frame. Guide updated with the performance note.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New Mappatura tab + mapping.js engine: each zone is a quad warped with a
projective homography (square->quad closed form, inverted per fragment)
on a dedicated WebGL2 canvas above the visual, black outside. Sources:
the live visual (with a source sub-rect for multi-panel LED walls) or an
image file (corner-pin onto physical surfaces). Edit mode draws handles
ON THE OUTPUT: corners (or whole quads) are dragged while looking at the
real projection, edits flow back to the panel which persists them. Zone
list with name, source portion, opacity and delete; included in
recordings; re-sent when the output restarts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- toFileURL and path-basename handling made Windows-safe (backslashes,
drive letters) so media/model loading works there
- Blender discovery scans Program Files\Blender Foundation; ffmpeg
candidates include common Windows paths
- build config: win/nsis target (x64, custom install dir), build/icon.ico
generated from the 1024 png, dist:win script
Cross-compiled from macOS: dist/DJ Visualizer Setup 1.6.0.exe (95MB) with
scripts unpacked and models/MediaPipe bundled. Untested on real Windows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dance clips are authored for the standard mannequin: on chunkier models
the same joint angles drive the arms through the torso (the ninja is
clean because its proportions match). New 'Apertura braccia' slider
(0-35deg, saved per model path): the upper arms get an extra outward
rotation about the world Z axis during clip playback (left +, right -),
solved back into each bone's local frame through the parent rotation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every loaded model (GLB or converted FBX) is added to 'I miei modelli'
in the Animazioni 3D tab: click a name to switch the dancer instantly
(active one highlighted), x removes it from the list (file untouched).
Persisted in localStorage; the current model is seeded on first run.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The model button now accepts .fbx too: a new model:convert IPC runs
Blender with scripts/fbx2modelglb.py (mesh + skin kept, animations
dropped, embedded diffuse recovered even when the FBX references
missing external textures) into userData/models3d, then the resulting
GLB loads as usual. anim/model conversion share one convertFbx helper.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
'Modello 3D', 'Interattivo Modello' and 'Interattivo Avatar' no longer
appear in the Effetti family filter or the preset list: the new
'Effetto 3D' block in the Animazioni 3D tab has its own family/preset
selectors (palette · variant) and an Attiva button, applying through the
same applyEffect path. Saved pads/sequences/scenes keep working (preset
indices untouched).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Auto VJ pill style (hidden checkbox, ragged flex wrap) didn't fit
the long clip names: #glb-anims now lays out as a two-column grid with
visible aligned checkboxes, ellipsis on overflow and green accent.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- models/dance_library.glb: skeleton-only GLB with the 13 Mixamo dances,
loaded at startup and bound BY BONE NAME to whatever rigged GLB the
user loads — new models dance immediately, no baking needed.
- Repertoire UI (Media tab): checkbox chips of the available clips, the
director only picks the ticked ones (none = all); persisted.
- 'Aggiungi animazioni': extra .glb clips load directly; .fbx are
converted on the fly by Blender via a new anim:convert IPC and the
bundled scripts/fbx2animglb.py (asarUnpacked for packaged builds).
- Manual BPM with TAP tempo: 0 = follow the detected beat, otherwise a
pure metronome drives the dance clock.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The uber-shader pass is now reusable (_renderUber): choosing 'fam:<i>'
in the Sfondo Modello 3D selector renders that family first (tinted with
the active preset's palette/hue/sat) and overlays the model on top. The
selector lists every family except fluids (already explicit options),
interactive and Modello 3D itself.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New 'Sfondo Modello 3D' selector (Media tab): gradient or any of the
five fluid modes. The fluid sim paints the canvas first, then the model
renders on top clearing only the depth buffer (overlay mode skips its
own backdrop pass). Palette and speed are shared with the preset;
persisted and re-sent when the output restarts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New model3d.js: minimal GLB loader (JSON+BIN chunks, accessors with
byteStride, node hierarchy baked into vertices, embedded PNG/JPEG base
colour textures) and a WebGL2 renderer on the shared canvas — palette
fill light, beat-pulsing fresnel rim, treble speculars, bass breathing
via normal displacement, orbiting camera auto-fitted to the bounding
box, gradient backdrop with a bass glow. A generated torus knot shows
before any GLB is loaded. 'Carica un modello .glb' button in the SVG
section; the path persists and is re-sent when the output restarts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Playlist reordering existed but was broken whenever a track was playing:
the ~400ms progress re-render replaced the dragged node and cancelled the
browser drag instantly. renderPlaylist now defers rebuilds until dragend,
drops show an insertion marker (top half = before, bottom half = after),
and internal drags no longer trigger the file-drop overlay.
Scene editor: elements get a drag grip; since the list is always shown
time-sorted, dropping an element between two others moves its appearance
time between theirs (before the first = half its time, after the last =
+5s). Grip-armed dragging keeps the sliders inside the cards working.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New 'Area LED' controls in the Schermo tab: W x H @ X,Y. Everything
(canvas, videos, images, logos, ticker) lives in a #stage box whose
transform makes it the containing block for the fixed layers, so resizing
it confines the whole show at once, black outside. The canvas resizes to
the stage, so shaders render at the wall's native resolution. Persisted
in localStorage and re-pushed when the output window (re)starts; the
recorder follows the canvas position.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
recStart now carries the format and an optional maxMs; the output stops
itself when the time is up (15/30/60/90s picker in the control UI), so a
reel doesn't depend on a manual stop.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three modes for where the director draws presets from: 'smart' keeps the
curated per-mood pools, 'all' removes the family restriction, 'custom'
limits picks to a user checklist (mood still shapes the speed variant,
with a fallback when the checklist exhausts it). Config persists in
localStorage and is re-pushed live while the director runs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The audio engine now tracks musical features: fast/slow energy EMAs, BPM
(median of beat intervals), a quiet/groove/peak mood with hysteresis, and
drop detection (fast energy diverging from slow right after a lull). An
output-side director, toggled from the control UI, switches presets every
16 beats (or ~14s without beats) and immediately on a drop, drawing from
mood-matched family pools (scenic for quiet, fluid/geometry for groove,
fractals/tunnels/fire for peak) while avoiding recent repeats. A manual
effect pick takes over and turns the director off.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The packaged app doesn't bundle ffmpeg, so on Macs without a system ffmpeg the
waveform stayed blank. Compute peaks by reading the file bytes (new file:read
IPC) and decoding with Web Audio's decodeAudioData in a low-rate AudioContext;
ffmpeg in main remains only as a fallback.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pointer on the waveform now seeks: scrub the playhead on the playing track
(new 'seek' output message setting currentTime) or start a stopped track from
the clicked point (playIndex(i, fromTime)). Grabbing within ~10px of the green/
red handles still adjusts the trim in/out instead of seeking.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Per-track start/end points (mm:ss inputs, 'set to current' buttons, draggable
handles on the waveform). Trim applied via audio.setTrim (seek to start, stop
at end) and pushed live to the playing track.
- Wider cards showing elapsed / total / remaining for the trimmed range.
- Waveform rendered per track: peaks computed in main via ffmpeg (mono 8kHz PCM
-> 400 normalized buckets, cached), drawn on a canvas with trim region +
playhead. New audio:peaks IPC + djv.peaks preload binding.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add interlude playlist entries with no audio that run their own scene for a set
duration, then auto-advance. Shares a unified timed-segment runner with the
inter-track gap (pause/resume via the Play button). New 'playSilence' output
message + audio.silence() to stop audio while keeping meters/recording alive.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- When a playlist video has an active scene effect, auto-apply 'screen' blend so
the effect shows through (only if the user left blend at default 'normal';
manual choices are respected). Restores on effect-off / next track.
- Per-track 'Pausa dopo' (seconds): after a track ends, keep its scene timeline
running for N seconds as an intermission (scene elements placed past the song
length appear during the pause), then advance. Countdown + badge in the row.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On restart, lastScene was reset to null and a channel with nothing active at
t=0 also evaluated to null, so the diff saw 'no change' and never sent the hide
command — leftover scene text stayed on screen. Use an undefined sentinel so
advanceCues applies (and thus clears) every channel once at scene start.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each scene element (effect, text, image) now has its own appearance time and
optional duration, with all styling options inline (no more capture-from-panel).
Live preview applies edits immediately on the playing track. Moved the playlist
and its video-render controls into a new Playlist tab.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Blend mode, opacity and fit for videos played from the playlist (mix with visuals).
- Save/Load buttons to export/import a playlist (with scenes/cues) to a JSON file
via native dialogs; the playlist already auto-persists between sessions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Audio and video files can both be added to the playlist; video tracks play
full-screen with their audio routed through the analyser (visuals/waveform
react), have duration/progress, and are included in recordings. Persisted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Loads a muted looping video as a layer above the WebGL canvas with opacity,
blend mode and fit controls; included in MP4 recordings and droppable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Each playlist track holds a timeline of cues (@time → effect/text/image);
cues fire automatically as the track plays, driven by progress reports.
- Playlist (tracks, hotkeys, cues) is saved to userData and restored on startup,
like the pad bank.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each playlist track gets an optional scene (🎬) bound to it: pick the current
effect, a ticker text and an overlay image. When the track plays, the scene is
applied automatically — a cue/queue per song. Scene image is a dedicated output
layer (also captured in recordings).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Scrolling text: font, size, weight, colour and movement effects (up/down, wave,
zoom, flash, rotate) rendered per-letter (and captured in recordings).
- Larger multiline text input.
- Pad bank: crossfade between pads (per-source gain ramps in the audio engine).
- Duration + remaining-time and progress bars for the playlist and the active pad,
via metadata probing and live progress reports from the output window.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>