다음을 통해 공유


오디오 세션 이벤트

공유 모드 오디오 스트림을 관리하는 애플리케이션은 세션 이벤트가 발생할 때 알림을 받도록 등록할 수 있습니다. 앞에서 설명한 대로 각 스트림은 오디오 세션속합니다. 세션 이벤트는 오디오 세션의 상태 변경으로 시작됩니다.

클라이언트 애플리케이션은 다음 유형의 세션 이벤트에 대한 알림을 받도록 등록할 수 있습니다.

  • 세션 서브믹스의 마스터 볼륨 수준 또는 음소거 상태가 변경되었습니다.
  • 세션 서브믹스의 하나 이상의 채널 볼륨 수준이 변경되었습니다.
  • 세션 연결이 끊어졌습니다.
  • 세션의 활동 상태가 활성, 비활성 또는 만료됨으로 변경되었습니다.
  • 세션에 새 그룹화 매개 변수가 할당되었습니다.
  • 세션의 사용자 인터페이스 속성(아이콘 또는 표시 이름)이 변경되었습니다.

클라이언트는 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상속되므로 클래스 정의에는 AddRef, ReleaseQueryInterfaceIUnknown 메서드의 구현이 포함됩니다. 클래스 정의의 나머지 공용 메서드는 IAudioSessionEvents 인터페이스와 관련이 있습니다.

일부 클라이언트는 모든 유형의 세션 이벤트를 모니터링하는 데 관심이 없을 수 있습니다. 앞의 코드 예제에서 CAudioSessionEvents 클래스의 여러 알림 메서드는 아무 작업도 수행하지 않습니다. 예를 들어 OnChannelVolumeChanged 메서드는 상태 코드 S_OK 반환하는 것 외에는 아무 작업도 수행하지 않습니다. 이 애플리케이션은 채널 볼륨을 변경하지 않으므로(IChannelAudioVolume 인터페이스에서 메서드를 호출함) 채널 볼륨을 변경하지 않으며 채널 볼륨을 변경할 수 있는 다른 애플리케이션과 세션을 공유하지 않기 때문에 채널 볼륨을 모니터링하지 않습니다.

세션 이벤트의 사용자에게 알리는 CAudioSessionEvents 클래스의 세 가지 메서드는 OnSimpleVolumeChanged, OnStateChangedOnSessionDisconnected. 예를 들어 사용자가 시스템 볼륨 제어 프로그램인 Sndvol을 실행하고 Sndvol의 볼륨 컨트롤을 사용하여 애플리케이션의 볼륨 수준을 변경하는 경우 OnSimpleVolumeChanged 즉시 새 볼륨 수준을 출력합니다.

클라이언트의 IAudioSessionEvents 인터페이스를 등록 및 등록 취소하는 코드 예제는 레거시 오디오 애플리케이션 대한오디오 이벤트를 참조하세요.

오디오 세션