From 40787e8b714df20fe6b99b1b7c25c0989d570f2b Mon Sep 17 00:00:00 2001 From: sudacode Date: Sat, 28 Feb 2026 02:19:25 -0800 Subject: [PATCH] fix(plugin): gate auto-start overlay by matching mpv IPC socket --- docs/mpv-plugin.md | 6 ++++-- plugin/subminer.conf | 2 ++ plugin/subminer/lifecycle.lua | 15 ++++++++++++++- plugin/subminer/process.lua | 24 +++++++++++++++++++++++ scripts/test-plugin-start-gate.lua | 31 ++++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/docs/mpv-plugin.md b/docs/mpv-plugin.md index 83f6e47..38ef8c1 100644 --- a/docs/mpv-plugin.md +++ b/docs/mpv-plugin.md @@ -77,9 +77,11 @@ texthooker_port=5174 backend=auto # Start the overlay automatically when a file is loaded. +# Runs only when mpv input-ipc-server matches socket_path. auto_start=no # Show the visible overlay on auto-start. +# Runs only when mpv input-ipc-server matches socket_path. auto_start_visible_overlay=no # Show OSD messages for overlay status changes. @@ -121,8 +123,8 @@ aniskip_button_duration=3 | `texthooker_enabled` | `yes` | `yes` / `no` | Enable texthooker server | | `texthooker_port` | `5174` | 1–65535 | Texthooker server port | | `backend` | `auto` | `auto`, `hyprland`, `sway`, `x11`, `macos` | Window manager backend | -| `auto_start` | `no` | `yes` / `no` | Auto-start overlay on file load | -| `auto_start_visible_overlay` | `no` | `yes` / `no` | Show visible layer on auto-start | +| `auto_start` | `no` | `yes` / `no` | Auto-start overlay on file load when mpv socket matches `socket_path` | +| `auto_start_visible_overlay` | `no` | `yes` / `no` | Show visible layer on auto-start when mpv socket matches `socket_path` | | `osd_messages` | `yes` | `yes` / `no` | Show OSD status messages | | `log_level` | `info` | `debug`, `info`, `warn`, `error` | Log verbosity | | `aniskip_enabled` | `yes` | `yes` / `no` | Enable AniSkip intro detection | diff --git a/plugin/subminer.conf b/plugin/subminer.conf index 6bea0da..c1adef8 100644 --- a/plugin/subminer.conf +++ b/plugin/subminer.conf @@ -21,9 +21,11 @@ texthooker_port=5174 backend=auto # Automatically start overlay when a file is loaded +# Runs only when mpv input-ipc-server matches socket_path. auto_start=yes # Automatically show visible overlay when overlay starts +# Runs only when mpv input-ipc-server matches socket_path. auto_start_visible_overlay=yes # Show OSD messages for overlay status diff --git a/plugin/subminer/lifecycle.lua b/plugin/subminer/lifecycle.lua index a691ac0..14b3476 100644 --- a/plugin/subminer/lifecycle.lua +++ b/plugin/subminer/lifecycle.lua @@ -34,7 +34,20 @@ function M.create(ctx) local should_auto_start = resolve_auto_start_enabled() if should_auto_start then - process.start_overlay() + if not process.has_matching_mpv_ipc_socket(opts.socket_path) then + subminer_log( + "info", + "lifecycle", + "Skipping auto-start: input-ipc-server does not match configured socket_path" + ) + schedule_aniskip_fetch("file-loaded", 0) + return + end + + process.start_overlay({ + auto_start_trigger = true, + socket_path = opts.socket_path, + }) -- Give the overlay process a moment to initialize before querying AniSkip. schedule_aniskip_fetch("overlay-start", 0.8) return diff --git a/plugin/subminer/process.lua b/plugin/subminer/process.lua index 1db2ebd..9994f2e 100644 --- a/plugin/subminer/process.lua +++ b/plugin/subminer/process.lua @@ -22,6 +22,26 @@ function M.create(ctx) return options_helper.coerce_bool(raw_visible_overlay, false) end + local function normalize_socket_path(path) + if type(path) ~= "string" then + return nil + end + local trimmed = path:match("^%s*(.-)%s*$") + if trimmed == "" then + return nil + end + return trimmed + end + + local function has_matching_mpv_ipc_socket(target_socket_path) + local expected_socket = normalize_socket_path(target_socket_path or opts.socket_path) + local active_socket = normalize_socket_path(mp.get_property("input-ipc-server")) + if expected_socket == nil or active_socket == nil then + return false + end + return expected_socket == active_socket + end + local function resolve_backend(override_backend) local selected = override_backend if selected == nil or selected == "" then @@ -56,6 +76,9 @@ function M.create(ctx) table.insert(args, socket_path) local should_show_visible = resolve_visible_overlay_startup() + if should_show_visible and overrides.auto_start_trigger == true then + should_show_visible = has_matching_mpv_ipc_socket(socket_path) + end if should_show_visible then table.insert(args, "--show-visible-overlay") else @@ -349,6 +372,7 @@ function M.create(ctx) return { build_command_args = build_command_args, + has_matching_mpv_ipc_socket = has_matching_mpv_ipc_socket, run_control_command_async = run_control_command_async, parse_start_script_message_overrides = parse_start_script_message_overrides, ensure_texthooker_running = ensure_texthooker_running, diff --git a/scripts/test-plugin-start-gate.lua b/scripts/test-plugin-start-gate.lua index 9fcce30..9d8bd31 100644 --- a/scripts/test-plugin-start-gate.lua +++ b/scripts/test-plugin-start-gate.lua @@ -17,6 +17,9 @@ local function run_plugin_scenario(config) if name == "platform" then return config.platform or "linux" end + if name == "input-ipc-server" then + return config.input_ipc_server or "" + end if name == "filename/no-ext" then return config.filename_no_ext or "" end @@ -370,7 +373,9 @@ do binary_path = binary_path, auto_start = "yes", auto_start_visible_overlay = "yes", + socket_path = "/tmp/subminer-socket", }, + input_ipc_server = "/tmp/subminer-socket", media_title = "Random Movie", files = { [binary_path] = true, @@ -397,7 +402,9 @@ do binary_path = binary_path, auto_start = "yes", auto_start_visible_overlay = "no", + socket_path = "/tmp/subminer-socket", }, + input_ipc_server = "/tmp/subminer-socket", media_title = "Random Movie", files = { [binary_path] = true, @@ -417,4 +424,28 @@ do ) end +do + local recorded, err = run_plugin_scenario({ + process_list = "", + option_overrides = { + binary_path = binary_path, + auto_start = "yes", + auto_start_visible_overlay = "yes", + socket_path = "/tmp/subminer-socket", + }, + input_ipc_server = "/tmp/other.sock", + media_title = "Random Movie", + files = { + [binary_path] = true, + }, + }) + assert_true(recorded ~= nil, "plugin failed to load for mismatched socket auto-start scenario: " .. tostring(err)) + fire_event(recorded, "file-loaded") + local start_call = find_start_call(recorded.async_calls) + assert_true( + start_call == nil, + "auto-start should be skipped when mpv input-ipc-server does not match configured socket_path" + ) +end + print("plugin start gate regression tests: OK")