fd
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
This commit is contained in:
@@ -40,6 +40,21 @@ def _repo_root() -> Path:
|
||||
return Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def _runtime_config_root() -> Path:
|
||||
"""Best-effort config root for runtime execution.
|
||||
|
||||
MPV can spawn this helper from an installed location while setting `cwd` to
|
||||
the repo root (see MPV.mpv_ipc). Prefer `cwd` when it contains `config.conf`.
|
||||
"""
|
||||
try:
|
||||
cwd = Path.cwd().resolve()
|
||||
if (cwd / "config.conf").exists():
|
||||
return cwd
|
||||
except Exception:
|
||||
pass
|
||||
return _repo_root()
|
||||
|
||||
|
||||
# Make repo-local packages importable even when mpv starts us from another cwd.
|
||||
_ROOT = str(_repo_root())
|
||||
if _ROOT not in sys.path:
|
||||
@@ -223,19 +238,57 @@ def _run_op(op: str, data: Any) -> Dict[str, Any]:
|
||||
|
||||
# Provide store backend choices using the same source as CLI/Typer autocomplete.
|
||||
if op_name in {"store-choices", "store_choices", "get-store-choices", "get_store_choices"}:
|
||||
from CLI import MedeiaCLI # noqa: WPS433
|
||||
# IMPORTANT:
|
||||
# - Prefer runtime cwd for config discovery (mpv spawns us with cwd=repo_root).
|
||||
# - Avoid returning a cached empty result if config was loaded before it existed.
|
||||
try:
|
||||
from config import reload_config # noqa: WPS433
|
||||
from Store import Store # noqa: WPS433
|
||||
|
||||
backends = MedeiaCLI.get_store_choices()
|
||||
choices = sorted({str(n) for n in (backends or []) if str(n).strip()})
|
||||
config_root = _runtime_config_root()
|
||||
cfg = reload_config(config_dir=config_root)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"error": None,
|
||||
"table": None,
|
||||
"choices": choices,
|
||||
}
|
||||
storage = Store(config=cfg, suppress_debug=True)
|
||||
backends = storage.list_backends() or []
|
||||
choices = sorted({str(n) for n in backends if str(n).strip()})
|
||||
|
||||
# Fallback: if initialization gated all backends (e.g., missing deps or offline stores),
|
||||
# still return configured instance names so the UI can present something.
|
||||
if not choices:
|
||||
store_cfg = cfg.get("store") if isinstance(cfg, dict) else None
|
||||
if isinstance(store_cfg, dict):
|
||||
seen = set()
|
||||
for _, instances in store_cfg.items():
|
||||
if not isinstance(instances, dict):
|
||||
continue
|
||||
for instance_key, instance_cfg in instances.items():
|
||||
name = None
|
||||
if isinstance(instance_cfg, dict):
|
||||
name = instance_cfg.get("NAME") or instance_cfg.get("name")
|
||||
candidate = (str(name or instance_key or "").strip())
|
||||
if candidate:
|
||||
seen.add(candidate)
|
||||
choices = sorted(seen)
|
||||
|
||||
debug(f"[store-choices] config_dir={config_root} choices={len(choices)}")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"error": None,
|
||||
"table": None,
|
||||
"choices": choices,
|
||||
}
|
||||
except Exception as exc:
|
||||
return {
|
||||
"success": False,
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"error": f"store-choices failed: {type(exc).__name__}: {exc}",
|
||||
"table": None,
|
||||
"choices": [],
|
||||
}
|
||||
|
||||
# Provide yt-dlp format list for a URL (for MPV "Change format" menu).
|
||||
# Returns a ResultTable-like payload so the Lua UI can render without running cmdlets.
|
||||
@@ -580,6 +633,17 @@ def main(argv: Optional[list[str]] = None) -> int:
|
||||
|
||||
try:
|
||||
_append_helper_log(f"[helper] version={MEDEIA_MPV_HELPER_VERSION} started ipc={args.ipc}")
|
||||
try:
|
||||
_append_helper_log(f"[helper] file={Path(__file__).resolve()} cwd={Path.cwd().resolve()}")
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
runtime_root = _runtime_config_root()
|
||||
_append_helper_log(
|
||||
f"[helper] config_root={runtime_root} exists={bool((runtime_root / 'config.conf').exists())}"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
debug(f"[mpv-helper] logging to: {_helper_log_path()}")
|
||||
except Exception:
|
||||
pass
|
||||
@@ -679,13 +743,11 @@ def main(argv: Optional[list[str]] = None) -> int:
|
||||
if (now - last_ready_ts) < 0.75:
|
||||
return
|
||||
try:
|
||||
client.send_command_no_wait(["set_property", READY_PROP, str(int(now))])
|
||||
client.send_command_no_wait(["set_property_string", READY_PROP, str(int(now))])
|
||||
last_ready_ts = now
|
||||
except Exception:
|
||||
return
|
||||
|
||||
_touch_ready()
|
||||
|
||||
# Mirror mpv's own log messages into our helper log file so debugging does
|
||||
# not depend on the mpv on-screen console or mpv's log-file.
|
||||
try:
|
||||
@@ -715,6 +777,46 @@ def main(argv: Optional[list[str]] = None) -> int:
|
||||
except Exception:
|
||||
return 3
|
||||
|
||||
# Mark ready only after the observer is installed to avoid races where Lua
|
||||
# sends a request before we can receive property-change notifications.
|
||||
try:
|
||||
_touch_ready()
|
||||
_append_helper_log(f"[helper] ready heartbeat armed prop={READY_PROP}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Pre-compute store choices at startup and publish to a cached property so Lua
|
||||
# can read immediately without waiting for a request/response cycle (which may timeout).
|
||||
try:
|
||||
startup_choices_payload = _run_op("store-choices", None)
|
||||
startup_choices = startup_choices_payload.get("choices") if isinstance(startup_choices_payload, dict) else None
|
||||
if isinstance(startup_choices, list):
|
||||
preview = ", ".join(str(x) for x in startup_choices[:50])
|
||||
_append_helper_log(f"[helper] startup store-choices count={len(startup_choices)} items={preview}")
|
||||
|
||||
# Publish to a cached property for Lua to read without IPC request.
|
||||
try:
|
||||
cached_json = json.dumps({"success": True, "choices": startup_choices}, ensure_ascii=False)
|
||||
client.send_command_no_wait(["set_property_string", "user-data/medeia-store-choices-cached", cached_json])
|
||||
_append_helper_log(f"[helper] published store-choices to user-data/medeia-store-choices-cached")
|
||||
except Exception as exc:
|
||||
_append_helper_log(f"[helper] failed to publish store-choices: {type(exc).__name__}: {exc}")
|
||||
else:
|
||||
_append_helper_log("[helper] startup store-choices unavailable")
|
||||
except Exception as exc:
|
||||
_append_helper_log(f"[helper] startup store-choices failed: {type(exc).__name__}: {exc}")
|
||||
|
||||
# Also publish config temp directory if available
|
||||
try:
|
||||
from config import load_config
|
||||
cfg = load_config()
|
||||
temp_dir = cfg.get("temp", "").strip() or os.getenv("TEMP") or "/tmp"
|
||||
if temp_dir:
|
||||
client.send_command_no_wait(["set_property_string", "user-data/medeia-config-temp", temp_dir])
|
||||
_append_helper_log(f"[helper] published config temp to user-data/medeia-config-temp={temp_dir}")
|
||||
except Exception as exc:
|
||||
_append_helper_log(f"[helper] failed to publish config temp: {type(exc).__name__}: {exc}")
|
||||
|
||||
last_seen_id: Optional[str] = None
|
||||
|
||||
try:
|
||||
@@ -864,7 +966,7 @@ def main(argv: Optional[list[str]] = None) -> int:
|
||||
try:
|
||||
# IMPORTANT: don't wait for a response here; waiting would consume
|
||||
# async events and can drop/skip property-change notifications.
|
||||
client.send_command_no_wait(["set_property", RESPONSE_PROP, json.dumps(resp, ensure_ascii=False)])
|
||||
client.send_command_no_wait(["set_property_string", RESPONSE_PROP, json.dumps(resp, ensure_ascii=False)])
|
||||
except Exception:
|
||||
# If posting results fails, there's nothing more useful to do.
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user