DirectSound 应用程序的设备角色

注意

MMDevice API 支持设备角色。 但是,Windows Vista 的用户界面不支持这一功能。 将来的 Windows 版本可能会对设备角色提供用户界面支持。 有关详细信息,请参阅 Windows Vista 中的设备角色

 

DirectSound API 没有为应用程序提供选择音频终结点设备的方法,用户已将其分配给特定设备角色。 但是,在 Windows Vista 中,核心音频 API 可与 DirectSound 应用程序配合使用,以便根据设备角色来选择设备。 借助核心音频 API,应用程序可以识别分配给特定角色的音频终结点设备,获取终结点设备的 DirectSound 设备 GUID,并调用 DirectSoundCreateDirectSoundCaptureCreate 函数来创建封装终结点设备的 IDirectSoundIDirectSoundCapture 接口实例。 有关 DirectSound 的详细信息,请参阅 Windows SDK 文档。

以下代码示例显示了如何获取当前分配给特定设备角色的呈现或捕获设备的 DirectSound 设备 GUID:

//-----------------------------------------------------------
// Get the DirectSound or DirectSoundCapture device GUID for
// an audio endpoint device. If flow = eRender, the function
// gets the DirectSound device GUID for the rendering device
// with the specified device role. If flow = eCapture, the
// function gets the DirectSoundCapture device GUID for the
// capture device with the specified device role.
//-----------------------------------------------------------
#define EXIT_ON_ERROR(hr)  \
              if (FAILED(hr)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

HRESULT GetDirectSoundGuid(EDataFlow flow, ERole role, GUID* pDevGuid)
{
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    IPropertyStore *pProps = NULL;

    PROPVARIANT var;
    PropVariantInit(&var);

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

    // Get a device enumerator for the audio endpoint
    // devices in the system.
    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                          NULL, CLSCTX_INPROC_SERVER,
                          __uuidof(IMMDeviceEnumerator),
                          (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

    // Get the endpoint device with the specified dataflow
    // direction (eRender or eCapture) and device role.
    hr = pEnumerator->GetDefaultAudioEndpoint(flow, role,
                                              &pDevice);
    EXIT_ON_ERROR(hr)

    hr = pDevice->OpenPropertyStore(STGM_READ, &pProps);
    EXIT_ON_ERROR(hr)

    // Get the DirectSound or DirectSoundCapture device GUID
    // (in WCHAR string format) for the endpoint device.
    hr = pProps->GetValue(PKEY_AudioEndpoint_GUID, &var);
    EXIT_ON_ERROR(hr)

    // Convert the WCHAR string to a GUID structure.
    hr = CLSIDFromString(var.pwszVal, pDevGuid);
    EXIT_ON_ERROR(hr)

Exit:
    PropVariantClear(&var);
    SAFE_RELEASE(pEnumerator);
    SAFE_RELEASE(pDevice);
    SAFE_RELEASE(pProps);
    return hr;
}

在前面的代码示例中,GetDirectSoundGuid 函数接受数据流方向(eRender 或 eCapture)和设备角色(eConsole、eMultimedia 或 eCommunications)作为输入参数。 第三个参数是一个指针,函数通过它写入设备 GUID,应用程序可将其作为输入参数提供给 DirectSoundCreateDirectSoundCaptureCreate 函数。

前面的代码示例通过以下方式获取 DirectSound 设备 GUID:

  • 创建一个 IMMDevice 接口实例,该实例代表具有指定数据流方向和设备角色的音频终结点设备。
  • 打开音频终结点设备的属性存储。
  • 从属性存储中获取 PKEY_AudioEndpoint_GUID 属性。 属性值是音频终结点设备的 DirectSound 设备 GUID 字符串表示形式。
  • 调用 CLSIDFromString 函数,将设备 GUID 的字符串表示形式转换为 GUID 结构。 有关 CLSIDFromString 的详细信息,请参阅 Windows SDK 文档。

从 GetDirectSoundGuid 函数中获取设备 GUID 后,应用程序可以使用该 GUID 调用 DirectSoundCreateDirectSoundCaptureCreate 以创建封装音频终结点设备的 DirectSound 呈现或捕获设备。 当 DirectSound 以这种方式创建设备时,总是将设备的音频流分配给默认会话,即由会话 GUID 值 GUID_NULL 标识的进程特定音频会话。

如果应用程序要求 DirectSound 将数据流分配给跨进程音频会话或具有非 NULL 会话 GUID 的会话,则应调用 IMMDevice::Activate 方法创建 IDirectSoundIDirectSoundCapture 对象,而不是使用前面代码示例中的技术。 有关如何使用 Activate 方法为流指定跨进程音频会话或非 NULL 会话 GUID 的代码示例,请参阅 DirectShow 应用程序的设备角色。 该部分的代码示例展示了如何创建 DirectShow 筛选器,但只需稍作修改,该代码就可用于创建 DirectSound 设备。

前面代码示例中的 GetDirectSoundGuid 函数会调用 CoCreateInstance 函数,为系统中的音频终结点设备创建一个枚举器。 除非调用程序先前调用了 CoInitializeCoInitializeEx 函数来初始化 COM 库,否则 CoCreateInstance 调用将失败。 有关 CoCreateInstanceCoInitializeCoInitializeEx 的详细信息,请参阅 Windows SDK 文档。

与传统音频 API 的互操作性