Most "wave" and USB audio filters register under KSCATEGORY_AUDIO, .._RENDER, and .._CAPTURE. i.e. you don't normally see separate render and capture filters for a given device. To make this crystal clear, run ksstudio and set it to enumerate KSCATEGORY_AUDIO. You can expand the enumerated filters in the left pane see see what categories they are aliased under. Mitch Rundle Microsoft This posting is provided "AS IS" with no warranties, and confers no rights. -----Original Message----- From: Jerry Evans [mailto:jerry@xxxxxxxxxx]=20 Sent: Sunday, April 06, 2003 8:15 AM To: wdmaudiodev@xxxxxxxxxxxxx Subject: [wdmaudiodev] Device Enumeration again ... 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,NUL L,(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=3D/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 =09 Sample usage: =09 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 =3D ipnames.begin(); it !=3D ipnames.end(); ++it) { // stuff .... } } STATIC_KSCATEGORY_AUDIO STATIC_KSCATEGORY_RENDER STATIC_KSCATEGORY_CAPTURE (C) Jerry Evans 2003 =09 jerry_ks@xxxxxxxxxxxxx =09 Permisssion to redistribute granted for source and binary formats. Please do not modify any of this comment block =09 */ //---------------------------------------------------------------------- ------- // auto-include relevant libraries //---------------------------------------------------------------------- ------- #include <Setupapi.h> #pragma comment( lib, "setupapi.lib") //---------------------------------------------------------------------- ------- //---------------------------------------------------------------------- ------- namespace Chordia { class CDeviceDescriptor { public: =09 std::string m_handle; std::string m_description; std::string m_name; std::string m_manufacturer; UINT m_id; =09 CDeviceDescriptor() { m_id =3D 0;} =09 CDeviceDescriptor(const CDeviceDescriptor& arg) { m_id =3D arg.m_id; m_handle =3D arg.m_handle; m_description =3D arg.m_description; m_name =3D arg.m_name; m_manufacturer =3D arg.m_manufacturer; } =09 CDeviceDescriptor& operator=3D(const CDeviceDescriptor& arg) { m_id =3D arg.m_id; m_handle =3D arg.m_handle; m_description =3D arg.m_description; m_name =3D arg.m_name; m_manufacturer =3D arg.m_manufacturer; return (*this);=09 } }; //---------------------------------------------------------------------- ------- // Enumerate kernel devices and return internal handle name and descriptions //---------------------------------------------------------------------- ------- class CDeviceEnumerator { public: =09 CDeviceEnumerator() {} =09 // enumerate names of devices matching GUIDS // size_t enumerate(IN const GUID category, IN const std::vector<GUID>& guids, OUT std::vector<CDeviceDescriptor>& descs) //=20 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 =3D SetupDiGetClassDevs(&category,=20 =09 NULL,=20 =09 NULL,=20 =09 DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); // failure ? if (hDevInfo =3D=3D INVALID_HANDLE_VALUE) { return 0; } // DWORD index =3D 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 =3D sizeof(DID); DID.Reserved =3D 0; DIDAlias.cbSize =3D sizeof(DIDAlias); DIDAlias.Reserved =3D 0; ZeroMemory(&DevInfoData,sizeof(DevInfoData)); DevInfoData.cbSize =3D sizeof(DevInfoData); DevInfoData.Reserved =3D 0; // enumerate all KS_CATEGORY_AUDIO ? if (SetupDiEnumDeviceInterfaces(hDevInfo,=20 =09 NULL,=20 =09 &category,=20 =09 index++, =09 &DID) =3D=3D 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 =3D sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR); // use vector so it will clean up afterwards std::vector<BYTE> buffer(size,0); //=20 SP_DEVICE_INTERFACE_DETAIL_DATA* pDevInterfaceDetails =3D reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(&buffer[0]); // pDevInterfaceDetails->cbSize =3D sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,=20 =09 &DID,=20 =09 pDevInterfaceDetails,=20 =09 size, =09 NULL,=20 =09 &DevInfoData)) { continue; } // check additional category guids which may (or may not) have been supplied if (!SetupDiGetDeviceInterfaceAlias(hDevInfo, =09 &DID, =09 &mode, =09 &DIDAlias)) { continue; } // Check if the this interface alias is enabled. if (!DIDAlias.Flags || (DIDAlias.Flags & SPINT_REMOVED)) { continue; } //=20 CDeviceDescriptor desc; desc.m_handle =3D pDevInterfaceDetails->DevicePath; // this is how I test device 'type' at the moment !!!! /* CKsAudFilter filter; if (filter.Instantiate(pDevInterfaceDetails->DevicePath) =3D=3D S_OK) { if (mode =3D=3D KSCATEGORY_RENDER) { if (filter.CountRenderPins() =3D=3D 0) { continue; } } if (mode =3D=3D KSCATEGORY_CAPTURE) { if (filter.CountCapturePins() =3D=3D 0) { continue; } } } */ =09 // DWORD reqSize =3D 0; BYTE name[64]; DWORD dw =3D 0; BOOL b =3D SetupDiGetDeviceRegistryProperty(hDevInfo, =09 &DevInfoData, =09 SPDRP_DEVTYPE, =09 NULL, =09 (PBYTE)&dw, =09 sizeof(dw), =09 &reqSize); // get friendly name=20 if (SetupDiGetDeviceRegistryProperty(hDevInfo, =09 &DevInfoData, =09 SPDRP_LOCATION_INFORMATION, =09 NULL, // don't need the reg type =09 &name[0], =09 sizeof(name), =09 &reqSize) =3D=3D TRUE) { desc.m_name =3D reinterpret_cast<TCHAR*>(name); name[reqSize] =3D '\0'; } // get device description if (SetupDiGetDeviceRegistryProperty(hDevInfo, =09 &DevInfoData, =09 SPDRP_DEVICEDESC, =09 NULL, // don't need the reg type =09 &name[0], =09 sizeof(name), =09 &reqSize) =3D=3D TRUE) { desc.m_description =3D reinterpret_cast<TCHAR*>(name); name[reqSize] =3D '\0'; } // get the manufacturers name if (SetupDiGetDeviceRegistryProperty(hDevInfo, =09 &DevInfoData, =09 SPDRP_MFG, =09 NULL, // don't need the reg type =09 &name[0], =09 sizeof(name), =09 &reqSize) =3D=3D TRUE) { desc.m_manufacturer =3D reinterpret_cast<TCHAR*>(name); name[reqSize] =3D '\0'; } // this gives us device numbering if we have multiple (say) USB devices std::string strDesc =3D desc.m_description; UINT id =3D 1; // find the name std::map<std::string,UINT>::iterator imi =3D id_map.find(strDesc); if (imi !=3D id_map.end()) { // increment the count id =3D ++imi->second; } else { // insert as <Name> <1> =09 id_map.insert(std::make_pair(strDesc,1)); } // desc.m_id =3D id; =09 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=3Dsubscribe Unsubscribe: mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=3Dunsubscribe Moderator: mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx URL to WDMAUDIODEV page: http://www.wdmaudiodev.de/ ****************** 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/