Compartilhar via


Obtendo eventos de ducking

Um aplicativo de mídia que deseja fornecer uma experiência de ducking personalizada deve ouvir as notificações de eventos quando um fluxo de comunicação é aberto ou fechado no sistema. A implementação personalizada pode ser fornecida usando MediaFoundation, DirectShow ou DirectSound, que usam as APIs de áudio principal. Um cliente WASAPI direto também pode substituir o tratamento padrão se souber quando a sessão de comunicação começa e termina.

Para fornecer uma implementação personalizada, um aplicativo de mídia precisa receber notificações do sistema quando um aplicativo de comunicação inicia ou termina um fluxo de comunicação. O aplicativo de mídia deve implementar a interface IAudioVolumeDuckNotification e registrar a implementação com o sistema de áudio. Após o registro bem-sucedido, o aplicativo de mídia recebe notificações de eventos na forma de retornos de chamada por meio dos métodos na interface. Para obter mais informações, consulte Considerações de implementação para notificações de evasão.

Para enviar notificações de ducking, o sistema de áudio deve saber qual sessão de áudio está ouvindo os eventos de ducking. Cada sessão de áudio é identificada exclusivamente com um GUID — identificador de instância de sessão. O gerenciador de sessão permite que um aplicativo obtenha informações sobre a sessão, como o título da sessão de áudio, o estado de renderização e o identificador da instância da sessão. O identificador pode ser recuperado usando a interface de controle de diretiva, IAudioSessionControl2.

As etapas a seguir resumem o processo de obtenção do identificador de instância de sessão do aplicativo de mídia:

  1. Instancie o enumerador de dispositivos e use-o para obter uma referência ao ponto de extremidade do dispositivo que o aplicativo de mídia está usando para renderizar o fluxo de não comunicação.
  2. Ative o gerenciador de sessão a partir do ponto de extremidade do dispositivo e obtenha uma referência à interface IAudioSessionManager2 do gerenciador de sessão.
  3. Usando o ponteiro IAudioSessionManager2, obtenha uma referência à interface IAudioSessionControl do gerenciador de sessão.
  4. Consulta para o IAudioSessionControl2 da interface IAudioSessionControl.
  5. Chame IAudioSessionControl2::GetSessionInstanceIdentifier e recupere uma cadeia de caracteres que contém o identificador de sessão para a sessão de áudio atual.

Para obter notificações sobre fluxos de comunicação, o aplicativo de mídia chama IAudioSessionManager2::RegisterDuckNotification. O aplicativo de mídia fornece seu identificador de instância de sessão para o sistema de áudio e um ponteiro para a implementação IAudioVolumeDuckNotification. O aplicativo agora pode receber notificação de evento quando um fluxo é aberto no dispositivo de comunicação. Para parar de receber notificação, o aplicativo de mídia deve chamar IAudioSessionManager2::UnregisterDuckNotification.

O código a seguir mostra como um aplicativo pode se registrar para receber notificações de evasão. A classe CMediaPlayer é definida em Considerações de implementação para notificações de fuga. O exemplo DuckingMediaPlayer implementa essa funcionalidade.

////////////////////////////////////////////////////////////////////
//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;
}

Usando um dispositivo de comunicação

Experiência padrão de ducking

Desativando a experiência de ducking padrão

Fornecendo um comportamento de ducking personalizado

Considerações de implementação para notificações de evasão