This commit is contained in:
2026-01-03 03:37:48 -08:00
parent 6e9a0c28ff
commit 73f3005393
23 changed files with 1791 additions and 442 deletions

View File

@@ -201,6 +201,69 @@ def _send_ipc_command(command: Dict[str, Any], silent: bool = False) -> Optional
return None
def _extract_store_and_hash(item: Any) -> tuple[Optional[str], Optional[str]]:
store: Optional[str] = None
file_hash: Optional[str] = None
try:
if isinstance(item, dict):
store = item.get("store")
file_hash = item.get("hash") or item.get("file_hash")
else:
store = getattr(item, "store", None)
file_hash = getattr(item, "hash", None) or getattr(item, "file_hash", None)
except Exception:
store = None
file_hash = None
try:
store = str(store).strip() if store else None
except Exception:
store = None
try:
file_hash = str(file_hash).strip().lower() if file_hash else None
except Exception:
file_hash = None
if not file_hash:
try:
text = None
if isinstance(item, dict):
text = item.get("path") or item.get("url") or item.get("filename")
else:
text = getattr(item, "path", None) or getattr(item, "url", None)
if text:
m = re.search(r"[0-9a-f]{64}", str(text).lower())
if m:
file_hash = m.group(0)
except Exception:
pass
return store, file_hash
def _set_mpv_item_context(store: Optional[str], file_hash: Optional[str]) -> None:
# Properties consumed by MPV.lyric
try:
_send_ipc_command(
{
"command": ["set_property", "user-data/medeia-item-store", store or ""],
"request_id": 901,
},
silent=True,
)
_send_ipc_command(
{
"command": ["set_property", "user-data/medeia-item-hash", file_hash or ""],
"request_id": 902,
},
silent=True,
)
except Exception:
pass
def _get_playlist(silent: bool = False) -> Optional[List[Dict[str, Any]]]:
"""Get the current playlist from MPV. Returns None if MPV is not running."""
cmd = {
@@ -1014,6 +1077,15 @@ def _queue_items(
if clear_first and i == 0:
mode = "replace"
# If we're replacing, this will start playing immediately: set store/hash context
# so MPV.lyric can resolve the correct backend for notes.
if mode == "replace":
try:
s, h = _extract_store_and_hash(item)
_set_mpv_item_context(s, h)
except Exception:
pass
# If this is a Hydrus path, set header property and yt-dlp headers before loading.
# Use the real target (not the memory:// wrapper) for detection.
if effective_hydrus_header and _is_hydrus_path(str(target),
@@ -1209,7 +1281,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
result_obj = {
"path": filename,
"title": title,
"cmdlet_name": ".pipe",
"cmdlet_name": ".mpv",
"source": "pipe",
"__pipe_index": items.index(current_item),
}
@@ -1392,7 +1464,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
# We also set the source command to .pipe -load <ID> so it loads it
table.set_row_selection_args(i, ["-load", str(pl["id"])])
table.set_source_command(".pipe")
table.set_source_command(".mpv")
# Register results
ctx.set_last_result_table_overlay(
@@ -1528,6 +1600,13 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
if should_autoplay and after_len > 0:
idx_to_play = min(max(0, before_len), after_len - 1)
# Prefer the store/hash from the piped item when auto-playing.
try:
s, h = _extract_store_and_hash(items_to_add[0])
_set_mpv_item_context(s, h)
except Exception:
pass
play_resp = _send_ipc_command(
{
"command": ["playlist-play-index",
@@ -1657,6 +1736,11 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
return 1
else:
# Play item
try:
s, h = _extract_store_and_hash(item)
_set_mpv_item_context(s, h)
except Exception:
pass
if hydrus_header and _is_hydrus_path(filename, hydrus_url):
header_cmd = {
"command":
@@ -1805,7 +1889,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
table.set_row_selection_args(i, [str(i + 1)])
table.set_source_command(".pipe")
table.set_source_command(".mpv")
# Register PipeObjects (not raw MPV items) with pipeline context
ctx.set_last_result_table_overlay(table, pipe_objects)
@@ -1980,6 +2064,15 @@ def _start_mpv(
debug("Timed out waiting for MPV IPC connection", file=sys.stderr)
return
# Publish context early so the lyric helper can resolve notes on the first
# target change (the helper may start before playback begins).
try:
if items:
s, h = _extract_store_and_hash(items[0])
_set_mpv_item_context(s, h)
except Exception:
pass
# main.lua is loaded at startup via --script; don't reload it here.
# Ensure lyric overlay is running (auto-discovery handled by MPV.lyric).
@@ -2020,10 +2113,10 @@ def _start_mpv(
CMDLET = Cmdlet(
name=".pipe",
alias=["pipe", "playlist", "queue", "ls-pipe"],
name=".mpv",
alias=[".pipe", "pipe", "playlist", "queue", "ls-pipe"],
summary="Manage and play items in the MPV playlist via IPC",
usage=".pipe [index|url] [-current] [-clear] [-list] [-url URL] [-log] [-borderless]",
usage=".mpv [index|url] [-current] [-clear] [-list] [-url URL] [-log] [-borderless]",
arg=[
CmdletArg(
name="index",