diff options
Diffstat (limited to 'opentrack-compat')
| -rw-r--r-- | opentrack-compat/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | opentrack-compat/camera-names.cpp | 113 | ||||
| -rw-r--r-- | opentrack-compat/camera-names.hpp | 22 | ||||
| -rw-r--r-- | opentrack-compat/compat-export.hpp | 15 | ||||
| -rw-r--r-- | opentrack-compat/compat-import.hpp | 15 | ||||
| -rw-r--r-- | opentrack-compat/export.hpp | 22 | ||||
| -rw-r--r-- | opentrack-compat/import.hpp | 15 | ||||
| -rw-r--r-- | opentrack-compat/options.cpp | 199 | ||||
| -rw-r--r-- | opentrack-compat/options.hpp | 325 | ||||
| -rw-r--r-- | opentrack-compat/shm.cpp | 121 | ||||
| -rw-r--r-- | opentrack-compat/shm.h | 30 | 
11 files changed, 845 insertions, 35 deletions
diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt index a92f4f31..8dba67e2 100644 --- a/opentrack-compat/CMakeLists.txt +++ b/opentrack-compat/CMakeLists.txt @@ -1,4 +1,5 @@ -opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT LINKAGE)  if(NOT WIN32 AND NOT APPLE)      target_link_libraries(opentrack-compat rt)  endif() +link_with_dinput8(opentrack-compat) diff --git a/opentrack-compat/camera-names.cpp b/opentrack-compat/camera-names.cpp new file mode 100644 index 00000000..72bcf41a --- /dev/null +++ b/opentrack-compat/camera-names.cpp @@ -0,0 +1,113 @@ +#include "camera-names.hpp" + +#if defined(OPENTRACK_API) && defined(_WIN32) +#   define NO_DSHOW_STRSAFE +#   include <windows.h> +#   include <dshow.h> +#endif + +#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) +#   include <unistd.h> +#endif + +#ifdef __linux +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/videodev2.h> +#include <cerrno> +#endif + +#include <QDebug> + +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name) +{ +    auto list = get_camera_names(); +    int ret = list.indexOf(name); +    if (ret < 0) +        ret = 0; +    return ret; +} + +OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names() { +    QList<QString> ret; +#if defined(_WIN32) +    // Create the System Device Enumerator. +    HRESULT hr; +    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); +    if (FAILED(hr)) +        qDebug() << "failed CoInitializeEx" << hr; +    ICreateDevEnum *pSysDevEnum = NULL; +    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); +    if (FAILED(hr)) +    { +        qDebug() << "failed CLSID_SystemDeviceEnum" << hr; +        return ret; +    } +    // Obtain a class enumerator for the video compressor category. +    IEnumMoniker *pEnumCat = NULL; +    hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &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. +                    QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); +                    ret.append(str); +                } +                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(); +    } +    else +        qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; +     +    pSysDevEnum->Release(); +#endif +#ifdef __linux +    for (int i = 0; i < 16; i++) { +        char buf[128]; +        sprintf(buf, "/dev/video%d", i); +        if (access(buf, F_OK) == 0) +            ret.append(buf); +        else +            continue; + +        if (access(buf, R_OK | W_OK) == 0) { +            int fd = open(buf, O_RDONLY); +            if (fd == -1) +                continue; +            struct v4l2_capability video_cap; +            if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) +            { +                qDebug() << "VIDIOC_QUERYCAP" << errno; +                close(fd); +                continue; +            } +            ret[ret.size()-1] = reinterpret_cast<const char*>(video_cap.card); +            close(fd); +        } +    } +#endif +    return ret; +}
\ No newline at end of file diff --git a/opentrack-compat/camera-names.hpp b/opentrack-compat/camera-names.hpp new file mode 100644 index 00000000..c2879000 --- /dev/null +++ b/opentrack-compat/camera-names.hpp @@ -0,0 +1,22 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik <sthalik@misaki.pl> + + * 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. + */ + +#pragma once + +#include <QList> +#include <QString> + +#ifdef BUILD_compat +#   include "compat-export.hpp" +#else +#   include "compat-import.hpp" +#endif + +OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names(); +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name); + diff --git a/opentrack-compat/compat-export.hpp b/opentrack-compat/compat-export.hpp new file mode 100644 index 00000000..2d6f1d3d --- /dev/null +++ b/opentrack-compat/compat-export.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_COMPAT_LINKAGE __declspec(dllexport) +#   else +#       define OPENTRACK_COMPAT_LINKAGE +#   endif + +#   ifndef _MSC_VER +#       define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +#   else +#       define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/compat-import.hpp b/opentrack-compat/compat-import.hpp new file mode 100644 index 00000000..161ccc5d --- /dev/null +++ b/opentrack-compat/compat-import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_COMPAT_LINKAGE __declspec(dllimport) +#   else +#       define OPENTRACK_COMPAT_LINKAGE +#   endif + +#   ifndef _MSC_VER +#       define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +#   else +#       define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/export.hpp b/opentrack-compat/export.hpp index f0983b75..100950a0 100644 --- a/opentrack-compat/export.hpp +++ b/opentrack-compat/export.hpp @@ -1,13 +1,15 @@  #pragma once -#ifdef _WIN32 -#   define OPENTRACK_LINKAGE __declspec(dllexport) -#else -#   define OPENTRACK_LINKAGE -#endif +#ifndef OPENTRACK_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_LINKAGE __declspec(dllexport) +#   else +#       define OPENTRACK_LINKAGE +#   endif -#ifndef _MSC_VER -#	define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE -#else -#	define OPENTRACK_EXPORT OPENTRACK_LINKAGE -#endif
\ No newline at end of file +#   ifndef _MSC_VER +#       define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +#   else +#       define OPENTRACK_EXPORT OPENTRACK_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/import.hpp b/opentrack-compat/import.hpp new file mode 100644 index 00000000..3747b141 --- /dev/null +++ b/opentrack-compat/import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_LINKAGE __declspec(dllimport) +#   else +#       define OPENTRACK_LINKAGE +#   endif + +#   ifndef _MSC_VER +#       define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +#   else +#       define OPENTRACK_EXPORT OPENTRACK_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp new file mode 100644 index 00000000..550fec24 --- /dev/null +++ b/opentrack-compat/options.cpp @@ -0,0 +1,199 @@ +#include "options.hpp" + +namespace options +{ + +namespace detail +{ +OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() +{ +    static opt_singleton ret; +    return ret; +} + +} + +group::group(const QString& name) : name(name) +{ +    auto conf = ini_file(); +    conf->beginGroup(name); +    for (auto& k_ : conf->childKeys()) +    { +        auto tmp = k_.toUtf8(); +        QString k(tmp); +        kvs[k] = conf->value(k_); +    } +    conf->endGroup(); +} + +void group::save() +{ +    auto s = ini_file(); +    s->beginGroup(name); +    for (auto& i : kvs) +        s->setValue(i.first, i.second); +    s->endGroup(); +    s->sync(); +} + +void group::put(const QString &s, const QVariant &d) +{ +    kvs[s] = d; +} + +bool group::contains(const QString &s) +{ +    return kvs.count(s) != 0; +} + +QString group::ini_directory() +{ +    const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); +    if (dirs.size() == 0) +        return ""; +    if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) +        return dirs[0] + "/" OPENTRACK_ORG; +    return ""; +} + +QString group::ini_filename() +{ +    QSettings settings(OPENTRACK_ORG); +    return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +QString group::ini_pathname() +{ +    const auto dir = ini_directory(); +    if (dir == "") +        return ""; +    QSettings settings(OPENTRACK_ORG); +    return dir + "/" + settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +const QStringList group::ini_list() +{ +    const auto dirname = ini_directory(); +    if (dirname == "") +        return QStringList(); +    QDir settings_dir(dirname); +    return settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); +} + +const mem<QSettings> group::ini_file() +{ +    const auto pathname = ini_pathname(); +    if (pathname != "") +        return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat); +    return std::make_shared<QSettings>(); +} + +impl_bundle::impl_bundle(const QString &group_name) +    : +      mtx(QMutex::Recursive), +      group_name(group_name), +      saved(group_name), +      transient(saved), +      modified(false) +{} + +void impl_bundle::reload() +{ +    { +        QMutexLocker l(&mtx); +        saved = group(group_name); +        transient = saved; +        modified = false; +    } +    emit reloading(); +} + +void impl_bundle::store_kv(const QString &name, const QVariant &datum) +{ +    QMutexLocker l(&mtx); + +    auto old = transient.get<QVariant>(name); +    if (!transient.contains(name) || datum != old) +    { +        modified = true; +        transient.put(name, datum); +    } +} + +bool impl_bundle::contains(const QString &name) +{ +    QMutexLocker l(&mtx); +    return transient.contains(name); +} + +void impl_bundle::save() +{ +    { +        QMutexLocker l(&mtx); +        modified = false; +        saved = transient; +        transient.save(); +    } +    emit saving(); +} + +bool impl_bundle::modifiedp() +{ +    QMutexLocker l(&mtx); +    return modified; +} + +namespace detail +{ + +pbundle opt_singleton::bundle(const opt_singleton::k &key) +{ +    QMutexLocker l(&implsgl_mtx); + +    if (implsgl_data.count(key) != 0) +    { +        auto shared = std::get<1>(implsgl_data[key]).lock(); +        if (shared != nullptr) +            return shared; +    } +     +    qDebug() << "bundle +" << key; + +    auto shr = std::make_shared<v>(key); +    implsgl_data[key] = tt(cnt(1), shr); +    return shr; +} + +void opt_singleton::bundle_decf(const opt_singleton::k &key) +{ +    QMutexLocker l(&implsgl_mtx); + +    if (--std::get<0>(implsgl_data[key]) == 0) +        implsgl_data.erase(key); +} + +opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) {} + +} + +opt_bundle::opt_bundle(const QString &group_name) +    : impl_bundle(group_name) +{ +} + +opt_bundle::~opt_bundle() +{ +    qDebug() << "bundle -" << group_name; +    detail::singleton().bundle_decf(group_name); +} + +base_value::base_value(pbundle b, const QString &name) : b(b), self_name(name) {} + +opts::~opts() +{ +    b->reload(); +} + +opts::opts(const QString &name) : b(bundle(name)) {} + +} diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp new file mode 100644 index 00000000..a317a1f7 --- /dev/null +++ b/opentrack-compat/options.hpp @@ -0,0 +1,325 @@ +/* Copyright (c) 2013-2015 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. + */ + +#pragma once + +#include <memory> +#include <tuple> +#include <map> + +#include <QObject> +#include <QSettings> +#include <QString> +#include <QVariant> +#include <QMutex> +#include <QMutexLocker> +#include <QWidget> +#include <QComboBox> +#include <QCheckBox> +#include <QDoubleSpinBox> +#include <QSpinBox> +#include <QSlider> +#include <QLineEdit> +#include <QLabel> +#include <QTabWidget> +#include <QCoreApplication> +#include <QFileInfo> +#include <QDir> +#include <QStandardPaths> + +#include <cinttypes> + +#include <QDebug> + +#include <memory> + +#ifdef BUILD_compat +#   include "compat-export.hpp" +#else +#   include "compat-import.hpp" +#endif + +template<typename t> using mem = std::shared_ptr<t>; + +#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" +#define OPENTRACK_DEFAULT_CONFIG "default.ini" +#define OPENTRACK_ORG "TrackHat opentrack-2.3" + +namespace options { +    template<typename k, typename v> using map = std::map<k, v>; + +    template<typename t> +    // don't elide usages of the function, qvariant default implicit +    // conversion results in nonsensical runtime behavior -sh +    inline t qcruft_to_t (const QVariant& datum); + +    template<> +    inline int qcruft_to_t<int>(const QVariant& t) +    { +        return t.toInt(); +    } + +    template<> +    inline QString qcruft_to_t<QString>(const QVariant& t) +    { +        return t.toString(); +    } + +    template<> +    inline bool qcruft_to_t<bool>(const QVariant& t) +    { +        return t.toBool(); +    } + +    template<> +    inline double qcruft_to_t<double>(const QVariant& t) +    { +        return t.toDouble(); +    } + +    template<> +    inline QVariant qcruft_to_t<QVariant>(const QVariant& t) +    { +        return t; +    } + +    // snapshot of qsettings group at given time +    class OPENTRACK_COMPAT_EXPORT group { +    private: +        map<QString, QVariant> kvs; +        QString name; +    public: +        group(const QString& name); +        void save(); +        void put(const QString& s, const QVariant& d); +        bool contains(const QString& s); +        static QString ini_directory(); +        static QString ini_filename(); +        static QString ini_pathname(); +        static const QStringList ini_list(); +        static const mem<QSettings> ini_file(); + +        template<typename t> +        t get(const QString& k) +        { +            return qcruft_to_t<t>(kvs[k]); +        } +    }; + +    class OPENTRACK_COMPAT_EXPORT impl_bundle : public QObject { +        Q_OBJECT +    protected: +        QMutex mtx; +        const QString group_name; +        group saved; +        group transient; +        bool modified; +        impl_bundle(const impl_bundle&) = delete; +        impl_bundle& operator=(const impl_bundle&) = delete; +    signals: +        void reloading(); +        void saving(); +    public: +        impl_bundle(const QString& group_name); +        QString name() { return group_name; } +        void reload(); +        void store_kv(const QString& name, const QVariant& datum); +        bool contains(const QString& name); +        void save(); +        bool modifiedp(); +         +        template<typename t> +        t get(const QString& name) +        { +            QMutexLocker l(&mtx); +            return transient.get<t>(name); +        } +    }; + +    class opt_bundle; + +    namespace detail +    { +        struct OPENTRACK_COMPAT_EXPORT opt_singleton +        { +        public: +            using k = QString; +            using v = opt_bundle; +            using cnt = int; +            using pbundle = std::shared_ptr<v>; +            using tt = std::tuple<cnt, std::weak_ptr<v>>; +        private: +            QMutex implsgl_mtx; +            map<k, tt> implsgl_data; +        public: +            opt_singleton(); +            pbundle bundle(const k& key); +            void bundle_decf(const k& key); +        }; +         +        OPENTRACK_COMPAT_EXPORT opt_singleton& singleton(); +    } +     +    using pbundle = std::shared_ptr<opt_bundle>; +     +    static inline pbundle bundle(const QString name) { return detail::singleton().bundle(name); } + +    class OPENTRACK_COMPAT_EXPORT opt_bundle : public impl_bundle +    { +    public: +        opt_bundle() : impl_bundle("i-have-no-name") {} +        opt_bundle(const QString& group_name); +        ~opt_bundle(); +    }; + +    class OPENTRACK_COMPAT_EXPORT base_value : public QObject +    { +        Q_OBJECT +#define DEFINE_SLOT(t) void setValue(t datum) { store(datum); } +#define DEFINE_SIGNAL(t) void valueChanged(t) +    public: +        QString name() { return self_name; } +        base_value(pbundle b, const QString& name); +    signals: +        DEFINE_SIGNAL(double); +        DEFINE_SIGNAL(int); +        DEFINE_SIGNAL(bool); +        DEFINE_SIGNAL(QString); +    protected: +        pbundle b; +        QString self_name; + +        template<typename t> +        void store(const t& datum) +        { +            b->store_kv(self_name, datum); +            emit valueChanged(static_cast<t>(datum)); +        } +    public slots: +        DEFINE_SLOT(double) +        DEFINE_SLOT(int) +        DEFINE_SLOT(QString) +        DEFINE_SLOT(bool) +    public slots: +        virtual void reload() = 0; +    }; + +    template<typename t> +    class value : public base_value { +    public: +        t operator=(const t datum) +        { +            store(datum); +            return datum; +        } +        static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; +        static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection; +        value(pbundle b, const QString& name, t def) : base_value(b, name), def(def) +        { +            QObject::connect(b.get(), SIGNAL(reloading()), +                             this, SLOT(reload()), +                             DIRECT_CONNTYPE); +            if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid) +                *this = def; +        } +        value(pbundle b, const char* name, t def) : value(b, QString(name), def) {} + +        operator t() const +        { +            return b->contains(self_name) ? b->get<t>(self_name) : def; +        } +        void reload() override { +            *this = static_cast<t>(*this); +        } +    private: +        t def; +    }; +     +    struct OPENTRACK_COMPAT_EXPORT opts +    { +        pbundle b; +        opts(const QString& name); +        ~opts(); +    }; + +    template<typename t, typename q> +    inline void tie_setting(value<t>&, q*); + +    template<> +    inline void tie_setting(value<int>& v, QComboBox* cb) +    { +        cb->setCurrentIndex(v); +        v = cb->currentIndex(); +        base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); +    } + +    template<> +    inline void tie_setting(value<QString>& v, QComboBox* cb) +    { +        cb->setCurrentText(v); +        v = cb->currentText(); +        base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.SAFE_CONNTYPE); +    } + +    template<> +    inline void tie_setting(value<bool>& v, QCheckBox* cb) +    { +        cb->setChecked(v); +        base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.SAFE_CONNTYPE); +    } + +    template<> +    inline void tie_setting(value<double>& v, QDoubleSpinBox* dsb) +    { +        dsb->setValue(v); +        base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.SAFE_CONNTYPE); +    } + +    template<> +    inline void tie_setting(value<int>& v, QSpinBox* sb) +    { +        sb->setValue(v); +        base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.SAFE_CONNTYPE); +    } + +    template<> +    inline void tie_setting(value<int>& v, QSlider* sl) +    { +        sl->setValue(v); +        v = sl->value(); +        base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.SAFE_CONNTYPE); +    } + +    template<> +    inline void tie_setting(value<QString>& v, QLineEdit* le) +    { +        le->setText(v); +        base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.SAFE_CONNTYPE); +    } + +    template<> +    inline void tie_setting(value<QString>& v, QLabel* lb) +    { +        lb->setText(v); +        base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE); +    } +     +    template<> +    inline void tie_setting(value<int>& v, QTabWidget* t) +    { +        t->setCurrentIndex(v); +        base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); +        base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); +    } +} diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index 029a4c95..55aa7a41 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -5,25 +5,140 @@   * copyright notice and this permission notice appear in all copies.   */ -#include <cstring>  #include "shm.h"  #if defined(_WIN32) + +#include <cstring> +#include <stdio.h> + +#include <accctrl.h> +#include <aclapi.h> + +struct secattr +{ +    bool success; +    SECURITY_DESCRIPTOR* pSD; +    SECURITY_ATTRIBUTES attrs; +    PSID pEveryoneSID; +    PACL pACL; + +    void cleanup() +    { +        if (pEveryoneSID) +            FreeSid(pEveryoneSID); +        if (pACL) +            LocalFree(pACL); +        if (pSD) +            LocalFree(pSD); +        success = false; +        pSD = nullptr; +        pEveryoneSID = nullptr; +        pACL = nullptr; +    } + +    secattr(DWORD perms) : success(true), pSD(nullptr), pEveryoneSID(nullptr), pACL(nullptr) +    { +        SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; +        EXPLICIT_ACCESS ea; + +        if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, +                         SECURITY_WORLD_RID, +                         0, 0, 0, 0, 0, 0, 0, +                         &pEveryoneSID)) +        { +            fprintf(stderr, "AllocateAndInitializeSid: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        memset(&ea, 0, sizeof(ea)); + +        ea.grfAccessPermissions = perms; +        ea.grfAccessMode = SET_ACCESS; +        ea.grfInheritance = NO_INHERITANCE; +        ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; +        ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; +        ea.Trustee.ptstrName  = (LPTSTR) pEveryoneSID; + +        if (SetEntriesInAcl(1, &ea, NULL, &pACL) != ERROR_SUCCESS) +        { +            fprintf(stderr, "SetEntriesInAcl: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        pSD = (SECURITY_DESCRIPTOR*) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); +        if (pSD == nullptr) +        { +            fprintf(stderr, "LocalAlloc: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        if (!InitializeSecurityDescriptor(pSD, +                    SECURITY_DESCRIPTOR_REVISION)) +        { +            fprintf(stderr, "InitializeSecurityDescriptor: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        if (!SetSecurityDescriptorDacl(pSD, +                                       TRUE, +                                       pACL, +                                       FALSE)) +        { +            fprintf(stderr, "SetSecurityDescriptorDacl: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        attrs.bInheritHandle = false; +        attrs.lpSecurityDescriptor = pSD; +        attrs.nLength = sizeof(SECURITY_ATTRIBUTES); + +        fflush(stderr); + +        return; +cleanup: +        fflush(stderr); +        cleanup(); +    } + +    ~secattr() +    { +        cleanup(); +    } +}; +  PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize)  { -    hMutex = CreateMutexA(NULL, false, mutexName); +    secattr sa(GENERIC_ALL|SYNCHRONIZE); + +    hMutex = CreateMutexA(sa.success ? &sa.attrs : nullptr, false, mutexName); +    if (!hMutex) +    { +        fprintf(stderr, "CreateMutexA: %d\n", (int) GetLastError()); +        fflush(stderr); +    }      hMapFile = CreateFileMappingA(                   INVALID_HANDLE_VALUE, -                 NULL, +                 sa.success ? &sa.attrs : nullptr,                   PAGE_READWRITE,                   0,                   mapSize,                   shmName); +    if (!hMapFile) +    { +        fprintf(stderr, "CreateFileMappingA: %d\n", (int) GetLastError()); +        fflush(stderr); +    }      mem = MapViewOfFile(hMapFile,                          FILE_MAP_WRITE,                          0,                          0,                          mapSize); +    if (!mem) +    { +        fprintf(stderr, "MapViewOfFile: %d\n", (int) GetLastError()); +        fflush(stderr); +    }  }  PortableLockedShm::~PortableLockedShm() diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h index c74534e7..3edb0080 100644 --- a/opentrack-compat/shm.h +++ b/opentrack-compat/shm.h @@ -19,32 +19,18 @@  #include <sys/types.h>  #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wattributes" -  #ifdef __GNUC__ -#   define COMPAT_GNUC_VISIBILITY __attribute__ ((visibility ("default"))) -#else -#   define COMPAT_GNUC_VISIBILITY +#   pragma GCC diagnostic push +#   pragma GCC diagnostic ignored "-Wattributes"  #endif -#ifdef BUILD_opentrack_compat -#   ifdef _WIN32 -#       define COMPAT_WIN32_EXPORT __declspec(dllexport) -#   else -#       define COMPAT_WIN32_EXPORT -#   endif +#ifdef BUILD_compat +#   include "compat-export.hpp"  #else -#   ifdef _WIN32 -#       define COMPAT_WIN32_EXPORT __declspec(dllimport) -#   else -#       define COMPAT_WIN32_EXPORT -#   endif +#   include "compat-import.hpp"  #endif -#define COMPAT_EXPORT COMPAT_WIN32_EXPORT COMPAT_GNUC_VISIBILITY - -class COMPAT_EXPORT PortableLockedShm { +class OPENTRACK_COMPAT_EXPORT PortableLockedShm {  public:      PortableLockedShm(const char *shmName, const char *mutexName, int mapSize);      ~PortableLockedShm(); @@ -61,4 +47,6 @@ private:  #endif  }; -#pragma GCC diagnostic pop +#ifdef __GNUC__ +#   pragma GCC diagnostic pop +#endif  | 
