I need to enumerate direct sound devices on windows, and serialise the actual device used to output a particular channel. This appears to be done normally by saving the direct sound device GUID. However, I need to connect to the same hardware if it exists on a different computer. I've tried using the GUID, but that is different on different computers with exactly the same audio device plugged in.
I believe since it's the audio hardware which I'm binding to, rather than a role, I should be using a device interface path, as shown in Windows device manager, but there doesn't seem to be a way to go from the direct sound object to the device manager path.
Is it possible to make this mapping?
There is an example found here: http://www.chrisnet.net/code.htm which shows how to use the CLSID_DirectSoundPrivate
interface, which is non-trivial, almost impossible to find via MSDN if you don't know what to look for, and has a terrible interface involving multiple calls which is not explained anywhere other than in this example.
I took this example, and ended up getting stack violations attempting to call the Get
method on the property set.
It turns out that direct show defines the same IKsPropertySet
interface with the same guid but with a different vtable, causing horrible vtable-related problems if you #include
dshow.h
or strmif.h
before dsound.h
. Needless to say, I'm unimpressed.
The calls needed are as follows:
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
NULL,
0,
&sDirectSoundDeviceDescription,
sizeof(sDirectSoundDeviceDescription),
&ulBytesReturned
);
if (ulBytesReturned)
{
// On the first call it notifies us of the required amount of memory in order to receive the strings.
// Allocate the required memory, the strings will be pointed to the memory space directly after the struct.
psDirectSoundDeviceDescription = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA)new BYTE[ulBytesReturned];
*psDirectSoundDeviceDescription = sDirectSoundDeviceDescription;
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
NULL,
0,
psDirectSoundDeviceDescription,
ulBytesReturned,
&ulBytesReturned
);