Saturday, July 30, 2011

Windows 7 Default Audio Device Changer

There are a number of posts on the internet regarding programmatically switching the default audio device in Windows Vista and Windows 7. I recently encountered this issues as well. I had purchased a USB headset.

The issue started from there. I did not want to have to plug and unplug the headset every time I wanted to use it, nor did I want to go to the Control Panel and manually change the default playback and recording devices.

Therefore, I started searching online to find a method. It appears that Microsoft does not support this in any way in Windows Vista and 7. I did discover that one of the program managers for Windows might pass this issue along to the developers for consideration, so we may not be out of luck in the next version.

The searches ended up revealing a number of methods to perform the change. I took a number of the suggestions, code snippets, helper DLLs, and came up with a solution of my own. All the source websites are credited in the list below and I am very grateful for their detailed groundwork.

The main points are as follows:
  • Enumerate a list of all rendering (output) and capture (input) audio devices in the system via the registry for easiest access
  • Use the unsupported Microsoft interface IPolicyConfig to actually make the switch
  • Develop a command-line application that can perform all the default audio device switching with a minimum of intervention and callable from AutoHotkey
This forum post on AutoHotkey is what got me started. However, as astutely observed by many others before me, Windows 7 did not support most of the non-UI methods that were described in this post. I first landed on Dave Amenta's site, which contained a full-functional application to do exactly what I wanted, minus the recording devices. Dave definitely has one of the best samples on the usage of IPolicyConfig I could find and I highly recommend his site for additional details.

I continued digging and eventually found an excellent set of references in this Microsoft forum post. In this post, I am deeply indebted to ghoster_e, albain, and EreTIk. albain got me started with his excellent reference on reading the writing the necessary registry entries to get and set the default audio device. However, this method did not notify any running applications that the default changed, necessitating restarting that application for it to recognize the change.

ghoster_e had some great information on the unsupported IPolicyConfig COM interface, along with some snippets of code. EreTIk also maintains a very useful website that includes this full C++ header file for inclusion in a C++ project.

This almost got me to where I needed to be. However, as I was writing this entire project in C#, I did not want to have to make the necessary COM conversions to use those IPolicyConfig interfaces. I searched some more and found Ray Molenkamp's CoreAudio project. This was missing the IPolicyConfig interfaces, but was almost feature-complete.

One more search landed me at MixerProNET; a full .NET-based library (CoreAudio.dll), with all the necessary functions to set the default audio device (both playback and recording) via the IPolicyConfig COM interface that sends out notifications to running applications notifying them of the change.

Once I had this, I was at last in position to finish off my project. I made the last tweaks, setup the necessary command-line parameters for the front-end command-line application and started testing. To my great and lasting enjoyment, all the tests worked. I now had the ability to setup AutoHotkey to trap any necessary keys and fire off my application with parameters indicating which devices I wanted to use as default.

I've included a reference of the application below and will be posting it in a few days.

AudioChanger.exe

Allows a command-line method of switching system default audio devices. Tested and found working on Windows 7 x64. Should also work on Windows 7 x86. In both cases, this program must be run as an administrator or with UAC disabled.

Parameters:

        /?                      Brings up this help message
        /list                   Display a list of currently enabled audio devices and the defaults
        /cro                    Returns the ID of the current default output audio device
        /cri                    Returns the ID of the current default input audio device
        /so {guid}              Sets the default output audio device based on a GUID
        /so devicename busname  Sets the default output audio device based on the device
                                name and device bus name (like Speakers, Creative SB X-Fi)
        /si {guid}              Sets the default input audio device based on a GUID
        /si devicename busname  Sets the default input audio device based on the device
                                name and device bus name (like Speakers, Creative SB X-Fi)
        /so devicename busname [devicename] [busname] ...       Switches between default output audio devices in the list of pairs; once it reaches the last one, it cycles back to the first item
        /si devicename busname [devicename] [busname] ...       Switches between default input audio devices in the list of pairs; once it reaches the last one, it cycles back to the first item



Credits
This project could not have been realized without the work of all those I've already mentioned in this post. However, to ensure that credit be given where credit is due, I've recapped all the people who've provided the groundwork (in no particular order):