feat(linux): native PipeWire/PulseAudio system-audio capture - #708
Open
loicfavory wants to merge 2 commits into
Open
feat(linux): native PipeWire/PulseAudio system-audio capture#708loicfavory wants to merge 2 commits into
loicfavory wants to merge 2 commits into
Conversation
Replace the ALSA monitor-hint hack (manual ~/.asoundrc entry with a "monitor" substring) with a native libpulse client for system-audio capture on Linux. System Audio entries now list real PulseAudio/ PipeWire sinks directly, and streaming goes through a dedicated Pulse backend instead of cpal's ALSA host, which has no native Pulse/PipeWire support and required per-machine manual setup to work at all.
…tion alsa-lib's snd_device_name_hint/snd_config_update_r mutate a process-global config cache and are not safe to call concurrently. list_audio_devices() is polled every 2-5s by the device disconnect/ reconnect monitor for the whole duration of a recording, and can also be triggered from the UI or recording_manager at any time; an overlapping call from a second Tokio worker thread corrupts alsa-lib's heap state, which glibc eventually detects and aborts on. This is what produced the SIGABRT crashes ~30-35 minutes into a recording (two coredumps, both inside alsa-lib/malloc, both after that consistent delay). A process-wide mutex now serializes every ALSA-touching enumeration call.
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Replaces the ALSA monitor-hint hack for Linux "System Audio" capture with a native PipeWire/PulseAudio client, and fixes a heap-corruption crash in the ALSA device-enumeration path that this branch still shares with the rest of the app.
Why the hack needed replacing: cpal has no native PulseAudio/PipeWire backend on Linux — only ALSA/JACK. Capturing system audio therefore only worked if a monitor source was hand-registered as a named ALSA pseudo-device in
~/.asoundrc(type pulse, ahint { show on }block, and a device name containing"monitor"since that's whatconfigure_linux_audio()filtered on). On a stock install with no such setup, the System Audio list is simply empty. #701 covers this in detail, and #702 (still open) fixes a related bug in that same ALSA-hack path — this PR bypasses that path entirely for System Audio rather than patching it further.The crash:
list_audio_devices()is polled every 2-5s by the device disconnect/reconnect monitor for the whole duration of a recording, and can also be triggered from the UI orrecording_managerat any time. alsa-lib'ssnd_device_name_hint/snd_config_update_rmutate a process-global config cache and are not safe to call concurrently — an overlapping call from a second Tokio worker thread was corrupting alsa-lib's heap state, which glibc eventually detected and aborted on. This produced SIGABRT crashes ~30-35 minutes into a recording (reproduced with two coredumps, both inside alsa-lib/malloc, both after that consistent delay).Related Issue
Fixes #701, #273, #383 — all three are the same underlying problem (Linux "System Audio" not capturing anything, via the ALSA monitor-hint hack), reported independently over the past few months:
configure_linux_audio()finds nothing because ALSA doesn't even havepulse/jackPCMs configured (Unknown PCM pulsein the logs) — this PR no longer depends on ALSA seeing those PCMs at all, since it talks to Pulse/PipeWire directly.Also related:
Type of Change
Fix
audio/capture/pulse_linux.rs(#[cfg(target_os = "linux")]), structured as the Linux sibling of the existing macOScapture/core_audio.rs: talks to the PulseAudio client protocol directly vialibpulse-binding/libpulse-simple-binding, which PipeWire also implements (pipewire-pulse). Lists real sink names/descriptions and opens a record stream on a sink's monitor source — no~/.asoundrcneeded on either PipeWire or classic PulseAudio.audio/stream.rs: Linux System Audio always routes through this native Pulse backend now, wired in the same way as macOS's Core Audio branch.audio/devices/platform/linux.rsandaudio/devices/speakers.rs: System Audio device listing/default resolution now come from the real Pulse sink list instead of the ALSA"monitor"name heuristic.audio/devices/discovery.rsandaudio/devices/platform/linux.rs: added a process-wideMutex(ALSA_ENUM_LOCK) serializing every remaining ALSA-touching enumeration call, to stop the concurrent-access heap corruption described above.Testing
Manual testing performed
All tests pass
cargo checkandcargo build --releasesucceed (Arch Linux, PipeWire 1.6.8, KDE Plasma / Wayland).Fresh state, zero
~/.asoundrccustomization: Settings → System Audio lists real sink names out of the box.Recorded while playing audio; confirmed the output file's system-audio track is non-silent (
ffmpeg -i recording.mp4 -af volumedetect -f null -).Switched outputs (different sink) mid-session and saw the new device picked up without an app restart.
Ran a recording past the ~30-35 minute mark that reliably triggered the pre-fix SIGABRT — no crash with the
ALSA_ENUM_LOCKchange.No automated tests added for
pulse_linux.rsbeyond two#[ignore]d manual tests (test_list_sinks,test_capture_reads_nonzero_samples) — both require a live PipeWire/PulseAudio server and real audio playback, so they're not meant to run in CI.Documentation
No user-facing docs affected. Module-level comments in
pulse_linux.rsand onALSA_ENUM_LOCKexplain the approach and the concurrency hazard being fixed, respectively.Checklist
Additional Notes
Once this lands, the ALSA
"monitor"-hint enumeration path for System Audio on Linux is effectively dead code (Microphone capture still needs the rest ofconfigure_linux_audio()). Left it in place — removing it is a separate cleanup, not folded into this PR.