Files
hms-mediaengine/launcher_core.py
T

101 lines
3.1 KiB
Python
Raw Normal View History

#!/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())