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>
This commit is contained in:
36
scripts/deploy.sh
Executable file
36
scripts/deploy.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copy the cross-compiled exe to a real Windows path and (re)start it.
|
||||
#
|
||||
# Run this on the WSL host, NOT inside the devcontainer: the container has no Windows
|
||||
# interop, so it can build the binary but cannot launch it. Copying to %LOCALAPPDATA%
|
||||
# rather than launching over \\wsl.localhost avoids zone-of-origin and file-locking
|
||||
# quirks on the WSL share.
|
||||
set -euo pipefail
|
||||
|
||||
repo="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
exe="$repo/target/x86_64-pc-windows-gnu/release/audioswitch.exe"
|
||||
|
||||
if [ ! -f "$exe" ]; then
|
||||
echo "No binary. Build it first: cargo build --release" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dest_win="$(cmd.exe /c 'echo %LOCALAPPDATA%' 2>/dev/null | tr -d '\r')\\AudioSwitch"
|
||||
dest="$(wslpath -u "$dest_win")"
|
||||
mkdir -p "$dest"
|
||||
|
||||
# Stop whatever is running, or the copy fails with the file locked.
|
||||
if [ -f "$dest/audioswitch.exe" ]; then
|
||||
"$dest/audioswitch.exe" --quit >/dev/null 2>&1 || true
|
||||
sleep 0.5
|
||||
fi
|
||||
|
||||
cp "$exe" "$dest/audioswitch.exe"
|
||||
|
||||
# `cmd.exe /c start` hangs forever under WSL interop here, so launch through PowerShell,
|
||||
# which detaches cleanly. The cd avoids cmd/powershell complaining about a UNC cwd.
|
||||
(cd /mnt/c && powershell.exe -NoProfile -Command \
|
||||
"Start-Process -FilePath '${dest_win}\\audioswitch.exe'") </dev/null >/dev/null 2>&1
|
||||
|
||||
echo "Deployed and started: ${dest_win}\\audioswitch.exe"
|
||||
Reference in New Issue
Block a user