***************************
* Raspberry Pi Beamertool *
***************************
Original von Moritz <mo@blog-srv.net>, portiert auf Raspberry Pi 4 /
Raspberry Pi OS Lite (64bit) bzw. Debian 13 "trixie".

--------------------------------
Architektur: mpv als alleiniger Anzeigepfad
--------------------------------
Das Original nutzte den alten Broadcom-"Legacy"-Grafikstack
(bcm_host/Dispmanx/EGL, OpenGL ES 1.1 Fixed-Function, OpenMAX IL/ilclient),
der auf dem Pi 4/Debian 13 nicht mehr existiert. Der erste Portierungs-
Ansatz (SDL2 mit dem "kmsdrm"-Videotreiber, direkt auf den Bildschirm
gezeichnet) erwies sich in der Praxis auf manchen Pi4/Debian-13-
Kombinationen als unzuverlässig - trotz erkanntem Monitor blieb der
Bildschirm mitunter schwarz, ohne dass ein Fehler geloggt wurde.

Die jetzige Architektur nutzt daher denselben Ansatz wie das parallel
entwickelte Python-Schwesterprojekt (rpi-beamertool v3, Pi Zero 2 W):
EINE dauerhaft laufende **mpv-Instanz ist der alleinige Anzeigepfad**.
mpv's eigener GPU/DRM-Renderpfad hat sich als deutlich robuster erwiesen.

 - Unser Programm zeichnet die Laser-Simulation komplett UNSICHTBAR im
   Hintergrund (EGL "surfaceless"-Kontext über /dev/dri/renderD128 - kein
   Bildschirm, kein Connector, keine Monitor-Erkennung nötig) und schickt
   die fertigen Frames als Rohvideo-Strom über eine benannte Pipe (FIFO)
   an mpv (Demuxer "rawvideo").
 - Der Media Player (Fotos/Videos aus ./media/) schaltet mpv per IPC-
   Kommando ("loadfile") stattdessen direkt auf die gewählte Datei um -
   mpv decodiert selbst, unser Programm muss dafür nichts mehr rendern.
 - Umschalten zwischen beiden Modi passiert nahtlos durch ein erneutes
   "loadfile" per IPC.

Das ist deutlich robuster, hat aber eine Konsequenz: Video-**Gobos**
innerhalb der Laser-Simulation (Textur-Dateien wie z.B. 194.h264) werden
aktuell NICHT dekodiert (ein zweiter Video-Decoder-Prozess würde mit dem
alleinigen mpv kollidieren) - sie zeigen einen blauen Platzhalter. Das
Kernfeature (DMX-gesteuerte Gobos/Muster als PNG/GIF) sowie der komplette
Media Player sind davon nicht betroffen.

Weitere Änderungen:
 - Autostart über systemd (rpi-beamertool.service) statt /etc/rc.local
 - Installer nutzt apt statt aptitude und baut aus dem Quellcode
 - Konfigurierbare Streaming-Auflösung/Framerate (config.txt:
   RENDER_WIDTH/RENDER_HEIGHT/RENDER_FPS, Standard 960x540@25fps -
   Kompromiss aus Bildschärfe und CPU-/Pipe-Last auf dem Pi4)

Unverändert/portabel geblieben: Art-Net-Empfang, ncurses-Konsole,
Canvas-/Zoom-/Rotationslogik, GIF-/PNG-Loader (für die normalen
Bild-Gobos), das PHP-Webinterface (tools/index.php).

-----------------------------
Media Player
-----------------------------
Zusätzlich zur Laser-Simulation gibt es einen Media Player, der Fotos/
Videos aus dem Verzeichnis /opt/rpi-beamertool/media/ abspielt (mpv spielt
sie direkt ab - Formate: alles was mpv kann, u.a. png/jpg/jpeg/bmp/gif/
mp4/mkv/mov/avi/webm). Er wird über ein eigenständiges DDF gesteuert
(rpi-beamertool-ModeMedia.xml, resources/ddf/), das unabhängig vom
Laser-Kanalblock an einer eigenen Adresse gepatcht wird (config.txt:
MEDIA_PLAYER_CHANNEL, ABSOLUTER Art-Net-Kanal - entspricht genau der
Patch-Adresse dieses DDFs in DMXControl):

 - Wert 0: normale Laser-Simulation (Standard)
 - Wert 1-255: Media Player aktiv, der Wert wählt die Datei aus dem
   alphabetisch sortierten Verzeichnisinhalt (in Einerschritten, mit
   Wraparound falls weniger Dateien vorhanden sind als DMX-Werte)

Details zu allen drei DDFs (Laser/ModeMedia/Overlays) und deren
Kanalzuordnung: resources/ddf/README.

-----------------------------
Nebel/Haze & Laser-Tunnel (Festival-Look)
-----------------------------
Zusätzlich zur reinen Gobo-Simulation gibt es zwei weitere, unabhängige
Effekte, die zusammen den Eindruck einer echten Festival-Lasershow mit
Nebelmaschine erzeugen. Beide gehören zum eigenständigen DDF
rpi-beamertool-overlays.xml (13 Kanäle, config.txt: FOG_DENSITY_CHANNEL
= ABSOLUTE Patch-Adresse dieses DDFs):

 - Nebeldichte (Kanal FOG_DENSITY_CHANNEL+0): ein bildschirmfüllender,
   kachelbarer Dunstschleier aus einer einmalig prozedural generierten,
   realistisch wirkenden Wolkentextur (resources/textures/fog.png), die sich
   langsam und leicht diagonal verschiebt (wie von Luft bewegter Nebel).
 - Laserstrahl-Sichtbarkeit (Kanal FOG_DENSITY_CHANNEL+1): zeigt
   zusätzlich zum scharfen Gobo im Vordergrund einen "Tunnel", der die
   FORM des aktuellen Gobos (z.B. ein Dreieck) mehrfach verkleinert zu
   einem festen, gemeinsamen Fluchtpunkt (Bühne/Tiefe, Bildmitte) hin
   abbildet - unabhängig von der Gobo-Position, so wie bei einem echten
   Laser mit festem Standort. Der Tunnel wird zusätzlich dort heller
   dargestellt, wo er auf eine lokal hellere/dichtere Nebelstelle trifft
   (eigener Shader sampelt Gobo- UND Nebeltextur gemeinsam).

Wichtig: Der Tunnel ist nur sichtbar, wenn BEIDE Kanäle aktiv sind UND das
Gobo selbst eine Helligkeit (Dimmer) über 0 hat - die Gesamthelligkeit des
Tunnels ergibt sich aus Dimmer × Laserstrahl-Sichtbarkeit × Nebeldichte.
Bei Nebeldichte=0 verschwindet der Tunnel komplett, es bleibt nur das
normale, scharfe Gobo im Vordergrund sichtbar (Dimmer-Steuerung
unverändert wie bisher).

Beide Kanäle 0-255 linear auf 0-100% abgebildet. FOG_DENSITY_CHANNEL
auskommentiert/-1 = alle Overlay-Effekte deaktiviert (Standard).

-----------------------------
Kachel-Effekt (Kaleidoskop-Look)
-----------------------------
Statt des Bildes 1:1 kann es stattdessen gekachelt dargestellt werden -
ein NxN-Raster, in dem jede Kachel das komplette Bild zeigt (nicht einen
Ausschnitt davon). Ebenfalls Teil von rpi-beamertool-overlays.xml:

 - Kanal FOG_DENSITY_CHANNEL+2 (Kachel-Anzahl): 0-63=aus, 64-127=4
   Kacheln (2x2), 128-191=16 Kacheln (4x4), 192-255=64 Kacheln (8x8)
 - Kanal FOG_DENSITY_CHANNEL+3 (Kachel-Spiegelung): 0-84=1:1 (jede Kachel
   identisch), 85-169=vertikal gespiegelt, 170-255=horizontal gespiegelt

Bei "vertikal gespiegelt" zeigt die obere Rasterhälfte das Bild normal,
die untere Hälfte auf dem Kopf (Spiegelsymmetrie an der waagerechten
Mitte - wie eine Wasserspiegelung). "Horizontal gespiegelt" funktioniert
analog an der senkrechten Mitte: linke Hälfte normal, rechte Hälfte
seitenverkehrt.

Technisch: die fertig gerenderte Szene wird in einem zweiten Rendering-
Durchgang (eigenes FBO) NxN-fach mit passender UV-Spiegelung pro Kachel
neu zusammengesetzt - kein zusätzlicher Shader nötig, der bestehende
Gobo-Textur-Shader wird wiederverwendet.

-----------------------------
Farbverlauf-Raster-Effekt (Kaleidoskop-Hintergrund)
-----------------------------
Ganz im Hintergrund (hinter Nebel, Laser-Tunnel und Gobos) kann ein
diagonaler Farbverlauf langsam durchlaufen, sichtbar durch ein
Kachel-Raster mit leicht "atmenden" Lücken hindurch (jede Rasterzelle
"pulsiert" unabhängig langsam in der Lückenbreite). Ebenfalls Teil von
rpi-beamertool-overlays.xml:

 - Kanal FOG_DENSITY_CHANNEL+4 (Sichtbarkeit): 0-255 linear -> 0-100%
 - Kanal FOG_DENSITY_CHANNEL+5 bis +10 (Anfangs-/Endfarbe): als EIN
   <matrix rows="2" columns="1"/>-Element ausgeführt (alle 6 Kanäle
   implizit), damit DMXControl zwei echte Farbpicker zeigt und seine
   Effekte darauf anwenden kann
 - Kanal FOG_DENSITY_CHANNEL+11 (Geschwindigkeit): 0-255 linear
 - Kanal FOG_DENSITY_CHANNEL+12 (Modus): Schalter - 0-127 = zwei Farben
   (Start/Ende pendeln als Dreieckswelle hin und her), 128-255 =
   Regenbogen (volles Farbspektrum, Start-/Endfarbe dann ungenutzt)

-----------------------------
Laserstrahl-Fächer
-----------------------------
Zusätzlich zum normalen Gobo kann pro Laser-Layer ein Fächer aus dünnen,
geraden Strahlen eingeschaltet werden, die radial von der Layer-Position
aus über den Bildschirmrand hinausragen - wie ein echter Laserprojektor,
der irgendwo im Raum steht. Gehört zu rpi-beamertool-laser.xml, nutzt die
vier Kanäle, die pro 20-Kanal-Layer sonst frei geblieben wären (siehe
DMX-Kanallayout weiter oben): +13 Sichtbarkeit, +17 Anzahl Strahlen
(2-64), +18 Länge, +19 Breite. Ursprung = Layer-Position (+2/+3),
Richtung = normale Layer-Rotation (+6/+15, derselbe "2D-Effekt", der auch
das Gobo dreht), Farbe = bestehender Farbkanal (+10/+11/+12), Helligkeit
= Sichtbarkeit × Dimmer (+1), unsichtbar bei geschlossenem Shutter (+14).
Additiv gemischt - sich kreuzende Strahlen hellen sich gegenseitig auf.

-----------------------------
Weitere Einstellungen (config.txt)
-----------------------------
 - TUNNEL_STEPS: Anzahl der verkleinerten Gobo-"Echo"-Kopien im Laser-
   Tunnel-Effekt (Standard 10). Mehr Schritte = dichterer/glatterer
   Tunnel, aber mehr Rechenlast pro Frame.
 - ARTNET_DEBUG=1: loggt jedes empfangene und geaenderte Art-Net-Signal
   (Universe/Kanal/Wert) - hilft zu pruefen, ob Pakete korrekt ankommen
   und zum richtigen Universe/Subnet passen. Nur zum Debuggen einschalten
   (journalctl -u rpi-beamertool -f), erzeugt bei aktivem Sender viele
   Logzeilen.
 - RECORD_VIDEO=1 + RECORD_VIDEO_PATH: zeichnet die Laser-Simulation
   zusaetzlich als MP4-Datei auf (z.B. fuer Demo-Zwecke), per ffmpeg im
   Hintergrund. Waehrend der Media Player aktiv ist, pausiert die
   Aufzeichnung automatisch (unser Renderer liefert dann keine Frames).

-----------------------------
Installation
-----------------------------
Getestet mit Raspberry Pi OS Lite (64bit, Bookworm/Trixie) und Debian 13
"trixie" auf einem Raspberry Pi 4.

Automatisch (empfohlen):

    sudo ./tools/rpi-bt-install.sh

Das Skript installiert die Build-Abhängigkeiten, baut das Programm, kopiert
alles nach /opt/rpi-beamertool und richtet den systemd-Autostart ein.

Manuell:

    sudo apt-get update
    sudo apt-get install build-essential cmake pkg-config \
        libegl1-mesa-dev libgles2-mesa-dev libncurses-dev mpv ffmpeg

    mkdir build && cd build
    cmake ..
    make -j$(nproc)
    ./rpi-beamertool

-----------------------------
Bedienung / Deinstallation
-----------------------------
    systemctl start rpi-beamertool      # bzw. tools/rpi-bt-start.sh
    systemctl restart rpi-beamertool    # bzw. tools/rpi-bt-restart.sh
    journalctl -u rpi-beamertool -f     # Logs
    sudo ./tools/rpi-bt-uninstall.sh    # deinstallieren

-----------------------------
Versionierung & weitere Doku
-----------------------------
    ./version.sh patch    # bzw. minor/major - vor dem Bauen ausfuehren
    ./version.sh show     # aktuelle Version anzeigen

Schreibt src/version.h (einzige Versionsquelle, wird einkompiliert) und
stempelt config.txt, die systemd-Unit sowie alle DDF-Dateien mit
Versionsnummer + Zeitstempel. Ausfuehrliches Handbuch: docs/manual.md

-----
INFO:
-----
 - Braucht einen angeschlossenen, erkannten Monitor (mpv zeigt sonst
   naturgemäß nichts an), aber KEINEN eigenen Bildschirmzugriff für unser
   Programm selbst mehr - dadurch auch kein TTY/VT-Gerangel mehr wie bei
   der direkten kmsdrm-Variante.
 - Der ausführende Nutzer muss in den Gruppen "video" und "render" sein
   (macht der Installer automatisch); nach dem ersten Hinzufügen ggf.
   einmal neu einloggen/rebooten.
 - Bei Rucklern in der Laser-Simulation zuerst RENDER_WIDTH/RENDER_HEIGHT/
   RENDER_FPS in config.txt reduzieren.
 - Video-Gobos (Textur-Dateien wie z.B. 194.h264) werden aktuell nicht
   dekodiert (blauer Platzhalter, siehe oben) - PNG/GIF-Gobos sind davon
   nicht betroffen.
 - Die Berechnung der automatischen Drehungen und des Shutters erfolgt pro
   Frame (wie im Original/Windows-Beamertool). Besser wäre eine
   Berechnung pro Zeit, da die Framerate bei vielen großen Gobos absinken
   kann.
 - Der Animationsregler ist wirkungslos, das Steuern von GIF-Animationen
   ist (noch) nicht implementiert.
 - Man kann wählen, ob sich die Zoomfunktion wie im Original verhält oder
   in einen Kreis zoomt.
