オーディオ セッション イベント

共有モードのオーディオ ストリームを管理するアプリケーションは、セッション イベントが発生したときに通知を受信するよう登録できます。 前述のように、各ストリームはオーディオ セッションに属しています。 セッション イベントは、オーディオ セッションの状態の変更によって開始されます。

クライアント アプリケーションは、次の種類のセッション イベントの通知を受信するよう登録できます。

  • セッション サブミックスのマスター ボリューム レベルまたはミュート状態が変更されました。
  • セッション サブミックスの 1 つ以上のチャネルのボリューム レベルが変更されました。
  • セッションが切断されました。
  • セッションのアクティビティ状態がアクティブ、非アクティブ、または期限切れに変更されました。
  • セッションには、新しいグループ化パラメーターが割り当てられます。
  • セッションのユーザー インターフェイス プロパティ (アイコンまたは表示名) が変更されました。

クライアントは、IAudioSessionEvents インターフェイスの実装においてメソッドを通じてこれらのイベントの通知を受け取ります。 WASAPI システム モジュールによって実装される WASAPI の他のインターフェイスとは異なり、クライアントは IAudioSessionEvents を実装します。 このインターフェイスのメソッドは、セッション イベントが発生したときに WASAPI システム モジュールからコールバックを受け取ります。

通知の受信を開始するため、クライアントは IAudioSessionControl::RegisterAudioSessionNotification メソッドを呼び出して、その IAudioSessionEvents インターフェイスを登録します。 クライアントは、通知が不要になると、IAudioSessionControl::UnregisterAudioSessionNotification メソッドを呼び出して登録を削除します。

次のコード例は、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;
    }
};

前のコード例の CAudioSessionEvents クラスは、IAudioSessionEvents インターフェイスの実装です。 この特定の実装は、コマンド プロンプト ウィンドウにセッション イベントに関する情報を出力するコンソール アプリケーションの一部となっている可能性があります。 IAudioSessionEventsIUnknown から継承されるため、クラス定義には IUnknown メソッドの AddRefReleaseQueryInterface の実装が含まれています。 クラス定義の残りのパブリック メソッドは、IAudioSessionEvents インターフェイスに固有です。

クライアントによっては、一部の種類のセッション イベントの監視を必要としないことがあります。 前のコード例では、CAudioSessionEvents クラス内のいくつかの通知メソッドによって何も発生しません。 たとえば、OnChannelVolumeChanged メソッドは、状態コード S_OK を返す以外は何も行いません。 このアプリケーションはチャネル ボリュームを監視しません。(IChannelAudioVolume インターフェイスでメソッドを呼び出すことによって) チャネル ボリュームを変更することはなく、チャネル ボリュームを変更する可能性がある他のアプリケーションとセッションを共有しないためです。

セッション イベントをユーザーに通知する CAudioSessionEvents クラスの 3 つのメソッドは、OnSimpleVolumeChangedOnStateChangedOnSessionDisconnected だけです。 たとえば、ユーザーがシステム ボリューム制御プログラム Sndvol を実行し、Sndvol のボリューム コントロールを使用してアプリケーションのボリューム レベルを変更した場合、OnSimpleVolumeChanged によりすぐに新しいボリューム レベルが出力されます。

クライアントの IAudioSessionEvents インターフェイスを登録および登録解除するコード例については、「レガシ オーディオ アプリケーションのオーディオ イベント」をご覧ください。

オーディオ セッション