Module audio_engine

Module audio_engine 

Source
Expand description

AudioEngine subprocess: the main app spawns the audio-engine JUCE binary (audio-engine/ CMake target), sends JSON lines on stdin, reads one JSON line per request. Keeps one child process alive (stdin loop in the AudioEngine) so stream state and IPC stay cheap. On app quit, shutdown_audio_engine_child runs from Tauri RunEvent::Exit / ExitRequested and from libc::atexit so the AudioEngine is always terminated with the host. AUDIO_HAXOR_PARENT_PID is set at spawn so the AudioEngine can exit if the host disappears without cleanup (e.g. macOS force quit / SIGKILL).

Shutdown must not take ENGINE_CHILD before killing the OS process. Another thread can hold that mutex while blocked on stdout.read_line(); waiting on the mutex first deadlocks quit (AudioEngine never receives kill). We keep the child PID in ENGINE_CHILD_PID and send SIGKILL / taskkill /F first, then clear the slot.

Structsยง

AudioEngineStub
Placeholder struct kept for serde stability / future prefs sync.
EngineChild ๐Ÿ”’

Constantsยง

EOF_WATCHDOG_POLL_MS ๐Ÿ”’
Only runs while the WebView poll is deferred โ€” ~1 Hz keeps idle CPU low; foreground-focused playback does not run this thread.

Staticsยง

ENGINE_CHILD ๐Ÿ”’
ENGINE_CHILD_PID ๐Ÿ”’
OS PID of the current AudioEngine (Child::id), or 0 if none. Used for kill-on-exit without waiting on ENGINE_CHILD (see module comment).
EOF_WATCHDOG_ACTIVE ๐Ÿ”’
Host-side playback_status poll for library playback EOF when the WebView defers its setInterval poll (isUiIdleHeavyCpu โ€” hidden, unfocused, minimized; see syncEnginePlaybackEofWatchdog in audio-engine.js). Throttled background timers can miss EOF for autoplay-next; this thread emits audio-engine-playback-eof on the same loaded && eof rising edge as the UI poll.

Functionsยง

audio_engine_child_pid
OS PID of the current AudioEngine subprocess (Child::id), or 0 if none has been spawned yet.
audio_engine_eof_watchdog_start
Start a background thread that polls playback_status every EOF_WATCHDOG_POLL_MS and emits audio-engine-playback-eof when loaded && eof transitions to true (same edge audio-engine.js uses for autoplay next). Idempotent โ€” if already running, returns immediately.
audio_engine_eof_watchdog_stop
Stop the host EOF poll (e.g. when library playback polling stops or the engine restarts).
binary_name ๐Ÿ”’
child_dead ๐Ÿ”’
clear_engine_pid ๐Ÿ”’
clear_engine_slot_after_os_kill ๐Ÿ”’
Reap Child handles after the OS process is gone. Never uses blocking Mutex::lock(). Returns true if the slot was cleared; false if we gave up waiting (~30s).
ensure_engine_child ๐Ÿ”’
find_audio_engine_under_target_ancestors ๐Ÿ”’
Walk parents of exe until audio-engine-artifacts/โ€ฆ or legacy target/โ€ฆ/<binary> exists (workspace root).
format_stderr_suffix ๐Ÿ”’
kill_pid_raw ๐Ÿ”’
Hard-kill by PID so quit works even when no Child handle is available.
log_ipc_failure ๐Ÿ”’
Log host-side IPC failure to app.log, appending recent AudioEngine stderr when available.
normalize_ipc_request_payload ๐Ÿ”’
Tauri may pass { "request": { "cmd": ... } } from invoke(..., { request: payload }); unwrap so stdin matches the audio-engine line protocol. If the top-level object already has cmd, it is left unchanged (even when request is also present).
read_engine_json_line ๐Ÿ”’
One response is one JSON object/array per line. A linked library may print warnings to stdout before the JSON line (e.g. Warning: thread locking is not implemented), which would break serde_json::from_str on the first read_line. Skip lines until one starts with { or [.
record_engine_pid ๐Ÿ”’
resolve_audio_engine_binary
Resolve path to the audio-engine executable.
restart_audio_engine_child
Drop the long-lived audio-engine child so the next IPC spawns a fresh process. Use after a crash or when the AudioEngine stops responding.
shutdown_audio_engine_child
Kill the JUCE AudioEngine when the host app exits. Idempotent (safe if no child was spawned).
spawn_audio_engine_request
Run one request against the audio-engine subprocess (stdin / stdout JSON lines).
spawn_audio_engine_request_at ๐Ÿ”’
spawn_engine_child ๐Ÿ”’
take_and_reap_engine_child ๐Ÿ”’
Drop the in-memory slot after the OS process is dead or being replaced. Caller must have cleared or updated ENGINE_CHILD_PID appropriately.