Événements de session audio

Une application qui gère les flux audio en mode partagé peut s’inscrire pour recevoir des notifications lorsque des événements de session se produisent. Comme expliqué précédemment, chaque flux appartient à une session audio. Un événement de session est initié par une modification du status d’une session audio.

Une application cliente peut s’inscrire pour recevoir des notifications des types d’événements de session suivants :

  • La master niveau de volume ou l’état de désactivation du sous-mix de session a changé.
  • Le niveau de volume d’un ou plusieurs canaux du sous-mix de session a changé.
  • La session a été déconnectée.
  • L’état de l’activité de la session est passé à actif, inactif ou expiré.
  • Un nouveau paramètre de regroupement a été attribué à la session.
  • Une propriété d’interface utilisateur de la session (icône ou nom d’affichage) a été modifiée.

Le client reçoit des notifications de ces événements par le biais des méthodes dans son implémentation de l’interface IAudioSessionEvents . Contrairement aux autres interfaces dans WASAPI, qui sont implémentées par le module système WASAPI, le client implémente IAudioSessionEvents. Les méthodes de cette interface reçoivent des rappels du module système WASAPI lorsque des événements de session se produisent.

Pour commencer à recevoir des notifications, le client appelle la méthode IAudioSessionControl::RegisterAudioSessionNotification pour inscrire son interface IAudioSessionEvents . Lorsque le client n’a plus besoin de notifications, il appelle la méthode IAudioSessionControl::UnregisterAudioSessionNotification pour supprimer l’inscription.

L’exemple de code suivant montre une implémentation possible de l’interface IAudioSessionEvents :

//-----------------------------------------------------------
// Client implementation of IAudioSessionEvents interface.
// WASAPI calls these methods to notify the application when
// a parameter or property of the audio session changes.
//-----------------------------------------------------------
class CAudioSessionEvents : public IAudioSessionEvents
{
    LONG _cRef;

public:
    CAudioSessionEvents() :
        _cRef(1)
    {
    }

    ~CAudioSessionEvents()
    {
    }

    // IUnknown methods -- AddRef, Release, and QueryInterface

    ULONG STDMETHODCALLTYPE AddRef()
    {
        return InterlockedIncrement(&_cRef);
    }

    ULONG STDMETHODCALLTYPE Release()
    {
        ULONG ulRef = InterlockedDecrement(&_cRef);
        if (0 == ulRef)
        {
            delete this;
        }
        return ulRef;
    }

    HRESULT STDMETHODCALLTYPE QueryInterface(
                                REFIID  riid,
                                VOID  **ppvInterface)
    {
        if (IID_IUnknown == riid)
        {
            AddRef();
            *ppvInterface = (IUnknown*)this;
        }
        else if (__uuidof(IAudioSessionEvents) == riid)
        {
            AddRef();
            *ppvInterface = (IAudioSessionEvents*)this;
        }
        else
        {
            *ppvInterface = NULL;
            return E_NOINTERFACE;
        }
        return S_OK;
    }

    // Notification methods for audio session events

    HRESULT STDMETHODCALLTYPE OnDisplayNameChanged(
                                LPCWSTR NewDisplayName,
                                LPCGUID EventContext)
    {
        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnIconPathChanged(
                                LPCWSTR NewIconPath,
                                LPCGUID EventContext)
    {
        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged(
                                float NewVolume,
                                BOOL NewMute,
                                LPCGUID EventContext)
    {
        if (NewMute)
        {
            printf("MUTE\n");
        }
        else
        {
            printf("Volume = %d percent\n",
                   (UINT32)(100*NewVolume + 0.5));
        }

        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged(
                                DWORD ChannelCount,
                                float NewChannelVolumeArray[],
                                DWORD ChangedChannel,
                                LPCGUID EventContext)
    {
        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnGroupingParamChanged(
                                LPCGUID NewGroupingParam,
                                LPCGUID EventContext)
    {
        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnStateChanged(
                                AudioSessionState NewState)
    {
        char *pszState = "?????";

        switch (NewState)
        {
        case AudioSessionStateActive:
            pszState = "active";
            break;
        case AudioSessionStateInactive:
            pszState = "inactive";
            break;
        }
        printf("New session state = %s\n", pszState);

        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnSessionDisconnected(
              AudioSessionDisconnectReason DisconnectReason)
    {
        char *pszReason = "?????";

        switch (DisconnectReason)
        {
        case DisconnectReasonDeviceRemoval:
            pszReason = "device removed";
            break;
        case DisconnectReasonServerShutdown:
            pszReason = "server shut down";
            break;
        case DisconnectReasonFormatChanged:
            pszReason = "format changed";
            break;
        case DisconnectReasonSessionLogoff:
            pszReason = "user logged off";
            break;
        case DisconnectReasonSessionDisconnected:
            pszReason = "session disconnected";
            break;
        case DisconnectReasonExclusiveModeOverride:
            pszReason = "exclusive-mode override";
            break;
        }
        printf("Audio session disconnected (reason: %s)\n",
               pszReason);

        return S_OK;
    }
};

La classe CAudioSessionEvents dans l’exemple de code précédent est une implémentation de l’interface IAudioSessionEvents . Cette implémentation particulière peut faire partie d’une application console qui imprime des informations sur les événements de session dans une fenêtre d’invite de commandes. Étant donné que IAudioSessionEvents hérite d’IUnknown, la définition de classe contient des implémentations des méthodes IUnknownAddRef, Release et QueryInterface. Les méthodes publiques restantes dans la définition de classe sont spécifiques à l’interface IAudioSessionEvents .

Certains clients peuvent ne pas être intéressés par la surveillance de tous les types d’événements de session. Dans l’exemple de code précédent, plusieurs méthodes de notification de la classe CAudioSessionEvents ne font rien. Par exemple, la méthode OnChannelVolumeChanged ne fait rien d’autre que pour retourner status code S_OK. Cette application ne surveille pas les volumes de canal, car elle ne modifie pas les volumes de canal (en appelant les méthodes dans l’interface IChannelAudioVolume ) et elle ne partage pas la session avec d’autres applications susceptibles de modifier les volumes de canal.

Les trois seules méthodes de la classe CAudioSessionEvents qui informent l’utilisateur des événements de session sont OnSimpleVolumeChanged, OnStateChanged et OnSessionDisconnected. Par exemple, si l’utilisateur exécute le programme de contrôle de volume système, Sndvol, et utilise le contrôle de volume dans Sndvol pour modifier le niveau de volume de l’application, OnSimpleVolumeChanged imprime immédiatement le nouveau niveau de volume.

Pour obtenir un exemple de code qui inscrit et annule l’inscription de l’interface IAudioSessionEvents d’un client, consultez Événements audio pour les applications audio héritées.

Audio Sessions