/* Copyright (c) 2016 Stanislaw Halik * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. */ #include "video-property-page.hpp" #ifdef _WIN32 #include #include #include #define CHECK(expr) if (FAILED(hr = (expr))) { qDebug() << QStringLiteral(#expr) << hr; goto done; } #define CHECK2(expr) if (!(expr)) { qDebug() << QStringLiteral(#expr); goto done; } bool video_property_page::show_from_capture(cv::VideoCapture& cap, int) { cap.set(cv::CAP_PROP_SETTINGS, 0); return true; } bool video_property_page::should_show_dialog(const QString& camera_name) { using re = QRegularExpression; static const re regexen[] = { re("^PS3Eye Camera$"), re("^A4 TECH "), }; bool avail = true; for (const re& r : regexen) { avail &= !r.match(camera_name).hasMatch(); if (!avail) break; } return avail; } bool video_property_page::show(int id) { IBaseFilter* filter = NULL; bool ret = false; CHECK2(filter = get_device(id)); ret = SUCCEEDED(ShowFilterPropertyPages(filter)); done: if (filter) filter->Release(); return ret; } HRESULT video_property_page::ShowFilterPropertyPages(IBaseFilter* filter) { ISpecifyPropertyPages* pProp = NULL; IUnknown* unk = NULL; CAUUID caGUID = { 0, NULL }; FILTER_INFO FilterInfo = { {0}, NULL }; HRESULT hr; CHECK(filter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pProp)); CHECK(pProp->GetPages(&caGUID)); CHECK(filter->QueryFilterInfo(&FilterInfo)); filter->QueryInterface(IID_IUnknown, (void**)&unk); // OleInitialize, CoCreateInstance et al. don't help with ps3 eye. // cl-eye uses this // perhaps more than IBaseFilter* -> IUnknown* needs be passed to lplpUnk // and the OleCreatePropertyFrame equiv #if 0 OCPFIPARAMS params; params.cbStructSize = sizeof(params); params.hWndOwner = GetActiveWindow(); params.x = 0; params.y = 0; params.lpszCaption = L"camera props"; params.cObjects = 1; params.lplpUnk = &unk; params.cPages = 1; //OleCreatePropertyFrameIndirect() #endif OleCreatePropertyFrame( NULL, // Parent window 0, 0, // Reserved FilterInfo.achName, // Caption for the dialog box 1, // Number of objects (just the filter) &unk, // Array of object pointers. caGUID.cElems, // Number of property pages caGUID.pElems, // Array of property page CLSIDs 0, // Locale identifier 0, NULL // Reserved ); done: if (FilterInfo.pGraph) FilterInfo.pGraph->Release(); if (caGUID.pElems) CoTaskMemFree(caGUID.pElems); if (pProp) pProp->Release(); if (unk) unk->Release(); return hr; } IBaseFilter* video_property_page::get_device(int id) { ICreateDevEnum* pSysDevEnum = NULL; IEnumMoniker* pEnumCat = NULL; IMoniker* pMoniker = NULL; IBaseFilter* filter = NULL; HRESULT hr; CHECK(CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum)); CHECK(pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0)); for (int i = 0; !filter && SUCCEEDED(pEnumCat->Next(1, &pMoniker, NULL)); pMoniker->Release(), i++) { if (i == id) { CHECK(pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&filter)); break; } } done: if (pMoniker) pMoniker->Release(); if (pEnumCat) pEnumCat->Release(); if (pSysDevEnum) pSysDevEnum->Release(); return filter; } #elif defined(__linux) # include # include "compat/camera-names.hpp" bool video_property_page::should_show_dialog(const QString&) { return true; } bool video_property_page::show(int idx) { const QList camera_names(get_camera_names()); if (idx >= 0 && idx < camera_names.size()) return QProcess::startDetached("qv4l2", QStringList() << "-d" << camera_names[idx]); else return false; } bool video_property_page::show_from_capture(cv::VideoCapture&, int idx) { return show(idx); } #else bool video_property_page::show(int) { return false; } bool video_property_page::show_from_capture(cv::VideoCapture&, int) { return false; } bool video_property_page::should_show_dialog(const QString& camera_name) { return false; } #endif