summaryrefslogtreecommitdiffhomepage
path: root/opentrack-compat
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2016-01-06 20:07:13 +0100
committerStanislaw Halik <sthalik@misaki.pl>2016-01-06 20:16:18 +0100
commit82f3d7373234cc0db79a22d476cb54b5eda7a0ea (patch)
tree65ee0194ad064cc470f95f7ca8efd533b089ca96 /opentrack-compat
parent7e3807d048c5e0a8e0aa64fb49807bf5dfd11fc1 (diff)
parentf02baa0868f219076a641634625f7c032d3a9eef (diff)
Merge branch 'unstable' into trackhat
* unstable: (140 commits) tracker/pt: increase auto threshold bucket size again tracker/pt: limit max amount of extracted blobs gui: don't update main window if we're minimized tracker/pt: only show widget if the frame is visible tracker/pt: don't resize twice in widget freetrack/games: regen contrib/make-csv: perl sort isn't stable, don't ignore case tracker/pt: avoid widget temp QImage allocation spline-widget: oops, pass by reference tracker/pt: don't allocate temporary dynamic size arrays tracker/pt: don't copy points array needlessly tracker/pt: don't allocate temporary frame tracker/pt: cv::Mat::at<T> is slow, use cv::Mat::ptr tracker/pt: avoid widget malloc when able tracker/pt: optimize widget tracker/pt: update video widget at 40 -> 50 ms cmake/mingw-w64: update tracker/pt: reduce mutex contention gui: fix left margin tracker/pt: remove krap tracker/pt: move ctor out of the loop tracker/pt: nix unused tracker/pt: don't fill mask on frame pose-widget: also bilinear interpolation of alpha value ui: adjust margin ui: make more compact glwidget: use transparent octopus background api/mat: fix typos/breakage api/joy: refresh only manually on certain events pt: histogram more granular 6 -> 8 cmake/api: link with strmiids.lib on win32 tracker/pt: reduce auto thresholding histogram bucket size api/keys: prevent idempotent keys api/joy: move from header api/joy: prevent idempotent keypressed passed to receiver compat/options: get rid of std::string usage compat/options: move from header gui/settings: set parent, otherwise not modal gui/settings: don't forget to show a modal dialog before executing gui/main: don't raise a new window, it's enough to set visible api/joy: speed up poll_axis path api/joy: nix static, now that we're not a singleton tracker/joy: adapt to non-singleton joy worker joystick: no longer singleton, use fake window handle api/keys: use a fake window for DirectInput handle gui/keys: allow for pausing global keystrokes for options dialog api/keys: nix tautological #ifdef contrib/aruco: oops, right extension contrib/aruco: use @frost555's marker image api/camera-names: move to compat/ ...
Diffstat (limited to 'opentrack-compat')
-rw-r--r--opentrack-compat/CMakeLists.txt3
-rw-r--r--opentrack-compat/camera-names.cpp113
-rw-r--r--opentrack-compat/camera-names.hpp22
-rw-r--r--opentrack-compat/compat-export.hpp15
-rw-r--r--opentrack-compat/compat-import.hpp15
-rw-r--r--opentrack-compat/export.hpp22
-rw-r--r--opentrack-compat/import.hpp15
-rw-r--r--opentrack-compat/options.cpp199
-rw-r--r--opentrack-compat/options.hpp325
-rw-r--r--opentrack-compat/shm.cpp121
-rw-r--r--opentrack-compat/shm.h30
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