mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-01 18:22:41 -08:00
Overlay 2.0 (#12)
This commit is contained in:
@@ -28,6 +28,8 @@ export const state = {
|
||||
};
|
||||
|
||||
const DETACHED_IDLE_MPV_PID_FILE = path.join(os.tmpdir(), 'subminer-idle-mpv.pid');
|
||||
const OVERLAY_START_SOCKET_READY_TIMEOUT_MS = 900;
|
||||
const OVERLAY_START_COMMAND_SETTLE_TIMEOUT_MS = 700;
|
||||
|
||||
function readTrackedDetachedMpvPid(): number | null {
|
||||
try {
|
||||
@@ -424,6 +426,7 @@ export function startMpv(
|
||||
socketPath: string,
|
||||
appPath: string,
|
||||
preloadedSubtitles?: { primaryPath?: string; secondaryPath?: string },
|
||||
options?: { startPaused?: boolean },
|
||||
): void {
|
||||
if (targetKind === 'file' && (!fs.existsSync(target) || !fs.statSync(target).isFile())) {
|
||||
fail(`Video file not found: ${target}`);
|
||||
@@ -473,8 +476,10 @@ export function startMpv(
|
||||
if (preloadedSubtitles?.secondaryPath) {
|
||||
mpvArgs.push(`--sub-file=${preloadedSubtitles.secondaryPath}`);
|
||||
}
|
||||
const aniSkipMetadata =
|
||||
targetKind === 'file' ? inferAniSkipMetadataForFile(target) : null;
|
||||
if (options?.startPaused) {
|
||||
mpvArgs.push('--pause=yes');
|
||||
}
|
||||
const aniSkipMetadata = targetKind === 'file' ? inferAniSkipMetadataForFile(target) : null;
|
||||
const scriptOpts = buildSubminerScriptOpts(appPath, socketPath, aniSkipMetadata);
|
||||
if (aniSkipMetadata) {
|
||||
log(
|
||||
@@ -498,7 +503,47 @@ export function startMpv(
|
||||
state.mpvProc = spawn('mpv', mpvArgs, { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
export function startOverlay(appPath: string, args: Args, socketPath: string): Promise<void> {
|
||||
async function waitForOverlayStartCommandSettled(
|
||||
proc: ReturnType<typeof spawn>,
|
||||
logLevel: LogLevel,
|
||||
timeoutMs: number,
|
||||
): Promise<void> {
|
||||
await new Promise<void>((resolve) => {
|
||||
let settled = false;
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
const finish = () => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
if (timer) clearTimeout(timer);
|
||||
proc.off('exit', onExit);
|
||||
proc.off('error', onError);
|
||||
resolve();
|
||||
};
|
||||
|
||||
const onExit = (code: number | null) => {
|
||||
if (typeof code === 'number' && code !== 0) {
|
||||
log('warn', logLevel, `Overlay start command exited with status ${code}`);
|
||||
}
|
||||
finish();
|
||||
};
|
||||
|
||||
const onError = (error: Error) => {
|
||||
log('warn', logLevel, `Overlay start command failed: ${error.message}`);
|
||||
finish();
|
||||
};
|
||||
|
||||
proc.once('exit', onExit);
|
||||
proc.once('error', onError);
|
||||
timer = setTimeout(finish, timeoutMs);
|
||||
|
||||
if (proc.exitCode !== null && proc.exitCode !== undefined) {
|
||||
onExit(proc.exitCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function startOverlay(appPath: string, args: Args, socketPath: string): Promise<void> {
|
||||
const backend = detectBackend(args.backend);
|
||||
log('info', args.logLevel, `Starting SubMiner overlay (backend: ${backend})...`);
|
||||
|
||||
@@ -512,9 +557,22 @@ export function startOverlay(appPath: string, args: Args, socketPath: string): P
|
||||
});
|
||||
state.overlayManagedByLauncher = true;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, 2000);
|
||||
});
|
||||
const [socketReady] = await Promise.all([
|
||||
waitForUnixSocketReady(socketPath, OVERLAY_START_SOCKET_READY_TIMEOUT_MS),
|
||||
waitForOverlayStartCommandSettled(
|
||||
state.overlayProc,
|
||||
args.logLevel,
|
||||
OVERLAY_START_COMMAND_SETTLE_TIMEOUT_MS,
|
||||
),
|
||||
]);
|
||||
|
||||
if (!socketReady) {
|
||||
log(
|
||||
'debug',
|
||||
args.logLevel,
|
||||
'Overlay start continuing before mpv socket readiness was confirmed',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function launchTexthookerOnly(appPath: string, args: Args): never {
|
||||
|
||||
Reference in New Issue
Block a user