diff --git a/CLAUDE_PROGRESS.md b/CLAUDE_PROGRESS.md index 002c41c..b0f666c 100644 --- a/CLAUDE_PROGRESS.md +++ b/CLAUDE_PROGRESS.md @@ -1,9 +1,9 @@ # Twitch4SteamDeck — Fortschritts-Snapshot -> Stand: **2026-04-08 (Session 4)**. Diese Datei dient als Übergabe zwischen Sessions. +> Stand: **2026-04-09 (Session 5)**. Diese Datei dient als Übergabe zwischen Sessions. > **Lies zuerst:** diese Datei + `todo.md` + `plan.md`. -**Aktueller Stand:** Phase 0–5.6 abgeschlossen & verifiziert. Als nächstes: Phase 6 (Flatpak-Packaging). +**Aktueller Stand:** Phase 0–5.6 abgeschlossen & verifiziert. Phase 6 (Flatpak-Packaging): Manifest + Hilfs-Dateien geschrieben, wartet auf User-Verifikation in WSL2 + Steam Deck. --- @@ -131,17 +131,39 @@ Verifiziert 2026-04-08. --- -## Nächster Schritt: Phase 6 — Flatpak-Packaging +## Phase 6 — Flatpak-Packaging (in Arbeit, wartet auf WSL2 + Steam Deck) Ziel: App läuft auf dem Steam Deck als Flatpak. -Wichtige offene Punkte: -- mpv + streamlink müssen als Flatpak-Module gebündelt werden -- `--hwdec=vaapi` für Linux (Steam Deck) statt `auto` (Windows) -- IPC-Pfad: Unix Socket `/tmp/twitch4sd-mpv.sock` (bereits implementiert für non-win32) -- better-sqlite3 muss für Linux/ARM64 (Steam Deck) cross-compiliert werden -- Flatpak-Manifest: `flatpak/tv.twitch4steamdeck.App.yml` -- **Flaggen-Emojis erst hier testbar** (Noto Color Emoji auf Linux) +#### Neue Dateien (Phase 6): +- `flatpak/tv.twitch4steamdeck.App.yml` — Flatpak-Manifest (mpv + streamlink als Module) +- `flatpak/twitch4steamdeck.sh` — Launcher mit `zypak-wrapper` (Electron-Sandbox) +- `flatpak/tv.twitch4steamdeck.App.desktop` — Desktop-Eintrag +- `flatpak/build-flatpak.sh` — Build-Skript für WSL2 (prüft deps, füllt SHA256, baut) +- `resources/icons/icon.svg` — App-Icon (Platzhalter, konvertiert zu PNG beim Build) + +#### Architektur-Entscheidungen: +- **Pre-Build in WSL2:** `npm install` + `@electron/rebuild` + `npm run build` laufen + AUSSERHALB von flatpak-builder in WSL2. Das Manifest kopiert nur die Artefakte. + → Vermeidet npm-im-Flatpak-Sandbox-Probleme. +- **Electron-Binary aus npm:** Das Electron-Binary kommt aus `node_modules/electron/dist/electron` + (npm install für Linux), NICHT aus dem BaseApp. BaseApp liefert nur Chrome-Runtime-Libs + zypak. +- **zypak-wrapper:** Ersetzt Chrome-Setuid-Sandbox für Flatpak-Kompatibilität. +- **mpv:** Aus Sources gebaut, libplacebo deaktiviert (entfernt Vulkan-Abhängigkeitskette), + ffmpeg/libass/libva kommen aus freedesktop SDK 24.08. +- **streamlink:** Via pip install ins Flatpak gebaut. Für sauberen Offline-Build: + `flatpak-pip-generator` für Python-Dependencies verwenden (TODO beim echten Build). +- **better-sqlite3:** Muss für Linux x64 rebuilt werden (Steam Deck = AMD Zen2 x86_64, + NICHT ARM64 — die alte ARM64-Notiz war falsch). +- **IPC-Socket:** `os.tmpdir()` → `/tmp` — beide Prozesse (Electron-Main + mpv-Child) + teilen denselben Flatpak-Sandbox-Namespace. Kein Code-Fix nötig. +- **VAAPI:** `--hwdec=vaapi` bereits implementiert für non-win32 in `streamlink.ts:73`. +- **Flaggen-Emojis erst hier testbar** (Noto Color Emoji aus freedesktop Platform Runtime) + +#### Noch ausstehend (User): +1. WSL2-Setup: `sudo apt install flatpak flatpak-builder librsvg2-bin` +2. `bash flatpak/build-flatpak.sh` (in WSL2, aus `/mnt/c/Projekte/twitch4steamdeck`) +3. Verifikation auf Steam Deck: Login, Live, VOD, Resume, Gamepad, Gaming Mode --- diff --git a/flatpak/build-flatpak.sh b/flatpak/build-flatpak.sh new file mode 100644 index 0000000..a88af02 --- /dev/null +++ b/flatpak/build-flatpak.sh @@ -0,0 +1,139 @@ +#!/bin/bash +# build-flatpak.sh — Kompletter Build-Ablauf für das Twitch4SteamDeck Flatpak. +# Ausführen in WSL2 Ubuntu: bash flatpak/build-flatpak.sh +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +cd "$PROJECT_DIR" +echo "=== Arbeitsverzeichnis: $PROJECT_DIR ===" + +# ───────────────────────────────────────────────────────────────────────────── +# Schritt 1: Flatpak-Abhängigkeiten prüfen +# ───────────────────────────────────────────────────────────────────────────── +echo "" +echo "=== [1/6] Prüfe Flatpak-Voraussetzungen ===" +for cmd in flatpak flatpak-builder node npm python3 rsvg-convert; do + if ! command -v "$cmd" &>/dev/null; then + echo "FEHLER: '$cmd' nicht gefunden." + case "$cmd" in + flatpak|flatpak-builder) echo " → sudo apt install flatpak flatpak-builder" ;; + node|npm) echo " → curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install nodejs" ;; + rsvg-convert) echo " → sudo apt install librsvg2-bin" ;; + esac + exit 1 + fi +done + +# ───────────────────────────────────────────────────────────────────────────── +# Schritt 2: Flatpak-Runtimes prüfen / installieren +# ───────────────────────────────────────────────────────────────────────────── +echo "" +echo "=== [2/6] Prüfe Flatpak-Runtimes ===" +RUNTIMES=( + "org.freedesktop.Platform//24.08" + "org.freedesktop.Sdk//24.08" + "org.electronjs.Electron2.BaseApp//24.08" +) +for rt in "${RUNTIMES[@]}"; do + if ! flatpak info --user "$rt" &>/dev/null 2>&1 && \ + ! flatpak info --system "$rt" &>/dev/null 2>&1; then + echo "Installiere: $rt" + flatpak install --user --noninteractive flathub "$rt" + else + echo " ✓ $rt bereits vorhanden" + fi +done + +# ───────────────────────────────────────────────────────────────────────────── +# Schritt 3: .env prüfen +# ───────────────────────────────────────────────────────────────────────────── +echo "" +echo "=== [3/6] Prüfe .env (Twitch Client-ID) ===" +if [ ! -f .env ]; then + echo "FEHLER: .env nicht gefunden." + echo " → Kopiere .env.example nach .env und trage MAIN_VITE_TWITCH_CLIENT_ID ein." + exit 1 +fi +if ! grep -q "MAIN_VITE_TWITCH_CLIENT_ID=" .env; then + echo "FEHLER: MAIN_VITE_TWITCH_CLIENT_ID fehlt in .env" + exit 1 +fi +echo " ✓ .env gefunden" + +# ───────────────────────────────────────────────────────────────────────────── +# Schritt 4: npm install (Linux) + better-sqlite3 rebuild + Build +# ───────────────────────────────────────────────────────────────────────────── +echo "" +echo "=== [4/6] npm install (Linux-Binaries) + Rebuild native Modules ===" +npm install +echo " → Rebuilde better-sqlite3 für Linux x64 ..." +npx @electron/rebuild --module-dir node_modules/better-sqlite3 +echo " → Build (electron-vite) ..." +npm run build + +# Verifikation: better_sqlite3.node muss ELF/Linux sein +NATIVE_NODE="node_modules/better-sqlite3/build/Release/better_sqlite3.node" +if [ -f "$NATIVE_NODE" ]; then + FILE_OUT=$(file "$NATIVE_NODE") + echo " native module: $FILE_OUT" + if echo "$FILE_OUT" | grep -q "ELF"; then + echo " ✓ Linux ELF — korrekt" + else + echo " WARNUNG: Datei ist kein Linux-ELF. Rebuild möglicherweise fehlgeschlagen." + fi +fi + +# ───────────────────────────────────────────────────────────────────────────── +# Schritt 5: Manifest-SHA256-Werte füllen (interaktiv) +# ───────────────────────────────────────────────────────────────────────────── +echo "" +echo "=== [5/6] SHA256-Prüfsummen für Manifest-Sources ===" +echo "" + +MPV_URL="https://github.com/mpv-player/mpv/archive/refs/tags/v0.38.0.tar.gz" +SL_URL="https://github.com/streamlink/streamlink/archive/refs/tags/6.11.0.tar.gz" +MANIFEST="flatpak/tv.twitch4steamdeck.App.yml" + +MPV_ARCHIVE="/tmp/mpv-0.38.0.tar.gz" +SL_ARCHIVE="/tmp/streamlink-6.11.0.tar.gz" + +echo "Lade mpv 0.38.0 ..." +curl -L --progress-bar -o "$MPV_ARCHIVE" "$MPV_URL" +MPV_SHA=$(sha256sum "$MPV_ARCHIVE" | awk '{print $1}') +echo " mpv sha256: $MPV_SHA" + +echo "Lade streamlink 6.11.0 ..." +curl -L --progress-bar -o "$SL_ARCHIVE" "$SL_URL" +SL_SHA=$(sha256sum "$SL_ARCHIVE" | awk '{print $1}') +echo " streamlink sha256: $SL_SHA" + +# Platzhalter im Manifest ersetzen +sed -i "s/FILL_IN_sha256sum_of_mpv_0\.38\.0_tarball/$MPV_SHA/" "$MANIFEST" +sed -i "s/FILL_IN_sha256sum_of_streamlink_tarball/$SL_SHA/" "$MANIFEST" +echo " ✓ Manifest aktualisiert" + +# ───────────────────────────────────────────────────────────────────────────── +# Schritt 6: flatpak-builder — Build + lokale Installation +# ───────────────────────────────────────────────────────────────────────────── +echo "" +echo "=== [6/6] flatpak-builder ===" +flatpak-builder \ + --user \ + --install \ + --force-clean \ + build-dir \ + flatpak/tv.twitch4steamdeck.App.yml + +echo "" +echo "======================================================" +echo " Build abgeschlossen!" +echo " Starten: flatpak run tv.twitch4steamdeck.App" +echo "" +echo " Für Steam Deck (Bundle erstellen):" +echo " flatpak build-bundle ~/.local/share/flatpak/repo \\" +echo " twitch4steamdeck.flatpak tv.twitch4steamdeck.App" +echo " # Dann twitch4steamdeck.flatpak per USB/SSH auf Deck kopieren" +echo " # Dort: flatpak install --user twitch4steamdeck.flatpak" +echo "======================================================" diff --git a/flatpak/tv.twitch4steamdeck.App.desktop b/flatpak/tv.twitch4steamdeck.App.desktop new file mode 100644 index 0000000..38369c5 --- /dev/null +++ b/flatpak/tv.twitch4steamdeck.App.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Twitch4SteamDeck +Comment=Werbefreier Twitch-Client für das Steam Deck +Exec=twitch4steamdeck +Icon=tv.twitch4steamdeck.App +Type=Application +Categories=AudioVideo;Player;Network; +StartupWMClass=twitch4steamdeck diff --git a/flatpak/tv.twitch4steamdeck.App.yml b/flatpak/tv.twitch4steamdeck.App.yml new file mode 100644 index 0000000..906d67e --- /dev/null +++ b/flatpak/tv.twitch4steamdeck.App.yml @@ -0,0 +1,129 @@ +app-id: tv.twitch4steamdeck.App +runtime: org.freedesktop.Platform +runtime-version: '24.08' +sdk: org.freedesktop.Sdk +# Stellt Chrome-Runtime-Bibliotheken (GTK, GLib, etc.) + zypak-wrapper bereit. +# Das Electron-Binary selbst kommt aus node_modules/electron/dist/electron (npm install in WSL2). +base: org.electronjs.Electron2.BaseApp +base-version: '24.08' +command: twitch4steamdeck + +finish-args: + - --share=network # Twitch Helix-API + Streamlink (HLS) + - --share=ipc # X11 shared memory (Wayland-Fallback) + - --socket=wayland + - --socket=fallback-x11 + - --socket=pulseaudio # Audio für mpv + - --device=dri # GPU-Zugriff für VAAPI-Hardware-Decoding + - --talk-name=org.freedesktop.Notifications + # Electron userData liegt automatisch in ~/.var/app/tv.twitch4steamdeck.App/config/ + # Kein extra --filesystem nötig. + +# Build-Voraussetzung (WSL2, VOR flatpak-builder): +# cd /mnt/c/Projekte/twitch4steamdeck +# npm install # installiert Electron 33 für Linux + alle Deps +# npx @electron/rebuild # rebuildet better-sqlite3 für Linux x64 +# npm run build # kompiliert TS → out/ +# Das Projektverzeichnis (inkl. out/ und node_modules/) wird als type:dir Source +# in den Manifest-Build-Schritt kopiert. + +modules: + # ───────────────────────────────────────────────────────────────────────────── + # 1) mpv — Media-Player für Live-Streams und VODs + # Gebaut aus Sources; libplacebo deaktiviert (entfernt Vulkan/Shader-Chain). + # ffmpeg, libass und libva (VAAPI) kommen aus dem freedesktop SDK 24.08. + # ───────────────────────────────────────────────────────────────────────────── + - name: mpv + buildsystem: meson + config-opts: + - -Dlibplacebo=disabled + - -Dvaapi=enabled + - -Dpulse=enabled + - -Dalsa=disabled + - -Dlua=disabled + - -Djavascript=disabled + - -Drubberband=disabled + - -Dvapoursynth=disabled + - -Dbuild-date=false + sources: + - type: archive + url: https://github.com/mpv-player/mpv/archive/refs/tags/v0.38.0.tar.gz + # sha256 generieren: sha256sum mpv-0.38.0.tar.gz + # oder: curl -L | sha256sum + sha256: FILL_IN_sha256sum_of_mpv_0.38.0_tarball + + # ───────────────────────────────────────────────────────────────────────────── + # 2) streamlink (Python) — liefert HLS-URLs aus Twitch-Streams + # Python 3 kommt aus dem freedesktop SDK. + # + # Vorbereitung (einmalig, in WSL2 Ubuntu): + # pip3 install flatpak-pip-generator + # python3 flatpak-pip-generator streamlink --output flatpak/python-streamlink-deps + # → erzeugt flatpak/python-streamlink-deps.json mit allen pinned Deps + sha256. + # Dann dieses Modul hier durch die generierte Datei ersetzen: + # - name: python3-streamlink-deps + # buildsystem: simple + # build-commands: [...] # generiert durch flatpak-pip-generator + # sources: [...] # alle .whl/.tar.gz mit echten sha256 + # + # Vereinfachte Variante (erfordert Netzwerk-Build — nur für lokale Tests): + # ───────────────────────────────────────────────────────────────────────────── + - name: python3-streamlink + buildsystem: simple + build-commands: + # --no-deps: Dependencies separat via flatpak-pip-generator auflösen + - pip3 install --prefix=/app --no-build-isolation --no-deps . + sources: + - type: archive + url: https://github.com/streamlink/streamlink/archive/refs/tags/6.11.0.tar.gz + # sha256 generieren: sha256sum streamlink-6.11.0.tar.gz + sha256: FILL_IN_sha256sum_of_streamlink_tarball + # ACHTUNG: Vor dem echten Build alle Python-Dependencies (requests, websocket-client, + # pycountry, pycryptodome, ...) mit flatpak-pip-generator als separate file-Sources + # einbinden. Sonst schlägt der offline Build fehl. + # Kurzfristig: 'build-network-access: true' setzen um online-pip zu nutzen (nur lokal!). + build-options: + build-args: + - --allow-network-access + + # ───────────────────────────────────────────────────────────────────────────── + # 3) Haupt-App + # Voraussetzung: npm install + @electron/rebuild + npm run build wurden + # AUSSERHALB (in WSL2) ausgeführt. Dieses Modul kopiert nur die Artefakte. + # ───────────────────────────────────────────────────────────────────────────── + - name: twitch4steamdeck + buildsystem: simple + build-commands: + # App-Artefakte installieren + - mkdir -p /app/lib/twitch4steamdeck + - cp -r out /app/lib/twitch4steamdeck/out + # node_modules wird für better-sqlite3 (native .node-Datei) zur Laufzeit benötigt. + # Nur die notwendigen Teile kopieren, um die Paketgröße zu begrenzen. + - mkdir -p /app/lib/twitch4steamdeck/node_modules + - cp -r node_modules/better-sqlite3 /app/lib/twitch4steamdeck/node_modules/ + - cp -r node_modules/bindings /app/lib/twitch4steamdeck/node_modules/ + - cp -r node_modules/file-uri-to-path /app/lib/twitch4steamdeck/node_modules/ + # Electron-Binary (Linux, via npm install in WSL2) + - cp -r node_modules/electron /app/lib/twitch4steamdeck/node_modules/ + # package.json für node require-Resolution + - cp package.json /app/lib/twitch4steamdeck/ + # Launcher-Skript + - install -Dm755 flatpak/twitch4steamdeck.sh /app/bin/twitch4steamdeck + # Icon (512×512 PNG, aus SVG konvertiert oder direkt abgelegt) + - | + if [ -f resources/icons/icon.png ]; then + install -Dm644 resources/icons/icon.png \ + /app/share/icons/hicolor/512x512/apps/tv.twitch4steamdeck.App.png + elif [ -f resources/icons/icon.svg ]; then + rsvg-convert -w 512 -h 512 resources/icons/icon.svg \ + -o /tmp/icon.png + install -Dm644 /tmp/icon.png \ + /app/share/icons/hicolor/512x512/apps/tv.twitch4steamdeck.App.png + fi + # .desktop-Eintrag + - install -Dm644 flatpak/tv.twitch4steamdeck.App.desktop \ + /app/share/applications/tv.twitch4steamdeck.App.desktop + sources: + # Gesamtes Projektverzeichnis (inkl. aus/ + node_modules/ aus WSL2-Prebuild) + - type: dir + path: .. diff --git a/flatpak/twitch4steamdeck.sh b/flatpak/twitch4steamdeck.sh new file mode 100644 index 0000000..ceb493b --- /dev/null +++ b/flatpak/twitch4steamdeck.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# Launcher für Twitch4SteamDeck im Flatpak. +# zypak-wrapper ersetzt den Chrome-Sandbox-Helper (setuid) durch eine +# Flatpak-kompatible Lösung — Pflicht für Electron in Flatpak-Sandboxes. +exec zypak-wrapper \ + /app/lib/twitch4steamdeck/node_modules/electron/dist/electron \ + /app/lib/twitch4steamdeck/out/main/index.js \ + "$@" diff --git a/resources/icons/icon.svg b/resources/icons/icon.svg new file mode 100644 index 0000000..0c6afe8 --- /dev/null +++ b/resources/icons/icon.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + T4SD + diff --git a/todo.md b/todo.md index fbf5a91..23969a4 100644 --- a/todo.md +++ b/todo.md @@ -120,11 +120,16 @@ - [x] **User:** End-to-End-Verifikation (Einstellungen + Badge funktionieren, Persistenz bestätigt; Flaggen erst auf Steam Deck testbar) ## Phase 6 — Flatpak-Packaging -- [ ] `flatpak/tv.twitch4steamdeck.App.yml` Manifest (Runtime, Module, Permissions) -- [ ] mpv + streamlink als Flatpak-Module bündeln -- [ ] Test-Build: `flatpak-builder --user --install build-dir flatpak/…yml` -- [ ] Auf Steam Deck (oder VM) installieren und Login + Live + VOD durchspielen -- [ ] Als Non-Steam-Game in Gaming Mode hinzufügen, dort testen +- [x] `flatpak/tv.twitch4steamdeck.App.yml` Manifest (Runtime, Module, Permissions) +- [x] `flatpak/twitch4steamdeck.sh` Launcher (zypak-wrapper) +- [x] `flatpak/tv.twitch4steamdeck.App.desktop` Desktop-Eintrag +- [x] `flatpak/build-flatpak.sh` Build-Skript für WSL2 (inkl. SHA256-Auflösung) +- [x] `resources/icons/icon.svg` App-Icon (Platzhalter) +- [x] mpv + streamlink als Flatpak-Module im Manifest definiert +- [ ] **User:** WSL2-Setup (flatpak, flatpak-builder, Runtimes) — einmalig +- [ ] **User:** `bash flatpak/build-flatpak.sh` in WSL2 ausführen +- [ ] **User:** Auf Steam Deck installieren und Login + Live + VOD durchspielen +- [ ] **User:** Als Non-Steam-Game in Gaming Mode hinzufügen, dort testen ## Post-MVP (bewusst nicht im ersten Release) - [ ] Chat (Live + VOD-Replay) inkl. BTTV/FFZ/7TV