Win7系统下C++实现客户端程序单独静音功能
本文主要是作为学习笔记而编写的,同时也希望能帮助需要的人!!
实现这个功能是为了解决公司浏览器中Win7下不能静音的BUG。搜索了很多网页,都没有找到这方面的实现!但我心里很清楚,一定是有方法解决这个问题的。所以,在心情还算良好的情况下,静下心来查看MSDN的英文介绍,果然让我找到了这个!Core Audio API——Win7系统以后才有的。而该库的相关中文介绍,可以参考以下文章:
1. http://caicaioffice.blog.163.com/blog/static/1417910220094154269427/
2.http://caicaioffice.blog.163.com/blog/static/14179102200941542637752/
通过看上面的文章,虽然能够实现设备音量的控制,但貌似还是木有针对一个程序来控制其静音,所以,只能靠MSDN帮忙了!
要实现客户端程序真正的单独静音,我们必须考虑以下两点:
1. 从客户端程序设置单独静音
提到客户端程序音量控制,首先就需要获取程序IAudioSessionManager会话(Session)。然后再通过调用会话对应的ISimpleAudioVolume中的SetMute函数,就可以设置客户端程序是否静音了。整个代码都先给出:
在TxMuted.h文件中的代码:
1 #ifndef TXMUTED_H 2 #define TXMUTED_H 3 4 #include "Mmdeviceapi.h" 5 #include "Audiopolicy.h" 6 7 // 初始化静音 8 IMMDeviceEnumerator* TxInitMuted(); 9 10 // 释放 11 bool TxUnMuted(); 12 13 // 设置静音 14 bool TxSetMuted(bool bMuted); 15 16 // 是否为Win7系统 17 BOOL IsWindows7(); 18 19 #endif
在TxMuted.cpp中的代码
1 #include "StdAfx.h" 2 #include "TxMuted.h" 3 #include "MutedSessionEvent.h" 4 5 extern volatile bool g_bMuted; 6 7 static IMMDeviceEnumerator* m_pEnumerator = NULL; 8 static IMMDevice* m_pDeviceOut = NULL; 9 static IAudioSessionManager* m_AudioSessionManager = NULL; 10 static IAudioSessionControl* m_AudioSessionControl = NULL; 11 static CMutedSessionEvents * m_pMutedSessionEvents = NULL; 12 13 BOOL IsWindows7() 14 { 15 OSVERSIONINFO osinfo; 16 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 17 18 if (!GetVersionEx(&osinfo)) 19 return FALSE; 20 21 DWORD dwPlatformId = osinfo.dwPlatformId; 22 DWORD dwMinorVersion = osinfo.dwMinorVersion; 23 DWORD dwMajorVersion = osinfo.dwMajorVersion; 24 DWORD dwBuildNumber = osinfo.dwBuildNumber & 0xFFFF; // Win 95 needs this 25 26 if (dwPlatformId == 2) 27 { 28 if ((dwMajorVersion == 6) && (dwMinorVersion == 1)) 29 { 30 return TRUE; 31 } 32 } 33 return FALSE; 34 } 35 36 IMMDeviceEnumerator* TxInitMuted() 37 { 38 CoInitializeEx( NULL , COINIT_MULTITHREADED ); 39 40 HRESULT hr; 41 42 //实例化 MMDeviceEnumerator 枚举器 43 hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),(void**)&m_pEnumerator); 44 if(FAILED(hr)) 45 { 46 return NULL; 47 } 48 49 // 默认设备的IMMDevice接口 50 hr = m_pEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_pDeviceOut); 51 if (FAILED(hr)) return false; 52 53 // 得到音频会话接口IAudioSessionManager 54 hr = m_pDeviceOut->Activate(__uuidof(m_AudioSessionManager), CLSCTX_ALL, NULL, (void**)&m_AudioSessionManager); 55 if (FAILED(hr)) return false; 56 57 // 设置会话(Session)参数 58 hr = m_AudioSessionManager->GetAudioSessionControl(NULL,0,&m_AudioSessionControl); 59 if (FAILED(hr)) return false; 60 61 // 设置声音改变参数通知 62 m_pMutedSessionEvents = new CMutedSessionEvents(m_AudioSessionManager); 63 hr = m_AudioSessionControl->RegisterAudioSessionNotification(m_pMutedSessionEvents); 64 if (FAILED(hr)) return false; 65 66 return m_pEnumerator; 67 } 68 69 bool TxUnMuted() 70 { 71 // ---- 解注册声音改变参数通知 72 if (m_AudioSessionControl!=NULL&&m_pMutedSessionEvents!=NULL) 73 { 74 m_AudioSessionControl->UnregisterAudioSessionNotification(m_pMutedSessionEvents); 75 } 76 77 // ---- 释放内存空间 78 if (m_AudioSessionControl != NULL) 79 { 80 m_AudioSessionControl->Release(); 81 m_AudioSessionControl = NULL; 82 } 83 if (m_pMutedSessionEvents != NULL) 84 { 85 m_pMutedSessionEvents->Release(); 86 m_pMutedSessionEvents = NULL; 87 } 88 if (m_pDeviceOut != NULL) 89 { 90 m_pDeviceOut->Release(); 91 m_pDeviceOut = NULL; 92 } 93 if(m_AudioSessionManager != NULL) 94 { 95 m_AudioSessionManager->Release(); 96 m_AudioSessionManager = NULL; 97 } 98 if (m_pEnumerator != NULL) 99 { 100 m_pEnumerator->Release(); 101 m_pEnumerator = NULL; 102 } 103 104 CoUninitialize(); 105 106 return true; 107 } 108 109 bool TxSetMuted(bool bMuted) 110 { 111 HRESULT hr = S_FALSE; 112 113 // 获得音量、静音控制接口 114 ISimpleAudioVolume *pAudioVolume = NULL; 115 hr = m_AudioSessionManager->GetSimpleAudioVolume(NULL,0,&pAudioVolume); 116 if (FAILED(hr)) return false; 117 118 if(SUCCEEDED(hr)) 119 { 120 pAudioVolume->SetMute(bMuted, &GUID_NULL); 121 122 // 更改全局静音状态 123 g_bMuted = bMuted; 124 } 125 126 if (pAudioVolume != NULL) 127 { 128 pAudioVolume->Release(); 129 pAudioVolume = NULL; 130 } 131 return true; 132 }
2.不允许用户从系统合成器中改变程序静音状态
对于这个功能,就得涉及到IAudioSessionEvents接口啦!主要是参考MSDN上的例子做的。废话不多说,直接贴代码了!
在MutedSessionEvents.h文件中的代码
1 #ifndef MUTEDSESSIONEVENT_H 2 #define MUTEDSESSIONEVENT_H 3 4 #include <mmdeviceapi.h> 5 #include <Audiopolicy.h> 6 7 class CMutedSessionEvents : public IAudioSessionEvents 8 { 9 public: 10 CMutedSessionEvents(IAudioSessionManager* pAudioSessionManager ); 11 ~CMutedSessionEvents(){} 12 13 // IUnknown methods -- AddRef, Release, and QueryInterface 14 15 ULONG STDMETHODCALLTYPE AddRef(){return InterlockedIncrement(&_cRef);} 16 17 ULONG STDMETHODCALLTYPE Release(); 18 19 HRESULT STDMETHODCALLTYPE QueryInterface( 20 REFIID riid, 21 VOID **ppvInterface); 22 23 // Notification methods for audio session events 24 25 HRESULT STDMETHODCALLTYPE OnDisplayNameChanged( 26 LPCWSTR NewDisplayName, 27 LPCGUID EventContext) 28 { 29 return S_OK; 30 } 31 32 HRESULT STDMETHODCALLTYPE OnIconPathChanged( 33 LPCWSTR NewIconPath, 34 LPCGUID EventContext) 35 { 36 return S_OK; 37 } 38 39 HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged( 40 float NewVolume, 41 BOOL NewMute, 42 LPCGUID EventContext); 43 44 HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged( 45 DWORD ChannelCount, 46 float NewChannelVolumeArray[], 47 DWORD ChangedChannel, 48 LPCGUID EventContext) 49 { 50 return S_OK; 51 } 52 53 HRESULT STDMETHODCALLTYPE OnGroupingParamChanged( 54 LPCGUID NewGroupingParam, 55 LPCGUID EventContext) 56 { 57 return S_OK; 58 } 59 60 HRESULT STDMETHODCALLTYPE OnStateChanged( 61 AudioSessionState NewState) 62 { 63 return S_OK; 64 } 65 66 HRESULT STDMETHODCALLTYPE OnSessionDisconnected( 67 AudioSessionDisconnectReason DisconnectReason) 68 { 69 return S_OK; 70 } 71 72 bool TxSetMuted(bool bMuted); 73 74 private: 75 LONG _cRef; 76 77 private: 78 IAudioSessionManager* m_AudioSessionManager; 79 }; 80 81 #endif
在MutedSessionEvents.cpp文件中的代码
1 #include "stdafx.h" 2 #include "MutedSessionEvent.h" 3 4 extern volatile bool g_bMuted; 5 6 CMutedSessionEvents::CMutedSessionEvents(IAudioSessionManager* pAudioSessionManager) 7 { 8 m_AudioSessionManager = pAudioSessionManager; 9 _cRef = 1; 10 } 11 12 ULONG STDMETHODCALLTYPE CMutedSessionEvents::Release() 13 { 14 ULONG ulRef = InterlockedDecrement(&_cRef); 15 if (0 == ulRef) 16 { 17 delete this; 18 } 19 return ulRef; 20 } 21 22 HRESULT STDMETHODCALLTYPE CMutedSessionEvents::QueryInterface( 23 REFIID riid, 24 VOID **ppvInterface) 25 { 26 if (IID_IUnknown == riid) 27 { 28 AddRef(); 29 *ppvInterface = (IUnknown*)this; 30 } 31 else if (__uuidof(IAudioSessionEvents) == riid) 32 { 33 AddRef(); 34 *ppvInterface = (IAudioSessionEvents*)this; 35 } 36 else 37 { 38 *ppvInterface = NULL; 39 return E_NOINTERFACE; 40 } 41 return S_OK; 42 } 43 44 HRESULT STDMETHODCALLTYPE CMutedSessionEvents::OnSimpleVolumeChanged( 45 float NewVolume, 46 BOOL NewMute, 47 LPCGUID EventContext) 48 { 49 // 防止其它程序对静音篡改 50 if ((BOOL)g_bMuted != NewMute) 51 { 52 TxSetMuted(g_bMuted); 53 } 54 55 return S_OK; 56 } 57 58 bool CMutedSessionEvents::TxSetMuted(bool bMuted) 59 { 60 HRESULT hr = S_FALSE; 61 62 // 获得音量、静音控制接口 63 ISimpleAudioVolume *pAudioVolume = NULL; 64 hr = m_AudioSessionManager->GetSimpleAudioVolume(NULL,0,&pAudioVolume); 65 if (FAILED(hr)) return false; 66 67 if(SUCCEEDED(hr)) 68 { 69 pAudioVolume->SetMute(bMuted, &GUID_NULL); 70 71 // 更改全局静音状态 72 g_bMuted = bMuted; 73 } 74 75 if (pAudioVolume != NULL) 76 { 77 pAudioVolume->Release(); 78 pAudioVolume = NULL; 79 } 80 return true; 81 }
好啦!以上代码为本人亲测后的代码,可以使用的!如果有什么问题,欢迎来指出~~ 请勿拍砖!!