True multi-output: one aux window per extra display, assignable content

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>
This commit is contained in:
lucianoandClaude Fable 5 committed 2026-08-05 15:16:25 +02:00
1 parent b5dc0275c8
commit 203efe3333
8 files changed
+398 -5

No files matched your search

+10 -1
View File
@@ -1,11 +1,20 @@
const { contextBridge, ipcRenderer, webUtils } = require('electron');
// Each window is launched with --role=control or --role=output.
// Each window is launched with --role=control, --role=output or --role=aux.
const roleArg = process.argv.find(a => a.startsWith('--role='));
const role = roleArg ? roleArg.split('=')[1] : 'control';
// Aux outputs also get the id of the display they live on.
const dispArg = process.argv.find(a => a.startsWith('--display='));
const displayId = dispArg ? parseInt(dispArg.split('=')[1], 10) : -1;
contextBridge.exposeInMainWorld('djv', {
role,
displayId,
// Audio analysis relay: main output -> aux outputs (~30 Hz).
sendAudio: (data) => ipcRenderer.send('afr', data),
onAudio: (cb) => ipcRenderer.on('afr', (_e, d) => cb(d)),
// Create/close aux output windows to match the given display-id list.
auxSync: (ids) => ipcRenderer.invoke('aux:sync', ids),
// Control -> Output commands.
send: (msg) => ipcRenderer.send('ctl', msg),
onControl: (cb) => ipcRenderer.on('ctl', (_e, m) => cb(m)),