Uso dell'enumeratore del dispositivo di sistema

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

L'enumeratore di dispositivi di sistema offre un modo uniforme per enumerare, per categoria, i filtri registrati nel sistema di un utente. Inoltre, distingue tra singoli dispositivi hardware, anche se lo stesso filtro li supporta. Ciò è particolarmente utile per i dispositivi che usano windows Driver Model (WDM) e il filtro KSProxy. Ad esempio, l'utente potrebbe avere diversi dispositivi di acquisizione video WDM, tutti supportati dallo stesso filtro. L'enumeratore del dispositivo di sistema li considera come istanze separate del dispositivo.

L'enumeratore di dispositivi di sistema funziona creando un enumeratore per una categoria specifica, ad esempio l'acquisizione audio o la compressione video. L'enumeratore di categorie restituisce un moniker univoco per ogni dispositivo nella categoria. L'enumeratore di categoria include automaticamente tutti i dispositivi Plug and Play pertinenti nella categoria. Per un elenco di categorie, vedere Categorie di filtro.

Per usare l'enumeratore di dispositivi di sistema, eseguire le operazioni seguenti:

  1. Creare l'enumeratore del dispositivo di sistema chiamando CoCreateInstance. L'identificatore di classe (CLSID) è CLSID_SystemDeviceEnum.
  2. Ottenere un enumeratore di categoria chiamando ICreateDevEnum::CreateClassEnumerator con CLSID della categoria desiderata. Questo metodo restituisce un puntatore all'interfaccia IEnumMoniker . Se la categoria è vuota (o non esiste), il metodo restituisce S_FALSE anziché un codice di errore. In tal caso, il puntatore IEnumMoniker restituito è NULL e dereferenziandolo causerà un'eccezione. Di conseguenza, testare in modo esplicito la S_OK quando si chiama CreateClassEnumerator, anziché chiamare la normale macro SUCCEEDED .
  3. Utilizzare il metodo IEnumMoniker::Next per enumerare ogni moniker. Questo metodo restituisce un puntatore all'interfaccia IMoniker . Quando il metodo Next raggiunge la fine dell'enumerazione, restituisce anche S_FALSE, quindi verificare di nuovo la presenza di S_OK.
  4. Per recuperare il nome descrittivo del dispositivo ,ad esempio per la visualizzazione nell'interfaccia utente, chiamare il metodo IMoniker::BindToStorage .
  5. Per creare e inizializzare il filtro DirectShow che gestisce il dispositivo, chiamare IMoniker::BindToObject nel moniker. Chiamare IFilterGraph::AddFilter per aggiungere il filtro al grafico.

La figura seguente illustra questo processo.

enumerazione dei dispositivi

Nell'esempio seguente viene illustrato come enumerare i compressori video installati nel sistema dell'utente. Per brevità, l'esempio esegue un controllo degli errori minimo.

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

Moniker dispositivo

Per i moniker del dispositivo, è possibile passare il moniker al metodo IFilterGraph2::AddSourceFilterForMoniker per creare un filtro di acquisizione per il dispositivo. Per un esempio di codice, vedere la documentazione relativa a tale metodo.

Il metodo IMoniker::GetDisplayName restituisce il nome visualizzato del moniker. Anche se il nome visualizzato è leggibile, in genere non viene visualizzato a un utente finale. Ottenere invece il nome descrittivo dal contenitore delle proprietà, come descritto in precedenza.

Il metodo IMoniker::P arseDisplayName o la funzione MkParseDisplayName può essere usata per creare un moniker di dispositivo predefinito per una determinata categoria di filtro. Usare un nome visualizzato con il formato @device:*:{category-clsid}, dove category-clsid è la rappresentazione di stringa del GUID della categoria. Il moniker predefinito è il primo moniker restituito dall'enumeratore del dispositivo per tale categoria.