ダッキング イベントの取得
カスタマイズされたダッキング エクスペリエンスを提供するメディア アプリケーションは、通信ストリームがシステムで開かれるか閉じられたときにイベント通知をリッスンする必要があります。 カスタム実装は、コア オーディオ API を使用する MediaFoundation、DirectShow、または DirectSound を使用して提供できます。 直接 WASAPI クライアントは、通信セッションの開始と終了を認識している場合に、既定の処理をオーバーライドすることもできます。
カスタム実装を提供するには、通信アプリケーションが通信ストリームを開始または終了するときに、メディア アプリケーションがシステムから通知を受け取る必要があります。 メディア アプリケーションは、IAudioVolumeDuckNotification インターフェイスを実装し、オーディオ システムに実装を登録する必要があります。 登録が成功すると、メディア アプリケーションは、インターフェイス内のメソッドを通じてコールバックの形式でイベント通知を受信します。 詳しくは、「ダッキング通知の実装に関する考慮事項」をご覧ください。
ダッキング通知を送信するには、オーディオ システムがダッキング イベントをリッスンしているオーディオ セッションを認識している必要があります。 各オーディオ セッションは、GUID (セッション インスタンス識別子) によって一意に識別されます。 セッション マネージャーを使用すると、アプリケーションは、オーディオ セッションのタイトル、レンダリング状態、セッション インスタンス識別子などのセッションに関する情報を取得できます。 識別子は、ポリシー制御インターフェイス IAudioSessionControl2 を使用して取得することができます。
次の手順は、メディア アプリケーションのセッション インスタンス識別子を取得するプロセスをまとめたものです。
- デバイス列挙子をインスタンス化し、それを使用して、メディア アプリケーションが非通信ストリームのレンダリングに使用しているデバイスのエンドポイントへの参照を取得します。
- デバイス エンドポイントからセッション マネージャーをアクティブ化し、セッション マネージャーの IAudioSessionManager2 インターフェイスへの参照を取得します。
- IAudioSessionManager2 ポインターを使用することにより、セッション マネージャーの IAudioSessionControl インターフェイスへの参照を取得します。
- IAudioSessionControl インターフェイスから IAudioSessionControl2 に対してクエリを実行します。
- IAudioSessionControl2::GetSessionInstanceIdentifier を呼び出し、現在のオーディオ セッションのセッション識別子を含む文字列を取得します。
通信ストリームに関するダッキング通知を取得するため、メディア アプリケーションは IAudioSessionManager2::RegisterDuckNotification を呼び出します。 メディア アプリケーションは、そのセッション インスタンス識別子をオーディオ システムに提供し、IAudioVolumeDuckNotification 実装へのポインターを提供します。 通信デバイスでストリームが開かれたときにアプリケーションでイベント通知を受信できるようになりました。 通知の取得を停止するには、メディア アプリケーションで IAudioSessionManager2::UnregisterDuckNotification を呼び出す必要があります。
次のコードは、アプリケーションがダッキング通知を取得できるよう登録する方法を示しています。 CMediaPlayer クラスは、「ダッキング通知の実装に関する考慮事項」で定義されています。 DuckingMediaPlayer サンプルでは、この機能が実装されています。
////////////////////////////////////////////////////////////////////
//Description: Registers for duck notifications depending on the
// the ducking options specified by the caller.
//Parameters:
// If DuckingOptOutChecked is TRUE, the client is registered for
// to receive ducking notifications;
// FALSE, the client's registration is deleted.
////////////////////////////////////////////////////////////////////
HRESULT CMediaPlayer::DuckingOptOut(bool DuckingOptOutChecked)
{
HRESULT hr = S_OK;
IMMDeviceEnumerator* pDeviceEnumerator NULL;
IMMDevice* pEndpoint = NULL;
IAudioSessionManager2* pSessionManager2 = NULL;
IAudioSessionControl* pSessionControl = NULL;
IAudioSessionControl2* pSessionControl2 = NULL;
LPWSTR sessionId = NULL;
// Start with the default endpoint.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pDeviceEnumerator));
if (SUCCEEDED(hr))
{
hr = pDeviceEnumerator>GetDefaultAudioEndpoint(
eRender, eConsole, &pEndpoint);
pDeviceEnumerator>Release();
pDeviceEnumerator = NULL;
}
// Activate the session manager.
if (SUCCEEDED(hr))
{
hr = pEndpoint->Activate(__uuidof(IAudioSessionManager2),
CLSCTX_INPROC_SERVER,
NULL,
reinterpret_cast<void **>
(&pSessionManager2));
pEndpoint->Release();
pEndpoint = NULL;
}
if (SUCCEEDED(hr))
{
hr = pSessionManager2->GetAudioSessionControl(
NULL, 0, &pSessionControl);
}
if (SUCCEEDED(hr))
{
hr = pSessionControl->QueryInterface(
IID_PPV_ARGS(&pSessionControl2));
pSessionControl->Release();
pSessionControl = NULL;
}
// Get the session instance identifier.
if (SUCCEEDED(hr))
{
hr = pSessionControl2->GetSessionInstanceIdentifier(
sessionId);
pSessionControl2->Release();
pSessionControl2 = NULL;
}
// Register for ducking events depending on
// the specified preference.
if (SUCCEEDED(hr))
{
if (DuckingOptOutChecked)
{
hr = pSessionManager2->RegisterDuckNotification(
sessionId, this);
}
else
{
hr = pSessionManager2->UnregisterDuckNotification
(FALSE);
}
pSessionManager2->Release();
pSessionManager2 = NULL;
}
return hr;
}
関連トピック