Getting basic device information
I need to find out (programmatically) whether the installed sound card supports duplex operation (i.e. recording and playing back simultaneously). I realise that most modern cards do support this but I still need to check.
I've discovered that waveInGetDevCaps() and waveOutGetDevCaps() will give me information about individual inputs & outputs but I can't find anything to tell me if the card supports duplex operation. In fact I can't even find anything to tell me the name of the sound card (although the above functions do tell me the names of the various inputs & outputs). I thought this would be supported in mmsystem.h and winmm.dll but I guess I must be looking in the wrong place. Can anyone point me in the right direction? :confused:
Re: Getting basic device information
I received a PM telling me that the answer could be found here:-
news://comp.os.ms-windows.programmer.win32
but although my email client (Outlook Express) looks like it can join me to news groups, I can't seem to join this particular one (Outlook Express keeps saying that it can't connect to the server). Is there something wrong with that URL or do I need to use a different kind of app to connect to a news service?
Re: Getting basic device information
Check out WMI and the Win32_SoundDevice class.
As far as the newsgroup link, consider it spam.
Re: Getting basic device information
Quote:
Originally Posted by
John E
I received a PM telling me that the answer could be found here:-
news://comp.os.ms-windows.programmer.win32
but although my email client (Outlook Express) looks like it can join me to news groups, I can't seem to join this particular one (Outlook Express keeps saying that it can't connect to the server). Is there something wrong with that URL or do I need to use a different kind of app to connect to a news service?
You can browse the newsgroup with you web browser by going to the following address:
http://groups.google.com/group/comp....r.win32/topics
Re: Getting basic device information
Configure Usenet with Windows Mail :
http://support.cox.com/sdccommon/asp...b-9ad40513af96
The answer had indeed been given several years ago on Win32 api newsgroup
It's the reference for Win32 api, in particular undocumented ones never seen elsewhere and for source code for all the Win32 80 000 apis (from Wine and other...),
like Codeguru is the reference for MFC.
MS newsgroups are not bad also, for Kernel and DDK, but newer, then archives are not huge like for Usenet....
Re: Getting basic device information
Thanks for persevering guys. I must admit, I'm struggling to find an API that will just give me the name of the installed sound card(s). Arjay's WMI SoundDevice class looked promising but I couldn't find a clear example of using it. :cry:
Any more ideas ?
Re: Getting basic device information
>> The answer had ... been given ... on Win32 api newsgroup
That's about as helpful as "the answer is on the internet". Spam indeed.
>> API that will just give me the name of the installed sound card(s)
I can help with that at least (non WMI version)
http://www.codeguru.com/forum/showthread.php?t=453421
For duplex detection, have you dug around the DirectX api's?
http://www.codeguru.com/forum/showthread.php?t=424415
gg
Re: Getting basic device information
Thanks Codeplug. I haven't tried your second link yet but I copied the code from your first link and it kinda worked. I ran the full program and it produced the output [MPU-401 Compatible MIDI Device] which is indeed listed by Device Manager under Sound,Video and Game Controllers. Strangely though, it didn't list my actual sound card which is shown in Device manager as RME HDSP 9632.
I've tried a few variations on the same theme (i.e. sending different GUID's to your function ListDeviceClassData(..) but I can't find anything that lists my actual sound card. Any ideas?
Re: Getting basic device information
Here's the list of "device interface class" GUIDs: http://msdn.microsoft.com/en-us/library/bb663138.aspx
Here are the relevant device interface class's for audio devices: http://msdn.microsoft.com/en-us/library/ms790578.aspx
KSCATEGORY_AUDIO would probably be better, but you may have to filter out "ROOT\SYSTEM\0000", which shows up on my systems.
Code:
const GUID KSAudioDevIntGuid = // KSCATEGORY_AUDIO
{0x6994AD04, 0x93EF, 0x11D0,
{0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
const GUID KSCaptureDevIntGuid = // KSCATEGORY_CAPTURE
{0x65E8773D, 0x8F56, 0x11D0,
{0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
gg
1 Attachment(s)
Re: Getting basic device information
Here's a WMI C++ example (see the attached file for complete source). The sample retrieves processor, sound card and memory information.
FYI: One of the hardest things with using WMI is to determine which class and properties are available. To help with this, download the WMI Administrative Tools and use the WMI CIM Studio Tool to view the class and property information.
Code:
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitialize( NULL );
{ // Scope all smart pointers (so they release before CoUninitialize is called)
IWbemServicesPtr spServicesPtr;
IWbemClassObjectPtr spProcessor;
IEnumWbemClassObjectPtr spSoundDeviceEnum;
IWbemClassObjectPtr spSoundDevice;
IEnumWbemClassObjectPtr spPhysicalMemoryEnum;
IWbemClassObjectPtr spPhysicalMemory;
try
{
CWMIHelper wmiHelper;
wmiHelper.Connect( );
wmiHelper.GetWMIClassObject( L"Win32_Processor.DeviceID=\"CPU0\"", spProcessor );
tcout << _T("Processor:") << std::endl;
PrintProperty( _T("Description\t\t" ), wmiHelper.GetPropertyString( spProcessor, _T("Description") ) );
PrintProperty( _T("Manufacturer\t\t" ), wmiHelper.GetPropertyString( spProcessor, _T("Manufacturer") ) );
PrintProperty( _T("ProcessorId\t\t" ), wmiHelper.GetPropertyString( spProcessor, _T("ProcessorId") ) );
PrintProperty( _T("Current Clock Speed\t" ), wmiHelper.GetPropertyLong( spProcessor, _T("CurrentClockSpeed") ) );
PrintProperty( _T("Max Clock Speed\t\t" ), wmiHelper.GetPropertyLong( spProcessor, _T("MaxClockSpeed") ) );
PrintProperty( _T("L2 Cache Size\t\t" ), wmiHelper.GetPropertyLong( spProcessor, _T("L2CacheSize") ) );
tcout << std::endl << _T("Sound Devices:") << std::endl;
wmiHelper.GetWMIClassObjectEnum(_T("Win32_SoundDevice"), spSoundDeviceEnum );
ULONG uReturned = 1;
while((SUCCEEDED(hr = spSoundDeviceEnum->Next(-1, 1, &spSoundDevice, &uReturned))) && (uReturned != 0))
{
PrintProperty( _T("Description\t\t" ), wmiHelper.GetPropertyString( spSoundDevice, _T("Description") ) );
PrintProperty( _T("Manufacturer\t\t" ), wmiHelper.GetPropertyString( spSoundDevice, _T("Manufacturer") ) );
PrintProperty( _T("DeviceId\t\t" ), wmiHelper.GetPropertyString( spSoundDevice, _T("DeviceId") ) );
tcout << std::endl;
}
tcout << std::endl << _T("Physical Memory:") << std::endl;
wmiHelper.GetWMIClassObjectEnum(_T("Win32_PhysicalMemory"), spPhysicalMemoryEnum );
while((SUCCEEDED(hr = spPhysicalMemoryEnum->Next(-1, 1, &spPhysicalMemory, &uReturned))) && (uReturned != 0))
{
PrintProperty( _T("Tag\t\t" ), wmiHelper.GetPropertyString( spPhysicalMemory, _T("Tag") ) );
PrintProperty( _T("Device Locator\t" ), wmiHelper.GetPropertyString( spPhysicalMemory, _T("DeviceLocator") ) );
PrintProperty( _T("Capacity\t" ), wmiHelper.GetPropertyLong( spPhysicalMemory, _T("Capacity") ) );
PrintProperty( _T("Form Factor\t" ), wmiHelper.GetPropertyLong( spPhysicalMemory, _T("FormFactor") ) );
PrintProperty( _T("Memory Type\t" ), wmiHelper.GetPropertyLong( spPhysicalMemory, _T("MemoryType") ) );
PrintProperty( _T("Speed\t\t" ), wmiHelper.GetPropertyLong( spPhysicalMemory, _T("Speed") ) );
PrintProperty( _T("Total Width\t" ), wmiHelper.GetPropertyLong( spPhysicalMemory, _T("TotalWidth") ) );
PrintProperty( _T("Type Detail\t" ), wmiHelper.GetPropertyLong( spPhysicalMemory, _T("TypeDetail") ) );
tcout << std::endl;
}
}
catch(_com_error& e)
{
tcout << e.ErrorMessage( ) << std::endl;
}
}
CoUninitialize( );
return 0;
}
Output:
Quote:
Processor:
Description x86 Family 6 Model 14 Stepping 8
Manufacturer GenuineIntel
ProcessorId BFE9FBFF000006E8
Current Clock Speed 1830
Max Clock Speed 1830
L2 Cache Size 2048
Sound Devices:
Description SigmaTel High Definition Audio CODEC
Manufacturer SigmaTel
DeviceId HDAUDIO\FUNC_01&VEN_8384&DEV_7690&SUBSYS_102801CD&REV_10
22\4&350F0B83&0&0001
Description Bluetooth AV Audio
Manufacturer IVT Corporation
DeviceId ROOT\MEDIA\0000
Description Bluetooth SCO Audio
Manufacturer IVT Corporation
DeviceId ROOT\MEDIA\0001
Physical Memory:
Tag Physical Memory 0
Device Locator DIMM_A
Capacity 1073741824
Form Factor 8
Memory Type 0
Speed 667
Total Width 64
Type Detail 128
Tag Physical Memory 1
Device Locator DIMM_B
Capacity 1073741824
Form Factor 8
Memory Type 0
Speed 667
Total Width 64
Type Detail 128
Re: Getting basic device information
Thanks very much for the ideas guys. Codeplug - your suggestion works perfectly on my laptop machine but for reasons I can't understand, it doesn't find the sound card on my desktop machine :confused: The only thing I can think is that the sound card might be registered as a different kind of device (i.e. something other than an audio device). Is there a GUID that will simply list all the devices, regardless of their type?
Arjay - your code definitely looks promising. After commenting out a few lines (see below) I've been able to run it in my debugger and it successfully lists RME HDSP 9632 which is my sound card !!!
But there's a problem.... I'm compiling under VC++6. Your file WMIHelper.h contains a couple of functions that look something like this:-
Code:
LPCTSTR GetPropertyDate( IWbemClassObjectPtr& rspObject, CComBSTR cbstrPropName )
{
HRESULT hr = S_OK;
CIMTYPE vtType;
CComVariant cvpVal;
m_sTempValue = _T("");
if( FAILED( hr = rspObject->Get( cbstrPropName, 0L, &cvpVal, &vtType, NULL ) ) )
{
throw _com_error( hr );
}
if( ( VT_BSTR == cvpVal.vt ) && ( CIM_DATETIME == vtType ) )
{
m_sTempValue = CString( cvpVal );
}
else
{
m_sTempValue = _T("");
}
return m_sTempValue;
}
VC++ 6 won't let me convert an object of CComVariant into a CString. Can you think of a way to convert it to some other kind of string (e.g. std::string) ?
Re: Getting basic device information
John, I answered your pm before I saw this post. Just use the string conversion macros.
If you are going to use std::string, I'd recommend defining it as 'Tstring' so if you compile for ANSI now and decide to port the code to UNICODE later, the code will continue to work.
Code:
#ifndef _TSTRING
#ifdef _UNICODE
#define Tstring std::wstring
#define Tstringstream std::wstringstream
#define Tfstream std::wfstream
#define Tiostream std::wiostream
#else // #ifdef _UNICODE
#define Tstring std::string
#define Tstringstream std::stringstream
#define Tfstream std::fstream
#define Tiostream std::iostream
#endif // #ifdef _UNICODE
#define _TSTRING
#endif // #ifndef _TSTRING
Given that, the m_sTempValue variable is declared as a Tstring.
Code:
LPCTSTR GetPropertyDate( IWbemClassObjectPtr& rspObject, CComBSTR cbstrPropName )
{
HRESULT hr = S_OK;
CIMTYPE vtType;
CComVariant cvpVal;
m_sTempValue = _T("");
if( FAILED( hr = rspObject->Get( cbstrPropName, 0L, &cvpVal, &vtType, NULL ) ) )
{
throw _com_error( hr );
}
if( ( VT_BSTR == cvpVal.vt ) && ( CIM_DATETIME == vtType ) )
{
// Use the conversion macro to convert the BSTR into a TCHAR
USES_CONVERSION;
m_sTempValue = OLE2T( cvpVal );
}
else
{
m_sTempValue = _T("");
}
return m_sTempValue;
}
Re: Getting basic device information
Thanks so much for persevering with this Arjay. I eventually managed to solve the problem using this line (where m_sTempValue is a Tstring).
Code:
m_sTempValue = OLE2T((unsigned short*)cvpVal.pbstrVal);
I guess this must be something that changed very subtlely sometime after VC++6 since most of my other attempts resulted in C2440: 'type cast' : cannot convert from 'class ATL::CComVariant' to 'unsigned short *'. Still, I got there in the end. :thumb: