Per-app send: UI on the Input/Output tab, saved per profile

Local checkpoint - NOT for public release. Builds on the engine core commit.

Ed's revisions to the plan: the send-mode chooser lives on the Input/Output tab
(not Preferences), right after "Send my audio", and the setting saves per profile.

Input/Output tab:
- New "How to send WASAPI audio" listbox (Alt+6) after the send checkbox, with
  two rows: send whole sound devices (classic) or send specific applications.
  Switching it swaps the tab live between the loopback-outputs list and the app
  section. Hidden entirely on Windows too old for process loopback (mode pinned
  to devices), so nothing changes for Win7.
- Applications section: "Send all applications" master checkbox (Alt+7, ticked by
  default = whole system audio, same as today) and an "Applications to send"
  checked list (Alt+8) shown only when the master is unticked.
- All house controls (AccessibleCheckBox, MnemonicLabel, WireCheckedListAccessibility),
  accessible names + Alt-shortcut suffixes, tab order slotted in.

Behaviour:
- App list reconciles on a 3s timer while visible: apps appear/disappear as they
  open and close, ticks preserved by process NAME, and a ticked app that closes
  stays in the list marked "(not running)" and resumes when it reappears.
- ApplySendSources: devices mode unchanged; applications mode sends either the
  default-render loopback (send all) or one process-loopback spec per running
  process of each ticked app. WASAPI mics and ASIO run alongside in both modes.
- Process-loopback sources are excluded from the single-source push-mode fast
  path (it opens an MMDevice; a "proc:<pid>" id has none) - they go via MixingEngine.
- "Is anything being sent" status/tray gates account for applications mode.

Persistence moved from AppConfig to Profile: WasapiSendMode / SendAllApplications /
SelectedSendApplications. Profile round-trip self-test extended. Gate: 15/15.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-07-12 10:53:58 +01:00
co-authored by Claude Opus 4.8
parent 8a7c4ddf2b
commit f8a42f2806
5 changed files with 380 additions and 33 deletions
-14
View File
@@ -230,20 +230,6 @@ public sealed class AppConfig
/// device, following it if the default changes. Machine-wide, opt-in, default false.</summary>
public bool UseDefaultLoopbackSend { get; set; }
/// <summary>How the WASAPI send side captures system audio: "devices" (the WASAPI outputs-to-send
/// loopback list — the classic behaviour, default) or "applications" (per-application process
/// loopback — Windows 10 2004+ only). Chosen in Preferences; the send tab shows the matching list.
/// ASIO capture runs alongside either way.</summary>
public string WasapiSendMode { get; set; } = "devices";
/// <summary>In "applications" send mode: when true (the default) every app's audio is sent (i.e. the
/// whole system audio); when false only the apps in <see cref="SelectedSendApplications"/> are sent.
/// Mirrors the "Send all applications" master checkbox.</summary>
public bool SendAllApplications { get; set; } = true;
/// <summary>In "applications" send mode with <see cref="SendAllApplications"/> off: the process names
/// (lower-case, no path/extension, e.g. "vlc", "firefox") whose audio to send. Tracked by NAME not
/// PID so the selection survives an app restart.</summary>
public List<string> SelectedSendApplications { get; set; } = new();
/// <summary>Remembered answer to the "untick the other outputs/inputs when you turn on Use Windows
/// default?" prompt. Null = ask each time; true = always untick; false = never untick. Set when the
/// user ticks "Don't ask again" on that prompt. Machine-wide.</summary>