Microsoft DirectX 9.0 |
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 use the System Device Enumerator, do the following:
The following diagram illustrates this process.
The following example shows how to enumerate the video compressors installed on the user's system. For brevity, the example performs minimal error checking.
// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
return hr;
}
// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);
if (hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
if (SUCCEEDED(hr))
{
// To retrieve the filter's friendly name, do the following:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr))
{
// Display the name in your UI somehow.
}
VariantClear(&varName);
// To create an instance of the filter, do the following:
IBaseFilter *pFilter;
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
(void**)&pFilter);
// Now add the filter to the graph.
//Remember to release pFilter later.
pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
}
pSysDevEnum->Release();
Device Monikers
The IMoniker::GetDisplayName method returns the display name of the moniker. For device monikers, you can pass the display name to the IFilterGraph2::AddSourceFilterForMoniker method to create a capture filter for the device:
LPOLESTR strName = NULL;
IBaseFilter pSrc = NULL;
hr = pMoniker->GetDisplayName(NULL, NULL, &strName);
if (SUCCEEDED(hr))
{
// Query the Filter Graph Manager for IFilterGraph2.
IFilterGraph2 *pFG2 = NULL;
hr = pGraph->QueryInterface(IID_IFilterGraph2, (void**)&pFG2);
if (SUCCEEDED(hr))
{
hr = pFG2->AddSourceFilterForMoniker(pMoniker, 0, L"Source", &pSrc);
pFG2->Release();
}
CoTaskMemFree(strName);
}
// If successful, remember to release pSrc.
Although the display name is readable, you would not typically display it to an end-user. Get the friendly name from the property bag instead, as described previously.
The IMoniker::ParseDisplayName method or the MkParseDisplayName function can be used to create a default device moniker for a given filter category. Use a display name with the form @device:*:{category-clsid}
, where category-clsid
is the string representation of the category GUID. The default moniker is the first moniker returned by the device enumerator for that category.
For example, the following code creates the default moniker for the video capture category:
// Video capture category
WCHAR szMon[] = L"@device:*:{860BB310-5D01-11d0-BD3B-00A0C911CE86}";
IBindCtx *pBindCtx;
hr = CreateBindCtx(0, &pBindCtx);
ULONG chEaten = 0;
IMoniker *pMoniker = 0;
hr = MkParseDisplayName(pBindCtx, szMon, &chEaten, &pMoniker);
pBindCtx->Release();
if (SUCCEEDED(hr))
{
// Get the display name, or bind to a DirectShow filter.
pMoniker->Release();
}