私がやりたいことは、Windows Media Player の音量レベルを設定することです。デフォルトでは、例えば下または上メニュー項目をクリックすると (再生 -> 音量 -> アップ)、音量は 10% 減少しますが、私の意見では、これでは十分ではありません (特に、誰かとスカイプをしているときに)音楽を聴く)。
メディア プレーヤーは、独立したアプリケーションのままにする必要があります。
現在、Spy++ で見られるパラメータを使用して、SendMessage を介してアプリ コマンドをプレーヤーに送信する小さなツールを使用しています。
目標を達成するために、次の 3 つの方法を考えました。
- WASAPI を使用してメディア プレーヤーのオーディオ セッションを取得し、音量レベルを動的に設定する
- メディア プレーヤー ホスト コントロールのボリューム スライダーにマウス ダウン/アップ イベントをポイント単位で送信する
- IWMPlayer4 を介してメディア プレーヤー コントロールのインスタンスを取得する
- Windowsフォームホスト内のWPFアプリケーションにメディアプレーヤーコントロールを含める(独立性が失われるため、推奨されません)
ポイント 2 は、メディア プレーヤー コントロールが COM 要素であり、spy++ がハンドルを 1 つしか表示しないため、ボリューム スライダーの正確な位置を特定し、非常に正確なマウス イベントを送信する必要があるため、かなり見苦しく見えます。さらに、これがまったく機能するかどうかはわかりません。
ポイント 3 には、ハンドルによって COM 要素のインスタンスを取得できるという前提があります。私はまだ COM 要素を扱っていないので、これが可能かどうかはわかりません。
更新:インターフェイスを使用して、リモートのメディア プレーヤーのインスタンスを取得できIWMPPlayer4
ます。設定を変更できるかどうかを確認する必要がありますが。
ポイント1は、さほど苦労せずにできる印象です。次の問題に直面することになりますが、メディア プレーヤーのオーディオ セッションを識別することです。を使用してそれらを列挙し、使用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 とシステム サウンドを除いて、ほとんどの場合空の文字列を出力します (他のプロセス自体がセッション名を設定していない可能性があります => デフォルトの名前が選択され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);
}
ISimpleAudioVolume
1 を介してインスタンスを取得する場合IAudioClient
、セッション ID を提供して、ボリュームの変更をイベント サブスクライバーに報告する必要があります。これは、このアプローチを使用して可能ですか?
アプリケーションにメディア プレーヤー コントロールを追加するのが最も簡単な方法であることはわかっていますが、可能であればこのオプションを使用したくありません。