gpt4 book ai didi

c++ - 设置 WMP 音量级别

转载 作者:行者123 更新时间:2023-11-28 06:04:59 33 4
gpt4 key购买 nike

我想要做的是设置 Windows Media Player 的音量级别。默认情况下,音量增加/减少 10%。单击向下或向上菜单项(播放 -> 音量 -> 向上),但在我看来,这还不够好(尤其是在例如边听音乐边与某人进行 Skype 通话时)。

媒体播放器应该是一个独立的应用程序。
目前我正在使用一个小工具,它通过 SendMessage 向播放器发送应用程序命令,其参数如 spy++ 中所示。

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

  • 使用 WASAPI 获取媒体播放器的 Audio Session 并动态设置音量级别
  • 按点向媒体播放器主机控件的音量 slider 发送鼠标按下/向上事件
  • 通过 IWMPPlayer4 获取媒体播放器控件的实例
  • 在我的 Windows 窗体主机内的 WPF 应用程序中包含一个媒体播放器控件(由于失去独立性而不是首选)

第 2 点看起来相当难看,因为媒体播放器控件是一个 COM 元素并且到目前为止 spy++ 只显示一个句柄,这意味着我必须确定音量 slider 的确切位置并发送非常精确的鼠标事件.另外,我不知道这是否可行。

第 3 点的前提是可以通过句柄获取 COM 元素的实例。由于我还没有使用过 COM 元素,所以我不知道这是否可行。
更新:可以使用IWMPPlayer4 接口(interface)获取远程媒体播放器的实例。虽然我必须看看是否可以更改设置。

第 1 点给我的印象是不费吹灰之力就可以实现。虽然我会面临下一个问题:识别媒体播放器 Audio Session 。使用 IAudioSessionManager2 枚举它们并使用

显示名称
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 和系统声音外,大多数时候打印一个空字符串(其他进程可能没有自己设置 session 名称 => 默认名称被选择并且 GetDisplayName 返回一个空字符串) .

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

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 实例时,必须提供一个 session ID,以便向事件订阅者报告音量变化。使用这种方法是否可行?

虽然我知道向我的应用程序添加媒体播放器控件是最简单的方法,但我希望尽可能不使用此选项。

最佳答案

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

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

关于c++ - 设置 WMP 音量级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32566068/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com