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文件中的代码:

View Code
 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中的代码

View Code
  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文件中的代码

View Code
 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文件中的代码

View Code
 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 }

  好啦!以上代码为本人亲测后的代码,可以使用的!如果有什么问题,欢迎来指出~~ 请勿拍砖!!

posted @ 2012-10-09 17:03  梦不醒  阅读(2177)  评论(1编辑  收藏  举报