Compartilhar via


Considerações de implementação para notificações de evasão

A Experiência de Ducking padrão fornecida pelo sistema elimina todos os fluxos de não comunicação disponíveis no sistema quando um fluxo de comunicação é aberto. Um aplicativo de mídia pode substituir o tratamento 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 exemplo DuckingMediaPlayer . O aplicativo pausa o fluxo de áudio que está sendo reproduzido quando recebe uma notificação de pato e continua a reprodução quando recebe uma notificação de unduck. Os eventos de pausa e continuação são refletidos na interface do usuário do aplicativo de mídia. Isso é suportado por meio de duas mensagens de janela definidas pelo aplicativo, WM_APP_SESSION_DUCKED e WM_APP_SESSION_UNDUCKED. As notificações de ducking 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 por meio de um mecanismo de notificação. Para fornecer uma experiência personalizada, o aplicativo de mídia deve implementar a interface IAudioVolumeDuckNotification e registrar a implementação com o sistema de áudio. Após o registro bem-sucedido, o aplicativo de mídia recebe notificações de eventos na forma de retornos de chamada por meio dos métodos na interface. O gerenciador de sessão que manipula a sessão de comunicação chama IAudioVolumeDuckNotification::OnVolumeDuckNotification quando o fluxo de comunicação é aberto e, em seguida, chama IAudioVolumeDuckNotification::OnVolumeUnduckNotification quando o fluxo é fechado no dispositivo de comunicação.

O código a seguir mostra uma implementação de exemplo da interface IAudioVolumeDuckNotification. Para obter a definição de CMediaPlayer::D uckingOptOut, consulte Obtendo eventos de evasão 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;   
}

Usando um dispositivo de comunicação

Experiência padrão de ducking

Desativando a experiência de ducking padrão

Fornecendo um comportamento de ducking personalizado

Obtendo eventos de ducking