Header文件:
#ifndef __MONITOR_AUDIO_DEVICE__
#define __MONITOR_AUDIO_DEVICE__
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include <mmdeviceapi.h>
#include <Functiondiscoverykeys_devpkey.h>
#include "iostream"
#include <stdio.h>
#include <functional>
using namespace std;
class MonitorAudioDevice : public IMMNotificationClient
{
public:
MonitorAudioDevice();
~MonitorAudioDevice();
public:
void SetCB(void (*pFunc)(const char* pDevName, long nStatus));
private:
bool Init();
void Uninit();
private:
// Private function to print device-friendly name
HRESULT NotifyState(LPCWSTR pwstrId, DWORD nState);
private:
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
private:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface);
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId);
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId);
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId);
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState);
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key);
private:// IUnknown methods -- AddRef, Release, and QueryInterface
LONG m_cRef = 1;
private:
IMMDeviceEnumerator* m_pEnumerator = NULL;
private:
std::function<void(const char*, long)> m_pFunc;
};
#endif
cpp文件:
#include "SingleTon.h"
#include "MonitorAudioDevice.h"
#include "UnicodeToUtf8.h"
MonitorAudioDevice::MonitorAudioDevice()
{
Init();
}
MonitorAudioDevice::~MonitorAudioDevice()
{
Uninit();
}
bool MonitorAudioDevice::Init()
{
// 初始化COM
::CoInitialize(NULL);
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&m_pEnumerator);
if (hr == S_OK) {
hr = m_pEnumerator->RegisterEndpointNotificationCallback((IMMNotificationClient*)this);
if (hr == S_OK) {
return true;
}
}
return false;
}
void MonitorAudioDevice::Uninit()
{
if (m_pEnumerator) {
m_pEnumerator->Release();
m_pEnumerator = NULL;
}
::CoUninitialize();
}
void MonitorAudioDevice::SetCB(void (*pFunc)(const char* pDevName, long nStatus))
{
m_pFunc = pFunc;
}
ULONG STDMETHODCALLTYPE MonitorAudioDevice::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG STDMETHODCALLTYPE MonitorAudioDevice::Release()
{
ULONG ulRef = InterlockedDecrement(&m_cRef);
if (0 == ulRef) {
delete this;
}
return ulRef;
}
HRESULT STDMETHODCALLTYPE MonitorAudioDevice::QueryInterface(REFIID riid, VOID** ppvInterface)
{
if (IID_IUnknown == riid) {
AddRef();
*ppvInterface = (IUnknown*)this;
}
else if (__uuidof(IMMNotificationClient) == riid) {
AddRef();
*ppvInterface = (IMMNotificationClient*)this;
}
else {
*ppvInterface = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE MonitorAudioDevice::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE MonitorAudioDevice::OnDeviceAdded(LPCWSTR pwstrDeviceId)
{
return S_OK;
};
HRESULT STDMETHODCALLTYPE MonitorAudioDevice::OnDeviceRemoved(LPCWSTR pwstrDeviceId)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE MonitorAudioDevice::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState)
{
NotifyState(pwstrDeviceId, dwNewState);
return S_OK;
}
HRESULT STDMETHODCALLTYPE MonitorAudioDevice::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key)
{
return S_OK;
}
HRESULT MonitorAudioDevice::NotifyState(LPCWSTR pwstrId, DWORD nState)
{
::CoInitialize(NULL);
IMMDeviceEnumerator* pEnumerator = NULL;
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
if (hr == S_OK) {
IMMDevice* pDevice = NULL;
hr = pEnumerator->GetDevice(pwstrId, &pDevice);
if (hr == S_OK) {
IPropertyStore* pProps = NULL;
hr = pDevice->OpenPropertyStore(STGM_READ, &pProps);
if (hr == S_OK) {
PROPVARIANT varString;
PropVariantInit(&varString);
hr = pProps->GetValue(PKEY_Device_FriendlyName, &varString);
if (hr == S_OK) {
if (m_pFunc) {
m_pFunc(SingleTon<UnicodeToUtf8>::GetInstance()->UNICODE_TO_UTF8(varString.pwszVal).c_str(), nState);
}
}
PropVariantClear(&varString);
if (pProps) {
pProps->Release();
pProps = NULL;
}
}
if (pDevice) {
pDevice->Release();
pDevice = NULL;
}
}
}
if (pEnumerator) {
pEnumerator->Release();
pEnumerator = NULL;
}
::CoUninitialize();
return S_OK;
}
调用:
__declspec(dllexport) bool __stdcall SetAudioDeviceStatusChangeCB(void (*pFunc)(const char*, long ))
{
g_Monitor.SetCB(pFunc);
return true;
}