Freigeben über


Implementierungsüberlegungen für Duckingbenachrichtigungen

Die vom System bereitgestellte Standard-Entenerfahrung entent alle im System verfügbaren Nicht-Kommunikationsdatenströme, wenn ein Kommunikationsstream geöffnet wird. Eine Medienanwendung kann die Standardbehandlung außer Kraft setzen, wenn sie weiß, wann die Kommunikationssitzung beginnt und endet.

Betrachten Sie das Szenario, das von der Medienanwendung im DuckingMediaPlayer-Beispiel implementiert wurde. Die Anwendung hält den audiostream an, den sie abgibt, wenn sie eine Entenbenachrichtigung empfängt, und setzt die Wiedergabe fort, wenn sie eine Benachrichtigung zum Rückgängigmachen empfängt. Die Pausen- und Fortsetzungsereignisse werden auf der Benutzeroberfläche der Medienanwendung widergespiegelt. Dies wird durch zwei anwendungsdefinierte Fenstermeldungen unterstützt, WM_APP_SESSION_DUCKED und WM_APP_SESSION_UNDUCKED. Die Entenbenachrichtigungen werden asynchron im Hintergrund empfangen, und die Medienanwendung darf den Benachrichtigungsthread nicht blockieren, um die Fenstermeldungen zu verarbeiten. Die Fenstermeldungen müssen im Benutzeroberflächenthread verarbeitet werden.

Das Duckverhalten funktioniert über einen Benachrichtigungsmechanismus. Um eine angepasste Benutzeroberfläche bereitzustellen, muss die Medienanwendung die IAudioVolumeDuckNotification-Schnittstelle implementieren und die Implementierung beim Audiosystem registrieren. Nach erfolgreicher Registrierung empfängt die Medienanwendung Ereignisbenachrichtigungen in Form von Rückrufen über die Methoden in der Schnittstelle. Der Sitzungs-Manager, der die Kommunikationssitzung verarbeitet, ruft IAudioVolumeDuckNotification::OnVolumeDuckNotification auf, wenn der Kommunikationsdatenstrom geöffnet wird, und ruft dann IAudioVolumeDuckNotification::OnVolumeUnduckNotification auf, wenn der Stream auf dem Kommunikationsgerät geschlossen wird.

Der folgende Code zeigt eine Beispielimplementierung der IAudioVolumeDuckNotification-Schnittstelle . Die Definition von CMediaPlayer::D uckingOptOut finden Sie unter Abrufen von Entenereignissen von einem Kommunikationsgerät.

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

Verwenden eines Kommunikationsgeräts

Standard-Ducking-Erfahrung

Deaktivieren der standardbeendigen Benutzeroberfläche

Bereitstellen eines benutzerdefinierten Duckingverhaltens

Abrufen von Duckingereignissen