host/audio: app enumeration + interactive picker (session 2 of 4)
list_playing_apps() shells out to `pactl -f json list sink-inputs`,
parses with serde_json, dedupes by application.name (BTreeMap for
stable ordering), returns Vec<App { name, stream_count }>.
Picker fires in interactive::run after preflight, before host::run.
Bypassed when --app NAME is on the CLI. Shows the apps with a
"per-app routing isn't live yet" explainer so users aren't surprised
that audio still captures system-wide. Empty-list path shows the
default + a "start your app first" hint so the feature stays
discoverable.
Banner softened to `system-audio (app pick saved: <name>)` when
opts.app is set — keeps the choice visible without lying about what
gets captured. Routing activation still gated on the
PIXELPASS_AUDIO_VIA_NULL_SINK env var (session 1's locked decision
#2); --app flips to that activation in session 3 once per-stream
filtering exists.
Verified end-to-end interactively: Strawberry shows up in the picker
during music playback, both default and app-pick paths advance into
the portal handshake, banner matches choice.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+5
-2
@@ -1,4 +1,4 @@
|
||||
mod audio;
|
||||
pub mod audio;
|
||||
mod capture;
|
||||
mod serve;
|
||||
mod wayland;
|
||||
@@ -317,8 +317,11 @@ fn copy_to_clipboard(text: &str) -> bool {
|
||||
|
||||
fn capture_summary(opts: &HostOpts) -> String {
|
||||
let mut bits = vec![if opts.window { "window" } else { "fullscreen" }.to_string()];
|
||||
// Per-stream routing isn't wired yet (session 3 owns activation), so
|
||||
// even when an app is selected the audio capture is system-wide. Keep
|
||||
// the choice visible in the banner but label it honestly.
|
||||
if let Some(app) = &opts.app {
|
||||
bits.push(format!("app-audio={app}"));
|
||||
bits.push(format!("system-audio (app pick saved: {app})"));
|
||||
} else {
|
||||
bits.push("system-audio".to_string());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user