Skip to content

fix(sndDevices): skip non-active devices when selecting playback device#537

Open
akai07 wants to merge 6 commits into
fxsound2:mainfrom
akai07:fix/skip-nonactive-devices-in-selection
Open

fix(sndDevices): skip non-active devices when selecting playback device#537
akai07 wants to merge 6 commits into
fxsound2:mainfrom
akai07:fix/skip-nonactive-devices-in-selection

Conversation

@akai07

@akai07 akai07 commented May 27, 2026

Copy link
Copy Markdown

Summary

Fixes two issues with a single root cause: when a device transitions to a non-active state (UNPLUGGED, NOTPRESENT), the device selection logic was ignoring the state and could still select the dead device as playback target, causing the audio pipeline to spin on a non-functional device.

Issues Fixed

Root Cause

sndDevices_GetAll enumerates devices with DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, so Bluetooth headphones that are powered off (UNPLUGGED) are still present in the device list. The device selection rules (sndDevicesImplementDeviceRules) were selecting devices based on default/priority logic without checking whether the selected device is actually in ACTIVE state. When the audio capture/playback pipeline tried to use a non-active device, the Windows Audio service would retry in a tight loop, causing high CPU usage.

Fix

Added a post-selection validation block after the PlaybackDeviceIsSelected label in sndDevicesImplementDeviceRules. If the selected playback device is not in DEVICE_STATE_ACTIVE, the code scans for the first ACTIVE real device (skipping mono devices if configured, and excluding the DFX virtual device) and falls back to it.

This means:

  • When BT headphones are powered off: FxSound automatically falls back to onboard/speakers
  • When RDP session makes devices unavailable: FxSound picks an available ACTIVE device
  • When the original device comes back: the reconnection logic (PR add GitHub sponsor button #1) handles restoring it

Files Changed

  • audiopassthru/src/sndDevices/sndDevicesImplementDeviceRules.cpp — Added DEVICE_STATE_ACTIVE validation and fallback after device selection

Related Issues

akai07 added 6 commits May 28, 2026 02:50
… in OnDeviceStateChanged

- Filter capture (eRender) device events in OnDeviceStateChanged via IMMEndpoint.GetDataFlow
  to prevent unnecessary playback reinit when input devices change state
- Track reconnected device GUID when state transitions to ACTIVE
- Add reconnection detection in sndDevicesImplementDeviceRules to auto-select
  reconnected playback devices (fixes BT headset reconnect after UNPLUGGED)
- Clear reconnection state on reinit
… system resume

- Call SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED)
  when audio processing starts to prevent system sleep during playback
- Revert to SetThreadExecutionState(ES_CONTINUOUS) when processing stops
- Handle PBT_APMRESUMEAUTOMATIC power event: check device changes and
  restore power state after system resume from sleep
- Clear execution state on controller destruction
…sizing and alpha

Replaced LoadIcon with LoadImage using explicit SM_CXSMICON/SM_CYSMICON
dimensions so tray icons are rendered at the correct size for the
notification area. LoadIcon uses default icon size which can cause
scaling artifacts and improper alpha blending on Windows 10/11,
especially in dark theme mode where transparency is critical.
…nges to same device

When video applications (Plex, etc.) switch between audio tracks with
different formats, Windows fires OnDefaultDeviceChanged even if the
device itself hasn't changed — only the format/role has. This was
causing the audio processing thread to restart unnecessarily, resulting
in audible pauses during video playback.

Fix: compare the new default device ID against our current playback
device. If they match, skip the re-init since it's a format change
on the same device, not an actual device switch.
After an update relocates the binary, the stale Run key path in
HKCU\...\Run causes the app to not launch at boot even though the
settings checkbox shows 'on' (the key exists but points to nowhere).

Fixes:
- isLaunchOnStartup: add error checking on all registry calls and
  validate the stored path matches the current executable path
- setLaunchOnStartup: write REG_SZ with correct cbData size
  ((wcslen+1)*sizeof) instead of sizeof(szPath)=520 bytes which
  appended uninitialized stack data to the registry value
- syncLaunchOnStartup: on each app init, detect stale Run key paths
  and re-write with the current executable path — automatically
  repairs startup after updates without user intervention
When Bluetooth headphones disconnect or are powered off, their state
transitions to DEVICE_STATE_UNPLUGGED. The device is still enumerated
by sndDevices_GetAll (which includes UNPLUGGED devices), so the device
selection logic could still pick it as the playback target. The audio
pipeline then tries to use the dead device, causing the Windows Audio
service to spin at 40-50% CPU.

Fix: after the playback device is selected by the rules, validate it is
in DEVICE_STATE_ACTIVE. If not, fall back to the first ACTIVE real
device. This handles:
- fxsound2#513: BT disconnect/power-off causing high CPU
- fxsound2#491: RDP sessions making devices temporarily unavailable
@bvijay74

Copy link
Copy Markdown
Member

Thanks @akai07 for your efforts for all the fixes you have done.
Can you please retarget all your PRs to develop/windows branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants