Consideraciones de implementación para las notificaciones de pato
La experiencia de pato predeterminada proporcionada por el sistema pato todas las secuencias que no son de comunicación disponibles en el sistema cuando se abre una secuencia de comunicación. Una aplicación multimedia puede invalidar el control predeterminado si sabe cuándo se inicia y finaliza la sesión de comunicación.
Considere el escenario implementado por la aplicación multimedia en el ejemplo DuckingMediaPlayer . La aplicación pausa la secuencia de audio que está reproduciendo cuando recibe una notificación de pato y continúa reproduciendo cuando recibe una notificación de desaprobación. Los eventos de pausa y continuación se reflejan en la interfaz de usuario de la aplicación multimedia. Esto se admite a través de dos mensajes de ventana definidos por la aplicación, WM_APP_SESSION_DUCKED y WM_APP_SESSION_UNDUCKED. Las notificaciones de pato se reciben de forma asincrónica en segundo plano y la aplicación multimedia no debe bloquear el subproceso de notificación para procesar los mensajes de la ventana. Los mensajes de ventana deben procesarse en el subproceso de la interfaz de usuario.
El comportamiento de pato funciona a través de un mecanismo de notificación. Para proporcionar una experiencia personalizada, la aplicación multimedia debe implementar la interfaz IAudioVolumeDuckNotification y registrar la implementación en el sistema de audio. Tras el registro correcto, la aplicación multimedia recibe notificaciones de eventos en forma de devoluciones de llamada a través de los métodos de la interfaz . El administrador de sesión que controla la sesión de comunicación llama a IAudioVolumeDuckNotification::OnVolumeDuckNotification cuando se abre la secuencia de comunicación y, a continuación, llama a IAudioVolumeDuckNotification::OnVolumeUnduckNotification cuando se cierra la secuencia en el dispositivo de comunicación.
El código siguiente muestra una implementación de ejemplo de la interfaz IAudioVolumeDuckNotification . Para obtener la definición de CMediaPlayer::D uckingOptOut, consulta Getting Ducking Events from a Communication Device.
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;
}
Temas relacionados