0CCh Blog

Windows7下控制单个进程音量的小技巧

2013-09-10_200213

如上图所示,Windows7下有一个很有趣的功能,就是可以给单独的进程调节音量。出于好奇,在网上翻了下资料,原来这个功能要归功于Windows7上新的音频接口——Core Audio APIs。这套API是用COM写,各种接口也比较多。但是如果我们的目的只是控制单个进程的音量,那还是很简单的。接下来的代码就是控制进程音量的函数了。

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioSessionManager2 = __uuidof(IAudioSessionManager2);
const IID IID_IAudioSessionControl2 = __uuidof(IAudioSessionControl2);
const IID IID_ISimpleAudioVolume = __uuidof(ISimpleAudioVolume);

BOOL SetProcessVolume(ULONG target_pid, float level)
{
CComPtr imm_dev_enumor;

HRESULT hr = imm_dev_enumor.CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL);

if (FAILED(hr)) {
return FALSE;
}

CComPtr imm_dev;
hr = imm_dev_enumor->GetDefaultAudioEndpoint(eRender, eMultimedia, &imm;_dev.p);
if (FAILED(hr)) {
return FALSE;
}

CComPtr session_mgr2;
hr = imm_dev->Activate(IID_IAudioSessionManager2, CLSCTX_ALL, NULL, (void **)&session;_mgr2.p);
if (FAILED(hr)) {
return FALSE;
}

CComPtr session_enumor;
hr = session_mgr2->GetSessionEnumerator(&session;_enumor.p);
if (FAILED(hr)) {
return FALSE;
}

int count;
if (FAILED(hr)) {
return FALSE;
}

hr = session_enumor->GetCount(&count;);
for (int i = 0; i < count; i++) {
CComPtr session_ctrl;
hr = session_enumor->GetSession(i, &session;_ctrl.p);
if (FAILED(hr)) {
continue;
}

CComPtr session_ctrl2;
hr = session_ctrl->QueryInterface(IID_IAudioSessionControl2, (void **)&session;_ctrl2.p);
if (FAILED(hr)) {

}

ULONG pid;
hr = session_ctrl2->GetProcessId(&pid;);
if (FAILED(hr)) {
continue;
}


if (pid != target_pid) {
continue;
}

CComPtr simple_vol;
hr = session_ctrl2->QueryInterface(IID_ISimpleAudioVolume, (void **)&simple;_vol.p);
if (FAILED(hr)) {
continue;
}

simple_vol->SetMasterVolume(level, NULL);
}

return TRUE;
}