5 Commits

Author SHA1 Message Date
khannurien
70494e96bc Add --refresh to repair stale device IDs, and rename to audioswitch
Windows gives a device a new endpoint ID when it reappears as another
instance, typically a DAC moved to a different USB port, which also
gains a "2- " name prefix. The old config line then silently dropped out
of the cycle. --refresh re-points each stale line at the present output
with the same name (ignoring that prefix), keeps order and comments, adds
unmentioned outputs as commented-out lines, and keeps a .bak of the
previous file.

Also replace every remaining "win-audio-output-switcher" with
"audioswitch": the config now lives in %APPDATA%\audioswitch, and the
autostart Run value and single-instance mutex use the new name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:43:55 +00:00
khannurien
c2825fa062 Updated gitignore 2026-09-19 13:24:27 +00:00
khannurien
a049fb7c6b Re-enumerate outputs through a fresh enumerator on each hotkey press
The enumerator created at startup could go stale and keep reporting the
device set from back then, so an unplugged DAC stayed in the cycle and a
replugged one never came back. A failed enumeration now empties the list
instead of keeping the old one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:24:01 +00:00
a7f02da17b added LICENSE 2026-09-17 07:29:41 +02:00
77be2c188d Cycle the Windows default audio output from a global hotkey
A single 306 KB GUI-subsystem binary with no tray icon and no settings
window: one hidden popup owns the hotkey, the device-change callbacks and
the flyout, and the process sleeps in GetMessageW at 0% CPU in between.

Windows exposes no public API for setting the default audio endpoint, so
this uses the undocumented IPolicyConfig COM interface, confined to
src/policy.rs. Verified working on build 26200. Everything else -
enumeration, IMMNotificationClient, RegisterHotKey, the flyout - is
documented Win32.

The flyout uses the DWM acrylic backdrop and rounded corners the shell
uses for its own flyouts, with text drawn via DrawThemeTextEx and
DTT_COMPOSITED into a 32-bpp DIB, which is what keeps GDI from leaving
black fringes on a composited surface.

Console and Multimedia roles move by default; Communications stays put so
voice chat keeps its headset. Config is a hand-parsed INI reloaded on the
next keypress, keeping the dependency list to the windows crate alone.

Built by cross-compiling from a devcontainer with mingw-w64, so nothing is
installed on the Windows host and the exe imports only system DLLs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 07:29:04 +02:00