设置WMP音量 [英] Set WMP volume level

查看:150
本文介绍了设置WMP音量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要设置Windows Media Player的音量.默认情况下,例如单击向下或向上菜单项(播放->音量->向上),但我认为这还不够好(尤其是在听音乐时与某人进行Skype跳舞时).

What i want to do is set the Windows Media Player's volume level. By default the volume is in-/decreased by 10% when e.g. clicking the down or up menu item (Play -> Volume -> Up), but this is, in my opinion, not fine enough (especially when e.g. skypeing with someone while listening to music).

媒体播放器应保持独立的应用程序.
目前,我正在使用一个小工具,该工具通过SendMessage将具有spy ++中所示参数的应用程序命令发送到播放器.

The media player should stay an independent application.
Currently i'm using a little tool that sends app commands via SendMessage to the player with parameters as seen in spy++.

我想到了三种实现目标的方法:

I thought of three ways to achieve my goal:

  • 使用WASAPI获取媒体播放器的音频会话并动态设置音量级别
  • 按点将鼠标下移/上移事件发送到媒体播放器主机控件的音量滑块
  • 通过IWMPPlayer4获取媒体播放器控件的实例
  • 在Windows窗体宿主中的WPF应用程序中包含媒体播放器控件(由于失去独立性,因此不推荐使用)

第2点看起来很丑陋,因为媒体播放器控件是一个COM元素,而spy ++仅显示一个手柄,这意味着我必须确定音量滑块的确切位置并发送非常精确的鼠标事件.另外我不知道这是否行得通.

Point 2 seems rather ugly due to the fact that the media player control is a COM element and has as far spy++ displays only one handle, meaning i would have to determine the exact position of the volume slider and send very precise mouse events. Additional i don't know whether this would work at all.

第3点的前提是可以通过句柄获取COM元素的实例.由于我尚未使用COM元素,因此我不知道这是否可行.
更新:人们可以使用IWMPPlayer4界面获取远程中介播放器的实例.虽然我必须看看是否可以更改设置.

Point 3 has the presupposition that one can get an instance of a COM element by a handle. Since i have yet not worked with COM elements i don't know if this is possible.
Update: One can get an instance of a remote mediay player using the IWMPPlayer4 interface. Though i have to see whether one can change settings.

第1点给我的印象是,无需付出太多努力就可以实现. 尽管我将面临下一个问题:确定媒体播放器的音频会话.使用IAudioSessionManager2枚举它们,并使用

Point 1 has the impression on me that it would be possible without much effort. Though i'd be facing the next problem: identifying the media players audio session. Enumerating them using IAudioSessionManager2 and displaying the name using

IAudioSessionControl2 ctrl2 = NULL;
// ...
hr = ctrl2->GetDisplayName(&name);

if (FAILED(hr))
{
    SafeRelease(ctrl);
    SafeRelease(ctrl2);
    continue;
}

String ^sessionName = gcnew String(name);
Console::WriteLine("Session name: '" + sessionName + "'");

大多数情况下会打印一个空字符串,除了Mozilla Firefox和System Sounds(其他进程可能没有为其设置会话名称,它们自己=>选择了默认名称,并且GetDisplayName返回空字符串).

prints most the times an emtpy string except for Mozilla Firefox and System Sounds (the other processes might not have set a session name themselfes => a default name is chosen and GetDisplayName returns an empty string).

更新2: 正如Simon Mourier指出的那样,可以比较进程ID以获取正确的ISimpleAudioVolume实例,并且它在WMP上可以采用更改.可以通过以下方式获取所述实例:

Update 2: As Simon Mourier pointed out one can compare the process ids to get the right ISimpleAudioVolume instance and it works as far as it comes to WMP to adopt the changes. The said instance is aquired the following way:

IMMDeviceEnumerator *pEnumerator = NULL;
ISimpleAudioVolume *pVolume = NULL;
IMMDevice *pDevice = NULL;
IAudioSessionManager2 *pManager = NULL;
IAudioSessionEnumerator *pSessionEnumerator = NULL;
int sessionCount = 0;

CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
    CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
pEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &pDevice);
pDevice->GetState(&deviceState);
pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**)&pManager);
pManager->GetSessionEnumerator(&pSessionEnumerator);
pSessionEnumerator->GetCount(&sessionCount);

for (int i = 0; i < sessionCount; i++)
{
    IAudioSessionControl *ctrl = NULL;
    IAudioSessionControl2 *ctrl2 = NULL;
    DWORD processId = 0;

    hr = pSessionEnumerator->GetSession(i, &ctrl);

    if (FAILED(hr))
    {
        continue;
    }

    hr = ctrl->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&ctrl2);

    if (FAILED(hr))
    {
        SafeRelease(ctrl);
        continue;
    }

    hr = ctrl2->GetProcessId(&processId);

    if (FAILED(hr))
    {
        SafeRelease(ctrl);
        SafeRelease(ctrl2);
        continue;
    }

    if (processId == wmpProcessId)
    {
        hr = ctrl2->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&pVolume);
        SafeRelease(ctrl);
        SafeRelease(ctrl2);
        break;
    }

    SafeRelease(ctrl);
    SafeRelease(ctrl2);
}

通过IAudioClient查询ISimpleAudioVolume实例时,必须提供一个会话ID,才能将数量变化报告给事件订阅者.使用这种方法有可能吗?

When aquiering an ISimpleAudioVolume instance via a IAudioClient one has to provide a session id to have volume changes reported to event subscribers. Is this possible using this approach?

尽管我知道将媒体播放器控件添加到我的应用程序是最简单的方法,但我希望在可能的情况下不使用此选项.

Though i know that adding a media player control to my application would be the easiest way, i'd like to not use this option if possible.

推荐答案

我不知道在初次尝试设置媒体播放器的音量时会发生什么,但是以下代码有效(排除了大多数异常处理):/p>

I don't know what may happened during my initial try to set the media player's volume level, but the following code works (most exception handling excluded):

HRESULT                 hr;
IMMDeviceEnumerator     *pEnumerator = NULL;
ISimpleAudioVolume      *pVolume = NULL;
IMMDevice               *pDevice = NULL;
IAudioSessionManager2   *pManager = NULL;
IAudioSessionEnumerator *pSessionEnumerator = NULL;
int                      sessionCount = 0;
int                      wmpProcess = GetWmpProcessId(); // Aquire WMPs process id

// Get the device enumerator and initialize the application for COM
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
         __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);

// Get the default device
hr = pEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender,
         ERole::eMultimedia, &pDevice);

// Get the session 2 manager
hr = pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL,
         NULL, (void**)&pManager);

// Get the session enumerator
hr = pManager->GetSessionEnumerator(&pSessionEnumerator);

// Get the session count
hr = pSessionEnumerator->GetCount(&sessionCount);

// Loop through all sessions
for (int i = 0; i < sessionCount; i++)
{
    IAudioSessionControl *ctrl = NULL;
    IAudioSessionControl2 *ctrl2 = NULL;
    DWORD processId = 0;

    hr = pSessionEnumerator->GetSession(i, &ctrl);

    if (FAILED(hr))
    {
        continue;
    }

    hr = ctrl->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&ctrl2);

    if (FAILED(hr))
    {
        SafeRelease(ctrl);
        continue;
    }

    //Identify WMP process
    hr = ctrl2->GetProcessId(&processId);

    if (FAILED(hr))
    {
        SafeRelease(ctrl);
        SafeRelease(ctrl2);
        continue;
    }

    if (processId != wmpProcess)
    {
        SafeRelease(ctrl);
        SafeRelease(ctrl2);
        continue;
    }

    hr = ctrl2->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&pVolume);

    if (FAILED(hr))
    {
        Error(hr, "Failed to get ISimpleAudioVolume.");

        SafeRelease(ctrl);
        SafeRelease(ctrl2);
        continue;
    }

    // Set the master volume
    hr = pVolume->SetMasterVolume(1.0, NULL);

    if (FAILED(hr))
    {
        Error(hr, "Failed to set the master volume.");
        SafeRelease(ctrl);
        SafeRelease(ctrl2);
        SafeRelease(pVolume);
        continue;
    }

    SafeRelease(ctrl);
    SafeRelease(ctrl2);
    SafeRelease(pVolume);
}

这篇关于设置WMP音量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆