ezeke 发表于 2015-5-15 10:51:06

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
5 #include
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         REFIIDriid,
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   REFIIDriid,
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 }
  好啦!以上代码为本人亲测后的代码,可以使用的!如果有什么问题,欢迎来指出~~ 请勿拍砖!!
页: [1]
查看完整版本: Win7系统下C++实现客户端程序单独静音功能