Skip to content

fix(live-input): warn when another process already publishes the live-input sink - #353

Merged
mgth merged 1 commit into
mainfrom
fix/duplicate-live-input-node-warning
Sep 2, 2026
Merged

fix(live-input): warn when another process already publishes the live-input sink#353
mgth merged 1 commit into
mainfrom
fix/duplicate-live-input-node-warning

Conversation

@mgth

@mgth mgth commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Problem

Two orender processes (one from another workflow, one launched by Studio) both published a PipeWire sink named omniphony (render.live_input.node, input_mode: pipewire_bridge). WirePlumber resolved the default sink omniphony to the older node, owned by an orphan renderer whose output device (a suspended headphone sink) never cycled. Firefox's stream attached to a driver-less node and video playback froze. Studio showed nothing wrong because its own renderer was healthy.

Change

  • New audio_input::pipewire_node_conflict: one registry round trip (get_registry + core.sync) on the backend's main loop, right after the core connects and before the node is published. One-shot at connect, off the realtime path. It collects the Audio/Sink nodes whose node.name matches ours plus the Client globals, joins them through client.id, and reports the nodes owned by another process (pid from pipewire.sec.pid, fallback application.process.id; binary from application.process.binary, fallback application.name). Same-pid nodes (a sibling connection, the previous incarnation of the backend still tearing down) are not conflicts; nodes with no resolvable owner are reported.
  • Both bridge backends call it: pipewire.rs (pw_stream) and pipewire_client_node.rs (pw_client_node).
  • On a hit: log::warn! naming pid, binary and node id, and InputControl::set_input_error so it reaches Studio's input status (applied.errorinputError). The node is never renamed. A scan that fails or times out (2 s bound) is logged and skipped, so it can never keep the sink from being published.
  • live_input.rs: the manager now clears input_error before spawning the capture thread instead of after, so the thread's connect-time warning is not wiped by the reset racing it.
  • Studio init.js: the Audio Input section auto-opens on the warning's rising edge, as it already does for bridge-path errors.

Example message:

duplicate PipeWire sink "omniphony": already published by pid 1491576 (orender) as node 477; clients targeting "omniphony" may attach to that node instead of this renderer

Tests

  • Unit tests for the pure parts: node/client property parsing, owner resolution (same-pid exclusion, unknown owners), message formatting.
  • live_registry_scan_completes_and_never_reports_this_process (#[ignore], needs a PipeWire session): run against this machine's daemon while another workflow's orender was publishing omniphony, it listed node 477, pid 1491576 (orender).
  • cargo test -p audio_input, cargo check -p omniphony-renderer and cargo fmt --all --check are clean; rustfmt was run only on the edited files.

Not covered (follow-up)

  • The PCM Live mode sink (run_pipewire_pcm_capture_loop in live_input.rs) publishes a name the same way and could call the same helper.
  • The check is one-shot at connect: a renderer that starts later under the same name is not detected by the earlier one (the later one warns).

🤖 Generated with Claude Code

…-input sink

Two renderers publishing the same `node.name` (an orender from another
workflow, an orphan from a previous session) let WirePlumber resolve the
default sink to the older, driver-less node: players hang on it while
the healthy renderer reports nothing.

Both PipeWire bridge backends now take one registry snapshot on their
main loop right after the core connects, before the node is published:
Audio/Sink nodes carrying our name are joined to their Client globals
and those owned by another process (pipewire.sec.pid) are logged with
pid, binary and node id, and posted to the input status Studio
displays. The node is never renamed; a scan that fails or times out is
skipped so it can never keep the sink from being published.

The live-input manager clears the previous input error before spawning
the capture thread so the thread's connect-time warning is not wiped by
the reset racing it, and Studio opens the Audio Input section on the
warning's rising edge as it does for bridge-path errors.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@mgth
mgth merged commit 1656170 into main Sep 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant