Considerazioni sull'implementazione per le notifiche di ducking

L'esperienza predefinita ducking fornita dal sistema anatra tutti i flussi non di comunicazione disponibili nel sistema quando si apre un flusso di comunicazione. Un'applicazione multimediale può eseguire l'override della gestione predefinita se sa quando viene avviata e terminata la sessione di comunicazione.

Si consideri lo scenario implementato dall'applicazione multimediale nell'esempio DuckingMediaPlayer . L'applicazione sospende il flusso audio che viene riprodotto quando riceve una notifica di anatra e continua la riproduzione quando riceve una notifica senza dollari. Gli eventi di sospensione e continuazione si riflettono nell'interfaccia utente dell'applicazione multimediale. Questa operazione è supportata tramite due messaggi di finestra definiti dall'applicazione, WM_APP_edizione StandardSSION_DUCKED e WM_APP_edizione StandardSSION_UNDUCKED. Le notifiche di anatraggio vengono ricevute in modo asincrono in background e l'applicazione multimediale non deve bloccare il thread di notifica per elaborare i messaggi della finestra. I messaggi della finestra devono essere elaborati nel thread dell'interfaccia utente.

Il comportamento di anatraggio funziona tramite un meccanismo di notifica. Per offrire un'esperienza personalizzata, l'applicazione multimediale deve implementare l'interfaccia IAudioVolumeDuckNotification e registrare l'implementazione con il sistema audio. Al termine della registrazione, l'applicazione multimediale riceve notifiche degli eventi sotto forma di callback tramite i metodi nell'interfaccia. Il gestore di sessioni che gestisce la sessione di comunicazione chiama IAudioVolumeDuckNotification::OnVolumeDuckNotification all'apertura del flusso di comunicazione e quindi chiama IAudioVolumeDuckNotification::OnVolumeUnduckNotification quando il flusso viene chiuso nel dispositivo di comunicazione.

Il codice seguente illustra un'implementazione di esempio dell'interfaccia IAudioVolumeDuckNotification . Per la definizione di CMediaPlayer::D uckingOptOut, vedi Recupero di eventi di anatraggio da un dispositivo di comunicazione.

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;   
}

Uso di un dispositivo di comunicazione

Esperienza predefinita di anatraggio

Disabilitazione dell'esperienza predefinita di ducking

Fornire un comportamento personalizzato di anatraggio

Recupero di eventi di anatraggio