How to keep up to date with availalbe audio devices.
There are three things that need to be done if you want to keep up to date with what audio devices are available. The first is to register for device change notifications.
When a device is added or removed, such as a USB headset, everyone gets a few WM_DEVICECHANGE messages. However without the call RegisterDeviceNotification, you'll only get the DBT_DEVNODES_CHANGED version of WM_DEVICECHANGE. You will not get important messages like the DBT_DEVICEREMOVECOMPLETE version of WM_DEVICECHANGE. This means that our attempt to keep the audio device list up to date (below) will always be one step behind on device removals.
It is possible to limit notifications to a particular kind of device. You'll note that we're not settings the interface class GUID in our notification filter and we're using the DEVICE_NOTIFY_ALL_INTERFACE_CLASSES. We're doing this because I'm lazy and restricting notifications to a particular device type doesn't serve any useful purpose in this example.
It is important to note that you need to have something to notify. In this case it is a window handle. A service status handle will also work. Just sticking in NULL for the window handle won't work.
Finally, note that we are hanging on to the return value from RegisterDeviceNotification. This is a handle that is used with UnregisterDeviceNotification when we clean up and exit. The return value should also be checked to make sure the call succeeded, but such error checking has been omitted here for clarity and simplicity.
Next, you need to make sure you have a handler set up for WM_DEVICECHANGE messages in your message map. In MFC it'll look something like:
In our ATL/COM objects in the SDK it looks more like:
Finally, on initial startup, and in response to WM_DEVICECHANGE messages we step through the available device list. That looks something like this:
This will leave you with a vector of the device names the Window's mixer knows about. Of course, what exactly you do here will depend on your application and what you're trying to accomplish.
DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
::ZeroMemory( ¬ificationFilter, sizeof(notificationFilter) );
notificationFilter.dbcc_size = sizeof(notificationFilter);
notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
m_hDevNotify = ::RegisterDeviceNotification(
m_hWnd,
¬ificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE|DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
When a device is added or removed, such as a USB headset, everyone gets a few WM_DEVICECHANGE messages. However without the call RegisterDeviceNotification, you'll only get the DBT_DEVNODES_CHANGED version of WM_DEVICECHANGE. You will not get important messages like the DBT_DEVICEREMOVECOMPLETE version of WM_DEVICECHANGE. This means that our attempt to keep the audio device list up to date (below) will always be one step behind on device removals.
It is possible to limit notifications to a particular kind of device. You'll note that we're not settings the interface class GUID in our notification filter and we're using the DEVICE_NOTIFY_ALL_INTERFACE_CLASSES. We're doing this because I'm lazy and restricting notifications to a particular device type doesn't serve any useful purpose in this example.
It is important to note that you need to have something to notify. In this case it is a window handle. A service status handle will also work. Just sticking in NULL for the window handle won't work.
Finally, note that we are hanging on to the return value from RegisterDeviceNotification. This is a handle that is used with UnregisterDeviceNotification when we clean up and exit. The return value should also be checked to make sure the call succeeded, but such error checking has been omitted here for clarity and simplicity.
Next, you need to make sure you have a handler set up for WM_DEVICECHANGE messages in your message map. In MFC it'll look something like:
BEGIN_MESSAGE_MAP(CListAudioDevicesDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_WM_DEVICECHANGE()
ON_BN_CLICKED(IDC_BUTTON1, &CListAudioDevicesDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
In our ATL/COM objects in the SDK it looks more like:
BEGIN_MSG_MAP(ThisClass)
MESSAGE_HANDLER(WM_DEVICECHANGE, OnDeviceChange);
END_MSG_MAP()
Finally, on initial startup, and in response to WM_DEVICECHANGE messages we step through the available device list. That looks something like this:
std::vector<tchar*> deviceNameVector;
int numDevs = ::mixerGetNumDevs();
for(int i = 0; i < numDevs; i++)
{
MIXERCAPS mcaps;
mixerGetDevCaps(i, &mcaps, sizeof(mcaps));
vec.push_back(mcaps.szPname);
}
This will leave you with a vector of the device names the Window's mixer knows about. Of course, what exactly you do here will depend on your application and what you're trying to accomplish.


0 Comments:
Post a Comment
<< Home