ダッキング通知の実装に関する考慮事項
システムによって提供される既定のダッキング エクスペリエンスは、通信ストリームが開いたときにシステムで使用可能なすべての非通信ストリームをダッキングします。 メディア アプリケーションは、通信セッションの開始と終了を認識している場合、既定の処理をオーバーライドできます。
DuckingMediaPlayer サンプルのメディア アプリケーションによって実装されるシナリオについて考えてみましょう。 アプリケーションは、ダック通知を受け取ったときに再生しているオーディオ ストリームを一時停止し、ダック解除通知を受信したときに再生を続行します。 一時停止イベントと続行イベントは、メディア アプリケーションのユーザー インターフェイスに反映されます。 これは、WM_APP_SESSION_DUCKED と WM_APP_SESSION_UNDUCKED の 2 つのアプリケーション定義ウィンドウ メッセージによってサポートされます。 ダッキング通知はバックグラウンドで非同期的に受信され、メディア アプリケーションはウィンドウ メッセージを処理する通知スレッドをブロックしてはなりません。 ウィンドウ メッセージは、ユーザー インターフェイス スレッドで処理する必要があります。
ダッキング動作は、通知メカニズムを通じて機能します。 カスタマイズされたエクスペリエンスを提供するには、メディア アプリケーションで IAudioVolumeDuckNotification インターフェイスを実装し、オーディオ システムに実装を登録する必要があります。 登録が成功すると、メディア アプリケーションは、インターフェイス内のメソッドを通じてコールバックの形式でイベント通知を受信します。 通信セッションを処理するセッション マネージャーは、通信ストリームが開いたときに IAudioVolumeDuckNotification::OnVolumeDuckNotification を呼び出し、通信デバイスでストリームが閉じられたときに IAudioVolumeDuckNotification::OnVolumeUnduckNotification を呼び出します。
次のコードは、IAudioVolumeDuckNotification インターフェイスの実装例を示しています。 CMediaPlayer::D uckingOptOut の定義については、「通信デバイスからのダッキング イベントの取得」をご覧ください。
class CMediaPlayer : public IAudioVolumeDuckNotification
{
LONG _refCount;
HWND _AppWindow;
~CMediaPlayer();
STDMETHOD(OnVolumeDuckNotification) (LPCWSTR sessionID,
UINT32 countCommunicationSessions);
STDMETHOD(OnVolumeUnduckNotification) (LPCWSTR sessionID);
public:
CDuckingImpl(HWND hWnd);
HRESULT DuckingOptOut(bool GetDuckEvents);
// IUnknown
IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void **ppv);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) Release();
};
CMediaPlayer::CMediaPlayer(HWND AppWindow) :
_AppWindow(AppWindow),
_refCount(1)
{
}
CMediaPlayer::~CMediaPlayer()
{
}
// When we receive a duck notification,
// post a "Session Ducked" message to the application window.
STDMETHODIMP CMediaPlayer::OnVolumeDuckNotification(LPCWSTR SessionID,
UINT32 CountCommunicationsSessions)
{
PostMessage(_AppWindow, WM_APP_SESSION_DUCKED, 0, 0);
return 0;
}
// When we receive an unduck notification,
// post a "Session Unducked" message to the application window.
STDMETHODIMP CMediaPlayer::OnVolumeUnduckNotification(LPCWSTR SessionID)
{
PostMessage(_AppWindow, WM_APP_SESSION_UNDUCKED, 0, 0);
return 0;
}
IFACEMETHODIMP CMediaPlayer::QueryInterface(REFIID iid, void **pvObject)
{
if (pvObject == NULL)
{
return E_POINTER;
}
*pvObject = NULL;
if (iid == IID_IUnknown)
{
*pvObject = static_cast<IUnknown *>(static_cast<IAudioVolumeDuckNotification *>
(this));
AddRef();
}
else if (iid == __uuidof(IAudioVolumeDuckNotification))
{
*pvObject = static_cast<IAudioVolumeDuckNotification *>(this);
AddRef();
}
else
{
return E_NOINTERFACE;
}
return S_OK;
}
IFACEMETHODIMP_(ULONG) CMediaPlayer::AddRef()
{
return InterlockedIncrement(&_refCount);
}
IFACEMETHODIMP_(ULONG) CMediaPlayer::Release()
{
LONG refs = InterlockedDecrement(&_refCount);
if (refs == 0)
{
delete this;
}
return refs;
}
関連トピック