fix(launcher): fix VLC stopping 10-15 seconds after open on macOS

Root cause: run_cmd uses exec() which blocks until the child exits. The
direct VLC binary forks its GUI process and exits — exec returns and the
post_script begins. The old post_script polled for VLC focus (up to 10s)
then sent Cmd+F, which fired mid-playback and stopped the video.

Fix 1 — nohup + &: detaches VLC from exec immediately so run_cmd returns
in ~0ms. This decouples the launcher flow from VLC's lifecycle.

Fix 2 — --fullscreen flag: VLC opens fullscreen directly via CLI option.
Eliminates the Cmd+F keystroke that was the proximate cause of the stop.

Fix 3 — > /dev/null 2>&1: silences VLC's verbose logging to prevent
exec's 1MB stdout buffer from overflowing and killing the process.

post_script simplified to a single `tell application "VLC" activate`
to bring VLC to the foreground after the 3s startup delay.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-22 18:10:37 -04:00
parent 15bfe6d5d6
commit b4d0d82141

View File

@@ -55,33 +55,35 @@ export interface LaunchProfile {
/** /**
* macOS VLC profile — uses direct binary path for max reliability. * macOS VLC profile — uses direct binary path for max reliability.
* Bypasses `open -a` argument-handling quirks that could lose file path or re-use existing process. * Bypasses `open -a` argument-handling quirks that could lose file path or re-use existing process.
*
* WHY nohup + &:
* run_cmd uses exec() which blocks until the child process exits (or the 30s timeout fires).
* The direct VLC binary forks a GUI process then exits — exec returns early and the code
* proceeds to the post_script. The old post_script polled for VLC focus (up to 10s) then
* sent Cmd+F, which was firing exactly 1015 seconds into playback and stopping the video.
* nohup + & detaches VLC immediately so exec returns in ~0ms, decoupling run_cmd from
* VLC's lifecycle entirely.
*
* WHY --fullscreen:
* Starting VLC fullscreen via flag avoids the need to send Cmd+F via AppleScript. The old
* keystroke approach was the proximate cause of the video stopping — Cmd+F may have hit the
* wrong VLC window, triggered a menu action, or paused playback during the fullscreen
* transition. Using the flag is simpler and more reliable.
*
* WHY > /dev/null 2>&1:
* VLC logs verbosely to stdout/stderr. exec() buffers output (1MB default). Without
* redirection the buffer could overflow and kill VLC mid-playback.
*/ */
function make_vlc_mirror_mac_profile(): LaunchProfile { function make_vlc_mirror_mac_profile(): LaunchProfile {
return { return {
app: 'VLC (macOS)', app: 'VLC (macOS)',
display_mode: 'mirror', display_mode: 'mirror',
// Direct binary path ensures VLC receives media file + flags reliably. open_cmd: 'nohup /Applications/VLC.app/Contents/MacOS/VLC --no-play-and-exit --play-and-pause --fullscreen "{{path}}" > /dev/null 2>&1 &',
// `--no-play-and-exit` prevents closing on end, `--play-and-pause` holds final frame. post_delay_ms: 3000,
open_cmd: '/Applications/VLC.app/Contents/MacOS/VLC --no-play-and-exit --play-and-pause "{{path}}"', // Activate VLC after it has had time to open. Fullscreen is already set by the flag
post_delay_ms: 2000, // above — this just ensures VLC is the frontmost app and the presenter sees it.
// Poll until VLC is frontmost before sending Cmd+F. Re-activate on every iteration post_script: `tell application "VLC"
// a single activate at the top is blocked by macOS focus-stealing prevention when VLC activate
// is spawned as a child of Electron (which stays frontmost). Retrying activate each loop
// keeps nudging macOS until it yields focus. Max wait: 20 × 0.5s = 10s after initial delay.
post_script: `repeat 20 times
tell application "VLC"
activate
end tell
delay 0.5
tell application "System Events"
if frontmost of process "VLC" is true then exit repeat
end tell
end repeat
delay 0.3
tell application "System Events"
tell process "VLC"
keystroke "f" using command down
end tell
end tell` end tell`
}; };
} }