diff options
-rw-r--r-- | bin/amcap.exe | bin | 70144 -> 0 bytes | |||
-rw-r--r-- | cmake/opentrack-install.cmake | 4 | ||||
-rw-r--r-- | cv/video-property-page.cpp | 224 | ||||
-rw-r--r-- | cv/video-property-page.hpp | 3 | ||||
-rw-r--r-- | tracker-aruco/ftnoir_tracker_aruco.cpp | 2 | ||||
-rw-r--r-- | tracker-pt/ftnoir_tracker_pt_dialog.cpp | 5 |
6 files changed, 96 insertions, 142 deletions
diff --git a/bin/amcap.exe b/bin/amcap.exe Binary files differdeleted file mode 100644 index 8a262fff..00000000 --- a/bin/amcap.exe +++ /dev/null diff --git a/cmake/opentrack-install.cmake b/cmake/opentrack-install.cmake index 1236d178..01f59722 100644 --- a/cmake/opentrack-install.cmake +++ b/cmake/opentrack-install.cmake @@ -41,10 +41,6 @@ otr_inst_exec("${opentrack-hier-pfx}" FILES "${CMAKE_SOURCE_DIR}/bin/NPClient64.dll" "${CMAKE_SOURCE_DIR}/bin/TrackIR.exe") -if(WIN32) - otr_inst_exec("${opentrack-hier-pfx}" FILES "${CMAKE_SOURCE_DIR}/bin/amcap.exe") -endif() - otr_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/CMakeLists.txt") otr_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/README.md") otr_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/CONTRIBUTING.md") diff --git a/cv/video-property-page.cpp b/cv/video-property-page.cpp index 0595f04a..66060caa 100644 --- a/cv/video-property-page.cpp +++ b/cv/video-property-page.cpp @@ -10,178 +10,141 @@ #ifdef _WIN32 #include "compat/camera-names.hpp" +#include "compat/sleep.hpp" +#include "compat/run-in-thread.hpp" #include "opentrack-library-path.h" #include <cstring> -#include <QRegularExpression> +#include <opencv2/videoio.hpp> + +#include <QApplication> #include <QProcess> +#include <QThread> +#include <QMessageBox> + #include <QDebug> -#include <QFile> #include <dshow.h> -#define CHECK(expr) if (FAILED(hr = (expr))) { qDebug() << QStringLiteral(#expr) << hr; goto done; } -#define CHECK2(expr) if (!(expr)) { qDebug() << QStringLiteral(#expr); goto done; } +#define CHECK(expr) if (FAILED(hr = (expr))) { qDebug() << QLatin1String(#expr) << hr; goto done; } +#define CHECK2(expr) if (!(expr)) { qDebug() << QLatin1String(#expr); goto done; } -bool video_property_page::show_from_capture(cv::VideoCapture& cap, int index) +bool video_property_page::show_from_capture(cv::VideoCapture& cap, int /*index */) { - const QString name = get_camera_names().value(index, ""); - - if (name == "PS3Eye Camera") - { - return QProcess::startDetached(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH "./amcap.exe"); - } - else - { - cap.set(cv::CAP_PROP_SETTINGS, 0); - return true; - } + cap.set(cv::CAP_PROP_SETTINGS, 0); + return true; } -bool video_property_page::should_show_dialog(const QString& camera_name) +struct prop_settings_worker final : QThread { - 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; -} + prop_settings_worker(int idx); + ~prop_settings_worker() override; + void _open_prop_page(); + void run() override; -bool video_property_page::show(int id) -{ - const QString name = get_camera_names().value(id, ""); + cv::VideoCapture cap; + int _idx = -1; +}; - if (name == "PS3Eye Camera") - return QProcess::startDetached(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH "./amcap.exe"); +prop_settings_worker::prop_settings_worker(int idx) +{ + if (cap.get(cv::CAP_PROP_SETTINGS) < 0 || 1) + run_in_thread_async(qApp, []() { + QMessageBox msg; + msg.setTextFormat(Qt::RichText); + msg.setWindowTitle("Camera properties"); + + static const char* uri = "https://github.com/opentrack/opencv/tree/fork"; + + msg.setText(QString("<p>Must use the opencv fork.</p>" + "<p>See <<a href='%1'>%1</a>></p>").arg(uri)); + msg.setStandardButtons(QMessageBox::Cancel); + msg.setIcon(QMessageBox::Warning); + msg.exec(); + }); + else if (cap.get(cv::CAP_PROP_SETTINGS > 0)) + run_in_thread_async(qApp, []() { + QMessageBox::warning(nullptr, + "Camera properties", + "Dialog already opened", + QMessageBox::Cancel, + QMessageBox::NoButton); + }); else { - IBaseFilter* filter = NULL; - bool ret = false; - - CHECK2(filter = get_device(id)); - - ret = SUCCEEDED(ShowFilterPropertyPages(filter)); - -done: - if (filter) - filter->Release(); - - return ret; + _idx = idx; + // DON'T MOVE IT + // ps3 eye will reset to default settings if done from another thread + _open_prop_page(); } } -int video_property_page::ShowFilterPropertyPages(IBaseFilter* filter) +void prop_settings_worker::_open_prop_page() { - 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 + cap.open(_idx); - 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 - ); + if (cap.isOpened()) + { + cv::Mat tmp; -done: - if (FilterInfo.pGraph) - FilterInfo.pGraph->Release(); + for (unsigned k = 0; k < 2000/50; k++) + { + if (cap.read(tmp)) + goto ok; + portable::sleep(50); + } + } - if (caGUID.pElems) - CoTaskMemFree(caGUID.pElems); + qDebug() << "property-page: can't open camera"; + _idx = -1; - if (pProp) - pProp->Release(); + return; - if (unk) - unk->Release(); +ok: + portable::sleep(100); - return hr; + qDebug() << "property-page: opening for" << _idx; + cap.set(cv::CAP_PROP_SETTINGS, 0); } -IBaseFilter* video_property_page::get_device(int id) +prop_settings_worker::~prop_settings_worker() { - ICreateDevEnum* pSysDevEnum = NULL; - IEnumMoniker* pEnumCat = NULL; - IMoniker* pMoniker = NULL; - IBaseFilter* filter = NULL; - HRESULT hr; + if (_idx != -1) + { + // ax filter is race condition-prone + portable::sleep(250); + cap.release(); + // idem + portable::sleep(250); - CHECK(CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum)); - CHECK(pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0)); + qDebug() << "property-page: closed" << _idx; + } +} - for (int i = 0; !filter && SUCCEEDED(pEnumCat->Next(1, &pMoniker, NULL)); pMoniker->Release(), i++) +void prop_settings_worker::run() +{ + if (_idx != -1) { - if (i == id) - { - CHECK(pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&filter)); - break; - } + while (cap.get(cv::CAP_PROP_SETTINGS) > 0) + portable::sleep(1000); } -done: - if (pMoniker) - pMoniker->Release(); - - if (pEnumCat) - pEnumCat->Release(); + connect(this, &QThread::finished, this, &QObject::deleteLater); +} - if (pSysDevEnum) - pSysDevEnum->Release(); +bool video_property_page::show(int idx) +{ + auto thread = new prop_settings_worker(idx); + thread->start(); - return filter; + return true; } #elif defined(__linux) # include <QProcess> # 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<QString> camera_names(get_camera_names()); @@ -199,8 +162,5 @@ bool video_property_page::show_from_capture(cv::VideoCapture&, int 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 + diff --git a/cv/video-property-page.hpp b/cv/video-property-page.hpp index 2acffd85..a9eed7bf 100644 --- a/cv/video-property-page.hpp +++ b/cv/video-property-page.hpp @@ -15,10 +15,9 @@ struct video_property_page final video_property_page() = delete; static bool show(int id); static bool show_from_capture(cv::VideoCapture& cap, int index); - static bool should_show_dialog(const QString& camera_name); private: #ifdef _WIN32 - static int ShowFilterPropertyPages(IBaseFilter* filter); static IBaseFilter* get_device(int id); + static cv::VideoCapture last_capture; #endif }; diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index a1bde523..0c6f2b75 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -555,7 +555,7 @@ void aruco_dialog::camera_settings() void aruco_dialog::update_camera_settings_state(const QString& name) { - ui.camera_settings->setEnabled(video_property_page::should_show_dialog(name)); + ui.camera_settings->setEnabled(true); } OPENTRACK_DECLARE_TRACKER(aruco_tracker, aruco_dialog, aruco_metadata) diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp index 35a029df..14fb6f91 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -209,10 +209,9 @@ void TrackerDialog_PT::poll_tracker_info_impl() } } -void TrackerDialog_PT::set_camera_settings_available(const QString& camera_name) +void TrackerDialog_PT::set_camera_settings_available(const QString& /* camera_name */) { - const bool avail = video_property_page::should_show_dialog(camera_name); - ui.camera_settings->setEnabled(avail); + ui.camera_settings->setEnabled(true); } void TrackerDialog_PT::show_camera_settings() |