import { fail, log } from '../log.js'; import { waitForUnixSocketReady, launchMpvIdleDetached, resolveLauncherRuntimePluginPath, } from '../mpv.js'; import type { LauncherCommandContext } from './context.js'; import { ensureLinuxRuntimePluginAvailable } from '../runtime-plugin-preflight.js'; interface MpvCommandDeps { ensureRuntimePluginReady(context: LauncherCommandContext): Promise; waitForUnixSocketReady(socketPath: string, timeoutMs: number): Promise; resolveRuntimePluginPath(context: LauncherCommandContext): string | null; launchMpvIdleDetached( socketPath: string, appPath: string, args: LauncherCommandContext['args'], runtimePluginPath?: string | null, runtimePluginConfig?: LauncherCommandContext['pluginRuntimeConfig'], ): Promise; } const defaultDeps: MpvCommandDeps = { ensureRuntimePluginReady: async (context) => { await ensureLinuxRuntimePluginAvailable({ appPath: context.appPath ?? undefined, scriptPath: context.scriptPath, logLevel: context.args.logLevel, }); }, waitForUnixSocketReady, resolveRuntimePluginPath: (context) => resolveLauncherRuntimePluginPath({ appPath: context.appPath ?? '', scriptPath: context.scriptPath, }), launchMpvIdleDetached, }; export async function runMpvPreAppCommand( context: LauncherCommandContext, deps: MpvCommandDeps = defaultDeps, ): Promise { const { args, mpvSocketPath, processAdapter } = context; if (args.mpvSocket) { processAdapter.writeStdout(`${mpvSocketPath}\n`); return true; } if (!args.mpvStatus) { return false; } const ready = await deps.waitForUnixSocketReady(mpvSocketPath, 500); log( ready ? 'info' : 'warn', args.logLevel, `[mpv] socket ${ready ? 'ready' : 'not ready'}: ${mpvSocketPath}`, ); processAdapter.exit(ready ? 0 : 1); return true; } export async function runMpvPostAppCommand( context: LauncherCommandContext, deps: MpvCommandDeps = defaultDeps, ): Promise { const { args, appPath, scriptPath, mpvSocketPath, pluginRuntimeConfig } = context; if (!args.mpvIdle) { return false; } if (!appPath) { fail('SubMiner app binary not found. Install to ~/.local/bin/ or set SUBMINER_APPIMAGE_PATH.'); } await deps.ensureRuntimePluginReady(context); await deps.launchMpvIdleDetached( mpvSocketPath, appPath, args, deps.resolveRuntimePluginPath(context), { ...pluginRuntimeConfig, backend: args.backend, texthookerEnabled: args.useTexthooker && pluginRuntimeConfig.texthookerEnabled, }, ); const ready = await deps.waitForUnixSocketReady(mpvSocketPath, 8000); if (!ready) { fail(`MPV IPC socket not ready after idle launch: ${mpvSocketPath}`); } log('info', args.logLevel, `[mpv] idle instance ready on ${mpvSocketPath}`); return true; }