From 42cdb92543ebba4d4cadff76f51712219245f347 Mon Sep 17 00:00:00 2001 From: Lev Zelenskiy Date: Fri, 27 Jul 2012 11:35:17 +1000 Subject: [PATCH] Use moniker display name for device string. Moniker names are unique, while device friendly names are not. Change-Id: Ic3e842e49d04c502cf5ad1fc40f89db657f0401a Reviewed-by: Michael Goddard Reviewed-by: Ling Hu --- src/plugins/directshow/camera/dscamerasession.cpp | 59 ++++------- .../directshow/camera/dsvideodevicecontrol.cpp | 117 +++++++++++---------- .../directshow/camera/dsvideodevicecontrol.h | 7 +- src/plugins/directshow/dsserviceplugin.cpp | 57 +--------- 4 files changed, 92 insertions(+), 148 deletions(-) diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index ccc39a8..71151b5 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -417,31 +417,23 @@ void DSCameraSession::setDevice(const QString &device) pEnum->Reset(); // go through and find all video capture devices IMoniker* pMoniker = NULL; + IMalloc *mallocInterface = 0; + CoGetMalloc(1, (LPMALLOC*)&mallocInterface); while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, - (void**)(&pPropBag)); - if(FAILED(hr)) { - pMoniker->Release(); - continue; // skip this one - } - // Find the description - WCHAR str[120]; - VARIANT varName; - varName.vt = VT_BSTR; - hr = pPropBag->Read(L"Description", &varName, 0); - if(FAILED(hr)) - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if(SUCCEEDED(hr)) { - wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); - QString temp(QString::fromUtf16((unsigned short*)str)); + + BSTR strName = 0; + hr = pMoniker->GetDisplayName(NULL, NULL, &strName); + if (SUCCEEDED(hr)) { + QString temp(QString::fromWCharArray(strName)); + mallocInterface->Free(strName); if(temp.contains(device)) { available = true; } } - pPropBag->Release(); + pMoniker->Release(); } + mallocInterface->Release(); pEnum->Release(); } pDevEnum->Release(); @@ -449,7 +441,7 @@ void DSCameraSession::setDevice(const QString &device) CoUninitialize(); if(available) { - m_device = QByteArray(device.toLocal8Bit().constData()); + m_device = QByteArray(device.toUtf8().constData()); graph = createFilterGraph(); if(!graph) available = false; @@ -698,36 +690,27 @@ bool DSCameraSession::createFilterGraph() pDevEnum->Release(); if (S_OK == hr) { pEnum->Reset(); + IMalloc *mallocInterface = 0; + CoGetMalloc(1, (LPMALLOC*)&mallocInterface); //go through and find all video capture devices while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0, 0, - IID_IPropertyBag, (void**)(&pPropBag)); - if(FAILED(hr)) { - pMoniker->Release(); - continue; // skip this one - } - // Find the description - WCHAR str[120]; - VARIANT varName; - varName.vt = VT_BSTR; - hr = pPropBag->Read(L"FriendlyName", &varName, 0); + + BSTR strName = 0; + hr = pMoniker->GetDisplayName(NULL, NULL, &strName); if (SUCCEEDED(hr)) { - // check if it is the selected device - wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); - QString output = QString::fromUtf16((unsigned short*)str); - if (m_device.contains(output.toLocal8Bit().constData())) { + QString output = QString::fromWCharArray(strName); + mallocInterface->Free(strName); + if (m_device.contains(output.toUtf8().constData())) { hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); if (SUCCEEDED(hr)) { - pPropBag->Release(); pMoniker->Release(); break; } } } - pPropBag->Release(); pMoniker->Release(); } + mallocInterface->Release(); if (NULL == pCap) { if (m_device.contains("default")) @@ -770,7 +753,7 @@ bool DSCameraSession::createFilterGraph() return false; } - pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&pSG); + hr = pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&pSG); if (FAILED(hr)) { qWarning() << "failed to get sample grabber"; return false; diff --git a/src/plugins/directshow/camera/dsvideodevicecontrol.cpp b/src/plugins/directshow/camera/dsvideodevicecontrol.cpp index 94b0704..7084c8e 100644 --- a/src/plugins/directshow/camera/dsvideodevicecontrol.cpp +++ b/src/plugins/directshow/camera/dsvideodevicecontrol.cpp @@ -61,75 +61,28 @@ DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent) { m_session = qobject_cast(parent); - devices.clear(); - descriptions.clear(); - - CoInitialize(NULL); - ICreateDevEnum* pDevEnum = NULL; - IEnumMoniker* pEnum = NULL; - // Create the System device enumerator - HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, - reinterpret_cast(&pDevEnum)); - if(SUCCEEDED(hr)) { - // Create the enumerator for the video capture category - hr = pDevEnum->CreateClassEnumerator( - CLSID_VideoInputDeviceCategory, &pEnum, 0); - if (S_OK == hr) { - pEnum->Reset(); - // go through and find all video capture devices - IMoniker* pMoniker = NULL; - while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, - (void**)(&pPropBag)); - if(FAILED(hr)) { - pMoniker->Release(); - continue; // skip this one - } - // Find the description - WCHAR str[120]; - VARIANT varName; - varName.vt = VT_BSTR; - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if(SUCCEEDED(hr)) { - wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); - QString temp(QString::fromUtf16((unsigned short*)str)); - devices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData()); - hr = pPropBag->Read(L"Description", &varName, 0); - wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); - QString temp2(QString::fromUtf16((unsigned short*)str)); - descriptions.append(temp2.toLocal8Bit().constData()); - } - pPropBag->Release(); - pMoniker->Release(); - } - pEnum->Release(); - } - pDevEnum->Release(); - } - CoUninitialize(); + enumerateDevices(&m_devices, &m_descriptions); selected = 0; } int DSVideoDeviceControl::deviceCount() const { - return devices.count(); + return m_devices.count(); } QString DSVideoDeviceControl::deviceName(int index) const { - if(index >= 0 && index <= devices.count()) - return devices.at(index); + if (index >= 0 && index <= m_devices.count()) + return QString::fromUtf8(m_devices.at(index).constData()); return QString(); } QString DSVideoDeviceControl::deviceDescription(int index) const { - if(index >= 0 && index <= descriptions.count()) - return descriptions.at(index); + if (index >= 0 && index <= m_descriptions.count()) + return m_descriptions.at(index); return QString(); } @@ -144,11 +97,65 @@ int DSVideoDeviceControl::selectedDevice() const return selected; } +void DSVideoDeviceControl::enumerateDevices(QList *devices, QStringList *descriptions) +{ + devices->clear(); + descriptions->clear(); + + CoInitialize(NULL); + ICreateDevEnum* pDevEnum = NULL; + IEnumMoniker* pEnum = NULL; + // Create the System device enumerator + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, + reinterpret_cast(&pDevEnum)); + if (SUCCEEDED(hr)) { + // Create the enumerator for the video capture category + hr = pDevEnum->CreateClassEnumerator( + CLSID_VideoInputDeviceCategory, &pEnum, 0); + if (S_OK == hr) { + pEnum->Reset(); + // go through and find all video capture devices + IMoniker* pMoniker = NULL; + IMalloc *mallocInterface = 0; + CoGetMalloc(1, (LPMALLOC*)&mallocInterface); + while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { + BSTR strName = 0; + hr = pMoniker->GetDisplayName(NULL, NULL, &strName); + if (SUCCEEDED(hr)) { + QString output(QString::fromWCharArray(strName)); + mallocInterface->Free(strName); + devices->append(output.toUtf8().constData()); + + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag)); + if (SUCCEEDED(hr)) { + // Find the description + VARIANT varName; + varName.vt = VT_BSTR; + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) { + output = QString::fromWCharArray(varName.bstrVal); + } + pPropBag->Release(); + } + descriptions->append(output); + } + pMoniker->Release(); + } + mallocInterface->Release(); + pEnum->Release(); + } + pDevEnum->Release(); + } + CoUninitialize(); +} + void DSVideoDeviceControl::setSelectedDevice(int index) { - if(index >= 0 && index <= devices.count()) { + if (index >= 0 && index <= m_devices.count()) { if (m_session) { - QString device = devices.at(index); + QString device = m_devices.at(index); if (device.startsWith("ds:")) device.remove(0,3); m_session->setDevice(device); diff --git a/src/plugins/directshow/camera/dsvideodevicecontrol.h b/src/plugins/directshow/camera/dsvideodevicecontrol.h index 7dbf248..0a621d0 100644 --- a/src/plugins/directshow/camera/dsvideodevicecontrol.h +++ b/src/plugins/directshow/camera/dsvideodevicecontrol.h @@ -43,6 +43,7 @@ #define DSVIDEODEVICECONTROL_H #include +#include QT_BEGIN_HEADER @@ -63,14 +64,16 @@ public: int defaultDevice() const; int selectedDevice() const; + static void enumerateDevices(QList *devices, QStringList *descriptions); + public Q_SLOTS: void setSelectedDevice(int index); private: DSCameraSession* m_session; - QList devices; - QList descriptions; + QList m_devices; + QStringList m_descriptions; int selected; }; diff --git a/src/plugins/directshow/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp index d3871c8..84ba84f 100644 --- a/src/plugins/directshow/dsserviceplugin.cpp +++ b/src/plugins/directshow/dsserviceplugin.cpp @@ -44,7 +44,7 @@ #include #include "dsserviceplugin.h" - +#include "dsvideodevicecontrol.h" #ifdef QMEDIA_DIRECTSHOW_CAMERA #include @@ -138,58 +138,9 @@ QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByt void DSServicePlugin::updateDevices() const { - m_cameraDevices.clear(); - m_cameraDescriptions.clear(); - BOOL bFound = TRUE; - CoInitialize(NULL); - ICreateDevEnum* pDevEnum = NULL; - IEnumMoniker* pEnum = NULL; - // Create the System device enumerator - HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, - reinterpret_cast(&pDevEnum)); - if(SUCCEEDED(hr)) { - // Create the enumerator for the video capture category - hr = pDevEnum->CreateClassEnumerator( - CLSID_VideoInputDeviceCategory, &pEnum, 0); - if (S_OK == hr) { - pEnum->Reset(); - // go through and find all video capture devices - IMoniker* pMoniker = NULL; - while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag, - (void**)(&pPropBag)); - if(FAILED(hr)) { - pMoniker->Release(); - continue; // skip this one - } - bFound = TRUE; - // Find the description - WCHAR str[120]; - VARIANT varName; - varName.vt = VT_BSTR; - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if(SUCCEEDED(hr)) { - wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); - QString temp(QString::fromUtf16((unsigned short*)str)); - m_cameraDevices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData()); - hr = pPropBag->Read(L"Description", &varName, 0); - wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); - QString temp2(QString::fromUtf16((unsigned short*)str)); - m_cameraDescriptions.append(temp2); - } else { - qWarning() << "No friendly name"; - } - pPropBag->Release(); - pMoniker->Release(); - } - pEnum->Release(); - } - pDevEnum->Release(); - } - CoUninitialize(); - if (!bFound) { + DSVideoDeviceControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions); + + if (m_cameraDevices.isEmpty()) { qWarning() << "No camera devices found"; } } -- 2.7.4