더킹 이벤트 가져오기

사용자 지정 더킹 환경을 제공하려는 미디어 애플리케이션은 시스템에서 통신 스트림을 열거나 닫을 때 이벤트 알림을 수신 대기해야 합니다. 사용자 지정 구현은 핵심 오디오 API를 사용하는 MediaFoundation, DirectShow 또는 DirectSound를 사용하여 제공할 수 있습니다. 직접 WASAPI 클라이언트는 통신 세션이 시작되고 종료되는 시기를 알고 있는 경우 기본 처리를 재정의할 수도 있습니다.

사용자 지정 구현을 제공하려면 통신 애플리케이션이 통신 스트림을 시작하거나 종료할 때 미디어 애플리케이션이 시스템에서 알림을 받아야 합니다. 미디어 애플리케이션은 IAudioVolumeDuckNotification 인터페이스를 구현하고 오디오 시스템에 구현을 등록해야 합니다. 등록에 성공하면 미디어 애플리케이션은 인터페이스의 메서드를 통해 콜백 형식으로 이벤트 알림을 받습니다. 자세한 내용은 Ducking 알림에 대한 구현 고려 사항을 참조하세요.

더킹 알림을 보내려면 오디오 시스템에서 더킹 이벤트를 수신 대기하는 오디오 세션을 알고 있어야 합니다. 각 오디오 세션은 GUID(세션 instance 식별자)로 고유하게 식별됩니다. 세션 관리자를 사용하면 애플리케이션이 오디오 세션 제목, 렌더링 상태 및 세션 instance 식별자와 같은 세션에 대한 정보를 가져올 수 있습니다. 식별자는 정책 제어 인터페이스 IAudioSessionControl2를 사용하여 검색할 수 있습니다.

다음 단계에서는 미디어 애플리케이션의 세션 instance 식별자를 가져오는 프로세스를 요약합니다.

  1. 디바이스 열거자를 인스턴스화하고 이를 사용하여 미디어 애플리케이션이 통신이 아닌 스트림을 렌더링하는 데 사용하는 디바이스의 엔드포인트에 대한 참조를 가져옵니다.
  2. 디바이스 엔드포인트에서 세션 관리자를 활성화하고 세션 관리자의 IAudioSessionManager2 인터페이스에 대한 참조를 가져옵니다.
  3. IAudioSessionManager2 포인터를 사용하여 세션 관리자의 IAudioSessionControl 인터페이스에 대한 참조를 가져옵니다.
  4. IAudioSessionControl 인터페이스에서 IAudioSessionControl2를 쿼리합니다.
  5. IAudioSessionControl2::GetSessionInstanceIdentifier를 호출하고 현재 오디오 세션에 대한 세션 식별자가 포함된 문자열을 검색합니다.

통신 스트림에 대한 더킹 알림을 받기 위해 미디어 애플리케이션은 IAudioSessionManager2::RegisterDuckNotification을 호출합니다. 미디어 애플리케이션은 세션 instance 식별자를 오디오 시스템에 제공하고 IAudioVolumeDuckNotification 구현에 대한 포인터를 제공합니다. 이제 통신 디바이스에서 스트림이 열릴 때 애플리케이션에서 이벤트 알림을 받을 수 있습니다. 알림 받기를 중지하려면 미디어 애플리케이션이 IAudioSessionManager2::UnregisterDuckNotification을 호출해야 합니다.

다음 코드에서는 애플리케이션을 등록하여 더킹 알림을 받는 방법을 보여 줍니다. CMediaPlayer 클래스는 더 킹 알림에 대한 구현 고려 사항에 정의되어 있습니다. DuckingMediaPlayer 샘플은 이 기능을 구현합니다.

////////////////////////////////////////////////////////////////////
//Description: Registers for duck notifications depending on the 
//             the ducking options specified by the caller.
//Parameters: 
//    If DuckingOptOutChecked is TRUE, the client is registered for
//    to receive ducking notifications; 
//    FALSE, the client's registration is deleted.
////////////////////////////////////////////////////////////////////

HRESULT CMediaPlayer::DuckingOptOut(bool DuckingOptOutChecked)
{
    HRESULT hr = S_OK;

    IMMDeviceEnumerator* pDeviceEnumerator NULL;
    IMMDevice* pEndpoint = NULL;
    IAudioSessionManager2* pSessionManager2 = NULL;
    IAudioSessionControl* pSessionControl = NULL;
    IAudioSessionControl2* pSessionControl2 = NULL;

    LPWSTR sessionId = NULL;

    //  Start with the default endpoint.

    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), 
                          NULL, 
                          CLSCTX_INPROC_SERVER, 
                          IID_PPV_ARGS(&pDeviceEnumerator));
    
    if (SUCCEEDED(hr))
    {
        hr = pDeviceEnumerator>GetDefaultAudioEndpoint(
              eRender, eConsole, &pEndpoint);

        pDeviceEnumerator>Release();
        pDeviceEnumerator = NULL;
    }

    // Activate the session manager.
    if (SUCCEEDED(hr))
    {
        hr = pEndpoint->Activate(__uuidof(IAudioSessionManager2), 
                                 CLSCTX_INPROC_SERVER,
                                 NULL, 
                                 reinterpret_cast<void **>
                                 (&pSessionManager2));
        pEndpoint->Release();
        pEndpoint = NULL;
    }
    if (SUCCEEDED(hr))
    {
        hr = pSessionManager2->GetAudioSessionControl(
                                  NULL, 0, &pSessionControl);
        
    }

    if (SUCCEEDED(hr))
    {
        hr = pSessionControl->QueryInterface(
                               IID_PPV_ARGS(&pSessionControl2));
                
        pSessionControl->Release();
        pSessionControl = NULL;
    }

    // Get the session instance identifier.
    
    if (SUCCEEDED(hr))
    {
        hr = pSessionControl2->GetSessionInstanceIdentifier(
                                 sessionId);
                
        pSessionControl2->Release();
        pSessionControl2 = NULL;
    }

    //  Register for ducking events depending on 
    //  the specified preference.

    if (SUCCEEDED(hr))
    {
        if (DuckingOptOutChecked)
        {
            hr = pSessionManager2->RegisterDuckNotification(
                                    sessionId, this);
        }
        else
        {
            hr = pSessionManager2->UnregisterDuckNotification
                                      (FALSE);
        }
        pSessionManager2->Release();
        pSessionManager2 = NULL;
    }
    return hr;
}

통신 디바이스 사용

기본 더킹 환경

기본 더킹 환경 비활성화

사용자 지정 더킹 동작 제공

Ducking 알림에 대한 구현 고려 사항