Controlling the volume of other applications
I am trying to make an app that controls the volume of another process using the Windows 7 Audio API.
What I'm looking for is the ISimpleAudioVolume for the session used by the other process.
I have tried using the 开发者_Python百科IAudioSessionEnumerator but it will only give me the IAudioSessionControl2 of the session. Using the IAudioSessionControl I have managed to receive notifications when I change the volume through sndvol but not change it myself.
I have also tried using GetSimpleAudioVolume() from IAudioSessionManager but it will only give me sessions within the current process.
How do you do it? It should be possible since sndvol is doing this.
Here is an example of muting another process using Core Audio API.
#include <windows.h>
#include <iostream>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <Audiopolicy.h>
#include <comdef.h>
#include <comip.h>
#define CHECK_HR(hr) \
if(FAILED(hr)) { \
std::cout << "error" << std::endl; \
return 0; \
}
_COM_SMARTPTR_TYPEDEF(IMMDevice, __uuidof(IMMDevice));
_COM_SMARTPTR_TYPEDEF(IMMDeviceEnumerator, __uuidof(IMMDeviceEnumerator));
_COM_SMARTPTR_TYPEDEF(IAudioSessionManager2, __uuidof(IAudioSessionManager2));
_COM_SMARTPTR_TYPEDEF(IAudioSessionManager2, __uuidof(IAudioSessionManager2));
_COM_SMARTPTR_TYPEDEF(IAudioSessionEnumerator, __uuidof(IAudioSessionEnumerator));
_COM_SMARTPTR_TYPEDEF(IAudioSessionControl2, __uuidof(IAudioSessionControl2));
_COM_SMARTPTR_TYPEDEF(IAudioSessionControl, __uuidof(IAudioSessionControl));
_COM_SMARTPTR_TYPEDEF(ISimpleAudioVolume, __uuidof(ISimpleAudioVolume));
IAudioSessionManager2Ptr CreateSessionManager()
{
HRESULT hr = S_OK;
IMMDevicePtr pDevice;
IMMDeviceEnumeratorPtr pEnumerator;
IAudioSessionManager2Ptr pSessionManager;
// Create the device enumerator.
CHECK_HR(hr = CoCreateInstance(
__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnumerator));
// Get the default audio device.
CHECK_HR(hr = pEnumerator->GetDefaultAudioEndpoint(
eRender, eConsole, &pDevice));
// Get the session manager.
CHECK_HR(hr = pDevice->Activate(
__uuidof(IAudioSessionManager2), CLSCTX_ALL,
NULL, (void**)&pSessionManager));
return pSessionManager;
}
bool MuteProcess(DWORD processId) {
IAudioSessionManager2Ptr mgr = CreateSessionManager();
if (!mgr) {
return false;
}
IAudioSessionEnumeratorPtr enumerator;
if (SUCCEEDED(mgr->GetSessionEnumerator(&enumerator))) {
int sessionCount;
if (SUCCEEDED(enumerator->GetCount(&sessionCount))) {
for (int i = 0; i < sessionCount; i++) {
IAudioSessionControlPtr control;
if (SUCCEEDED(enumerator->GetSession(i, &control))) {
IAudioSessionControl2Ptr control2;
if (SUCCEEDED(control->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&control2))) {
DWORD foundProcessId;
if (SUCCEEDED(control2->GetProcessId(&foundProcessId))) {
if (foundProcessId == processId) {
ISimpleAudioVolumePtr volume;
if (SUCCEEDED(control2->QueryInterface(_uuidof(ISimpleAudioVolume), (void**)&volume))) {
if (SUCCEEDED(volume->SetMute(TRUE, 0))) {
return true;
}
}
}
}
}
}
}
}
}
return false;
}
int _tmain(int argc, _TCHAR* argv[]){
CoInitialize(NULL);
DWORD processId = 11944;
MuteProcess(processId);
return 0;
}
There is an MSDN forum question and Blog Post about this very question. Hope this helps.
According to Larry Osterman
"There is no publicly documented mechanism for doing what you're trying to do."
精彩评论