From be140bc2868a56e886eb05ccba163b7400f54b65 Mon Sep 17 00:00:00 2001 From: Leo Vasanko Date: Fri, 22 May 2026 16:30:19 +0000 Subject: [PATCH] Simplify startup flow and defer media root activation --- mediahive/assets/mediahive-logo.png | Bin 52029 -> 0 bytes mediahive/server.py | 146 ++++++----- mediahive/winmain.py | 367 ++++------------------------ scripts/MediaHive.spec | 3 - 4 files changed, 127 insertions(+), 389 deletions(-) delete mode 100644 mediahive/assets/mediahive-logo.png diff --git a/mediahive/assets/mediahive-logo.png b/mediahive/assets/mediahive-logo.png deleted file mode 100644 index d7fdfa0afdf2fbf0e9ae7f3851eb2af3c85a8b99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52029 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
  • n-4WfyGD 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 Path: + if MEDIAROOT is None: + raise HTTPException(status_code=503, detail="Media root not initialized yet") + return MEDIAROOT + + async def _send_event(event: ScanEvent) -> None: """Push a scan event onto the queue (passed to hivescan as *send*).""" await _scan_events.put(event) @@ -135,42 +147,39 @@ async def _consume_scan_events() -> None: @asynccontextmanager async def lifespan(app: FastAPI): - global MEDIAROOT, store, _scanner_active, _consumer_task + global MEDIAROOT, store, _scanner_active, _consumer_task, _folder_switch_task - if not os.environ.get("MEDIAHIVE_PATH"): - raise RuntimeError("MEDIAHIVE_PATH environment variable must be set") - - MEDIAROOT = Path(os.environ["MEDIAHIVE_PATH"]) await frontend.load() - # Initialise the in-memory index store - snapshot_path = MEDIAROOT / ".mediahive" / "index.json" - store = IndexStore(snapshot_path, media_root=str(MEDIAROOT)) + # Bring up the API immediately with an empty in-memory store. + # Media-root initialization/scanner startup are deferred to a background task + # so macOS permission prompts cannot block server readiness. + store = IndexStore(_BOOTSTRAP_SNAPSHOT, media_root=None) await store.load_snapshot() + _scanner_active = False + logger.info( - "Index store ready: %d movies, %d series", - len(store.movies), - len(store.series), + "Server started without active media root; waiting for folder activation" ) - # Start the scanner subsystem - from mediahive.hivescan.scanner import ( - start as start_scanner, - ) - from mediahive.hivescan.scanner import ( - stop as stop_scanner, - ) - - _consumer_task = asyncio.create_task(_consume_scan_events()) - await start_scanner(_send_event) - _scanner_active = True - yield # Shutdown + if _folder_switch_task and not _folder_switch_task.done(): + _folder_switch_task.cancel() + try: + await _folder_switch_task + except asyncio.CancelledError: + pass + await stop_scanner() + _scanner_active = False if _consumer_task: _consumer_task.cancel() + try: + await _consumer_task + except asyncio.CancelledError: + pass await store.flush_snapshot() @@ -193,14 +202,11 @@ def normalize_path(url_path: str) -> Path: Returns: MEDIAROOT/.mediahive/Movies/... """ clean_path = url_path.lstrip("/") - return MEDIAROOT / clean_path + return _require_media_root() / clean_path def _load_resume_positions() -> dict[str, int]: - if MEDIAROOT is None: - return {} - - playback_state_path = MEDIAROOT / ".mediahive" / "playback-state.json" + playback_state_path = _require_media_root() / ".mediahive" / "playback-state.json" try: raw = json.loads(playback_state_path.read_text(encoding="utf-8")) except Exception: @@ -268,43 +274,50 @@ async def change_folder_endpoint(request: Request): async def _switch_folder(new_root: Path) -> None: - global MEDIAROOT, store, _consumer_task, _scan_events + global MEDIAROOT, store, _consumer_task, _scan_events, _scanner_active - try: - # Cancel scanner tasks immediately — no need to wait 30 s - await stop_scanner() + async with _folder_switch_lock: + try: + # Cancel scanner tasks immediately — no need to wait 30 s + await stop_scanner() + _scanner_active = False - # Tear down the old event consumer - if _consumer_task and not _consumer_task.done(): - _consumer_task.cancel() - try: - await _consumer_task - except asyncio.CancelledError: - pass + # Tear down the old event consumer + if _consumer_task and not _consumer_task.done(): + _consumer_task.cancel() + try: + await _consumer_task + except asyncio.CancelledError: + pass - # Flush the old index snapshot - if store: + # Flush the old index snapshot await store.flush_snapshot() - # Update env and module globals - os.environ["MEDIAHIVE_PATH"] = str(new_root) - MEDIAROOT = new_root + # Update env and module globals + os.environ["MEDIAHIVE_PATH"] = str(new_root) + MEDIAROOT = new_root - # Fresh event queue — discard any stale events from the old folder - _scan_events = asyncio.Queue() + # Fresh event queue — discard any stale events from the old folder + _scan_events = asyncio.Queue() - # Re-initialise the index store - snapshot_path = MEDIAROOT / ".mediahive" / "index.json" - store = IndexStore(snapshot_path, media_root=str(MEDIAROOT)) - await store.load_snapshot() + # Re-initialise the index store + snapshot_path = MEDIAROOT / ".mediahive" / "index.json" + store = IndexStore(snapshot_path, media_root=str(MEDIAROOT)) + await store.load_snapshot() + logger.info( + "Index store ready: %d movies, %d series", + len(store.movies), + len(store.series), + ) - # Restart consumer and scanner - _consumer_task = asyncio.create_task(_consume_scan_events()) - await start_scanner(_send_event) + # Restart consumer and scanner + _consumer_task = asyncio.create_task(_consume_scan_events()) + await start_scanner(_send_event) + _scanner_active = True - logger.info("Switched media folder to %s", MEDIAROOT) - except Exception: - logger.exception("Error switching media folder to %s", new_root) + logger.info("Switched media folder to %s", MEDIAROOT) + except Exception: + logger.exception("Error switching media folder to %s", new_root) @app.get("/api/index") @@ -377,7 +390,7 @@ async def play_media(request: Request): """ req = msgspec.json.decode(await request.body(), type=PlayMediaRequest) print(f"[play] Received path: {req.file_path}") - file_path = MEDIAROOT / req.file_path + file_path = _require_media_root() / req.file_path if not file_path.exists(): print(f"[play] File not found: {file_path}") @@ -400,7 +413,7 @@ async def open_folder(request: Request): """ req = msgspec.json.decode(await request.body(), type=OpenFolderRequest) print(f"[open-folder] Received path: {req.folder_path}") - target_path = MEDIAROOT / req.folder_path + target_path = _require_media_root() / req.folder_path if not target_path.exists(): print(f"[open-folder] Path not found: {target_path}") @@ -466,10 +479,11 @@ async def serve_media_file(file_path: str, request: Request): Serve a media file asynchronously. """ full_path = normalize_path(file_path) + media_root = _require_media_root() # Security: ensure path doesn't escape base try: - full_path.resolve().relative_to(MEDIAROOT.resolve()) + full_path.resolve().relative_to(media_root.resolve()) except ValueError: raise HTTPException(status_code=403, detail="Access denied") diff --git a/mediahive/winmain.py b/mediahive/winmain.py index 135ff0c..9383b10 100644 --- a/mediahive/winmain.py +++ b/mediahive/winmain.py @@ -5,7 +5,6 @@ Or from PyInstaller: MediaHive.exe [media_folder] """ import argparse -import base64 import ctypes import html import json @@ -19,7 +18,6 @@ import time import urllib.error import urllib.parse import urllib.request -from collections.abc import Callable from concurrent.futures import Future, ThreadPoolExecutor from pathlib import Path @@ -27,16 +25,15 @@ import msgspec.structs import uvicorn import webview -from mediahive.__main__ import resolve_media_root from mediahive.config import load_config, save_config logger = logging.getLogger("mediahive.winmain") BACKEND_HOST = "127.0.0.1" BACKEND_PORT = 8420 +HEALTH_TIMEOUT = 2 # seconds BACKEND_HEALTH_REQUEST_TIMEOUT = 2 # seconds BACKEND_HEALTH_POLL_SECONDS = 0.25 -STARTUP_LOG_TAIL_LINES = 120 MPC_BE_URL = "http://127.0.0.1:13579" GAMEPAD_REPEAT_SECONDS = 0.008 GAMEPAD_POLL_SECONDS = 0.008 @@ -632,194 +629,11 @@ _SETUP_HTML = """ """ -_STARTUP_HTML_TEMPLATE = """ -MediaHive -

    -
    - -
    -
    -
    Starting MediaHive
    -
    Waiting for startup logs...
    -
    - -
    -
    -
    - -""" - - class JsApi: """Python methods exposed to the frontend via window.pywebview.api.""" def __init__(self) -> None: self._window: webview.Window | None = None - self._startup_state: dict[str, object] | None = None - self._startup_state_lock: threading.Lock | None = None - self._startup_log_path: Path | None = None - self._request_quit_callback: Callable[[], None] | None = None def pick_folder(self) -> str | None: """Open a native OS folder picker and return the chosen path (or None).""" @@ -828,46 +642,6 @@ class JsApi: result = self._window.create_file_dialog(webview.FOLDER_DIALOG) return result[0] if result else None - def configure_startup_bridge( - self, - startup_state: dict[str, object], - startup_state_lock: threading.Lock, - startup_log_path: Path | None, - request_quit_callback: Callable[[], None], - ) -> None: - self._startup_state = startup_state - self._startup_state_lock = startup_state_lock - self._startup_log_path = startup_log_path - self._request_quit_callback = request_quit_callback - - def startup_status(self) -> dict[str, object]: - if self._startup_state is None or self._startup_state_lock is None: - return { - "ready": False, - "failed": False, - "message": "Initializing startup bridge...", - "backend_url": "", - } - with self._startup_state_lock: - return dict(self._startup_state) - - def startup_log_tail(self) -> str: - if self._startup_log_path is None: - return "Log file unavailable in development mode." - try: - lines = self._startup_log_path.read_text(encoding="utf-8").splitlines() - except Exception as exc: - return f"Could not read startup log: {exc}" - if not lines: - return "No startup log entries yet." - return "\n".join(lines[-STARTUP_LOG_TAIL_LINES:]) - - def quit_app(self) -> None: - if self._request_quit_callback is not None: - self._request_quit_callback() - if self._window is not None: - self._window.destroy() - def _prepend_meipass_to_path() -> None: """When frozen, ensure bundled binaries (ffmpeg) are found first on PATH.""" @@ -900,53 +674,6 @@ def _icon_path() -> str | None: return str(ico) if ico.exists() else None -def _runtime_package_base() -> Path: - """Return runtime package base for frozen and development layouts.""" - if getattr(sys, "frozen", False): - meipass = Path(sys._MEIPASS) # type: ignore[attr-defined] - packaged = meipass / "mediahive" - return packaged if packaged.exists() else meipass - return Path(__file__).parent - - -def _startup_logo_path() -> Path | None: - """Locate the startup logo asset for embedding in the splash page.""" - base = _runtime_package_base() - png = base / "assets" / "mediahive-logo.png" - if png.exists(): - return png - webp = base / "assets" / "mediahive.webp" - if webp.exists(): - return webp - ico = base / "assets" / "mediahive.ico" - if ico.exists(): - return ico - icns = base / "assets" / "mediahive.icns" - if icns.exists(): - return icns - return None - - -def _startup_html() -> str: - logo_uri = "" - logo_path = _startup_logo_path() - if logo_path is not None: - try: - data = logo_path.read_bytes() - ext = logo_path.suffix.lower() - mime = { - ".png": "image/png", - ".webp": "image/webp", - ".ico": "image/x-icon", - ".icns": "image/icns", - }.get(ext, "application/octet-stream") - encoded = base64.b64encode(data).decode("ascii") - logo_uri = f"data:{mime};base64,{encoded}" - except Exception: - logo_uri = "" - return _STARTUP_HTML_TEMPLATE.replace("__MEDIAHIVE_LOGO_URI__", logo_uri) - - def _webview_start_kwargs() -> dict[str, str]: """Return platform-specific pywebview startup kwargs.""" # On macOS, force Qt backend so pywebview uses Chromium/WebEngine instead of WKWebView. @@ -986,6 +713,27 @@ def _run_initial_setup() -> str | None: return chosen[0] if chosen else None +def _normalize_media_root_input(path: str) -> Path: + """Normalize configured media path without touching filesystem. + + This intentionally avoids exists()/is_dir()/resolve() checks so startup can + continue even if macOS shows a permission dialog for the selected folder. + """ + parts = Path(path).expanduser().parts + match parts: + case (*rest, ".mediahive", "index.json"): + ... + case (*rest, ".mediahive"): + ... + case rest: + ... + + base = Path(*rest) + if not base.is_absolute(): + base = Path.cwd() / base + return base + + def _supports_gamepad_remote() -> bool: return sys.platform == "win32" @@ -1010,9 +758,8 @@ def winmain() -> None: _prepend_meipass_to_path() # In a frozen (windowed) build there is no console — redirect output to a log file - startup_log_path: Path | None = None if getattr(sys, "frozen", False): - startup_log_path = _setup_logging() + _setup_logging() # Resolution order: CLI arg → MEDIAHIVE_PATH env → saved config → ask user folder = ( @@ -1026,7 +773,7 @@ def winmain() -> None: if not folder: return # user cancelled the folder picker - mediaroot = resolve_media_root(folder) + mediaroot = _normalize_media_root_input(folder) os.environ["MEDIAHIVE_PATH"] = mediaroot.as_posix() backend_port = _reserve_backend_port() @@ -1053,56 +800,29 @@ def winmain() -> None: ) backend_thread.start() - startup_state_lock = threading.Lock() - startup_state: dict[str, object] = { - "ready": False, - "failed": False, - "message": "Starting MediaHive", - "backend_url": backend_url, - } + def _activate_initial_folder() -> None: + body = json.dumps({"folder": mediaroot.as_posix()}).encode("utf-8") + req = urllib.request.Request( + url=f"{backend_url}/api/change-folder", + data=body, + method="POST", + headers={"Content-Type": "application/json"}, + ) + try: + with urllib.request.urlopen(req, timeout=10): + logger.info("Requested initial media folder activation") + except Exception as exc: + logger.warning("Initial media folder activation request failed: %s", exc) - def _request_quit() -> None: + if not _wait_for_backend(timeout=HEALTH_TIMEOUT): server.should_exit = True - - def _set_startup_state(**updates: object) -> None: - with startup_state_lock: - startup_state.update(updates) - - def _monitor_backend_ready() -> None: - _set_startup_state(message="Starting MediaHive") - while not server.should_exit: - if _wait_for_backend(timeout=5): - _set_startup_state( - ready=True, - failed=False, - message="Backend ready. Opening MediaHive...", - ) - return - if not backend_thread.is_alive(): - _set_startup_state( - ready=False, - failed=True, - message="Backend stopped unexpectedly. Check logs or quit.", - ) - return - - threading.Thread( - target=_monitor_backend_ready, - daemon=True, - name="mediahive-startup-monitor", - ).start() + raise RuntimeError(f"Backend did not become ready within {HEALTH_TIMEOUT}s") api = JsApi() - api.configure_startup_bridge( - startup_state=startup_state, - startup_state_lock=startup_state_lock, - startup_log_path=startup_log_path, - request_quit_callback=_request_quit, - ) logger.info("Configured pywebview backend: %s", _selected_webview_backend()) window = webview.create_window( title="MediaHive", - html=_startup_html(), + url=backend_url, fullscreen=True, js_api=api, ) @@ -1123,6 +843,13 @@ def winmain() -> None: if poll_thread is None and _supports_gamepad_remote(): poll_thread = _start_gamepad_remote(poll_stop, mediaroot) + # Trigger initial folder activation after main UI is shown. + threading.Thread( + target=_activate_initial_folder, + daemon=True, + name="mediahive-initial-folder-activation", + ).start() + webview.start(func=on_shown, icon=_icon_path(), **_webview_start_kwargs()) poll_stop.set() diff --git a/scripts/MediaHive.spec b/scripts/MediaHive.spec index d3d4807..925b3b1 100644 --- a/scripts/MediaHive.spec +++ b/scripts/MediaHive.spec @@ -17,7 +17,6 @@ block_cipher = None _pkg = Path(mediahive.server.__file__).parent _frontend_build = _pkg / "frontend-build" _logo_webp = _pkg / "assets" / "mediahive.webp" -_logo_png = _pkg / "assets" / "mediahive-logo.png" _icon_win = _pkg / "assets" / "mediahive.ico" _icon_mac = _pkg / "assets" / "mediahive.icns" _tools_dir = Path(SPECPATH).parent / "build" / "ffmpeg" @@ -39,8 +38,6 @@ if _icon_mac.exists(): _datas.append((str(_icon_mac), "mediahive/assets")) if _logo_webp.exists(): _datas.append((str(_logo_webp), "mediahive/assets")) -if _logo_png.exists(): - _datas.append((str(_logo_png), "mediahive/assets")) _hiddenimports = [ # uvicorn dynamic imports