Enumeration of Sound Devices

For an application that is simply going to play sounds through the user's preferred playback device, you need not enumerate the available devices. When you create the DirectSound object with NULL as the device identifier, the interface will automatically be associated with the default device if one is present. If no device driver is present, the call to the DirectSoundCreate function will fail.

However, if you are looking for a particular kind of device or need to work with two or more devices, you must get DirectSound to enumerate the devices available on the system.

Enumeration serves three purposes:

To enumerate devices you must first set up a callback function that will be called each time DirectSound finds a device. You can do anything you want within this function, and you can give it any name, but you must declare it in the same form as DSEnumCallback, a prototype in this documentation. The callback function must return TRUE if enumeration is to continue, or FALSE otherwise (for instance, after finding a device with the capabilities you need).

If you are working with more than one device—for example, a capture and a playback device—the callback function is a good place to create and initialize the DirectSound object for each device.

The following example, extracted from Dsenum.c in the Dsshow sample, enumerates the available devices and adds information about each to a list in a combo box. Here is the callback function in its entirety:

BOOL CALLBACK DSEnumProc(LPGUID lpGUID, 
                         LPCTSTR lpszDesc,
                         LPCTSTR lpszDrvName, 
                         LPVOID lpContext )
    {
    HWND   hCombo = *(HWND *)lpContext;
    LPGUID lpTemp = NULL;
 
    if( lpGUID != NULL )
        {
        if(( lpTemp = LocalAlloc( LPTR, sizeof(GUID))) == NULL )
        return( TRUE );
 
        memcpy( lpTemp, lpGUID, sizeof(GUID));
    }
 
    ComboBox_AddString( hCombo, lpszDesc );
    ComboBox_SetItemData( hCombo,
                ComboBox_FindString( hCombo, 0, lpszDesc ),
                lpTemp );
    return( TRUE );
    }
 

The enumeration is set in motion when the dialog containing the combo box is initialized:

if (DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc, &hCombo)
    != DS_OK )
    {
    EndDialog( hDlg, TRUE );
    return( TRUE );
    }
 

Note that the address of the handle to the combo box is passed into DirectSoundEnumerate, which in turn passes it to the callback function. This parameter can be any 32-bit value that you want to have access to within the callback.