デバイスのプロパティ (コア オーディオ API)

オーディオ エンドポイント デバイスを列挙するプロセス中、クライアント アプリケーションはデバイスのプロパティについてエンドポイント オブジェクトに問い合わせることができます。 デバイスのプロパティは、MMDevice API の IPropertyStore インターフェイスの実装で公開されます。 エンドポイント オブジェクトの IMMDevice インターフェイスへの参照を指定すると、クライアントは IMMDevice::OpenPropertyStore メソッドを呼び出すことにより、エンドポイント オブジェクトのプロパティ ストアへの参照を取得できます。

クライアントは、これらのプロパティを読み取ることができますが、設定してはなりません。 プロパティ値は PROPVARIANT 構造として格納されます。

エンドポイント マネージャーは、エンドポイントの基本的なデバイス プロパティを設定します。 エンドポイント マネージャーは、オーディオ エンドポイント デバイスの存在を検出する Windows コンポーネントです。

次の一覧の各 PKEY_Xxx プロパティ識別子は、ヘッダー ファイル Functiondiscoverykeys_devpkey.h で定義されている PROPERTYKEY 型の定数です。 すべてのオーディオ エンドポイント デバイスには、これらのデバイス プロパティがあります。

プロパティ 説明
PKEY_DeviceInterface_FriendlyName エンドポイント デバイスが接続されているオーディオ アダプターのフレンドリ名 ("XYZ オーディオ アダプター" など)。
PKEY_Device_DeviceDesc エンドポイント デバイスのデバイスの説明 (例: "スピーカー")。
PKEY_Device_FriendlyName エンドポイント デバイスのフレンドリ名 (例: "スピーカー (XYZ オーディオ アダプター)")。
PKEY_Device_InstanceId オーディオ エンドポイントのデバイス インスタンス識別子を格納します。 この値は、IMMDevice::GetId メソッドを通じて取得することもできます。 このプロパティについて詳しくは、「エンドポイント ID 文字列」と「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 関数の for ループ本体が IMMDevice::GetId メソッドを呼び出して、IMMDevice インターフェイス インスタンスによって表されるオーディオ エンドポイント デバイスのエンドポイント ID 文字列を取得しています。 この文字列は、システム内の他のすべてのオーディオ エンドポイント デバイスに関してデバイスを一意に識別します。 クライアントは、エンドポイント ID 文字列を使用し、IMMDeviceEnumerator::GetDevice メソッドを呼び出すことにより、後で、または別のプロセスでオーディオ エンドポイント デバイスのインスタンスを作成できます。 クライアントは、エンドポイント ID 文字列の内容を不透明として扱う必要があります。 つまり、クライアントが文字列の内容を解析してデバイスに関する情報を取得してはなりません。 その理由は、文字列形式が未定義であり、MMDevice API の実装から次の実装に変わる可能性があるためです。

前のコード例の PrintEndpointNames 関数によって取得されるフレンドリ デバイス名とエンドポイント ID 文字列は、デバイスの列挙時に DirectSound によって提供されるフレンドリ デバイス名およびエンドポイント ID 文字列と同じです。 詳しくは、「レガシ オーディオ アプリケーションのオーディオ イベント」をご覧ください。

前のコード例では、PrintEndpointNames 関数が CoCreateInstance 関数を呼び出して、システム内のオーディオ エンドポイント デバイスの列挙子を作成しています。 呼び出し元のプログラムが COM ライブラリを 初期化するために CoInitialize 関数または CoInitializeEx 関数を以前に呼び出していない限り、CoCreateInstance 呼び出しは失敗します。 CoCreateInstanceCoInitializeCoInitializeEx の詳細については、Windows SDK のドキュメントを参照してください。

IMMDeviceEnumeratorIMMDeviceCollection、および IMMDevice インターフェイスの詳細については、「MMDevice API」をご覧ください。

オーディオ エンドポイント デバイス