[wdmaudiodev] Device Enumeration again ...

  • From: "Jerry Evans" <jerry@xxxxxxxxxx>
  • To: <wdmaudiodev@xxxxxxxxxxxxx>
  • Date: Sun, 6 Apr 2003 16:14:31 +0100

Hi all.

I'm now getting much more detail about the various devices installed in the
system.  However my enumerator has (I think) got a problem with
distinguishing between KSCATEGORY_RENDER and KSCATEGORY_CAPTURE categories.
It would appear to be getting _all_ entries for the KSCATEGORY_AUDIO hive.

It is worth noting I have also tried querying the registry using this:

SetupDiGetDeviceRegistryProperty(hDevInfo,&DevInfoData,SPDRP_DEVTYPE,NULL,(P
BYTE)&dw,sizeof(dw),&reqSize);

The theory here being that the enumerations indicate unambiguously what type
of device we have. The MSDN link is
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/k
march/devobjts_5hnr.asp Howver this fails with GetLastError() returning an
'invalid data' message.

I have taken the liberty of attaching the relevant C++ class which is
reasonably well commented. If anyone would care to comment on why the
enumeration returns both Capture AND Render devices I would be delighted. It
should only require a #include to an existing project with a call as shown
in the header comments.


TVMIA

Jerry


-- Attached file included as plaintext by Ecartis --
-- File: DEVENUM2.H

/*

        KS device enumerator
        
        Sample usage:
        
        Chordia::CDeviceEnumerator enumerator;
        std::vector<Chordia::CDeviceDescriptor> ipnames;
        std::vector<Chordia::CDeviceDescriptor> opnames;
        // do the enumeration for AUDIO + CAPTURE devices only
        if (enumerator.enumerate(KSCATEGORY_AUDIO,KSCATEGORY_CAPTURE,ipnames) > 
0)
        {
                for (std::vector<Chordia::CDeviceDescriptor>::iterator it = 
ipnames.begin();
                                it != ipnames.end();
                                ++it)
                {
                        // stuff ....
                }
        }

        STATIC_KSCATEGORY_AUDIO
        STATIC_KSCATEGORY_RENDER
        STATIC_KSCATEGORY_CAPTURE

        (C) Jerry Evans 2003
        
        jerry_ks@xxxxxxxxxxxxx
                
        Permisssion to redistribute granted for source and binary formats.
        Please do not modify any of this comment block
        
*/


//-----------------------------------------------------------------------------
// auto-include relevant libraries
//-----------------------------------------------------------------------------

#include <Setupapi.h>

#pragma comment( lib, "setupapi.lib")

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

namespace Chordia
{

class CDeviceDescriptor
{
        public:
        
        std::string m_handle;
        std::string m_description;
        std::string m_name;
        std::string m_manufacturer;
        UINT m_id;
        
        CDeviceDescriptor()     { m_id = 0;}
        
        CDeviceDescriptor(const CDeviceDescriptor& arg)
        {
                m_id = arg.m_id;
                m_handle = arg.m_handle;
                m_description = arg.m_description;
                m_name = arg.m_name;
                m_manufacturer = arg.m_manufacturer;
        }
        
        CDeviceDescriptor& operator=(const CDeviceDescriptor& arg)
        {
                m_id = arg.m_id;
                m_handle = arg.m_handle;
                m_description = arg.m_description;
                m_name = arg.m_name;
                m_manufacturer = arg.m_manufacturer;
                return (*this); 
        }
};

//-----------------------------------------------------------------------------
// Enumerate kernel devices and return internal handle name and descriptions
//-----------------------------------------------------------------------------

class CDeviceEnumerator
{
        public:
        
        CDeviceEnumerator()     {}
        
        // enumerate names of devices matching GUIDS
        // size_t enumerate(IN const GUID category, IN const std::vector<GUID>& 
guids, OUT std::vector<CDeviceDescriptor>& descs)
        // 
        size_t enumerate(IN const GUID category, IN const GUID& mode, OUT 
std::vector<CDeviceDescriptor>& descs)
        {
                std::map<std::string,UINT> id_map;
                // Get a handle to the device set specified by the guid
                HDEVINFO hDevInfo = SetupDiGetClassDevs(&category, 
                                                                                
                NULL, 
                                                                                
                NULL, 
                                                                                
                DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
                // failure ?                                                    
                                        
                if (hDevInfo == INVALID_HANDLE_VALUE)
                {
                        return 0;
                }
                //
                DWORD index = 0;
                // Loop through members of the set and get details for each
                while (true)
                {
                        SP_DEVICE_INTERFACE_DATA            DID;
                        SP_DEVICE_INTERFACE_DATA            DIDAlias;
                        SP_DEVINFO_DATA                     DevInfoData;

                        DID.cbSize = sizeof(DID);
                        DID.Reserved = 0;
                        DIDAlias.cbSize = sizeof(DIDAlias);
                        DIDAlias.Reserved = 0;

                        ZeroMemory(&DevInfoData,sizeof(DevInfoData));
                        DevInfoData.cbSize = sizeof(DevInfoData);
                        DevInfoData.Reserved = 0;

                        // enumerate all KS_CATEGORY_AUDIO ?
                        if (SetupDiEnumDeviceInterfaces(hDevInfo, 
                                                                                
        NULL, 
                                                                                
        &category, 
                                                                                
        index++,
                                                                                
        &DID) == FALSE)
                        {
                                // This just means that we've enumerate all the 
devices - it's not a real error
                                break;
                        }

                        // new scope so buffer will come & go
                        {
                                // Get details for the device registered in 
this class
                                DWORD size = 
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
                                // use vector so it will clean up afterwards
                                std::vector<BYTE> buffer(size,0);
                                // 
                                SP_DEVICE_INTERFACE_DETAIL_DATA* 
pDevInterfaceDetails = 
reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(&buffer[0]);
                                //
                                pDevInterfaceDetails->cbSize = 
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //
                                if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, 
                                                                                
                        &DID, 
                                                                                
                        pDevInterfaceDetails, 
                                                                                
                        size,
                                                                                
                        NULL, 
                                                                                
                        &DevInfoData))
                                {
                                        continue;
                                }

                                // check additional category guids which may 
(or may not) have been supplied
                                if (!SetupDiGetDeviceInterfaceAlias(hDevInfo,
                                                                                
                                &DID,
                                                                                
                                &mode,
                                                                                
                                &DIDAlias))
                                {
                                        continue;
                                }                                               
                                        

                                // Check if the this interface alias is enabled.
                                if (!DIDAlias.Flags || (DIDAlias.Flags & 
SPINT_REMOVED))
                                {
                                        continue;
                                }
                                // 
                                CDeviceDescriptor desc;
                                desc.m_handle = 
pDevInterfaceDetails->DevicePath;

                                // this is how I test device 'type' at the 
moment !!!!
/*
                                CKsAudFilter filter;
                                if 
(filter.Instantiate(pDevInterfaceDetails->DevicePath) == S_OK)
                                {
                                        if (mode == KSCATEGORY_RENDER)
                                        {
                                                if (filter.CountRenderPins() == 
0)
                                                {
                                                        continue;
                                                }
                                        }
                                        if (mode == KSCATEGORY_CAPTURE)
                                        {
                                                if (filter.CountCapturePins() 
== 0)
                                                {
                                                        continue;
                                                }
                                        }
                                }
*/                              
                                //
                                DWORD reqSize = 0;
                                BYTE name[64];
                                DWORD dw = 0;
                                BOOL b = 
SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                                                
                                        &DevInfoData,
                                                                                
                                        SPDRP_DEVTYPE,
                                                                                
                                        NULL,
                                                                                
                                        (PBYTE)&dw,
                                                                                
                                        sizeof(dw),
                                                                                
                                        &reqSize);

                                // get friendly name 
                                if (SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                                                
                                &DevInfoData,
                                                                                
                                SPDRP_LOCATION_INFORMATION,
                                                                                
                                NULL, // don't need the reg type
                                                                                
                                &name[0],
                                                                                
                                sizeof(name),
                                                                                
                                &reqSize) == TRUE)
                                {                                               
                
                                        desc.m_name = 
reinterpret_cast<TCHAR*>(name);
                                        name[reqSize] = '\0';
                                }
                                // get device description
                                if (SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                                                
                                &DevInfoData,
                                                                                
                                SPDRP_DEVICEDESC,
                                                                                
                                NULL, // don't need the reg type
                                                                                
                                &name[0],
                                                                                
                                sizeof(name),
                                                                                
                                &reqSize) == TRUE)
                                {                                               
                
                                        desc.m_description = 
reinterpret_cast<TCHAR*>(name);
                                        name[reqSize] = '\0';
                                }
                                // get the manufacturers name
                                if (SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                                                
                                &DevInfoData,
                                                                                
                                SPDRP_MFG,
                                                                                
                                NULL, // don't need the reg type
                                                                                
                                &name[0],
                                                                                
                                sizeof(name),
                                                                                
                                &reqSize) == TRUE)
                                {                                               
                
                                        desc.m_manufacturer = 
reinterpret_cast<TCHAR*>(name);
                                        name[reqSize] = '\0';
                                }
                                // this gives us device numbering if we have 
multiple (say) USB devices
                                std::string strDesc = desc.m_description;
                                UINT id = 1;
                                // find the name
                                std::map<std::string,UINT>::iterator imi = 
id_map.find(strDesc);
                                if (imi != id_map.end())
                                {
                                        // increment the count
                                        id = ++imi->second;
                                }
                                else
                                {
                                        // insert as <Name> <1>
                                        
id_map.insert(std::make_pair(strDesc,1));
                                }
                                //
                                desc.m_id = id;                         
                                descs.push_back(desc);
                        }
                }
                // clean up and go home
                SetupDiDestroyDeviceInfoList(hDevInfo);
                //
                return descs.size();
        }
};

//-----------------------------------------------------------------------------
// end namespace
//-----------------------------------------------------------------------------

};

//-----------------------------------------------------------------------------
// end file
//-----------------------------------------------------------------------------

******************

WDMAUDIODEV addresses:
Post message: mailto:wdmaudiodev@xxxxxxxxxxxxx
Subscribe:    mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=subscribe
Unsubscribe:  mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=unsubscribe
Moderator:    mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx

URL to WDMAUDIODEV page:
http://www.wdmaudiodev.de/

Other related posts: