Windows音频设备及状态
2022-09-27
214
0
Windows音频设备都在注册表:
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\
下,不过这里存储的是系统中当前存在的和以前存在的音频设备。
当然,在设备管理器中,也可以通过显示隐藏设备来显示。
在设备管理器中,凡是以灰色显示的是当前不在线的设备。
当然,音频设备的枚举也可以通过wasapi来枚举。
不过,我们这里通过注册表来枚举系统中所有的设备,并以通过注册情属性来判断是否存在。
其实原理很简单,就是打开注册表
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\
路径下,根据需要打开render或者capture项,然后枚举注册表项。
vector<wstring> RegistryHelper::enumSubKeys(wstring key)
{
vector<wstring> result;
HKEY keyHandle = openKey(key, KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY);
wchar_t keyName[256];
DWORD keyLength = sizeof(keyName) / sizeof(wchar_t);
int i = 0;
LSTATUS status;
while ((status = RegEnumKeyExW(keyHandle, i++, keyName, &keyLength, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
{
keyLength = sizeof(keyName) / sizeof(wchar_t);
result.push_back(keyName);
}
RegCloseKey(keyHandle);
if (status != ERROR_NO_MORE_ITEMS)
throw RegistryException(L"Error while enumerating sub keys of registry key " + key + L": " + StringHelper::getSystemErrorString(status));
return result;
}
调用方法如下:
vector<wstring> deviceGuidStrings = RegistryHelper::enumSubKeys(0 ? captureKeyPath : renderKeyPath);
当然,在注册表的项上有个状态DeviceState,表示设备的状态信息。
这里的值是:
unsigned long RegistryHelper::readDWORDValue(wstring key, wstring valuename)
{
unsigned long result;
HKEY keyHandle = openKey(key, KEY_QUERY_VALUE | KEY_WOW64_64KEY);
LSTATUS status;
DWORD type;
DWORD bufSize;
status = RegQueryValueExW(keyHandle, valuename.c_str(), NULL, &type, NULL, &bufSize);
if (status != ERROR_SUCCESS)
{
RegCloseKey(keyHandle);
throw RegistryException(L"Error while reading registry value " + key + L"\\" + valuename + L": " + StringHelper::getSystemErrorString(status));
}
if (type != REG_DWORD)
{
RegCloseKey(keyHandle);
throw RegistryException(L"Registry value " + key + L"\\" + valuename + L" has wrong type");
}
BYTE* buf = new BYTE[bufSize];
status = RegQueryValueExW(keyHandle, valuename.c_str(), NULL, NULL, buf, &bufSize);
RegCloseKey(keyHandle);
if (status != ERROR_SUCCESS)
{
delete buf;
throw RegistryException(L"Error while reading registry value " + key + L"\\" + valuename + L": " + StringHelper::getSystemErrorString(status));
}
result = ((unsigned long*)buf)[0];
delete buf;
return result;
}
返回的设备状态devicestate的组合如下:
#define DEVICE_STATE_ACTIVE 0x00000001
#define DEVICE_STATE_DISABLED 0x00000002
#define DEVICE_STATE_NOTPRESENT 0x00000004
#define DEVICE_STATE_UNPLUGGED 0x00000008
#define DEVICE_STATEMASK_ALL 0x0000000f
如不在线的设备可以用如下判断:
unsigned long deviceState = RegistryHelper::readDWORDValue(keyPath, L"DeviceState");
if (deviceState & DEVICE_STATE_NOTPRESENT)
return false;