Considérations relatives à l’implémentation des notifications de canardage

L’expérience de canardage par défaut fournie par le système supprime tous les flux non de communication disponibles dans le système lorsqu’un flux de communication s’ouvre. Une application multimédia peut remplacer la gestion par défaut si elle sait quand la session de communication démarre et se termine.

Considérez le scénario implémenté par l’application multimédia dans l’exemple DuckingMediaPlayer . L’application interrompt le flux audio qu’elle lit lorsqu’elle reçoit une notification canard et continue la lecture lorsqu’elle reçoit une notification de non-réception. Les événements pause et continue sont répercutés dans l’interface utilisateur de l’application multimédia. Cela est pris en charge par le biais de deux messages de fenêtre définis par l’application, WM_APP_SESSION_DUCKED et WM_APP_SESSION_UNDUCKED. Les notifications d’ardage sont reçues de manière asynchrone en arrière-plan et l’application multimédia ne doit pas bloquer le thread de notification pour traiter les messages de fenêtre. Les messages de fenêtre doivent être traités sur le thread d’interface utilisateur.

Le comportement de canardage fonctionne par le biais d’un mécanisme de notification. Pour fournir une expérience personnalisée, l’application multimédia doit implémenter l’interface IAudioVolumeDuckNotification et inscrire l’implémentation auprès du système audio. Une fois l’inscription réussie, l’application multimédia reçoit des notifications d’événements sous forme de rappels via les méthodes de l’interface. Le gestionnaire de session qui gère la session de communication appelle IAudioVolumeDuckNotification::OnVolumeDuckNotification lorsque le flux de communication s’ouvre, puis appelle IAudioVolumeDuckNotification::OnVolumeUnduckNotification lorsque le flux est fermé sur le périphérique de communication.

Le code suivant montre un exemple d’implémentation de l’interface IAudioVolumeDuckNotification . Pour la définition de CMediaPlayer::D uckingOptOut, consultez 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;   
}

Utilisation d’un appareil de communication

Expérience de canardage par défaut

Désactivation de l’expérience de canardage par défaut

Fournir un comportement de canardage personnalisé

Obtention d’événements de canardage