diff --git a/MPV/LUA/main.lua b/MPV/LUA/main.lua index 92513dc..793fe97 100644 --- a/MPV/LUA/main.lua +++ b/MPV/LUA/main.lua @@ -2831,41 +2831,82 @@ mp.register_script_message('medios-load-url-event', function(json) close_menu() end) end) -end) -- Menu integration with UOSC function M.show_menu() - _lua_log('M.show_menu called') + _lua_log('[MENU] M.show_menu called') + + -- Build menu items local items = { + { title = "Load URL", value = {"script-message-to", mp.get_script_name(), "medios-load-url"} }, { title = "Get Metadata", value = "script-binding medios-info", hint = "Ctrl+i" }, { title = "Delete File", value = "script-binding medios-delete", hint = "Ctrl+Del" }, - { title = "Load URL", value = {"script-message-to", mp.get_script_name(), "medios-load-url"} }, - { title = "Cmd", value = {"script-message-to", mp.get_script_name(), "medios-open-cmd"}, hint = "Run quick commands (screenshot, trim, etc)" }, + { title = "Cmd", value = {"script-message-to", mp.get_script_name(), "medios-open-cmd"}, hint = "screenshot/trim/etc" }, { title = "Download", value = {"script-message-to", mp.get_script_name(), "medios-download-current"} }, { title = "Change Format", value = {"script-message-to", mp.get_script_name(), "medios-change-format-current"} }, } - -- Only show "Start Helper" if helper is not running (conditional menu item) + -- Conditionally add "Start Helper" if not running if not _is_pipeline_helper_ready() then - table.insert(items, { title = "Start Helper", hint = "(for pipeline actions)", value = {"script-message-to", mp.get_script_name(), "medios-start-helper"} }) + table.insert(items, { title = "Start Helper", hint = "(pipeline actions)", value = {"script-message-to", mp.get_script_name(), "medios-start-helper"} }) end + _lua_log('[MENU] Built ' .. #items .. ' menu items') + + -- Check UOSC availability + local uosc_ready = ensure_uosc_loaded() + _lua_log('[MENU] ensure_uosc_loaded returned: ' .. tostring(uosc_ready)) + + if not uosc_ready then + _lua_log('[MENU] ERROR: uosc not available; menu cannot open') + mp.osd_message('Menu unavailable (uosc not loaded)', 3) + return + end + + -- Format menu for UOSC local menu_data = { title = "Medios Macina", items = items, } local json = utils.format_json(menu_data) - if ensure_uosc_loaded() then + _lua_log('[MENU] Sending menu JSON to uosc: ' .. string.sub(json, 1, 200) .. '...') + + -- Try to open menu via uosc script message + -- Note: UOSC expects JSON data as a string parameter + local ok, err = pcall(function() + -- Method 1: Try commandv with individual arguments mp.commandv('script-message-to', 'uosc', 'open-menu', json) + end) + + if not ok then + _lua_log('[MENU] Method 1 failed: ' .. tostring(err)) + -- Method 2: Try command with full string + local cmd = 'script-message-to uosc open-menu ' .. json + local ok2, err2 = pcall(function() + mp.command(cmd) + end) + if not ok2 then + _lua_log('[MENU] Method 2 failed: ' .. tostring(err2)) + mp.osd_message('Menu error', 3) + else + _lua_log('[MENU] Menu command sent via method 2') + end else - _lua_log('menu: uosc not available; cannot open-menu') + _lua_log('[MENU] Menu command sent successfully') end end --- Keybindings -mp.add_key_binding("m", "medios-menu", M.show_menu) -mp.add_key_binding("mbtn_right", "medios-menu-right-click", M.show_menu) +-- Keybindings with logging wrappers +mp.add_key_binding("m", "medios-menu", function() + _lua_log('[KEY] mbtn m pressed') + M.show_menu() +end) + +mp.add_key_binding("mbtn_right", "medios-menu-right-click", function() + _lua_log('[KEY] mbtn_right pressed (right-click)') + M.show_menu() +end) mp.add_key_binding("ctrl+i", "medios-info", M.get_file_info) mp.add_key_binding("ctrl+del", "medios-delete", M.delete_current_file) diff --git a/MPV/lyric.py b/MPV/lyric.py index 05cba27..650b5db 100644 --- a/MPV/lyric.py +++ b/MPV/lyric.py @@ -177,10 +177,15 @@ def _ipc_get_property( *, raise_on_disconnect: bool = False, ) -> object: - resp = client.send_command({ - "command": ["get_property", - name] - }) + try: + resp = client.send_command({ + "command": ["get_property", + name] + }) + except Exception as exc: + if raise_on_disconnect: + raise ConnectionError(f"Lost mpv IPC connection: {exc}") from exc + return default if resp is None: if raise_on_disconnect: raise ConnectionError("Lost mpv IPC connection") diff --git a/MPV/mpv_ipc.py b/MPV/mpv_ipc.py index 0c107c7..39271ae 100644 --- a/MPV/mpv_ipc.py +++ b/MPV/mpv_ipc.py @@ -870,13 +870,35 @@ class MPVIPCClient: if not self.connect(): raise MPVIPCError("Not connected") - if self.is_windows: - pipe = cast(BinaryIO, self.sock) - pipe.write(payload.encode("utf-8")) - pipe.flush() - else: - sock_obj = cast(socket.socket, self.sock) - sock_obj.sendall(payload.encode("utf-8")) + try: + if self.is_windows: + pipe = cast(BinaryIO, self.sock) + pipe.write(payload.encode("utf-8")) + pipe.flush() + else: + sock_obj = cast(socket.socket, self.sock) + sock_obj.sendall(payload.encode("utf-8")) + except (OSError, IOError, BrokenPipeError) as exc: + # Pipe became invalid (disconnected, corrupted, etc.). + # Disconnect and attempt one reconnection. + if not self.silent: + debug(f"Pipe write failed: {exc}; attempting reconnect") + self.disconnect() + if self.connect(): + # Retry once after reconnect + try: + if self.is_windows: + pipe = cast(BinaryIO, self.sock) + pipe.write(payload.encode("utf-8")) + pipe.flush() + else: + sock_obj = cast(socket.socket, self.sock) + sock_obj.sendall(payload.encode("utf-8")) + except (OSError, IOError, BrokenPipeError) as retry_exc: + self.disconnect() + raise MPVIPCError(f"Pipe write failed after reconnect: {retry_exc}") from retry_exc + else: + raise MPVIPCError("Failed to reconnect after pipe write error") from exc def _readline(self, *, timeout: Optional[float] = None) -> Optional[bytes]: if not self.sock: @@ -890,7 +912,11 @@ class MPVIPCClient: try: pipe = cast(BinaryIO, self.sock) return pipe.readline() - except (OSError, IOError): + except (OSError, IOError, BrokenPipeError) as exc: + # Pipe error; try to reconnect once + if not self.silent: + debug(f"Pipe readline failed: {exc}") + self.disconnect() return None # Unix: buffer until newline. diff --git a/MPV/pipeline_helper.py b/MPV/pipeline_helper.py index 239a042..154cc30 100644 --- a/MPV/pipeline_helper.py +++ b/MPV/pipeline_helper.py @@ -577,6 +577,16 @@ def _append_helper_log(text: str) -> None: print(f"[mpv-helper] {payload}", file=sys.stderr) +def _helper_log_path() -> str: + try: + log_dir = _repo_root() / "Log" + log_dir.mkdir(parents=True, exist_ok=True) + return str((log_dir / "medeia-mpv-helper.log").resolve()) + except Exception: + tmp = tempfile.gettempdir() + return str((Path(tmp) / "medeia-mpv-helper.log").resolve()) + + def _acquire_ipc_lock(ipc_path: str) -> Optional[Any]: """Best-effort singleton lock per IPC path. @@ -902,8 +912,6 @@ def main(argv: Optional[list[str]] = None) -> int: # Also publish config temp directory if available try: - from SYS.config import load_config - cfg = load_config() temp_dir = cfg.get("temp", "").strip() or os.getenv("TEMP") or "/tmp" if temp_dir: diff --git a/MPV/portable_config/input.conf b/MPV/portable_config/input.conf new file mode 100644 index 0000000..ce46089 --- /dev/null +++ b/MPV/portable_config/input.conf @@ -0,0 +1,18 @@ +# Custom input bindings for Medios-Macina +# This file overrides MPV's default input bindings to ensure our script bindings work. + +# Override MPV's default right-click behavior (which toggles pause) +# and route it to our custom menu handler instead. +# Use script-message to directly call the Lua function +mbtn_right script-message medios-menu-trigger + +# Menu toggle (middle-click alternative if needed) +m script-message medios-menu-trigger + +# Standard info/delete shortcuts +ctrl+i script-message medios-info-trigger +ctrl+Del script-message medios-delete-trigger + +# Lyrics +l script-message medeia-lyric-toggle-trigger +L script-message medeia-lyric-toggle-shift-trigger diff --git a/MPV/portable_config/mpv.conf b/MPV/portable_config/mpv.conf index 39e96b3..839af29 100644 --- a/MPV/portable_config/mpv.conf +++ b/MPV/portable_config/mpv.conf @@ -13,7 +13,7 @@ ontop=yes autofit=45% # Avoid showing embedded cover art for audio-only files if uosc isn't working, # but we keep it enabled for now to ensure a window exists. -audio-display=yes +audio-display=no keepaspect=no video-unscaled=no cursor-autohide=1000