#!/usr/bin/env python3 """Gemeinsame Launcher-Logik fuer Windows-Starter und macOS. Unsichtbarer Ablauf: GStreamer vorhanden -> Engine im Hintergrund starten, auf die Web-UI warten, Browser oeffnen. Fehlt etwas -> grafischer Installer (installer_gui.py) oeffnen. """ from __future__ import annotations import json import subprocess import sys import time import urllib.request import webbrowser from pathlib import Path ROOT = Path(__file__).resolve().parent IS_WIN = sys.platform == "win32" def web_port() -> int: try: cfg = json.loads((ROOT / "config.json").read_text("utf-8")) return int(cfg.get("web", {}).get("port", 8080)) except Exception: # noqa: BLE001 return 8080 def gst_ok() -> bool: try: import gi # noqa: F401 gi.require_version("Gst", "1.0") from gi.repository import Gst Gst.init(None) return True except Exception: # noqa: BLE001 return False def _spawn(py: str, target: str, hidden: bool) -> None: if IS_WIN and hidden: subprocess.Popen( [py, str(ROOT / target)], cwd=str(ROOT), creationflags=0x08000000, # CREATE_NO_WINDOW stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) else: subprocess.Popen( [py, str(ROOT / target)], cwd=str(ROOT), stdout=open("/tmp/hms-mediaengine.log", "ab"), stderr=subprocess.STDOUT, start_new_session=not IS_WIN) def wait_health(port: int, timeout_s: float = 25.0) -> bool: deadline = time.monotonic() + timeout_s while time.monotonic() < deadline: try: with urllib.request.urlopen( f"http://localhost:{port}/api/health", timeout=1.5) as r: if json.loads(r.read().decode()).get("status") == "ok": return True except Exception: # noqa: BLE001 time.sleep(0.4) return False def launch() -> int: if gst_ok(): _spawn(sys.executable, "run.py", hidden=True) port = web_port() if wait_health(port): webbrowser.open(f"http://localhost:{port}") return 0 print("[Launcher] Engine antwortete nicht rechtzeitig – " "oeffne Installer.", file=sys.stderr) _spawn(sys.executable, "installer_gui.py", hidden=False) return 1 if __name__ == "__main__": sys.exit(launch())