Device Roles for DirectShow Applications

Note

The MMDevice API supports device roles. However, the user interface in Windows Vista does not implement support for this feature. User interface support for device roles might be implemented in a future version of Windows. For more information, see Device Roles in Windows Vista.

 

The DirectShow API does not provide a means for an application to select the audio endpoint device that is assigned to a particular device role. However, in Windows Vista, the core audio APIs can be used in conjunction with a DirectShow application to enable device selection based on device role. With the help of the core audio APIs, the application can:

  • Identify the audio endpoint device that the user has assigned to a particular device role.
  • Create a DirectShow audio rendering filter with an IBaseFilter interface that encapsulates the audio endpoint device.
  • Build a DirectShow graph that incorporates the filter.

For more information about DirectShow and IBaseFilter, see the Windows SDK documentation.

The following code example shows how to create a DirectShow audio rendering filter that encapsulates the rendering endpoint device that is assigned to a particular device role:

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

In the preceding code example, the CreateAudioRenderer function accepts a device role (eConsole, eMultimedia, or eCommunications) as an input parameter. The second parameter is a pointer through which the function writes the address of an IBaseFilter interface instance. In addition, the example shows how to use the IMMDevice::Activate method to assign the audio stream in the IBaseFilter instance to a cross-process audio session with an application-specific session GUID (specified by the guidAudioSessionId constant). The third parameter in the Activate call points to a structure that contains the session GUID and cross-process flag. If the user runs multiple instances of the application, then the audio streams from all the instances use the same session GUID and thus belong to the same session.

Alternatively, the caller can specify NULL as the third parameter in the Activate call to assign the stream to the default session as the process-specific session with session GUID value GUID_NULL. For more information, see IMMDevice::Activate.

Interoperability with Legacy Audio APIs