Uso dell'enumeratore di dispositivi di sistema
[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEnginee dall’Acquisizione audio/video in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice utilizzi MediaPlayer, IMFMediaEngine e Acquisizione audio/video in Media Foundation anziché 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 di dispositivi di sistema li considera come istanze del dispositivo separate.
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 categorie include automaticamente tutti i dispositivi Plug and Play pertinenti nella categoria. Per un elenco di categorie, vedere Categorie di filtri.
Per usare l'enumeratore di dispositivi di sistema, eseguire le operazioni seguenti:
- Creare l'enumeratore di dispositivi di sistema chiamando CoCreateInstance. L'identificatore di classe (CLSID) è CLSID_SystemDeviceEnum.
- Ottenere un enumeratore di categorie chiamando ICreateDevEnum::CreateClassEnumerator con CLSID della categoria desiderata. Questo metodo restituisce un puntatore a 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 il tentativo di dereferenziarlo causerà un'eccezione. Pertanto, eseguire un test esplicito per S_OK nel momento in cui si chiama CreateClassEnumerator, invece di utilizzare la normale macro SUCCEEDED.
- Usare il metodo IEnumMoniker::Next per enumerare ogni moniker. Questo metodo restituisce un puntatore a interfaccia IMoniker. Quando il metodo Next raggiunge la fine dell'enumerazione, restituisce anche S_FALSE, quindi verificare di nuovo la presenza di S_OK.
- Per recuperare il nome descrittivo del dispositivo (ad esempio, per visualizzare nell'interfaccia utente), chiamare il metodo IMoniker::BindToStorage.
- 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.
Il diagramma seguente illustra questo processo.
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();
Nomi dei dispositivi
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. Prendere invece il nome descrittivo dal contenitore delle proprietà, come descritto in precedenza.
Il metodo IMoniker::ParseDisplayName o la funzione MkParseDisplayName possono essere usate per creare un moniker del dispositivo predefinito per una determinata categoria di filtro. Usare un nome visualizzato con il formato @device:*:{category-clsid}
, dove category-clsid
è la rappresentazione come stringa del GUID della categoria. Il moniker predefinito è il primo moniker restituito dall'enumeratore del dispositivo per tale categoria.