Свойства устройства (основные API-интерфейсы аудио)

В процессе перечисления звуковых конечных точек клиентское приложение может просить объекты конечной точки для их свойств устройства. Свойства устройства предоставляются в реализации API MMDevice интерфейса IPropertyStore. Учитывая ссылку на интерфейс IMMDevice объекта конечной точки, клиент может получить ссылку на хранилище свойств конечной точки, вызвав метод IMMDevice::OpenPropertyStore.

Клиенты могут читать эти свойства, но не должны задавать их. Значения свойств хранятся в виде структур PROPVARIANT .

Диспетчер конечных точек задает базовые свойства устройства для конечных точек. Диспетчер конечных точек — это компонент Windows, отвечающий за обнаружение наличия устройств аудиоконечной точки.

Каждый идентификатор свойства PKEY_Xxx в следующем списке является константой типа PROPERTYKEY , определенной в файле заголовка Functiondiscoverykeys_devpkey.h. Все устройства конечной точки аудио имеют эти свойства устройства.

Свойство Description
PKEY_DeviceInterface_FriendlyName Понятное имя звукового адаптера, к которому подключено устройство конечной точки (например, XYZ Audio Adapter).
PKEY_Device_DeviceDesc Описание устройства конечной точки (например, "Динамики").
PKEY_Device_FriendlyName Понятное имя устройства конечной точки (например, "Динамики (аудиоадаптер XYZ)").
PKEY_Device_InstanceId Сохраняет идентификатор экземпляра устройства аудио конечной точки. Значение также можно получить с помощью метода IMMDevice::GetId . Дополнительные сведения об этом свойстве см. в разделе "Строки идентификатора конечной точки" и DEVPKEY_Device_InstanceId.
PKEY_Device_ContainerId Хранит идентификатор контейнера устройства PnP, реализующего конечную точку звука. Дополнительные сведения об этом свойстве см. в DEVPKEY_Device_ContainerId.

Некоторые устройства конечной точки аудио могут иметь дополнительные свойства, которые не отображаются в предыдущем списке. Дополнительные сведения о дополнительных свойствах см. в разделе "Свойства конечной точки аудио".

Дополнительные сведения о PROPERTYKEY см. в документации по системе свойств Windows.

В следующем примере кода отображаются имена всех устройств конечной точки отрисовки звука в системе:

//-----------------------------------------------------------
// This function enumerates all active (plugged in) audio
// rendering endpoint devices. It prints the friendly name
// and endpoint ID string of each endpoint device.
//-----------------------------------------------------------
#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);

void PrintEndpointNames()
{
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDeviceCollection *pCollection = NULL;
    IMMDevice *pEndpoint = NULL;
    IPropertyStore *pProps = NULL;
    LPWSTR pwszID = NULL;

    hr = CoCreateInstance(
           CLSID_MMDeviceEnumerator, NULL,
           CLSCTX_ALL, IID_IMMDeviceEnumerator,
           (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

    hr = pEnumerator->EnumAudioEndpoints(
                        eRender, DEVICE_STATE_ACTIVE,
                        &pCollection);
    EXIT_ON_ERROR(hr)

    UINT  count;
    hr = pCollection->GetCount(&count);
    EXIT_ON_ERROR(hr)

    if (count == 0)
    {
        printf("No endpoints found.\n");
    }

    // Each loop prints the name of an endpoint device.
    for (ULONG i = 0; i < count; i++)
    {
        // Get pointer to endpoint number i.
        hr = pCollection->Item(i, &pEndpoint);
        EXIT_ON_ERROR(hr)

        // Get the endpoint ID string.
        hr = pEndpoint->GetId(&pwszID);
        EXIT_ON_ERROR(hr)
        
        hr = pEndpoint->OpenPropertyStore(
                          STGM_READ, &pProps);
        EXIT_ON_ERROR(hr)

        PROPVARIANT varName;
        // Initialize container for property value.
        PropVariantInit(&varName);

        // Get the endpoint's friendly-name property.
        hr = pProps->GetValue(
                       PKEY_Device_FriendlyName, &varName);
        EXIT_ON_ERROR(hr)

        // GetValue succeeds and returns S_OK if PKEY_Device_FriendlyName is not found.
        // In this case vartName.vt is set to VT_EMPTY.      
        if (varName.vt != VT_EMPTY)
        {
            // Print endpoint friendly name and endpoint ID.
            printf("Endpoint %d: \"%S\" (%S)\n", 
                    i, varName.pwszVal, pwszID);
        }

        CoTaskMemFree(pwszID);
        pwszID = NULL;
        PropVariantClear(&varName);
        SAFE_RELEASE(pProps)
        SAFE_RELEASE(pEndpoint)
    }
    SAFE_RELEASE(pEnumerator)
    SAFE_RELEASE(pCollection)
    return;

Exit:
    printf("Error!\n");
    CoTaskMemFree(pwszID);
    SAFE_RELEASE(pEnumerator)
    SAFE_RELEASE(pCollection)
    SAFE_RELEASE(pEndpoint)
    SAFE_RELEASE(pProps)
}

Макрос FAILED в предыдущем примере кода определен в файле заголовка Winerror.h.

В приведенном выше примере кода текст цикла в функции PrintEndpointNames вызывает метод IMMDevice::GetId, чтобы получить строку идентификатора конечной точки для устройства аудио конечной точки, представленного экземпляром интерфейса IMMDevice. Строка однозначно идентифицирует устройство относительно всех других звуковых конечных точек в системе. Клиент может использовать строку идентификатора конечной точки для создания экземпляра устройства аудио конечной точки позже или в другом процессе путем вызова метода IMMDeviceEnumerator::GetDevice. Клиенты должны рассматривать содержимое строки идентификатора конечной точки как непрозрачную. То есть клиенты не должны пытаться проанализировать содержимое строки для получения сведений об устройстве. Причина заключается в том, что формат строки не определен и может измениться с одной реализации API MMDevice на следующую.

Понятные имена устройств и строки идентификатора конечной точки, полученные функцией PrintEndpointNames в предыдущем примере кода, идентичны понятным именам устройств и строкам идентификатора конечной точки, предоставляемым DirectSound во время перечисления устройств. Дополнительные сведения см. в разделе "События аудио" для устаревших звуковых приложений.

В приведенном выше примере кода функция PrintEndpointNames вызывает функцию CoCreateInstance для создания перечислителя для устройств аудио конечной точки в системе. Если ранее вызываемая программа не вызывала функцию CoInitialize или CoInitializeEx для инициализации библиотеки COM, вызов CoCreateInstance завершится ошибкой. Дополнительные сведения о CoCreateInstance, CoInitialize и CoInitializeEx см. в документации по пакету SDK для Windows.

Дополнительные сведения об интерфейсах IMMDeviceEnumerator, IMMDeviceCollection и IMMDevice см. в разделе API MMDevice.

Устройства аудиоконечной точки