一、注意事项

1、获取音频设备需要调用CoInitialize以及CoUninitialize。

2、由于C++没有finally关键字,代码中的CUSTOM_FINALLY为自定义宏,是为了实现类似try...catch...finally的效果,本身没有什么意义:

//定义空宏,处理finally
#ifndef CUSTOM_FINALLY
#define CUSTOM_FINALLY
#endif // CUSTOM_FINALLY

3、打印日志宏:

#define PNTLOG(format, ...) wprintf(format L"\n", __VA_ARGS__)
#define PNTERR(format, ...) PNTLOG(L"Error: " format, __VA_ARGS__)
#define PNTERRMSG(msg) wprintf(L"Error: %s \n", msg)

4、PKEY_Device_FriendlyName需要引用相应的头文件:

#include <functiondiscoverykeys_devpkey.h>

5、获取扬声器设备使用eRender枚举类型,获取麦克风设备使用eCapture枚举类型。

二、代码

1、获取默认扬声器

(1)获取设备指针

bool GetDefaultDevice(IMMDevice **ppMMDevice)
{bool ret = false;IMMDeviceEnumerator *pMMDeviceEnumerator = nullptr;wchar_t wszErrMsg[MAX_PATH] = { 0 };try{HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL,__uuidof(IMMDeviceEnumerator),reinterpret_cast<void**>(&pMMDeviceEnumerator));if (FAILED(hr)){wsprintf(wszErrMsg, L"CoCreateInstance(IMMDeviceEnumerator) failed: hr = 0x%08x", hr);throw std::exception();}// get the default render endpointhr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, ppMMDevice);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceEnumerator::GetDefaultAudioEndpoint failed: hr = 0x%08x", hr);throw std::exception();}ret = true;}catch(std::exception&){PNTERRMSG(wszErrMsg);}//释放资源CUSTOM_FINALLY{if (pMMDeviceEnumerator != nullptr){pMMDeviceEnumerator->Release();}}return ret;
}

(2)获取设备Id和名称

bool GetDefaultDevice(wstring& deviceId, wstring& deviceName)
{IMMDevice* pMMDevice = nullptr;if (!GetDefaultDevice(&pMMDevice)){return false;}bool ret = true;wchar_t wszErrMsg[MAX_PATH] = { 0 };HRESULT hr;IPropertyStore* pPropertyStore = nullptr;PROPVARIANT pv;PropVariantInit(&pv);try{LPWSTR pwszDeviceId = nullptr;hr = pMMDevice->GetId(&pwszDeviceId);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDevice::GetId failed: hr = 0x%08x", hr);throw;}// open the property store on that devicehr = pMMDevice->OpenPropertyStore(STGM_READ, &pPropertyStore);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDevice::OpenPropertyStore failed: hr = 0x%08x", hr);throw;}// get the long name propertyhr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv);if (FAILED(hr)){wsprintf(wszErrMsg, L"IPropertyStore::GetValue failed: hr = 0x%08x", hr);throw;}if (VT_LPWSTR != pv.vt){wsprintf(wszErrMsg, L"PKEY_Device_FriendlyName variant type is %u - expected VT_LPWSTR", pv.vt);throw;}deviceId = pwszDeviceId;deviceName = pv.pwszVal;}catch (std::exception&){PNTERRMSG(wszErrMsg);ret = false;}//释放资源CUSTOM_FINALLY{if (pMMDevice != nullptr){pMMDevice->Release();}if (pPropertyStore != nullptr){pPropertyStore->Release();}if (pv.vt != VT_EMPTY){hr = PropVariantClear(&pv);if (FAILED(hr)){PNTERR(L"PropVariantClear failed: hr = 0x%08x", hr);ret = false;}}}return ret;
}

2、获取设备列表

bool GetDevices(map<wstring, wstring>& deviceMap)
{deviceMap.clear();bool ret = false;wchar_t wszErrMsg[MAX_PATH] = { 0 };IMMDeviceEnumerator *pMMDeviceEnumerator = nullptr;IMMDeviceCollection *pMMDeviceCollection = nullptr;  try{HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL,__uuidof(IMMDeviceEnumerator),reinterpret_cast<void**>(&pMMDeviceEnumerator));if (FAILED(hr)){wsprintf(wszErrMsg, L"CoCreateInstance(IMMDeviceEnumerator) failed: hr = 0x%08x", hr);throw std::exception();}// get all the active render endpointshr = pMMDeviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pMMDeviceCollection);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceEnumerator::EnumAudioEndpoints failed: hr = 0x%08x", hr);throw std::exception();}ret = GetDevices(pMMDeviceCollection, deviceMap);}catch (std::exception&){PNTERRMSG(wszErrMsg);}//释放资源CUSTOM_FINALLY{if (pMMDeviceEnumerator != nullptr){pMMDeviceEnumerator->Release();}if (pMMDeviceCollection != nullptr){pMMDeviceCollection->Release();}}return ret;
}bool GetDevices(IMMDeviceCollection *pMMDeviceCollection, map<wstring, wstring>& deviceMap)
{bool ret = true;wchar_t wszErrMsg[MAX_PATH] = { 0 };UINT count;HRESULT hr = pMMDeviceCollection->GetCount(&count);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceCollection::GetCount failed: hr = 0x%08x", hr);PNTERRMSG(wszErrMsg);return false;}PNTLOG(L"Active render endpoints found: %u", count);for (UINT i = 0; i < count; i++){      IMMDevice *pMMDevice = nullptr;IPropertyStore *pPropertyStore = nullptr;PROPVARIANT pv;PropVariantInit(&pv);try{// get the "n"th devicehr = pMMDeviceCollection->Item(i, &pMMDevice);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceCollection::Item failed: hr = 0x%08x", hr);throw;}LPWSTR pwszDeviceId = nullptr;hr = pMMDevice->GetId(&pwszDeviceId);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceCollection::GetId failed: hr = 0x%08x", hr);throw;}// open the property store on that devicehr = pMMDevice->OpenPropertyStore(STGM_READ, &pPropertyStore);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDevice::OpenPropertyStore failed: hr = 0x%08x", hr);throw;}// get the long name propertyhr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv);if (FAILED(hr)){wsprintf(wszErrMsg, L"IPropertyStore::GetValue failed: hr = 0x%08x", hr);throw;}if (VT_LPWSTR != pv.vt){wsprintf(wszErrMsg, L"PKEY_Device_FriendlyName variant type is %u - expected VT_LPWSTR", pv.vt);throw;}deviceMap[pwszDeviceId] = pv.pwszVal;PNTLOG(L"    %ls", pv.pwszVal);}catch (std::exception&){PNTERRMSG(wszErrMsg);ret = false;}//释放资源CUSTOM_FINALLY{if (pMMDevice != nullptr){pMMDevice->Release();}if (pPropertyStore != nullptr){pPropertyStore->Release();}if (pv.vt != VT_EMPTY){hr = PropVariantClear(&pv);if (FAILED(hr)){PNTERR(L"PropVariantClear failed: hr = 0x%08x", hr);ret = false;}}}//出现异常if (!ret){break;}}return ret;
}

3、获取指定设备

bool GetSpecificDevice(LPCWSTR pwszLongName, IMMDevice **ppMMDevice)
{bool ret = false;wchar_t wszErrMsg[MAX_PATH] = { 0 };IMMDeviceEnumerator *pMMDeviceEnumerator = nullptr;IMMDeviceCollection *pMMDeviceCollection = nullptr;*ppMMDevice = nullptr;try{HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL,__uuidof(IMMDeviceEnumerator),reinterpret_cast<void**>(&pMMDeviceEnumerator));if (FAILED(hr)){wsprintf(wszErrMsg, L"CoCreateInstance(IMMDeviceEnumerator) failed: hr = 0x%08x", hr);throw std::exception();}// get all the active render endpointshr = pMMDeviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pMMDeviceCollection);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceEnumerator::EnumAudioEndpoints failed: hr = 0x%08x", hr);throw std::exception();}ret = GetSpecificDevice(pMMDeviceCollection, pwszLongName, ppMMDevice);}catch (std::exception&){PNTERRMSG(wszErrMsg);}//释放资源CUSTOM_FINALLY{if (pMMDeviceEnumerator != nullptr){pMMDeviceEnumerator->Release();}if (pMMDeviceCollection != nullptr){pMMDeviceCollection->Release();}}return ret;
}bool GetSpecificDevice(IMMDeviceCollection *pMMDeviceCollection, LPCWSTR pwszLongName, IMMDevice **ppMMDevice)
{bool ret = true;wchar_t wszErrMsg[MAX_PATH] = { 0 };UINT count;HRESULT hr = pMMDeviceCollection->GetCount(&count);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceCollection::GetCount failed: hr = 0x%08x", hr);PNTERRMSG(wszErrMsg);return false;}PNTLOG(L"Active render endpoints found: %u", count);for (UINT i = 0; i < count; i++){IMMDevice *pMMDevice = nullptr;IPropertyStore *pPropertyStore = nullptr;PROPVARIANT pv;PropVariantInit(&pv);try{// get the "n"th devicehr = pMMDeviceCollection->Item(i, &pMMDevice);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDeviceCollection::Item failed: hr = 0x%08x", hr);throw;}// open the property store on that devicehr = pMMDevice->OpenPropertyStore(STGM_READ, &pPropertyStore);if (FAILED(hr)){wsprintf(wszErrMsg, L"IMMDevice::OpenPropertyStore failed: hr = 0x%08x", hr);throw;}// get the long name propertyhr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv);if (FAILED(hr)){wsprintf(wszErrMsg, L"IPropertyStore::GetValue failed: hr = 0x%08x", hr);throw;}if (VT_LPWSTR != pv.vt){wsprintf(wszErrMsg, L"PKEY_Device_FriendlyName variant type is %u - expected VT_LPWSTR", pv.vt);throw;}// is it a match?if (0 == _wcsicmp(pv.pwszVal, pwszLongName)){// did we already find it?if (nullptr == *ppMMDevice){*ppMMDevice = pMMDevice;pMMDevice->AddRef();}else{wsprintf(wszErrMsg, L"Found (at least) two devices named %ls", pwszLongName);throw;}}}catch (std::exception&){PNTERRMSG(wszErrMsg);ret = false;}//释放资源CUSTOM_FINALLY{if (pMMDevice != nullptr){pMMDevice->Release();}if (pPropertyStore != nullptr){pPropertyStore->Release();}if (pv.vt != VT_EMPTY){hr = PropVariantClear(&pv);if (FAILED(hr)){PNTERR(L"PropVariantClear failed: hr = 0x%08x", hr);ret = false;}}}//出现异常if (!ret){if (*ppMMDevice != nullptr){(*ppMMDevice)->Release();}break;}}if (nullptr == *ppMMDevice){PNTERR(L"Could not find a device named %ls", pwszLongName);}return ret;
}

C++获取Windows音频设备列表相关推荐

  1. Python 对os.listdir()获取的文件列表进行 Windows 的按名称方式排序,natsort 库的应用

    Python 对os.listdir()获取的文件列表进行 Windows 的按名称方式排序,natsort 库的应用 1.前言 日前,使用os.listdir()读取一个文件夹下的所有文件和子文件夹 ...

  2. C++操作windows注册列表

    为什么80%的码农都做不了架构师?>>>    我需要查找某程序的安装目录,首先想到的是如果正常安装,不需要遍历整个文件树,直接通过注册列表的查询就可以读取程序的安装目录,看了看网络 ...

  3. android SDK manager 无法获取更新版本列表【转载】

    http://mirrors.neusoft.edu.cn/eclipse/releases/luna/ 打开这个网址就可以看到adt的详细信息:  http://developer.android. ...

  4. VB获取windows各常用目录的函数(模块)

            以下的函数,可以用来获取windows 诸如"windows.temp.sendto.desktop.开始菜单" 等目录. -------------------- ...

  5. 获取windows程序界面数据

    文章目录 结论 可以尝试的其他方向 最后的挣扎 基础知识 win7/win10查看某个进程的句柄数 句柄的概念 Windows MFC.SDK和API的区别和联系 Windows MFC(C++开发) ...

  6. android之网络请求 -- 获取RecyclerView的列表项(图片 + 文字)

    android之网络请求 -- 获取RecyclerView的列表项 示意图,网络请求的地址,插件及依赖 代码架构 代码内容 MainActivity.java activity_main.xml R ...

  7. Resilio Sync 无法获取追踪器列表 解决方法

    以下解决方法来自于Resilio Sync官网 最近频繁收到用户反馈 使用Resilio Sync 最新版过程中出现了:"无法获取追踪器列表/ cannot get the list of ...

  8. C# 获取Windows系统ICON图标的四种方式-可提取各种文件夹、文件等等图标

    本文介绍的是提取Windows系统内部Icon图标的方法,就是系统资源管理器里面显示的图标,包括文件夹.文件,如:常规文件夹的图标.特定文件夹图标(磁盘根目录.收藏夹.网络共享目录等).各文件类型图标 ...

  9. el-tree实现类似windows文件列表,并支持折叠、展开和重命名

    el-tree实现类似windows文件列表,并支持折叠.展开和重命名 1.需求: 后台管理系统的左侧导航菜单中文件管理下是个文件夹列表树, UI给的设计稿是这样的 实现:左侧用了element的el ...

最新文章

  1. R语言自定义多分类混淆矩阵可视化函数(mutlti class confusion matrix)、R语言多分类混淆矩阵可视化
  2. amqp协议_AMQP协议、模型及RabbitMQ常用组件
  3. Windows 95 诞生 25 周年
  4. php+sqlrelay+mysql实现连接池及读写负载均衡
  5. 在mac上命令行里面如何打开文本编辑器?
  6. codevs 2924 数独挑战
  7. python画玫瑰图_央视都在用的“南丁格尔玫瑰图”,原来Python也可以画
  8. System.IO 的三个抽象类
  9. java面试题二十 try catch
  10. 内核抢占,让世界变得更美好 | Linux 内核
  11. 《锋利的jQuery》要点归纳(五)jQuery与ajax的应用(上)
  12. mongodb(2) 1
  13. CSS属性值之百分数
  14. 用 Doc2Vec 得到文档/段落/句子的向量表达
  15. php zip类,php ZIP压缩类实例步骤详解
  16. 虚拟机ip、主机ip、代理ip
  17. Processing 案例 | 三角函数之美
  18. 此windows副本不是正版
  19. 五个真实的数据挖掘故事
  20. 3D中的OBJ文件格式详解

热门文章

  1. 看这里看这里:结构体的超级详细讲解
  2. 解决ORA-01033: ORACLE initialization or shutdown in progress
  3. 隐藏手机号的方法总结
  4. 论文笔记 | CT影像结节分割研究进展
  5. STM32软件学习笔记(一)基于HAL库的STM32F429单片机串口打印程序
  6. rf2o_laser_odometry常见问题
  7. Linux命令之nc命令
  8. 调用QQ客服对话聊天窗口:
  9. 403 Forbidden You don‘t have permission to access this resource. Apache Server at IP Port 80的解决方法
  10. 电路与模拟电子技术第三章(要点及部分习题)