Considerações de implementação para notificações de desvio
O Default Ducking Experience fornecido pelo sistema atenua todos os streams não relacionados à comunicação disponíveis no sistema quando um stream de comunicação é iniciado. Um aplicativo de mídia pode substituir a manipulação padrão se souber quando a sessão de comunicação começa e termina.
Considere o cenário implementado pelo aplicativo de mídia no DuckingMediaPlayer exemplo. A aplicação pausa a transmissão de áudio que está a reproduzir quando recebe uma notificação de redução de volume e continua a reprodução quando recebe uma notificação de retorno de volume. Os eventos pause e continue são refletidos na interface do usuário do aplicativo de mídia. Isso é suportado através de duas mensagens de janela definidas pela aplicação, WM_APP_SESSION_DUCKED e WM_APP_SESSION_UNDUCKED. As notificações de desvio são recebidas de forma assíncrona em segundo plano e o aplicativo de mídia não deve bloquear o thread de notificação para processar as mensagens da janela. As mensagens da janela devem ser processadas no thread da interface do usuário.
O comportamento de ducking funciona através de um mecanismo de notificação. Para fornecer uma experiência personalizada, o aplicativo de mídia deve implementar o interface IAudioVolumeDuckNotification e registrar a implementação com o sistema de áudio. Após o registo bem-sucedido, a aplicação de mídia recebe notificações de eventos na forma de callbacks através dos métodos na interface. O gestor de sessão que gere a sessão de comunicação chama IAudioVolumeDuckNotification::OnVolumeDuckNotification quando o stream de comunicação é aberto e, em seguida, chama IAudioVolumeDuckNotification::OnVolumeUnduckNotification quando o stream é fechado no dispositivo de comunicação.
O código a seguir mostra uma implementação de exemplo do IAudioVolumeDuckNotification interface. Para obter a definição de CMediaPlayer::DuckingOptOut, consulte a Obtenção de Eventos de Ducking de um Dispositivo de Comunicação.
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;
}
Tópicos relacionados