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
+10
View File
@@ -370,6 +370,11 @@ internal static class SelfTest
p.AudioPort = 47830;
p.AsioDriverName = "Some ASIO Driver";
p.SelectedWasapiSendInputs.Add("device-id-abc");
// Per-application send mode (issue #20) is per-profile — round-trip it too.
p.WasapiSendMode = "applications";
p.SendAllApplications = false;
p.SelectedSendApplications.Add("vlc");
p.SelectedSendApplications.Add("firefox");
store.Save(p);
var back = store.Load("selftest roundtrip");
@@ -381,6 +386,11 @@ internal static class SelfTest
&& back.AsioDriverName == "Some ASIO Driver"
&& back.SelectedWasapiSendInputs.Contains("device-id-abc"),
"profile fields must survive a save/reload");
Check(back.WasapiSendMode == "applications"
&& !back.SendAllApplications
&& back.SelectedSendApplications.Contains("vlc")
&& back.SelectedSendApplications.Contains("firefox"),
"per-application send settings must survive a save/reload");
return null;
}
finally