Controlling the volume of other applications

2019-02-25 09:35发布

问题:

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 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.

回答1:

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;
}


回答2:

There is an MSDN forum question and Blog Post about this very question. Hope this helps.



回答3:

According to Larry Osterman

"There is no publicly documented mechanism for doing what you're trying to do."