Geräteeigenschaften (Core Audio APIs)

Während des Aufzählens von Audioendpunktgeräten kann eine Clientanwendung die Endpunktobjekte für ihre Geräteeigenschaften abhören. Die Geräteeigenschaften werden in der Implementierung der IPropertyStore-Schnittstelle der MMDevice-API verfügbar gemacht. Bei einem Verweis auf die IMMDevice-Schnittstelle eines Endpunktobjekts kann ein Client einen Verweis auf den Eigenschaftenspeicher des Endpunktobjekts abrufen, indem er die IMMDevice::OpenPropertyStore-Methode aufruft.

Das Property Store-Objekt macht eine IPropertyStore-Schnittstelle verfügbar. Die beiden primären Methoden in dieser Schnittstelle sind IPropertyStore::GetValue, das einen Geräteeigenschaftswert erhält, und IPropertyStore::SetValue, das einen Geräteeigenschaftswert fest legt. Weitere Informationen zu IPropertyStore finden Sie in der Windows SDK-Dokumentation.

Die Implementierung des Eigenschaftenspeichers durch die MMDevice-API ist anders als das Standardobjekt des Shell-Eigenschaftenspeichers. Um einen Eigenschaftswert zu ändern, muss die Clientanwendung die IPropertyStore::SetValue-Methode aufrufen. Während dieses Aufrufs werden die neuen Werte festgelegt und in die Registrierung geschrieben. Daher muss die Anwendung die IPropertyStore::Commit-Methode nach dem SetValue-Aufruf nicht aufrufen. Das Handle für die Registrierung wird nur geschlossen, wenn der Client den Schnittstellenzeiger frei gibt.

In der Regel rufen Clientanwendungen von Drittanbietern die GetValue-Methode auf, aber nicht die SetValue-Methode. Der Endpunkt-Manager legt die grundlegenden Geräteeigenschaften für Endpunkte fest. Der Endpunkt-Manager ist die Windows Vista-Komponente, die für die Erkennung des Vorhandenseins von Audioendpunktgeräten zuständig ist.

Jeder PKEY Xxx-Eigenschaftenbezeichner in der folgenden Liste ist eine Konstante vom Typ PROPERTYKEY, die in der Headerdatei _ Functiondiscoverykeys _ devpkey.h definiert ist. Alle Audioendpunktgeräte verfügen über diese drei Geräteeigenschaften.

Eigenschaft BESCHREIBUNG
PKEY _ DeviceInterface _ FriendlyName Der Angezeigte Name des Audioadapters, an den das Endpunktgerät angefügt ist (z. B. "XYZ-Audioadapter"). PropVARIANT member vt is set to VT _ LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the friendly name.
PKEY _ Device _ DeviceDesc Die Gerätebeschreibung des Endpunktgeräts (z. B. "Sprecher"). PropVARIANT member vt ist auf VT LPWSTR festgelegt, und member pwszVal zeigt auf eine null-terminierte Breitzeichenfolge, die die _ Gerätebeschreibung enthält.
PKEY _ Device _ FriendlyName Der Angezeigte Name des Endpunktgeräts (z. B. "Lautsprecher (XYZ-Audioadapter)"). PropVARIANT member vt is set to VT _ LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the friendly name.

Einige Audioendpunktgeräte verfügen möglicherweise über zusätzliche Eigenschaften, die in der vorherigen Liste nicht angezeigt werden. Weitere Informationen zu zusätzlichen Eigenschaften finden Sie unter Audioendpunkteigenschaften. Weitere Informationen zu PROPERTYKEY finden Sie in der dokumentation Windows SDK.

Im folgenden Codebeispiel werden die Anzeigenamen aller Audiorendering-Endpunktgeräte im System gedruckt:

//-----------------------------------------------------------
// 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)

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

Das FAILED-Makro im vorherigen Codebeispiel ist in der Headerdatei Winerror.h definiert.

Im vorherigen Codebeispiel ruft der for-loop-Text in der PrintEndpointNames-Funktion die IMMDevice::GetId-Methode auf, um die Endpunkt-ID-Zeichenfolge für das Audioendpunktgerät zu erhalten, das durch die IMMDevice-Schnittstelleninstanz dargestellt wird. Die Zeichenfolge identifiziert das Gerät in Bezug auf alle anderen Audioendpunktgeräte im System eindeutig. Ein Client kann die Endpunkt-ID-Zeichenfolge verwenden, um eine Instanz des Audioendpunktgeräts zu einem späteren Zeitpunkt oder in einem anderen Prozess durch Aufrufen der IMMDeviceEnumerator::GetDevice-Methode zu erstellen. Clients sollten den Inhalt der Endpunkt-ID-Zeichenfolge als nicht transparent behandeln. Das heißt, Clients sollten nicht versuchen, den Inhalt der Zeichenfolge zu analysieren, um Informationen zum Gerät zu erhalten. Der Grund dafür ist, dass das Zeichenfolgenformat nicht definiert ist und sich von einer Implementierung der MMDevice-API zur nächsten ändern kann.

Die benutzerfreundlichen Gerätenamen und Endpunkt-ID-Zeichenfolgen, die von der PrintEndpointNames-Funktion im vorherigen Codebeispiel abgerufen werden, sind identisch mit den benutzerfreundlichen Gerätenamen und Endpunkt-ID-Zeichenfolgen, die von DirectSound während der Geräteenumeration bereitgestellt werden. Weitere Informationen finden Sie unter Audioereignisse für Ältere Audioanwendungen.

Im vorherigen Codebeispiel ruft die PrintEndpointNames-Funktion die CoCreateInstance-Funktion auf, um einen Enumerator für die Audioendpunktgeräte im System zu erstellen. Sofern das aufrufende Programm zuvor weder die CoInitialize- noch die CoInitializeEx-Funktion aufgerufen hat, um die COM-Bibliothek zu initialisieren, ist der CoCreateInstance-Aufruf nicht fehlgeschlagen. Weitere Informationen zu CoCreateInstance, CoInitialize und CoInitializeEx finden Sie in der Dokumentation zum Windows SDK.

Weitere Informationen zu den Schnittstellen IMMDeviceEnumerator, IMMDeviceCollection und IMMDevice finden Sie unter MMDevice API.

Audioendpunktgeräte