Fix Windows mpv shortcut launch and subtitle dedupe

This commit is contained in:
2026-04-02 23:28:43 -07:00
parent 640c8acd7c
commit 85e3aa4c6b
15 changed files with 480 additions and 22 deletions

View File

@@ -41,21 +41,57 @@ test('resolveWindowsMpvPath falls back to where.exe output', () => {
});
test('buildWindowsMpvLaunchArgs uses explicit SubMiner defaults and targets', () => {
assert.deepEqual(buildWindowsMpvLaunchArgs(['C:\\a.mkv', 'C:\\b.mkv']), [
assert.deepEqual(
buildWindowsMpvLaunchArgs(
['C:\\a.mkv', 'C:\\b.mkv'],
[],
'C:\\SubMiner\\SubMiner.exe',
'C:\\Program Files\\SubMiner\\resources\\plugin\\subminer\\main.lua',
),
[
'--player-operation-mode=pseudo-gui',
'--force-window=immediate',
'--script=C:\\Program Files\\SubMiner\\resources\\plugin\\subminer\\main.lua',
'--input-ipc-server=\\\\.\\pipe\\subminer-socket',
'--alang=ja,jp,jpn,japanese,en,eng,english,enus,en-us',
'--slang=ja,jp,jpn,japanese,en,eng,english,enus,en-us',
'--sub-auto=fuzzy',
'--sub-file-paths=.;subs;subtitles',
'--sub-file-paths=subs;subtitles',
'--sid=auto',
'--secondary-sid=auto',
'--secondary-sub-visibility=no',
'--script-opts=subminer-binary_path=C:\\SubMiner\\SubMiner.exe,subminer-socket_path=\\\\.\\pipe\\subminer-socket',
'C:\\a.mkv',
'C:\\b.mkv',
]);
});
test('buildWindowsMpvLaunchArgs keeps shortcut-only launches in idle mode', () => {
assert.deepEqual(
buildWindowsMpvLaunchArgs(
[],
[],
'C:\\SubMiner\\SubMiner.exe',
'C:\\Program Files\\SubMiner\\resources\\plugin\\subminer\\main.lua',
),
[
'--player-operation-mode=pseudo-gui',
'--force-window=immediate',
'--idle=yes',
'--script=C:\\Program Files\\SubMiner\\resources\\plugin\\subminer\\main.lua',
'--input-ipc-server=\\\\.\\pipe\\subminer-socket',
'--alang=ja,jp,jpn,japanese,en,eng,english,enus,en-us',
'--slang=ja,jp,jpn,japanese,en,eng,english,enus,en-us',
'--sub-auto=fuzzy',
'--sub-file-paths=subs;subtitles',
'--sid=auto',
'--secondary-sid=auto',
'--secondary-sub-visibility=no',
'--script-opts=subminer-binary_path=C:\\SubMiner\\SubMiner.exe,subminer-socket_path=\\\\.\\pipe\\subminer-socket',
],
);
});
test('launchWindowsMpv reports missing mpv path', () => {
const errors: string[] = [];
const result = launchWindowsMpv(
@@ -82,13 +118,16 @@ test('launchWindowsMpv spawns detached mpv with targets', () => {
calls.push(args.join('|'));
},
}),
[],
'C:\\SubMiner\\SubMiner.exe',
'C:\\Program Files\\SubMiner\\resources\\plugin\\subminer\\main.lua',
);
assert.equal(result.ok, true);
assert.equal(result.mpvPath, 'C:\\mpv\\mpv.exe');
assert.deepEqual(calls, [
'C:\\mpv\\mpv.exe',
'--player-operation-mode=pseudo-gui|--input-ipc-server=\\\\.\\pipe\\subminer-socket|--alang=ja,jp,jpn,japanese,en,eng,english,enus,en-us|--slang=ja,jp,jpn,japanese,en,eng,english,enus,en-us|--sub-auto=fuzzy|--sub-file-paths=.;subs;subtitles|--sid=auto|--secondary-sid=auto|--secondary-sub-visibility=no|C:\\video.mkv',
'--player-operation-mode=pseudo-gui|--force-window=immediate|--script=C:\\Program Files\\SubMiner\\resources\\plugin\\subminer\\main.lua|--input-ipc-server=\\\\.\\pipe\\subminer-socket|--alang=ja,jp,jpn,japanese,en,eng,english,enus,en-us|--slang=ja,jp,jpn,japanese,en,eng,english,enus,en-us|--sub-auto=fuzzy|--sub-file-paths=subs;subtitles|--sid=auto|--secondary-sid=auto|--secondary-sub-visibility=no|--script-opts=subminer-binary_path=C:\\SubMiner\\SubMiner.exe,subminer-socket_path=\\\\.\\pipe\\subminer-socket|C:\\video.mkv',
]);
});

View File

@@ -33,17 +33,36 @@ export function resolveWindowsMpvPath(deps: WindowsMpvLaunchDeps): string {
return '';
}
export function buildWindowsMpvLaunchArgs(targets: string[], extraArgs: string[] = []): string[] {
export function buildWindowsMpvLaunchArgs(
targets: string[],
extraArgs: string[] = [],
binaryPath?: string,
pluginEntrypointPath?: string,
): string[] {
const launchIdle = targets.length === 0;
const scriptOpts =
typeof binaryPath === 'string' && binaryPath.trim().length > 0
? `--script-opts=subminer-binary_path=${binaryPath.trim().replace(/,/g, '\\,')},subminer-socket_path=\\\\.\\pipe\\subminer-socket`
: null;
const scriptEntrypoint =
typeof pluginEntrypointPath === 'string' && pluginEntrypointPath.trim().length > 0
? `--script=${pluginEntrypointPath.trim()}`
: null;
return [
'--player-operation-mode=pseudo-gui',
'--force-window=immediate',
...(launchIdle ? ['--idle=yes'] : []),
...(scriptEntrypoint ? [scriptEntrypoint] : []),
'--input-ipc-server=\\\\.\\pipe\\subminer-socket',
'--alang=ja,jp,jpn,japanese,en,eng,english,enus,en-us',
'--slang=ja,jp,jpn,japanese,en,eng,english,enus,en-us',
'--sub-auto=fuzzy',
'--sub-file-paths=.;subs;subtitles',
'--sub-file-paths=subs;subtitles',
'--sid=auto',
'--secondary-sid=auto',
'--secondary-sub-visibility=no',
...(scriptOpts ? [scriptOpts] : []),
...extraArgs,
...targets,
];
@@ -53,6 +72,8 @@ export function launchWindowsMpv(
targets: string[],
deps: WindowsMpvLaunchDeps,
extraArgs: string[] = [],
binaryPath?: string,
pluginEntrypointPath?: string,
): { ok: boolean; mpvPath: string } {
const mpvPath = resolveWindowsMpvPath(deps);
if (!mpvPath) {
@@ -64,7 +85,10 @@ export function launchWindowsMpv(
}
try {
deps.spawnDetached(mpvPath, buildWindowsMpvLaunchArgs(targets, extraArgs));
deps.spawnDetached(
mpvPath,
buildWindowsMpvLaunchArgs(targets, extraArgs, binaryPath, pluginEntrypointPath),
);
return { ok: true, mpvPath };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);