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>
53 lines
2.1 KiB
HTML
53 lines
2.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="it">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<title>DJ Visualizer — Output</title>
|
|
<link rel="stylesheet" href="css/style.css" />
|
|
</head>
|
|
<body class="output">
|
|
<canvas id="gl"></canvas>
|
|
|
|
<video id="bg-video" class="bg-video" loop muted playsinline></video>
|
|
<video id="track-video" class="track-video" playsinline></video>
|
|
<div id="overlay-images"></div>
|
|
<img id="scene-image" class="scene-image" />
|
|
<img id="logo-0" class="logo" />
|
|
<img id="logo-1" class="logo" />
|
|
|
|
<div id="ticker"><div id="ticker-track"><span class="tick-copy"></span><span class="tick-copy"></span></div></div>
|
|
<div id="side-text">
|
|
<div class="side-col left"><div class="side-track"><span class="side-copy"></span><span class="side-copy"></span></div></div>
|
|
<div class="side-col right"><div class="side-track"><span class="side-copy"></span><span class="side-copy"></span></div></div>
|
|
</div>
|
|
|
|
<div id="drop-hint">
|
|
<div class="big">🎛 In attesa dell'audio…</div>
|
|
<div class="small">Controlla dal telefono · apri questa pagina a tutto schermo</div>
|
|
</div>
|
|
|
|
<script>window.DJV_ROLE = 'output';</script>
|
|
<script src="js/net.js"></script>
|
|
<script src="js/engine/shaders.js"></script>
|
|
<script src="js/engine/effects.js"></script>
|
|
<script src="js/engine/visualizer.js"></script>
|
|
<script src="js/engine/audio.js"></script>
|
|
<script src="js/output.js"></script>
|
|
<!-- Tap anywhere to enter fullscreen & unlock audio (browser autoplay policy). -->
|
|
<script>
|
|
addEventListener('click', () => {
|
|
const el = document.documentElement;
|
|
if (el.requestFullscreen) el.requestFullscreen().catch(() => {});
|
|
}, { once: true });
|
|
djv.onControl((m) => {
|
|
if (m && m.type === 'outputFullscreen') {
|
|
const el = document.documentElement;
|
|
if (!document.fullscreenElement && el.requestFullscreen) el.requestFullscreen().catch(() => {});
|
|
else if (document.exitFullscreen) document.exitFullscreen().catch(() => {});
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|