diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2018-01-04 08:23:27 +0100 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2018-01-04 08:23:27 +0100 | 
| commit | 4b517fccf19a8de4e517532dca2df11cca36f3eb (patch) | |
| tree | 657189b7f8928d09c11c6a4ed76ef2985b684859 /cv | |
| parent | 3a987e9ae9aa72f361bb7a549102cb66c5abd268 (diff) | |
cv: fixed ps3 eye dialog
Diffstat (limited to 'cv')
| -rw-r--r-- | cv/video-property-page.cpp | 224 | ||||
| -rw-r--r-- | cv/video-property-page.hpp | 3 | 
2 files changed, 93 insertions, 134 deletions
| 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  }; | 
