audio: tag the fourth playback path, rodio's ClipPlayer

ClipPlayer opens a rodio default sink, which on Linux reaches the graph
through PipeWire's ALSA plugin. It was untagged through all of phase 1,
and it is a real echo path: B broadcasts music, A tunes in, A shares
their desktop, B hears their own track played back at them. Confirmed
live as `alsa_playback.peerspeak-...` with no ownership properties.

rodio exposes no way to set PipeWire node properties, so the carrier is
PIPEWIRE_ALSA, set once at the top of main while still single-threaded.

Measured, with PIPEWIRE_PROPS and PULSE_PROP unset, to establish that
setting it process-wide is safe:
  - aplay (ALSA plugin)   -> both carriers land. Confirms the mechanism.
  - pw-play (native)      -> untouched. Our own call-playback and capture
                             streams are native, so they keep their own
                             explicit tagging and are unaffected.
  - arecord (ALSA capture)-> IS tagged, on a Stream/Input/Audio. Not
                             surgical in the role dimension; harmless only
                             because R10-1 honours the carriers on
                             producers alone. This is why R10-1 lands first.

Local playlist tracks are tagged too, not just inbound peer audio. A
local track is already broadcast to peers over the call on the same
keypress, so sharing it again through the screen share would send the far
end two copies at differing latency. That is a defect, not a feature.

Codex phase-1 review F1. Round 10, R10-2.

New live exit-gate row drives the real ClipPlayer; mutation-verified
(drop the tag -> no node within 5s). The wiring guard is mutation-
verified too, and its first version was WRONG: it searched raw source and
passed against a main with the call deleted, because the comment above it
named the function. It strips comments now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 20:52:22 -04:00
co-authored by Claude Opus 5
parent 503f78153b
commit b5569fe2c6
3 changed files with 212 additions and 0 deletions
+16
View File
@@ -3,6 +3,22 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
// Tag the audio we play through ALSA (rodio's `ClipPlayer`: chat clips,
// peer music, local playlist tracks) so the screen-share exclusion engine
// can recognise it as ours and refuse to fan it back to the far end.
//
// First statement in the program, and that is load-bearing: this sets an
// environment variable, which is only sound while the process is still
// single-threaded, and PipeWire's ALSA plugin reads it when a stream is
// opened. See `audio::ownership::tag_this_process_alsa_audio`.
//
// SAFETY: nothing has been spawned yet, so no thread can be reading the
// environment concurrently.
#[cfg(target_os = "linux")]
unsafe {
peerspeak::audio::ownership::tag_this_process_alsa_audio()
};
if let Err(e) = peerspeak::app::run_gui() {
eprintln!("Error running GUI: {:?}", e);
}