カクタスソフトウェア
カクタスソフトウェア
サウンド MIDI マルチメディア アプリケーション

デバイスの列挙

デバイスの列挙によってシステムにどのような入力および出力デバイスがインストールされているかを調べます。デフォルトデバイスを用いるときはデバイスの列挙を省略することができます。

ただしビデオ入力などデバイスがインストールされていないこともあるので、デフォルトの入力デバイスを用いる場合でも列挙を行って確認すると良いでしょう。

デバイスの列挙は以下の手順で行います。少し手順が混み入っていますが順を追って説明します。以下に実際のコード例を示します。

HRESULT CMyClass::EnumFilter(void)
{
    ICreateDevEnum  *pSysDevEnum = NULL;
    IEnumMoniker    *pEnumCat = NULL;
    IMoniker        *pMoniker = NULL;
    IPropertyBag    *pPropBag = NULL;

    HRESULT result = S_OK;
    ULONG cFetched;

    try
    {
        result = CoCreateInstance(
                                  CLSID_SystemDeviceEnum,
                                  NULL,
                                  CLSCTX_INPROC_SERVER,
                                  IID_ICreateDevEnum,
                                  (void **)&pSysDevEnum);
        if (FAILED(result))     throw result;

        result = pSysDevEnum->CreateClassEnumerator(
                                                    CLSID_AudioRendererCategory,
                                                    &pEnumCat,
                                                    0);
        if (result != S_OK)     throw result;

        while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
        {
            // IMonikerを使った処理

            result = pMoniker->BindToStorage(
                                             0,
                                             0,
                                             IID_IPropertyBag,
                                             (void **)&pPropBag);
            if (SUCCEEDED(result))
            {
                VARIANT varName;
                VariantInit(&varName);
                result = pPropBag->Read(L"FriendlyName", &varName, 0);

                if (SUCCEEDED(result))
                {
                    // IPropertyBagを使った処理
                }
                VariantClear(&varName);
            }
            SAFE_RELEASE(pPropBag);
            SAFE_RELEASE(pMoniker);
        }
    }
    catch (HRESULT result)
    {
        // エラー処理
    }
    SAFE_RELEASE(pPropBag);
    SAFE_RELEASE(pMoniker);
    SAFE_RELEASE(pEnumCat);
    SAFE_RELEASE(pSysDevEnum);
    return result;
}
デバイス列挙子を作るインターフェースを作らなければならないというあたりが面倒です。さらにデバイスの識別子モニカからデバイス名を取得する手順も手間がかかります。

CoCreateInstance()関数でICreateDevEnumインターフェースを作成する

ICreateDevEnumインターフェースはデバイスの列挙に用いるデバイス列挙子の作成を支援します。ICreateDevEnumの作成にはCoCreateInstance()関数を用います。

ICreateDevEnum  *pSysDevEnum = NULL;

    HRESULT result = CoCreateInstance(
        CLSID_SystemDeviceEnum,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_ICreateDevEnum,
        (void **)&pSysDevEnum);
    if (FAILED(result))     throw result;

    // TODO:

    SAFE_RELEASE(pSysDevEnum);

ICreateDevEnumの利用が終わったらリリースします。

ICreateDevEnum::CreateClassEnumerator()関数でIEnumMonikerインターフェースを作成する

列挙子作成支援インターフェースICreateDevEnumのCreateClassEnumerator()関数でIEnumMonikerインターフェースを作成します。IEnumMonikerはデバイスを識別するモニカの列挙に使う列挙子です。

IEnumMoniker    *pEnumCat = NULL;

    result = pSysDevEnum->CreateClassEnumerator(
        CLSID_AudioRendererCategory,
        &pEnumCat,
        0);
    if (result != S_OK)     throw result;

    // TODO:

    SAFE_RELEASE(pEnumCat);

第一引数に列挙したいデバイスカテゴリのクラス識別子(CLSID)を指定します。以下にデバイスカテゴリとCLSIDの対応(一部)を示します。

デバイス CLSID
Audio録音 CLSID_AudioInputDeviceCategory
Audio再生 CLSID_AudioRendererCategory
MIDI再生 CLSID_MidiRendererCategory
Video入力 CLSID_VideoInputDeviceCategory

もし1つのデバイスも見つからなかった場合、pEnumCatはNULLとなり、resultにはS_FALSEが戻ります。そのためエラーチェックはFAILEDマクロではなく、S_OKとの比較で行います。

IEnumMonikerの利用が終わったらリリースします。

IEnumMoniker::Next()関数でIMonikerインターフェースを列挙する

モニカの列挙子IEnumMonikerのNext()関数でデバイスの識別に用いるIMonikerインターフェースを列挙します。IMonikerを用いてモニカの内部情報にアクセスします。

IMoniker        *pMoniker = NULL;
ULONG           cFetched;

    while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        // IMonikerを使った処理
        SAFE_RELEASE(pMoniker);
    }

ここで得られたpMonikerはデバイスを指定するときに用いることができます。

IMonikerの利用が終わったら、リリースします。ただし後でモニカを用いた処理(フィルターの作成など)を行うためにpMonikerを保存した場合はリリースしてはいけません。

IMoniker::BindToStorage()関数でIPropertyBagインターフェースを取得する

BindToStorage()関数はモニカが管理する領域にアクセスするためのコマンドです。ここではモニカのプロパティを読み書きするIPropertyBagインターフェースを取得します。

IPropertyBag    *pPropBag = NULL;

        result = pMoniker->BindToStorage(
            0,
            0,
            IID_IPropertyBag,
            (void **)&pPropBag);

        if (SUCCEEDED(result))
        {
            // IPropertyBagを使った処理
        }
        SAFE_RELEASE(pPropBag);

IPropertyBagの利用が終わったら、リリースします。

IPropertyBag::Read()関数でデバイス名を取得する

IPropertyBagインターフェースのRead()関数でデバイス名を取得します。

        VARIANT varName;
        VariantInit(&varName);
        result = pPropBag->Read(L"FriendlyName", &varName, 0);
        // varName.bstrValを利用する
        VariantClear(&varName);

varName.bstrValで得られる文字列はユニコードです。

VARIANTはVariantInit()関数で初期化し、利用が終わったらVariantClear()関数で領域を開放します。

ドキュメントの先頭へ

カクタスソフトウェア 技術協力 資料室 資料室の広場 SourceForge.jp お問い合わせ