#!/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" # Portable GStreamer laden (macOS: HMS-Portable-Install.command) _fw = ROOT / "runtime" / "GStreamer.framework" / "Versions" / "1.0" if _fw.is_dir(): import os as _os _lib = str(_fw / "lib") _os.environ["DYLD_LIBRARY_PATH"] = _lib + ":" + _os.environ.get("DYLD_LIBRARY_PATH", "") _gst = str(_fw / "lib" / "gstreamer-1.0") _os.environ["GST_PLUGIN_PATH"] = _gst _os.environ["GST_PLUGIN_SYSTEM_PATH_1_0"] = _gst _os.environ["GI_TYPELIB_PATH"] = (str(_fw / "lib" / "girepository-1.0") + ":" + _os.environ.get("GI_TYPELIB_PATH", "")) for _v in ("python3.12", "python3.13", "python3.11"): _sp = _fw / "lib" / _v / "site-packages" if (_sp / "gi").is_dir(): sys.path.insert(0, str(_sp)) break 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())