v3.4: handle-leak fix, Realtek ASIO block, device notifications, quick profile switch, hotkey announcements

Freezes the v3.4 feature set (everything since the v3.3 public release):

- Fix the receiver handle leak: the 3-second device-refresh timer reopened the
  configured ASIO driver every tick, and Realtek's ASIO driver leaks Event+Mutant
  handles on every open. Cache the ASIO probe per driver so it is opened once.
- Realtek ASIO block: detect a Realtek ASIO driver, offer once to disable it, and
  never touch it again if disabled; Options-menu toggle to reverse. Global config.
- Device hot-plug is event-driven (AudioDeviceChangeNotifier) instead of a 3s poll;
  debounced refresh, falls back to polling if registration fails.
- Quick profile switch: new global hotkey opens an NVDA-friendly popup of all
  profiles (current marked); Enter/click switches; plays a new "profile menu open"
  cue with Preferences mute + custom-sound.
- Announce assigned global hotkeys on the controls/menu items they drive (NVDA reads
  "press X anywhere"). File > Open already had Ctrl+O.
- Held-back changes folded in: config-folder migration, codec-column fix, Tailscale
  endpoint network-prune, empty-password guard, and the handle-leak diagnostics
  (ProcessSelfMeter, HandleTypeProbe).

Version bumped to 3.4.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-06-08 09:12:11 +01:00
co-authored by Claude Opus 4.8
parent fc451ba3e3
commit dd70613017
18 changed files with 1325 additions and 64 deletions
+6
View File
@@ -115,6 +115,9 @@ public sealed class Profile
public bool? EnableRecordStopCue { get; set; }
public bool? EnableSaveCue { get; set; }
public bool? EnableProfileSwitchCue { get; set; }
/// <summary>When true (the default), the "profile menu open" cue plays as the Quick profile
/// switch popup opens. Per-profile so each setup can mute it independently.</summary>
public bool? EnableProfileMenuOpenCue { get; set; }
/// <summary>Plays the update cue just before an update starts installing (manual or
/// silent). Null = unset → defaults to on, so a silent background update still gives an
/// audible heads-up. Added 2026-05-31.</summary>
@@ -206,6 +209,9 @@ public sealed class Profile
/// <summary>Hotkey that sends a "toggle Windows default-output-device mute" command to
/// every connected peer.</summary>
public HotkeyRecord? SystemMuteToggleHotkey { get; set; }
/// <summary>Global hotkey that opens the Quick profile switch popup — a list of all profiles you
/// can arrow through and press Enter to switch to, from anywhere in Windows. Unset by default.</summary>
public HotkeyRecord? QuickProfileSwitchHotkey { get; set; }
/// <summary>When true, this machine honours incoming Control packets from connected
/// peers — adjusts the local volume slider or toggles mute. Default false: receiving
/// remote control is opt-in even though the audio allow-list already gates who's