Skip to content

Conversation

philpax
Copy link

@philpax philpax commented Oct 1, 2025

Fixes #740 (mostly). Updated version of #754 that aims to address the issues mentioned in that PR.

Background

When you currently play some audio on the default device using cpal, the default device is fetched once, and then a stream is created from that device to play audio. However, changing the default device will lead to that stream continuing to play on the original device, and removing the device entirely (e.g. unplugging headphones) will result in the stream dying as it no longer has a device to output to.

I spent several hours trying to fix this properly - that is, trying to update the device and rebuild the stream when it changes - and stopped when I realised that a significant amount of the WASAPI stream code would need to be revised to handle a changing device. For those curious, you can see my experimental work here. The goal was to replicate the flow of this Chromium code, which implements this logic.

The Imperfect Fix

However, you don't actually need to do any of that if you don't care about supporting <Windows 8. Windows 8 introduced ActivateAudioInterfaceAsync, and with it, virtual device interfaces. ActivateAudioInterfaceAsync can be used instead of Audio::IMMDevice::Activate to generate a Audio::IAudioClient that will automatically reroute audio for you if the device changes.

This is what the previous PR did, and it works great. On top of that PR, this PR:

  • brings it up to date
  • pushes these changes into a default-on feature
  • makes name use the current default device
  • does some minor cleanup

Ramifications

I've added a default-on feature, wasapi-virtual-default-devices, that adds support for this. Users that need to support older versions of Windows can turn this feature off, and it will behave as the current status quo does. (I'm not actually sure what happens if you have this feature on for an older Windows: in an ideal world, it does nothing, and newer Windows users can enjoy virtual devices. Please let me know if you've tested this.)

One downside of this is that I had to bump the minimum windows version to 0.61. This is because 0.61 removed the previously-explicitly-required implement feature in 0.61, and I can't see any way to conditionally include that feature for older versions of windows. cargo will refuse to resolve the windows dependency with a feature that doesn't exist for the version it's resolving to. I'm happy to drop it back down if anyone can think of a workaround for this.

@philpax philpax force-pushed the audio-device-fix-updated branch from 2517c28 to 0830b3f Compare October 1, 2025 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Respect Windows output device selection
2 participants