Funções de dispositivo para aplicativos DirectShow

Observação

A API MMDevice oferece suporte a funções de dispositivo. No entanto, a interface do usuário no Windows Vista não implementa suporte para esse recurso. O suporte à interface do usuário para funções de dispositivo pode ser implementado em uma versão futura do Windows. Para obter mais informações, consulte Funções de dispositivo no Windows Vista.

 

A API do DirectShow não fornece um meio para um aplicativo selecionar o dispositivo de ponto de extremidade de áudio atribuído a uma função de dispositivo específica. No entanto, no Windows Vista, as APIs de áudio principais podem ser usadas em conjunto com um aplicativo DirectShow para habilitar a seleção de dispositivo com base na função do dispositivo. Com a ajuda das principais APIs de áudio, o aplicativo pode:

  • Identifique o dispositivo de ponto de extremidade de áudio que o usuário atribuiu a uma função de dispositivo específica.
  • Crie um filtro de renderização de áudio DirectShow com uma interface IBaseFilter que encapsula o dispositivo de ponto de extremidade de áudio.
  • Crie um gráfico DirectShow que incorpore o filtro.

Para obter mais informações sobre DirectShow e IBaseFilter, consulte a documentação do SDK do Windows.

O exemplo de código a seguir mostra como criar um filtro de renderização de áudio DirectShow que encapsula o dispositivo de ponto de extremidade de renderização atribuído a uma função de dispositivo específica:

//-----------------------------------------------------------
// Create a DirectShow audio rendering filter that
// encapsulates the audio endpoint device that is currently
// assigned to the specified device role.
//-----------------------------------------------------------
#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

// This application's audio session GUID
const GUID guidAudioSessionId = {
    0xb13ff52e, 0xa5cf, 0x4fca,
    {0x9f, 0xc3, 0x42, 0x26, 0x5b, 0x0b, 0x14, 0xfb}
};

HRESULT CreateAudioRenderer(ERole role, IBaseFilter** ppAudioRenderer)
{
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDevice *pDevice = NULL;

    if (ppAudioRenderer == NULL)
    {
        return E_POINTER;
    }

    // Activate the IBaseFilter interface on the
    // audio renderer with the specified role.
    hr = CoCreateInstance(CLSID_MMDeviceEnumerator,
                          NULL, CLSCTX_INPROC_SERVER,
                          __uuidof(IMMDeviceEnumerator),
                          (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, role,
                                              &pDevice);
    EXIT_ON_ERROR(hr)

    DIRECTX_AUDIO_ACTIVATION_PARAMS  daap;
    daap.cbDirectXAudioActivationParams = sizeof(daap);
    daap.guidAudioSession = guidAudioSessionId;
    daap.dwAudioStreamFlags = AUDCLNT_STREAMFLAGS_CROSSPROCESS;

    PROPVARIANT  var;
    PropVariantInit(&var);

    var.vt = VT_BLOB;
    var.blob.cbSize = sizeof(daap);
    var.blob.pBlobData = (BYTE*)&daap;

    hr = pDevice->Activate(__uuidof(IBaseFilter),
                           CLSCTX_ALL, &var,
                           (void**)ppAudioRenderer);
    EXIT_ON_ERROR(hr)

Exit:
    SAFE_RELEASE(pEnumerator);
    SAFE_RELEASE(pDevice);
    return hr;
}

No exemplo de código anterior, a função CreateAudioRenderer aceita uma função de dispositivo (eConsole, eMultimedia ou eCommunications) como um parâmetro de entrada. O segundo parâmetro é um ponteiro através do qual a função grava o endereço de uma instância de interface IBaseFilter. Além disso, o exemplo mostra como usar o método IMMDevice::Activate para atribuir o fluxo de áudio na instância IBaseFilter a uma sessão de áudio de processo cruzado com um GUID de sessão específico do aplicativo (especificado pela constante guidAudioSessionId). O terceiro parâmetro na chamada Activate aponta para uma estrutura que contém o GUID da sessão e o sinalizador entre processos. Se o usuário executar várias instâncias do aplicativo, os fluxos de áudio de todas as instâncias usarão o mesmo GUID de sessão e, portanto, pertencerão à mesma sessão.

Como alternativa, o chamador pode especificar NULL como o terceiro parâmetro na chamada Activate para atribuir o fluxo à sessão padrão como a sessão específica do processo com o valor GUID da sessão GUID_NULL. Para obter mais informações, consulte IMMDevice::Activate.

Interoperabilidade com APIs de áudio herdadas