win7音訊 audio service調節單個程式音量控制

Martin89發表於2018-03-12

以下程式碼的作用是控制當前程式的聲音,並將其他程式的聲音關閉。

程式碼如下:

[cpp] view plain copy

  1. BOOL SetCurrentProcessVolume(DWORD dwVolume,BOOL IsMixer/*TRUE*/)  
  2. {  
  3.     HRESULT hr <span style="white-space:pre">                 </span>= S_OK;  
  4.     IMMDeviceCollection *pMultiDevice       = NULL;  
  5.     IMMDevice *pDevice              = NULL;  
  6.     IAudioSessionEnumerator *pSessionEnum       = NULL;  
  7.     IAudioSessionManager2 *pASManager       = NULL;  
  8.     IMMDeviceEnumerator *m_pEnumerator      = NULL;  
  9.     const IID IID_ISimpleAudioVolume        = __uuidof(ISimpleAudioVolume);  
  10.     const IID IID_IAudioSessionControl2     = __uuidof(IAudioSessionControl2);  
  11.   
  12.     CoInitialize(NULL);  
  13.     hr = CoCreateGuid(&m_guidMyContext);  
  14.     if(FAILED(hr))  
  15.         return FALSE;  
  16.     // Get enumerator for audio endpoint devices.  
  17.     hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),  
  18.         NULL, CLSCTX_ALL,  
  19.         __uuidof(IMMDeviceEnumerator),  
  20.         (void**)&m_pEnumerator);  
  21.     if(FAILED(hr))  
  22.         return FALSE;  
  23.   
  24.     if (IsMixer)  
  25.     {  
  26.         hr = m_pEnumerator->EnumAudioEndpoints(eRender,DEVICE_STATE_ACTIVE, &pMultiDevice);  
  27.     }   
  28.     else  
  29.     {  
  30.         hr = m_pEnumerator->EnumAudioEndpoints(eCapture,DEVICE_STATE_ACTIVE, &pMultiDevice);  
  31.     }  
  32.     if(FAILED(hr))  
  33.         return FALSE;  
  34.   
  35.     UINT deviceCount = 0;  
  36.     hr = pMultiDevice->GetCount(&deviceCount);        
  37.     if(FAILED(hr))  
  38.         return FALSE;    
  39.       
  40.     if((int)dwVolume < 0)  
  41.         dwVolume = 0;  
  42.     if((int)dwVolume > 100)  
  43.         dwVolume = 100;  
  44.     for (UINT ii=0; ii<deviceCount; ii++)  
  45.     {  
  46.         pDevice = NULL;        
  47.         hr = pMultiDevice->Item(ii,&pDevice);      
  48.         if(FAILED(hr))  
  49.             return FALSE;   
  50.         hr = pDevice->Activate(__uuidof(IAudioSessionManager),CLSCTX_ALL, NULL,(void**)&pASManager);  
  51.   
  52.         if(FAILED(hr))  
  53.             return FALSE;   
  54.         hr = pASManager->GetSessionEnumerator(&pSessionEnum);  
  55.         if(FAILED(hr))  
  56.             return FALSE;   
  57.         int nCount;  
  58.         hr = pSessionEnum->GetCount(&nCount);  
  59.         for (int i = 0; i < nCount; i++)   
  60.         {  
  61.             IAudioSessionControl *pSessionCtrl;  
  62.             hr = pSessionEnum->GetSession(i, &pSessionCtrl);  
  63.             if (FAILED(hr))   
  64.                 continue;  
  65.             IAudioSessionControl2 *pSessionCtrl2;  
  66.             hr = pSessionCtrl->QueryInterface(IID_IAudioSessionControl2, (void **)&pSessionCtrl2);  
  67.             if(FAILED(hr))  
  68.                 continue;  
  69.             ULONG pid;  
  70.             hr = pSessionCtrl2->GetProcessId(&pid);  
  71.             if (FAILED(hr))  
  72.                 continue;  
  73.               
  74.             ISimpleAudioVolume *pSimplevol;  
  75.             hr = pSessionCtrl2->QueryInterface(IID_ISimpleAudioVolume, (void **)&pSimplevol);  
  76.             if (FAILED(hr))   
  77.                 continue;  
  78.             if (pid == GetCurrentProcessId())  
  79.             {                 
  80.                 pSimplevol->SetMasterVolume((float)dwVolume/100, NULL);  
  81.             }  
  82.             else  
  83.             {  
  84.                 pSimplevol->SetMasterVolume((float)0/100, NULL);  
  85.             }  
  86.               
  87.         }         
  88.     }  
  89.     SAFE_RELEASE(m_pEnumerator);  
  90.     return TRUE;  
  91. }  

說明:

1.IMMDeviceEnumerator::EnumAudioEndpoints 

EnumAudioEndpoints 方法用於生成符合指定標準的終端裝置的一個合集。

第一個引數為列舉值,包括以下三個:

eRender:音訊渲染流,從應用程式到裝置終端的流。設定為eRender,獲取播放裝置。

eCapture:音訊捕捉流,從裝置終端到應用程式的流。設定為eCapture,獲取錄音裝置。

eAll:獲取以上兩種。

第二個引數也是列舉值,包括以下幾個:

DEVICE_STATE_ACTIVE:當前啟用的裝置

DEVICE_STATE_DISABLED:當前禁用的裝置

 

DEVICE_STATE_NOTPRESENT:不存在的終端裝置,即已經中系統中刪除的裝置,或者在裝置管理器中禁用的裝置。

DEVICE_STATE_UNPLUGGED:未插電的裝置。

第三個引數,指向裝置集合物件的介面。

2.用GetCount函式獲取裝置總數量

3.用Item函式索引單個裝置。

4.用獲取到的裝置指標,啟用應用程式音量管理指標。

Activate函式

第一個引數:裝置標示符。是對GUID的一個引用,標示請求啟用的介面。呼叫者將使用這個介面與COM物件通訊。

第二個引數:用於管理將要執行的物件,可以將多個列舉值相或來設定,也可以使用CLSCTX_ALL,可以通過指定CLSCTX_ALL避免上下文的限制。

第三個引數:當用來啟用裝置的IAudioClient、IAudioEndpointVolume IAudioMeterInformation IAudioSessionManager或IDeviceTopology這些介面時,設定為NULL。

第四個引數:指向指定介面引數地址的指標。

5.用GetSessionEnumerator獲取IAudioSessionEnumerator指標。其中包含了所有應用程式音量的控制指標。同樣可以用GetCount來獲取到總數。

6.用GetSession獲取IAudioSessionControl指標。以上文的Item函式相似。

7.用QueryInterface通過IAudioSessionControl指標查詢到IAudioSessionControl2指標,根據第一個引數設定的IID的值去查詢相應的指標。

8.獲取到該應用程式的PID

9.用QueryInterface獲取音量控制指標

10.如果當前應用程式的PID與IAudioSessionControl2指標獲取到的PID相等,則裝置當前應用程式的音量。自然,也可以指定PID來控制特定應用程式的音量。

相關文章