Microsoft DirectX 8.0

Enumerating Devices and Filters

Sometimes an application needs to locate a particular filter on the user's system. For example, a video capture application might display a list of available capture devices. Because Microsoft® DirectShow® uses a component-based architecture, it is not always possible to know until run time what filters are installed on the system. This is particularly true for filters that represent hardware devices. Two components in DirectShow make it easier to locate registered filters:

The enumerators discussed in this section follow the standard form used by COM enumeration interfaces. For more information, see the IEnumXXXX topic in the Microsoft Platform Software Development Kit (SDK). This section contains the following topics:

Using the System Device Enumerator

The system device enumerator provides a uniform way to enumerate, by category, the filters registered on a user's system. Moreover, it differentiates between individual hardware devices, even if the same filter supports them. This is particularly useful for devices that use the Windows Driver Model (WDM) and the KSProxy filter. For example, the user might have several WDM video capture devices, all supported by the same filter. The system device enumerator treats them as separate device instances.

The system device enumerator works by creating an enumerator for a specific category, such as audio capture or video compression. The category enumerator returns a unique moniker for each device in the category. The category enumerator automatically includes any relevant Plug and Play devices in the category. For a list of categories, see Filter Categories.

To create the system device enumerator, call CoCreateInstance with a class identifier (CLSID) of CLSID_SystemDeviceEnum. To retrieve the category enumerator, call ICreateDevEnum::CreateClassEnumerator with the CLSID of the desired category. The category enumerator supports the IEnumMoniker interface, which you can use to enumerate the individual monikers. Call IMoniker::BindToObject on a moniker to create and initialize the device object, or IMoniker::BindToStorage to retrieve the friendly name of the device (for example, to populate a list box in a user interface). The following diagram illustrates this process.

Enumerating devices

The following example shows how to create an instance of the system device enumerator and then use it to enumerate video compressor devices. For brevity, the example omits any error checking.

ICreateDevEnum *pSysDevEnum = NULL;
CoCreateInstance(CLSID_SystemDeviceEnum, 
    NULL, CLSCTX_INPROC, IID_ICreateDevEnum, 
    (void **)&pSysDevEnum);

IEnumMoniker *pEnumCat = NULL;
pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);

IMoniker *pMoniker;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
    IPropertyBag *pPropBag;
    pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);

    VARIANT varName;
    varName.vt = VT_BSTR;
    pPropBag->Read(L"FriendlyName", &varName, 0);

    // Do something with the name.

    SysFreeString(varName.bstrVal);
    pPropBag->Release();
    pMoniker->Release();
}
pEnumCat->Release();
pSysDevEnum->Release();

Using the Filter Mapper

The filter mapper is a COM object that enumerates filters based on various search criteria. The filter mapper is less efficient than the system device enumerator, so if you need filters from a particular category, use the system device enumerator. But if you need to locate a filter that supports a certain combination of media types, but does not fall into a clear-cut category, you might need to use the filter mapper. An example would be a renderer filter or a decoder filter.

The filter mapper supports the IFilterMapper2 interface. To search for a filter, call IFilterMapper2::EnumMatchingFilters. This method takes several parameters that define the search criteria, and returns with an enumerator for the matching filters. The enumerator supports IEnumMoniker, and supplies a unique moniker for each matching filter.

The following example enumerates filters that accept digital video (DV) input and have at least one output pin, of any media type. (The DV Video Decoder filter matches these criteria.)

IFilterMapper2 *pMapper = NULL;
IEnumMoniker *pEnum = NULL;

CoCreateInstance(CLSID_FilterMapper2, 
    NULL, CLSCTX_INPROC, IID_IFilterMapper2, 
    (void **) &pMapper);
    
GUID arrayInTypes[2];
arrayInTypes[0] = MEDIATYPE_Video;
arrayInTypes[1] = MEDIASUBTYPE_dvsd;

hr = pMapper->EnumMatchingFilters(
        &pEnum,
        0,                  // Reserved.
        TRUE,               // Use exact match?
        MERIT_DO_NOT_USE+1, // Minimum merit.
        TRUE,               // At least one input pin?
        1,                  // Number of major type/subtype pairs for input.
        arrayInTypes,       // Array of major type/subtype pairs for input.
        NULL,               // Input medium.
        NULL,               // Input pin category.
        FALSE,              // Must be a renderer?
        TRUE,               // At least one output pin?
        0,                  // Number of major type/subtype pairs for output.
        NULL,               // Array of major type/subtype pairs for output.
        NULL,               // Output medium.
        NULL);              // Output pin category.

// Enumerate using pEnum, as in the previous example.

The EnumMatchingFilters method has a fairly large number of parameters, which are commented in the example. The significant ones for this example include: