-
In-app audio device picker (controller-driven)
release / Build Windows .zip (push) Canceled after 0sreleased this
2026-05-31 09:07:39 +03:00 The shell mode was missing a way to switch the default audio device from
a controller — the only path was the Settings button that popped open
the Windows "Параметры → Звук" page, mouse-only and outside the
fullscreen shell. Same gap the monitor picker closed earlier.internal/audio (Windows-only, no CGO):
- enumerates active render+capture endpoints via the documented MMDevice
API (IMMDeviceEnumerator, IPropertyStore, PKEY_Device_FriendlyName); - switches the default via undocumented IPolicyConfigVista
(CLSID 870af99c-..., IID 568b9108-..., SetDefaultEndpoint at vtable
slot 12 — same interface SoundSwitch, NirSoft, AHK scripts have used
for ~15 years; stable across Vista→Win11); - hand-rolled vtable dispatch via syscall.SyscallN, CoInitializeEx(MTA)
- LockOSThread per call. Same pattern as internal/display.
- SetDefault flips Console + Multimedia roles (what the Windows "Set
Default" button does); Communications role left alone.
AudioPicker (frontend):
- two columns (output / input), pre-selects current default per column;
- controller bindings mirror MonitorPicker: ↑↓ within column,
←→/LB/RB swap columns, A applies, B/Esc closes; same for keyboard.
Wired into three surfaces:
- Settings page: replaces "Открыть «Параметры → Звук»" button with the
inline picker (system shortcut kept as a fallback sibling button); - 🎧 corner icon next to 🖥 monitor switch in shell mode;
- one-shot auto-chain on shell startup: after MonitorPicker.onDone fires
for the first time (or if the picker was skipped because there's only
one display) the AudioPicker opens once. Guard via useRef so
re-picking a monitor mid-session does not drag audio back open.
inputBlocked in ShellApp now also gates on audioOpen so the carousel
behind the picker doesn't double-handle d-pad/A.ADR: .claude/decisions/0023-in-app-audio-device-picker.md.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Downloads
- enumerates active render+capture endpoints via the documented MMDevice