From 9040b187a1c4fa380f8a12207b9dd6d04b3a10ac Mon Sep 17 00:00:00 2001 From: Stanislaw Halik <sthalik@misaki.pl> Date: Fri, 12 Aug 2016 18:00:49 +0200 Subject: all: rename modules s#^opentrack-##. and opentrack -> api Adjust usages. --- CMakeLists.txt | 5 +- api/CMakeLists.txt | 3 + api/dtors.cpp | 11 + api/export.hpp | 28 ++ api/is-window-visible.cpp | 33 ++ api/is-window-visible.hpp | 7 + api/plugin-api.hpp | 180 ++++++++ api/plugin-support.hpp | 216 +++++++++ api/variance.hpp | 52 +++ cmake/mingw-w64.cmake | 2 +- cmake/opentrack-version.cmake | 2 +- compat/CMakeLists.txt | 8 + compat/camera-names.cpp | 111 +++++ compat/camera-names.hpp | 18 + compat/export.hpp | 27 ++ compat/make-unique.hpp | 43 ++ compat/nan.cpp | 17 + compat/nan.hpp | 11 + compat/options.cpp | 239 ++++++++++ compat/options.hpp | 481 +++++++++++++++++++++ compat/pi-constant.hpp | 3 + compat/process-list.hpp | 169 ++++++++ compat/qcopyable-mutex.hpp | 37 ++ compat/shm.cpp | 199 +++++++++ compat/shm.h | 48 ++ compat/sleep.hpp | 22 + compat/slider.cpp | 73 ++++ compat/slider.hpp | 62 +++ compat/timer.hpp | 100 +++++ compat/util.hpp | 93 ++++ compat/win32-com.cpp | 60 +++ compat/win32-com.hpp | 18 + cv/camera-dialog.hpp | 6 +- cv/camera-dialog.hpp.OO4364 | 4 +- cv/video-widget.cpp | 2 +- cv/video-widget.hpp | 2 +- dinput/CMakeLists.txt | 4 + dinput/dinput.cpp | 98 +++++ dinput/dinput.hpp | 58 +++ dinput/export.hpp | 28 ++ dinput/keybinding-worker.cpp | 201 +++++++++ dinput/keybinding-worker.hpp | 80 ++++ dinput/win32-joystick.cpp | 359 +++++++++++++++ dinput/win32-joystick.hpp | 101 +++++ filter-accela/ftnoir_filter_accela.cpp | 2 +- filter-accela/ftnoir_filter_accela.h | 6 +- filter-accela/ftnoir_filter_accela_dialog.cpp | 2 +- filter-ewma2/ftnoir_filter_ewma2.cpp | 2 +- filter-ewma2/ftnoir_filter_ewma2.h | 6 +- filter-ewma2/ftnoir_filter_ewma2_dialog.cpp | 2 +- filter-kalman/kalman.h | 6 +- gui/keyboard.h | 4 +- gui/main-window.cpp | 4 +- gui/main-window.hpp | 14 +- gui/main.cpp | 4 +- gui/mapping-window.cpp | 2 +- gui/mapping-window.hpp | 2 +- gui/new_file_dialog.h | 2 +- gui/options-dialog.hpp | 2 +- gui/process_detector.cpp | 2 +- gui/process_detector.h | 6 +- logic/CMakeLists.txt | 7 + logic/export.hpp | 28 ++ logic/main-settings.hpp | 109 +++++ logic/mappings.hpp | 89 ++++ logic/selected-libraries.cpp | 37 ++ logic/selected-libraries.hpp | 25 ++ logic/shortcuts.cpp | 130 ++++++ logic/shortcuts.h | 68 +++ logic/simple-mat.cpp | 97 +++++ logic/simple-mat.hpp | 279 ++++++++++++ logic/state.hpp | 32 ++ logic/tracker.cpp | 385 +++++++++++++++++ logic/tracker.h | 85 ++++ logic/tracklogger.cpp | 47 ++ logic/tracklogger.hpp | 65 +++ logic/win32-shortcuts.cpp | 196 +++++++++ logic/win32-shortcuts.h | 24 + logic/work.cpp | 73 ++++ logic/work.hpp | 43 ++ opentrack-compat/CMakeLists.txt | 8 - opentrack-compat/camera-names.cpp | 111 ----- opentrack-compat/camera-names.hpp | 18 - opentrack-compat/export.hpp | 27 -- opentrack-compat/make-unique.hpp | 43 -- opentrack-compat/nan.cpp | 17 - opentrack-compat/nan.hpp | 11 - opentrack-compat/options.cpp | 239 ---------- opentrack-compat/options.hpp | 481 --------------------- opentrack-compat/pi-constant.hpp | 3 - opentrack-compat/process-list.hpp | 169 -------- opentrack-compat/qcopyable-mutex.hpp | 37 -- opentrack-compat/shm.cpp | 199 --------- opentrack-compat/shm.h | 48 -- opentrack-compat/sleep.hpp | 22 - opentrack-compat/slider.cpp | 73 ---- opentrack-compat/slider.hpp | 62 --- opentrack-compat/timer.hpp | 100 ----- opentrack-compat/util.hpp | 93 ---- opentrack-compat/win32-com.cpp | 60 --- opentrack-compat/win32-com.hpp | 18 - opentrack-dinput/CMakeLists.txt | 4 - opentrack-dinput/dinput.cpp | 98 ----- opentrack-dinput/dinput.hpp | 58 --- opentrack-dinput/export.hpp | 28 -- opentrack-dinput/keybinding-worker.cpp | 201 --------- opentrack-dinput/keybinding-worker.hpp | 80 ---- opentrack-dinput/win32-joystick.cpp | 359 --------------- opentrack-dinput/win32-joystick.hpp | 101 ----- opentrack-logic/CMakeLists.txt | 7 - opentrack-logic/export.hpp | 28 -- opentrack-logic/main-settings.hpp | 109 ----- opentrack-logic/mappings.hpp | 89 ---- opentrack-logic/selected-libraries.cpp | 37 -- opentrack-logic/selected-libraries.hpp | 25 -- opentrack-logic/shortcuts.cpp | 130 ------ opentrack-logic/shortcuts.h | 68 --- opentrack-logic/simple-mat.cpp | 97 ----- opentrack-logic/simple-mat.hpp | 279 ------------ opentrack-logic/state.hpp | 32 -- opentrack-logic/tracker.cpp | 385 ----------------- opentrack-logic/tracker.h | 85 ---- opentrack-logic/tracklogger.cpp | 47 -- opentrack-logic/tracklogger.hpp | 65 --- opentrack-logic/win32-shortcuts.cpp | 196 --------- opentrack-logic/win32-shortcuts.h | 24 - opentrack-logic/work.cpp | 73 ---- opentrack-logic/work.hpp | 43 -- opentrack/CMakeLists.txt | 3 - opentrack/dtors.cpp | 11 - opentrack/export.hpp | 28 -- opentrack/is-window-visible.cpp | 33 -- opentrack/is-window-visible.hpp | 7 - opentrack/plugin-api.hpp | 180 -------- opentrack/plugin-support.hpp | 216 --------- opentrack/variance.hpp | 52 --- pose-widget/glwidget.cpp | 4 +- pose-widget/glwidget.h | 6 +- proto-fg/ftnoir_protocol_fg.cpp | 2 +- proto-fg/ftnoir_protocol_fg.h | 4 +- proto-fg/ftnoir_protocol_fg_dialog.cpp | 2 +- proto-fsuipc/ftnoir_protocol_fsuipc.cpp | 2 +- proto-fsuipc/ftnoir_protocol_fsuipc.h | 4 +- proto-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp | 2 +- proto-ft/ftnoir_protocol_ft.cpp | 2 +- proto-ft/ftnoir_protocol_ft.h | 6 +- proto-ftn/ftnoir_protocol_ftn.cpp | 2 +- proto-ftn/ftnoir_protocol_ftn.h | 4 +- proto-ftn/ftnoir_protocol_ftn_dialog.cpp | 2 +- proto-libevdev/ftnoir_protocol_libevdev.cpp | 2 +- proto-libevdev/ftnoir_protocol_libevdev.h | 2 +- proto-libevdev/ftnoir_protocol_libevdev_dialog.cpp | 2 +- proto-mouse/ftnoir_protocol_mouse.cpp | 2 +- proto-mouse/ftnoir_protocol_mouse.h | 4 +- proto-mouse/ftnoir_protocol_mouse_dialog.cpp | 2 +- proto-sc/ftnoir_protocol_sc.cpp | 2 +- proto-sc/ftnoir_protocol_sc.h | 4 +- proto-sc/ftnoir_protocol_sc_dialog.cpp | 2 +- proto-vjoystick/vjoystick.cpp | 2 +- proto-vjoystick/vjoystick.h | 2 +- proto-vjoystick/vjoystick_dialog.cpp | 2 +- proto-wine/ftnoir_protocol_wine.h | 4 +- proto-wine/ftnoir_protocol_wine_dialog.cpp | 2 +- proto-wine/opentrack-wrapper-wine-main.cxx | 4 +- proto-wine/opentrack-wrapper-wine-posix.cxx | 4 +- proto-wine/opentrack-wrapper-wine-windows.cxx | 4 +- spline-widget/spline-widget.cpp | 2 +- spline-widget/spline-widget.hpp | 2 +- spline-widget/spline.hpp | 2 +- tracker-aruco/ftnoir_tracker_aruco.cpp | 8 +- tracker-aruco/ftnoir_tracker_aruco.h | 4 +- tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp | 4 +- tracker-freepie-udp/ftnoir_tracker_freepie-udp.h | 4 +- .../ftnoir_tracker_freepie-udp_dialog.cpp | 2 +- tracker-hatire/ftnoir_tracker_hat.h | 2 +- tracker-hatire/ftnoir_tracker_hat_dialog.h | 2 +- tracker-hatire/ftnoir_tracker_hat_settings.h | 2 +- tracker-hatire/thread.cpp | 2 +- tracker-hatire/thread.hpp | 4 +- tracker-ht/ftnoir_tracker_ht.cpp | 32 +- tracker-ht/ftnoir_tracker_ht.h | 8 +- tracker-hydra/ftnoir_tracker_hydra.cpp | 4 +- tracker-hydra/ftnoir_tracker_hydra.h | 4 +- tracker-hydra/ftnoir_tracker_hydra_dialog.cpp | 2 +- tracker-joystick/ftnoir_tracker_joystick.cpp | 2 +- tracker-joystick/ftnoir_tracker_joystick.h | 6 +- .../ftnoir_tracker_joystick_dialog.cpp | 2 +- tracker-pt/camera.cpp | 4 +- tracker-pt/ftnoir_tracker_pt.cpp | 4 +- tracker-pt/ftnoir_tracker_pt.h | 6 +- tracker-pt/ftnoir_tracker_pt_dialog.cpp | 2 +- tracker-pt/ftnoir_tracker_pt_dialog.h | 2 +- tracker-pt/ftnoir_tracker_pt_settings.h | 4 +- tracker-pt/point_extractor.cpp | 2 +- tracker-pt/point_extractor.h | 2 +- tracker-pt/point_tracker.cpp | 8 +- tracker-pt/point_tracker.h | 2 +- tracker-rift-025/ftnoir_tracker_rift_025.cpp | 4 +- tracker-rift-025/ftnoir_tracker_rift_025.h | 4 +- .../ftnoir_tracker_rift_dialog_025.cpp | 2 +- tracker-rift-042/ftnoir_tracker_rift_042.cpp | 4 +- tracker-rift-042/ftnoir_tracker_rift_042.h | 4 +- .../ftnoir_tracker_rift_dialog_042.cpp | 2 +- tracker-rift-080/ftnoir_tracker_rift_080.cpp | 4 +- tracker-rift-080/ftnoir_tracker_rift_080.h | 4 +- .../ftnoir_tracker_rift_dialog_080.cpp | 2 +- tracker-rs/ftnoir_tracker_rs.cpp | 40 +- tracker-rs/ftnoir_tracker_rs.h | 2 +- tracker-test/test.cpp | 2 +- tracker-test/test.h | 6 +- tracker-test/test_dialog.cpp | 2 +- tracker-udp/ftnoir_tracker_udp.cpp | 2 +- tracker-udp/ftnoir_tracker_udp.h | 4 +- tracker-udp/ftnoir_tracker_udp_dialog.cpp | 2 +- 214 files changed, 5324 insertions(+), 5315 deletions(-) create mode 100644 api/CMakeLists.txt create mode 100644 api/dtors.cpp create mode 100644 api/export.hpp create mode 100644 api/is-window-visible.cpp create mode 100644 api/is-window-visible.hpp create mode 100644 api/plugin-api.hpp create mode 100644 api/plugin-support.hpp create mode 100644 api/variance.hpp create mode 100644 compat/CMakeLists.txt create mode 100644 compat/camera-names.cpp create mode 100644 compat/camera-names.hpp create mode 100644 compat/export.hpp create mode 100644 compat/make-unique.hpp create mode 100644 compat/nan.cpp create mode 100644 compat/nan.hpp create mode 100644 compat/options.cpp create mode 100644 compat/options.hpp create mode 100644 compat/pi-constant.hpp create mode 100644 compat/process-list.hpp create mode 100644 compat/qcopyable-mutex.hpp create mode 100644 compat/shm.cpp create mode 100644 compat/shm.h create mode 100644 compat/sleep.hpp create mode 100644 compat/slider.cpp create mode 100644 compat/slider.hpp create mode 100644 compat/timer.hpp create mode 100644 compat/util.hpp create mode 100644 compat/win32-com.cpp create mode 100644 compat/win32-com.hpp create mode 100644 dinput/CMakeLists.txt create mode 100644 dinput/dinput.cpp create mode 100644 dinput/dinput.hpp create mode 100644 dinput/export.hpp create mode 100644 dinput/keybinding-worker.cpp create mode 100644 dinput/keybinding-worker.hpp create mode 100644 dinput/win32-joystick.cpp create mode 100644 dinput/win32-joystick.hpp create mode 100644 logic/CMakeLists.txt create mode 100644 logic/export.hpp create mode 100644 logic/main-settings.hpp create mode 100644 logic/mappings.hpp create mode 100644 logic/selected-libraries.cpp create mode 100644 logic/selected-libraries.hpp create mode 100644 logic/shortcuts.cpp create mode 100644 logic/shortcuts.h create mode 100644 logic/simple-mat.cpp create mode 100644 logic/simple-mat.hpp create mode 100644 logic/state.hpp create mode 100644 logic/tracker.cpp create mode 100644 logic/tracker.h create mode 100644 logic/tracklogger.cpp create mode 100644 logic/tracklogger.hpp create mode 100644 logic/win32-shortcuts.cpp create mode 100644 logic/win32-shortcuts.h create mode 100644 logic/work.cpp create mode 100644 logic/work.hpp delete mode 100644 opentrack-compat/CMakeLists.txt delete mode 100644 opentrack-compat/camera-names.cpp delete mode 100644 opentrack-compat/camera-names.hpp delete mode 100644 opentrack-compat/export.hpp delete mode 100644 opentrack-compat/make-unique.hpp delete mode 100644 opentrack-compat/nan.cpp delete mode 100644 opentrack-compat/nan.hpp delete mode 100644 opentrack-compat/options.cpp delete mode 100644 opentrack-compat/options.hpp delete mode 100644 opentrack-compat/pi-constant.hpp delete mode 100644 opentrack-compat/process-list.hpp delete mode 100644 opentrack-compat/qcopyable-mutex.hpp delete mode 100644 opentrack-compat/shm.cpp delete mode 100644 opentrack-compat/shm.h delete mode 100644 opentrack-compat/sleep.hpp delete mode 100644 opentrack-compat/slider.cpp delete mode 100644 opentrack-compat/slider.hpp delete mode 100644 opentrack-compat/timer.hpp delete mode 100644 opentrack-compat/util.hpp delete mode 100644 opentrack-compat/win32-com.cpp delete mode 100644 opentrack-compat/win32-com.hpp delete mode 100644 opentrack-dinput/CMakeLists.txt delete mode 100644 opentrack-dinput/dinput.cpp delete mode 100644 opentrack-dinput/dinput.hpp delete mode 100644 opentrack-dinput/export.hpp delete mode 100644 opentrack-dinput/keybinding-worker.cpp delete mode 100644 opentrack-dinput/keybinding-worker.hpp delete mode 100644 opentrack-dinput/win32-joystick.cpp delete mode 100644 opentrack-dinput/win32-joystick.hpp delete mode 100644 opentrack-logic/CMakeLists.txt delete mode 100644 opentrack-logic/export.hpp delete mode 100644 opentrack-logic/main-settings.hpp delete mode 100644 opentrack-logic/mappings.hpp delete mode 100644 opentrack-logic/selected-libraries.cpp delete mode 100644 opentrack-logic/selected-libraries.hpp delete mode 100644 opentrack-logic/shortcuts.cpp delete mode 100644 opentrack-logic/shortcuts.h delete mode 100644 opentrack-logic/simple-mat.cpp delete mode 100644 opentrack-logic/simple-mat.hpp delete mode 100644 opentrack-logic/state.hpp delete mode 100644 opentrack-logic/tracker.cpp delete mode 100644 opentrack-logic/tracker.h delete mode 100644 opentrack-logic/tracklogger.cpp delete mode 100644 opentrack-logic/tracklogger.hpp delete mode 100644 opentrack-logic/win32-shortcuts.cpp delete mode 100644 opentrack-logic/win32-shortcuts.h delete mode 100644 opentrack-logic/work.cpp delete mode 100644 opentrack-logic/work.hpp delete mode 100644 opentrack/CMakeLists.txt delete mode 100644 opentrack/dtors.cpp delete mode 100644 opentrack/export.hpp delete mode 100644 opentrack/is-window-visible.cpp delete mode 100644 opentrack/is-window-visible.hpp delete mode 100644 opentrack/plugin-api.hpp delete mode 100644 opentrack/plugin-support.hpp delete mode 100644 opentrack/variance.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 22ad863b..948bfe04 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,10 @@ file(GLOB opentrack-subprojects "tracker-*/${C}" "proto-*/${C}" "filter-*/${C}" - "opentrack*/${C}" + "api/${C}" + "compat/${C}" + "logic/${C}" + "dinput/${C}" "gui/${C}" "x-plane-plugin/${C}" "csv/${C}" diff --git a/api/CMakeLists.txt b/api/CMakeLists.txt new file mode 100644 index 00000000..5151cbf7 --- /dev/null +++ b/api/CMakeLists.txt @@ -0,0 +1,3 @@ +opentrack_boilerplate(opentrack-api NO-COMPAT BIN) +target_link_libraries(opentrack-api opentrack-compat) +target_include_directories(opentrack-api PUBLIC ${CMAKE_BINARY_DIR}) diff --git a/api/dtors.cpp b/api/dtors.cpp new file mode 100644 index 00000000..5cc87187 --- /dev/null +++ b/api/dtors.cpp @@ -0,0 +1,11 @@ +#include "plugin-api.hpp" + +// these exist only so that vtable is emitted in a single compilation unit, not all of them. + +Metadata::~Metadata() {} +IFilter::~IFilter() {} +IFilterDialog::~IFilterDialog() {} +IProtocol::~IProtocol() {} +IProtocolDialog::~IProtocolDialog() {} +ITracker::~ITracker() {} +ITrackerDialog::~ITrackerDialog() {} diff --git a/api/export.hpp b/api/export.hpp new file mode 100644 index 00000000..a9f3521e --- /dev/null +++ b/api/export.hpp @@ -0,0 +1,28 @@ +#pragma once + +#ifdef BUILD_api +# ifdef _WIN32 +# define OPENTRACK_API_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_API_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_API_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_API_LINKAGE +# else +# define OPENTRACK_API_EXPORT OPENTRACK_API_LINKAGE +# endif + +#else + #ifdef _WIN32 + # define OPENTRACK_API_LINKAGE __declspec(dllimport) + #else + # define OPENTRACK_API_LINKAGE + #endif + + #ifndef _MSC_VER + # define OPENTRACK_API_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_API_LINKAGE + #else + # define OPENTRACK_API_EXPORT OPENTRACK_API_LINKAGE + #endif +#endif diff --git a/api/is-window-visible.cpp b/api/is-window-visible.cpp new file mode 100644 index 00000000..fc25bb7d --- /dev/null +++ b/api/is-window-visible.cpp @@ -0,0 +1,33 @@ +#include "is-window-visible.hpp" +#include <QPoint> + +#ifdef _WIN32 + +#include <windows.h> + +OPENTRACK_API_EXPORT bool is_window_visible(const QWidget* widget) +{ + const QPoint p = widget->mapToGlobal(QPoint(0, 0)); + const QSize s = widget->size(); + + const POINT points[] = + { + { p.x(), p.y() }, + { p.x() + s.width(), p.y() }, + { p.x() + s.width(), p.y() + s.height() }, + { p.x(), p.y() + s.height() }, + { p.x() + s.width()/2, p.y() + s.height()/2 }, + }; + + for (const POINT& pt : points) + if (WindowFromPoint(pt) == (HWND) widget->winId()) + return true; + return false; +} + +#else +OPENTRACK_API_EXPORT bool is_window_visible(const QWidget* widget) +{ + return true; +} +#endif diff --git a/api/is-window-visible.hpp b/api/is-window-visible.hpp new file mode 100644 index 00000000..18c9251a --- /dev/null +++ b/api/is-window-visible.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include <QWidget> +#include "export.hpp" + +OPENTRACK_API_EXPORT bool is_window_visible(const QWidget* widget); + diff --git a/api/plugin-api.hpp b/api/plugin-api.hpp new file mode 100644 index 00000000..1e5c0fe0 --- /dev/null +++ b/api/plugin-api.hpp @@ -0,0 +1,180 @@ +/* Copyright (c) 2013-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 <QString> +#include <QWidget> +#include <QFrame> +#include <QIcon> + +#include "export.hpp" + +#ifndef OPENTRACK_PLUGIN_EXPORT +# ifdef _WIN32 +# define OPENTRACK_PLUGIN_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_PLUGIN_LINKAGE +# endif +# ifndef _MSC_VER +# define OPENTRACK_PLUGIN_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_PLUGIN_LINKAGE +# else +# define OPENTRACK_PLUGIN_EXPORT OPENTRACK_PLUGIN_LINKAGE +# endif +#endif + +enum Axis { + TX, TY, TZ, Yaw, Pitch, Roll +}; + +namespace plugin_api { +namespace detail { + +class OPENTRACK_API_EXPORT BaseDialog : public QWidget +{ + Q_OBJECT +public: + void closeEvent(QCloseEvent *) override { emit closing(); } +signals: + void closing(); +}; + +} // ns +} // ns + +#define OPENTRACK_DECLARE_PLUGIN_INTERNAL(ctor_class, ctor_ret_class, metadata_class, dialog_class, dialog_ret_class) \ + extern "C" OPENTRACK_PLUGIN_EXPORT ctor_ret_class* GetConstructor(); \ + extern "C" OPENTRACK_PLUGIN_EXPORT Metadata* GetMetadata(); \ + extern "C" OPENTRACK_PLUGIN_EXPORT dialog_ret_class* GetDialog(); \ + \ + extern "C" OPENTRACK_PLUGIN_EXPORT ctor_ret_class* GetConstructor() \ + { \ + return new ctor_class; \ + } \ + extern "C" OPENTRACK_PLUGIN_EXPORT Metadata* GetMetadata() \ + { \ + return new metadata_class; \ + } \ + extern "C" OPENTRACK_PLUGIN_EXPORT dialog_ret_class* GetDialog() \ + { \ + return new dialog_class; \ + } + +// implement this in all plugins +// also you must link against "opentrack-api" in CMakeLists.txt to avoid vtable link errors +struct OPENTRACK_API_EXPORT Metadata +{ + Metadata(const Metadata&) = delete; + Metadata(Metadata&&) = delete; + Metadata& operator=(const Metadata&) = delete; + inline Metadata() {} + + // plugin name to be displayed in the interface + virtual QString name() = 0; + // plugin icon, you can return an empty QIcon() + virtual QIcon icon() = 0; + // optional destructor + virtual ~Metadata(); +}; + +// implement this in filters +struct OPENTRACK_API_EXPORT IFilter +{ + IFilter(const IFilter&) = delete; + IFilter(IFilter&&) = delete; + IFilter& operator=(const IFilter&) = delete; + inline IFilter() {} + + // optional destructor + virtual ~IFilter(); + // perform filtering step. + // you have to take care of dt on your own, try "opentrack-compat/timer.hpp" + virtual void filter(const double *input, double *output) = 0; + // optionally reset the filter when centering + virtual void center() {} +}; + +struct OPENTRACK_API_EXPORT IFilterDialog : public plugin_api::detail::BaseDialog +{ + // optional destructor + virtual ~IFilterDialog(); + // receive a pointer to the filter from ui thread + virtual void register_filter(IFilter* filter) = 0; + // received filter pointer is about to get deleted + virtual void unregister_filter() = 0; +}; + +// call once with your chosen class names in the plugin +#define OPENTRACK_DECLARE_FILTER(filter_class, dialog_class, metadata_class) \ + OPENTRACK_DECLARE_PLUGIN_INTERNAL(filter_class, IFilter, metadata_class, dialog_class, IFilterDialog) + +// implement this in protocols +struct OPENTRACK_API_EXPORT IProtocol +{ + IProtocol(const IProtocol&) = delete; + IProtocol(IProtocol&&) = delete; + IProtocol& operator=(const IProtocol&) = delete; + inline IProtocol() {} + + // optional destructor + virtual ~IProtocol(); + // return true if protocol was properly initialized + virtual bool correct() = 0; + // called 250 times a second with XYZ yaw pitch roll pose + // try not to perform intense computation here. if you must, use a thread. + virtual void pose(const double* headpose) = 0; + // return game name or placeholder text + virtual QString game_name() = 0; +}; + +struct OPENTRACK_API_EXPORT IProtocolDialog : public plugin_api::detail::BaseDialog +{ + // optional destructor + virtual ~IProtocolDialog(); + // receive a pointer to the protocol from ui thread + virtual void register_protocol(IProtocol *protocol) = 0; + // received protocol pointer is about to get deleted + virtual void unregister_protocol() = 0; +}; + +// call once with your chosen class names in the plugin +#define OPENTRACK_DECLARE_PROTOCOL(protocol_class, dialog_class, metadata_class) \ + OPENTRACK_DECLARE_PLUGIN_INTERNAL(protocol_class, IProtocol, metadata_class, dialog_class, IProtocolDialog) + +// implement this in trackers +struct OPENTRACK_API_EXPORT ITracker +{ + ITracker(const ITracker&) = delete; + ITracker(ITracker&&) = delete; + ITracker& operator=(const ITracker&) = delete; + inline ITracker() {} + + // optional destructor + virtual ~ITracker(); + // start tracking, and grab a frame to display webcam video in, optionally + virtual void start_tracker(QFrame* frame) = 0; + // return XYZ yaw pitch roll data. don't block here, use a separate thread for computation. + virtual void data(double *data) = 0; + // tracker notified of centering + // returning true makes identity the center pose + virtual bool center() { return false; } +}; + +struct OPENTRACK_API_EXPORT ITrackerDialog : public plugin_api::detail::BaseDialog +{ + // optional destructor + virtual ~ITrackerDialog(); + // receive a pointer to the tracker from ui thread + virtual void register_tracker(ITracker *tracker) = 0; + // received tracker pointer is about to get deleted + virtual void unregister_tracker() = 0; +}; + +// call once with your chosen class names in the plugin +#define OPENTRACK_DECLARE_TRACKER(tracker_class, dialog_class, metadata_class) \ + OPENTRACK_DECLARE_PLUGIN_INTERNAL(tracker_class, ITracker, metadata_class, dialog_class, ITrackerDialog) diff --git a/api/plugin-support.hpp b/api/plugin-support.hpp new file mode 100644 index 00000000..072c8da7 --- /dev/null +++ b/api/plugin-support.hpp @@ -0,0 +1,216 @@ +/* Copyright (c) 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 "plugin-api.hpp" +#include "compat/options.hpp" + +#include <QWidget> +#include <QDebug> +#include <QString> +#include <QLibrary> +#include <QFrame> +#include <QList> + +#include <cstdio> +#include <cinttypes> +#include <iostream> +#include <algorithm> + +#include <QCoreApplication> +#include <QFile> +#include <QDir> +#include <QList> +#include <QStringList> + +#if defined(__APPLE__) +# define OPENTRACK_SOLIB_EXT "dylib" +#elif defined(_WIN32) +# define OPENTRACK_SOLIB_EXT "dll" +#else +# define OPENTRACK_SOLIB_EXT "so" +#endif + +#include <iostream> + +#ifdef _MSC_VER +# define OPENTRACK_SOLIB_PREFIX "" +#else +# define OPENTRACK_SOLIB_PREFIX "lib" +#endif + +extern "C" typedef void* (*OPENTRACK_CTOR_FUNPTR)(void); +extern "C" typedef Metadata* (*OPENTRACK_METADATA_FUNPTR)(void); + +struct dylib final { + enum Type { Filter, Tracker, Protocol }; + + dylib(const QString& filename, Type t) : + type(t), + filename(filename), + Dialog(nullptr), + Constructor(nullptr), + Meta(nullptr), + handle(nullptr) + { + // otherwise dlopen opens the calling executable + if (filename.size() == 0) + return; + + handle = new QLibrary(filename); + handle->setLoadHints(QLibrary::PreventUnloadHint | handle->loadHints()); + + struct _foo { + static bool die(QLibrary*& l, bool failp) + { + if (failp) + { + qDebug() << "failed" << l->errorString(); + delete l; + l = nullptr; + } + return failp; + } + }; + + if (_foo::die(handle, !handle->load())) + return; + + Dialog = (OPENTRACK_CTOR_FUNPTR) handle->resolve("GetDialog"); + if (_foo::die(handle, !Dialog)) + return; + + Constructor = (OPENTRACK_CTOR_FUNPTR) handle->resolve("GetConstructor"); + if (_foo::die(handle, !Constructor)) + return; + + Meta = (OPENTRACK_METADATA_FUNPTR) handle->resolve("GetMetadata"); + if (_foo::die(handle, !Meta)) + return; + + auto m = mem<Metadata>(Meta()); + + icon = m->icon(); + name = m->name(); + } + ~dylib() + { + if (handle) + delete handle; + } + + static QList<mem<dylib>> enum_libraries(const QString& library_path) + { + const char* filters_n[] = { OPENTRACK_SOLIB_PREFIX "opentrack-filter-*." OPENTRACK_SOLIB_EXT, + OPENTRACK_SOLIB_PREFIX "opentrack-tracker-*." OPENTRACK_SOLIB_EXT, + OPENTRACK_SOLIB_PREFIX "opentrack-proto-*." OPENTRACK_SOLIB_EXT, + }; + const Type filters_t[] = { Filter, Tracker, Protocol }; + + QDir settingsDir(library_path); + + QList<mem<dylib>> ret; + + for (int i = 0; i < 3; i++) + { + QString glob = filters_n[i]; + Type t = filters_t[i]; + QStringList filenames = settingsDir.entryList(QStringList { glob }, QDir::Files, QDir::Name); + + for (const QString& filename : filenames) + { + QIcon icon; + QString longName; + auto lib = std::make_shared<dylib>(library_path + filename, t); + qDebug() << "Loading" << filename; + std::cout.flush(); + if (!get_metadata(lib, longName, icon)) + continue; + using d = const mem<dylib>&; + if (std::any_of(ret.cbegin(), + ret.cend(), + [&](d a) {return a->type == lib->type && a->name == lib->name;})) + { + qDebug() << "Duplicate lib" << lib->filename; + continue; + } + ret.push_back(lib); + } + } + + return ret; + } + + Type type; + QString filename; + + QIcon icon; + QString name; + + OPENTRACK_CTOR_FUNPTR Dialog; + OPENTRACK_CTOR_FUNPTR Constructor; + OPENTRACK_METADATA_FUNPTR Meta; +private: + QLibrary* handle; + + static bool get_metadata(mem<dylib> lib, QString& name, QIcon& icon) + { + Metadata* meta; + if (!lib->Meta || ((meta = lib->Meta()), !meta)) + return false; + name = meta->name(); + icon = meta->icon(); + delete meta; + return true; + } +}; + +struct Modules +{ + Modules(const QString& library_path) : + module_list(dylib::enum_libraries(library_path)), + filter_modules(filter(dylib::Filter)), + tracker_modules(filter(dylib::Tracker)), + protocol_modules(filter(dylib::Protocol)) + {} + QList<mem<dylib>>& filters() { return filter_modules; } + QList<mem<dylib>>& trackers() { return tracker_modules; } + QList<mem<dylib>>& protocols() { return protocol_modules; } +private: + QList<mem<dylib>> module_list; + QList<mem<dylib>> filter_modules; + QList<mem<dylib>> tracker_modules; + QList<mem<dylib>> protocol_modules; + + template<typename t> + static void sort(QList<t>& xs) + { + std::sort(xs.begin(), xs.end(), [&](const t& a, const t& b) { return a->name.toLower() < b->name.toLower(); }); + } + + QList<mem<dylib>> filter(dylib::Type t) + { + QList<mem<dylib>> ret; + for (auto x : module_list) + if (x->type == t) + ret.push_back(x); + + sort(ret); + + return ret; + } +}; + +template<typename t> +mem<t> make_dylib_instance(mem<dylib> lib) +{ + mem<t> ret; + if (lib != nullptr && lib->Constructor) + ret = mem<t>(reinterpret_cast<t*>(reinterpret_cast<OPENTRACK_CTOR_FUNPTR>(lib->Constructor)())); + return ret; +} diff --git a/api/variance.hpp b/api/variance.hpp new file mode 100644 index 00000000..55060b02 --- /dev/null +++ b/api/variance.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include <cmath> + +// no copyright information other than the attribution below. + +// code shared as an example/tutorial of running variance +// written by John D. Cook on the website <http://www.johndcook.com/blog/standard_deviation> + +// following references in the site's article: + +// Chan, Tony F.; Golub, Gene H.; LeVeque, Randall J. (1983). +// Algorithms for Computing the Sample Variance: Analysis and Recommendations. +// The American Statistician 37, 242-247. + +// Ling, Robert F. (1974). +// Comparison of Several Algorithms for Computing Sample Means and Variances. +// Journal of the American Statistical Association, Vol. 69, No. 348, 859-866. + +class variance +{ + double m_old, m_new, s_old, s_new; + unsigned long cnt; + +public: + variance() : cnt(0) {} + + void clear() { *this = variance(); } + + void input(double x) + { + cnt++; + + if (cnt == 1) + { + m_old = m_new = x; + s_old = 0; + } + else + { + m_new = m_old + (x - m_old)/cnt; + s_new = s_old + (x - m_old)*(x - m_new); + + m_old = m_new; + s_old = s_new; + } + } + + double avg() const { return cnt > 0 ? m_new : 0; } + double Var() const { return cnt > 1 ? s_new/(cnt - 1) : 0; } + double stddev() const { return std::sqrt(Var()); } +}; diff --git a/cmake/mingw-w64.cmake b/cmake/mingw-w64.cmake index ecf4cff3..860259ca 100644 --- a/cmake/mingw-w64.cmake +++ b/cmake/mingw-w64.cmake @@ -10,7 +10,7 @@ unset(c) unset(e) # specify the cross compiler if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") - set(p P:/mingw-w64/i686-5.3.0-posix-dwarf-rt_v4-rev0/mingw32/bin/) + set(p P:/mingw-w64/i686-6.1.0-posix-dwarf-rt_v5-rev0/mingw32/bin/) set(e .exe) endif() set(c ${p}i686-w64-mingw32-) diff --git a/cmake/opentrack-version.cmake b/cmake/opentrack-version.cmake index 5a4901ef..bb907525 100644 --- a/cmake/opentrack-version.cmake +++ b/cmake/opentrack-version.cmake @@ -19,7 +19,7 @@ file(WRITE ${CMAKE_BINARY_DIR}/opentrack-version.h "#define OPENTRACK_VERSION \" set(version-string " #define BUILD_compat -#include \"opentrack-compat/export.hpp\" +#include \"compat/export.hpp\" #ifdef __cplusplus extern \"C\" diff --git a/compat/CMakeLists.txt b/compat/CMakeLists.txt new file mode 100644 index 00000000..2bbb496c --- /dev/null +++ b/compat/CMakeLists.txt @@ -0,0 +1,8 @@ +opentrack_boilerplate(opentrack-compat NO-COMPAT BIN) +if(NOT WIN32 AND NOT APPLE) + target_link_libraries(opentrack-compat rt) +endif() +if(CMAKE_COMPILER_IS_GNUCXX) + set_source_files_properties(nan.cpp PROPERTIES + COMPILE_FLAGS "-fno-fast-math -fno-finite-math-only -O0") +endif() diff --git a/compat/camera-names.cpp b/compat/camera-names.cpp new file mode 100644 index 00000000..21ff3b52 --- /dev/null +++ b/compat/camera-names.cpp @@ -0,0 +1,111 @@ +#include "camera-names.hpp" + +#ifdef _WIN32 +# define NO_DSHOW_STRSAFE +# include <dshow.h> +# include "win32-com.hpp" +# include <cwchar> +#elif 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; + init_com_threading(com_apartment); + 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, int(std::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; +} diff --git a/compat/camera-names.hpp b/compat/camera-names.hpp new file mode 100644 index 00000000..ae0c6b25 --- /dev/null +++ b/compat/camera-names.hpp @@ -0,0 +1,18 @@ +/* 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> + +#include "export.hpp" + +OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names(); +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name); + diff --git a/compat/export.hpp b/compat/export.hpp new file mode 100644 index 00000000..ba10f131 --- /dev/null +++ b/compat/export.hpp @@ -0,0 +1,27 @@ +#pragma once + +#ifdef BUILD_compat +# 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 +#else + #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/compat/make-unique.hpp b/compat/make-unique.hpp new file mode 100644 index 00000000..bb5315c5 --- /dev/null +++ b/compat/make-unique.hpp @@ -0,0 +1,43 @@ +#pragma once + +// GNU 5.4.0 doesn't have std::make_unique in -std=c++14 mode + +// this implementation was taken from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm + +#include <memory> +#include <utility> +#include <cstddef> + +namespace detail { +template<class T> struct Unique_if +{ + typedef std::unique_ptr<T> Single_object; +}; + +template<class T> struct Unique_if<T[]> +{ + typedef std::unique_ptr<T[]> Unknown_bound; +}; + +template<class T, size_t N> struct Unique_if<T[N]> +{ + typedef void Known_bound; +}; +} + +template<class T, class... Args> + typename detail::Unique_if<T>::Single_object + make_unique(Args&&... args) { + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); + } + +template<class T> + typename detail::Unique_if<T>::Unknown_bound + make_unique(std::size_t n) { + typedef typename std::remove_extent<T>::type U; + return std::unique_ptr<T>(new U[n]()); + } + +template<class T, class... Args> + typename detail::Unique_if<T>::Known_bound + make_unique(Args&&...) = delete; diff --git a/compat/nan.cpp b/compat/nan.cpp new file mode 100644 index 00000000..899b907a --- /dev/null +++ b/compat/nan.cpp @@ -0,0 +1,17 @@ +#include <cmath> +#include "export.hpp" + +#if defined(__GNUC__) +extern "C" OPENTRACK_COMPAT_EXPORT bool __attribute__ ((noinline)) nanp(double value) +#elif defined(_WIN32) +extern "C" OPENTRACK_COMPAT_EXPORT __declspec(noinline) bool nanp(double value) +#else +extern "C" OPENTRACK_COMPAT_EXPORT bool nanp(double value) +#endif +{ + using std::isnan; + using std::isinf; + + const volatile double x = value; + return isnan(x) || isinf(x); +} diff --git a/compat/nan.hpp b/compat/nan.hpp new file mode 100644 index 00000000..9926da13 --- /dev/null +++ b/compat/nan.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "export.hpp" + +#if defined(__GNUC__) +extern "C" OPENTRACK_COMPAT_EXPORT bool __attribute__ ((noinline)) nanp(double value); +#elif defined(_WIN32) +extern "C" OPENTRACK_COMPAT_EXPORT __declspec(noinline) bool nanp(double value); +#else +extern "C" OPENTRACK_COMPAT_EXPORT bool nanp(double value); +#endif diff --git a/compat/options.cpp b/compat/options.cpp new file mode 100644 index 00000000..8c6e6c65 --- /dev/null +++ b/compat/options.cpp @@ -0,0 +1,239 @@ +#include "options.hpp" + +namespace options +{ + +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() const +{ + auto s = ini_file(); + s->beginGroup(name); + for (auto& i : kvs) + s->setValue(i.first, i.second); + s->endGroup(); +} + +void group::put(const QString &s, const QVariant &d) +{ + kvs[s] = d; +} + +bool group::contains(const QString &s) const +{ + 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 ""; + return dir + "/" + ini_filename(); +} + +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>(); +} + +bool group::operator==(const group& other) const +{ + for (const auto& kv : kvs) + { + const QVariant val = other.get<QVariant>(kv.first); + if (!other.contains(kv.first) || kv.second != val) + { + qDebug() << "bundle" << name << "modified" << "key" << kv.first << "-" << val << "<>" << kv.second; + return false; + } + } + + for (const auto& kv : other.kvs) + { + const QVariant val = get<QVariant>(kv.first); + if (!contains(kv.first) || kv.second != val) + { + qDebug() << "bundle" << name << "modified" << "key" << kv.first << "-" << kv.second << "<>" << val; + return false; + } + } + return true; +} + +impl_bundle::impl_bundle(const QString& group_name) + : + mtx(QMutex::Recursive), + group_name(group_name), + saved(group_name), + transient(saved) +{ +} + +void impl_bundle::reload() +{ + { + QMutexLocker l(&mtx); + saved = group(group_name); + transient = saved; + } + emit reloading(); +} + +void impl_bundle::store_kv(const QString& name, const QVariant& datum) +{ + QMutexLocker l(&mtx); + + transient.put(name, datum); +} + +bool impl_bundle::contains(const QString &name) const +{ + QMutexLocker l(const_cast<QMutex*>(&mtx)); + return transient.contains(name); +} + +void impl_bundle::save() +{ + bool modified_ = false; + + { + QMutexLocker l(&mtx); + if (saved != transient) + { + qDebug() << "bundle" << group_name << "changed, saving"; + modified_ = true; + saved = transient; + saved.save(); + } + } + + if (modified_) + emit saving(); +} + +bool impl_bundle::modifiedp() const // XXX unused +{ + QMutexLocker l(const_cast<QMutex*>(&mtx)); + return transient != saved; +} + +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)) +{ +} + +custom_type_initializer::custom_type_initializer() +{ + qRegisterMetaTypeStreamOperators<slider_value>("slider_value"); + QMetaType::registerDebugStreamOperator<slider_value>(); +} + +custom_type_initializer custom_type_initializer::singleton; + +namespace detail { + +opt_bundle::opt_bundle(const QString& group_name) + : impl_bundle(group_name) +{ +} + +opt_bundle::~opt_bundle() +{ + detail::singleton().bundle_decf(group_name); +} + +void opt_singleton::bundle_decf(const opt_singleton::k& key) +{ + QMutexLocker l(&implsgl_mtx); + + if (--std::get<0>(implsgl_data[key]) == 0) + { + qDebug() << "bundle -" << key; + + implsgl_data.erase(key); + } +} + +opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) +{ +} + +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(1, shr); + return shr; +} + +OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() +{ + static opt_singleton ret; + return ret; +} + + +} // end options::detail + +} // end options + diff --git a/compat/options.hpp b/compat/options.hpp new file mode 100644 index 00000000..40aca2de --- /dev/null +++ b/compat/options.hpp @@ -0,0 +1,481 @@ +/* Copyright (c) 2013-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. + */ + +#pragma once + +#include <memory> +#include <tuple> +#include <map> +#include <cinttypes> +#include <vector> +#include <memory> + +#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 <QApplication> + +#include <QMetaType> +#include <QDataStream> + +#include <QDebug> + +#include "export.hpp" +#include "slider.hpp" + +#include "util.hpp" + +#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" +#define OPENTRACK_DEFAULT_CONFIG "default.ini" +#define OPENTRACK_ORG "opentrack-2.3" + +namespace options { + namespace { + class custom_type_initializer + { + custom_type_initializer(); + static custom_type_initializer singleton; + }; + } + + template<typename k, typename v> using map = std::map<k, v>; + + // 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() const; + void put(const QString& s, const QVariant& d); + bool contains(const QString& s) const; + static QString ini_directory(); + static QString ini_filename(); + static QString ini_pathname(); + static const QStringList ini_list(); + static const mem<QSettings> ini_file(); + bool operator==(const group& other) const; + bool operator!=(const group& other) const { return !(*this == other); } + + template<typename t> + t get(const QString& k) const + { + auto value = kvs.find(k); + if (value != kvs.cend()) + return value->second.value<t>(); + return t(); + } + }; + + class OPENTRACK_COMPAT_EXPORT impl_bundle : public QObject + { + Q_OBJECT + protected: + QMutex mtx; + const QString group_name; + group saved; + group transient; + impl_bundle(const impl_bundle&) = delete; + impl_bundle& operator=(const impl_bundle&) = delete; + signals: + void reloading(); + void saving() const; + 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) const; + void save(); + bool modifiedp() const; + + template<typename t> + t get(const QString& name) const + { + QMutexLocker l(const_cast<QMutex*>(&mtx)); + return transient.get<t>(name); + } + }; + + namespace detail + { + class OPENTRACK_COMPAT_EXPORT opt_bundle final : public impl_bundle + { + public: + opt_bundle(const QString& group_name); + ~opt_bundle(); + }; + + 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<detail::opt_bundle>; + + inline pbundle bundle(const QString& name) + { + return detail::singleton().bundle(name); + } + +#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); } +#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) + + class OPENTRACK_COMPAT_EXPORT base_value : public QObject + { + Q_OBJECT + public: + QString name() const { return self_name; } + base_value(pbundle b, const QString& name); + signals: + OPENTRACK_DEFINE_SIGNAL(double); + OPENTRACK_DEFINE_SIGNAL(float); + OPENTRACK_DEFINE_SIGNAL(int); + OPENTRACK_DEFINE_SIGNAL(bool); + OPENTRACK_DEFINE_SIGNAL(const QString&); + OPENTRACK_DEFINE_SIGNAL(const slider_value&); + protected: + pbundle b; + QString self_name; + + template<typename t> + void store(const t& datum) + { + b->store_kv(self_name, QVariant::fromValue(datum)); + emit valueChanged(static_cast<t>(datum)); + } + void store(float datum) + { + store(double(datum)); + } + + public slots: + OPENTRACK_DEFINE_SLOT(double) + OPENTRACK_DEFINE_SLOT(int) + OPENTRACK_DEFINE_SLOT(bool) + OPENTRACK_DEFINE_SLOT(const QString&) + OPENTRACK_DEFINE_SLOT(const slider_value&) + public slots: + virtual void reload() = 0; + }; + + namespace detail { + template<typename t> + struct value_get_traits + { + static inline t get(const t& val, const t&) + { + return val; + } + }; + + template<> + struct value_get_traits<slider_value> + { + using t = slider_value; + static inline t get(const t& val, const t& def) + { + return t(val.cur(), def.min(), def.max()); + } + }; + } + + template<typename t_> + class value : public base_value + { + template<typename t__, typename Enable = void> + struct get_t + { using t = t__; }; + + // Qt uses int a lot in slots so use it for all enums + template<typename t__> + struct get_t<t__, typename std::enable_if<std::is_enum<t__>::value>::type> + //{ using t = typename std::underlying_type<t__>::type; }; + { using t = int; }; + + using t = t_; + public: + using underlying_t = typename get_t<t_>::t; + + t operator=(const t& datum) + { + store(static_cast<underlying_t>(datum)); + return datum; + } + + static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::AutoConnection; + static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection; + + 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) + { + } + + t get() const + { + t val = b->contains(self_name) + ? static_cast<t>(b->get<underlying_t>(self_name)) + : def; + return detail::value_get_traits<t>::get(val, def); + } + + operator t() const { return get(); } + + void reload() override + { + *this = static_cast<t>(*this); + } + + private: + t def; + }; + + struct OPENTRACK_COMPAT_EXPORT opts + { + pbundle b; + opts(const QString& name); + opts& operator=(const opts&) = delete; + opts(const opts&) = delete; + ~opts(); + }; + + template<typename t, typename q> + inline void tie_setting(value<t>&, q*); + + template<typename t> + inline + typename std::enable_if<std::is_enum<t>::value>::type + tie_setting(value<t>& v, QComboBox* cb) + { + cb->setCurrentIndex(cb->findData((unsigned)static_cast<t>(v))); + v = static_cast<t>(cb->currentData().toInt()); + + // QObject::connect plays badly with std::bind of std::shared_ptr. Data seems to get freed. + // Direct accesses of cb->currentData within arbitrary thread context cause crashes as well. + // Hence we go for a verbose implementation. + + std::vector<int> enum_cases; + enum_cases.reserve(unsigned(cb->count())); + + for (int i = 0; i < cb->count(); i++) + enum_cases.push_back(cb->itemData(i).toInt()); + + struct fn1 + { + value<t>& v; + QComboBox* cb; + std::vector<int> enum_cases; + + fn1(value<t>& v, QComboBox* cb, const std::vector<int>& enum_cases) : + v(v), + cb(cb), + enum_cases(enum_cases) + { + } + + void operator()(int idx) + { + if (idx < 0 || idx >= (int)enum_cases.size()) + v = static_cast<t>(-1); + else + v = static_cast<t>(t(std::intptr_t(enum_cases[idx]))); + } + }; + + struct fn2 + { + value<t>& v; + QComboBox* cb; + std::vector<int> enum_cases; + + fn2(value<t>& v, QComboBox* cb, const std::vector<int>& enum_cases) : + v(v), + cb(cb), + enum_cases(enum_cases) + { + } + + void operator()(int val) + { + for (unsigned i = 0; i < enum_cases.size(); i++) + { + if (val == enum_cases[i]) + { + cb->setCurrentIndex(i); + return; + } + } + cb->setCurrentIndex(-1); + } + }; + + base_value::connect(cb, + static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + &v, + fn1(v, cb, enum_cases), + v.DIRECT_CONNTYPE); + base_value::connect(&v, + static_cast<void (base_value::*)(int)>(&base_value::valueChanged), + cb, + fn2(v, cb, enum_cases), + v.DIRECT_CONNTYPE); + } + + 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.DIRECT_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); + } + + template<> + inline void tie_setting(value<slider_value>& v, QSlider* w) + { + // we can't get these at runtime since signals cross threads + const int q_min = w->minimum(); + const int q_max = w->maximum(); + const int q_diff = q_max - q_min; + + slider_value sv(v); + + const double sv_max = sv.max(); + const double sv_min = sv.min(); + const double sv_c = sv_max - sv_min; + + w->setValue(int((sv.cur() - sv_min) / sv_c * q_diff + q_min)); + v = slider_value(q_diff <= 0 ? 0 : (w->value() - q_min) * sv_c / (double)q_diff + sv_min, sv_min, sv_max); + + base_value::connect(w, + &QSlider::valueChanged, + &v, + [=, &v](int pos) -> void + { + if (q_diff <= 0 || pos <= 0) + v = slider_value(sv_min, sv_min, sv_max); + else + v = slider_value((pos - q_min) * sv_c / (double)q_diff + sv_min, sv_min, sv_max); + }, + v.DIRECT_CONNTYPE); + base_value::connect(&v, + static_cast<void(base_value::*)(double)>(&base_value::valueChanged), + w, + [=](double value) -> void + { + w->setValue(int(value * q_diff) + q_min); + }, + v.SAFE_CONNTYPE); + } +} + diff --git a/compat/pi-constant.hpp b/compat/pi-constant.hpp new file mode 100644 index 00000000..52b98a7f --- /dev/null +++ b/compat/pi-constant.hpp @@ -0,0 +1,3 @@ +#pragma once + +#define OPENTRACK_PI 3.14159265358979323846 diff --git a/compat/process-list.hpp b/compat/process-list.hpp new file mode 100644 index 00000000..10613791 --- /dev/null +++ b/compat/process-list.hpp @@ -0,0 +1,169 @@ +/* Copyright (c) 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 <QDebug> +#include <QStringList> + +#if defined _WIN32 + +#include <windows.h> +#include <tlhelp32.h> + +template<typename = void> +static QStringList get_all_executable_names() +{ + QStringList ret; + HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (h == INVALID_HANDLE_VALUE) + return ret; + + PROCESSENTRY32 e; + e.dwSize = sizeof(e); + + if (Process32First(h, &e) != TRUE) + { + CloseHandle(h); + return ret; + } + + do { + ret.append(e.szExeFile); + } while (Process32Next(h, &e) == TRUE); + + CloseHandle(h); + + return ret; +} +#elif defined __APPLE__ +#include <libproc.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/sysctl.h> +#include <cerrno> +#include <cstring> +#include <vector> + +template<typename = void> +static QStringList get_all_executable_names() +{ + QStringList ret; + std::vector<int> vec; + + while (true) + { + int numproc = proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0); + if (numproc == -1) + { + qDebug() << "proc_listpids numproc failed" << errno; + return ret; + } + vec.resize(numproc); + int cnt = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(int) * numproc); + + if (cnt <= numproc) + { + std::vector<char> arglist; + int mib[2] { CTL_KERN, KERN_ARGMAX }; + size_t sz = sizeof(int); + int maxarg = 0; + if (sysctl(mib, 2, &maxarg, &sz, NULL, 0) == -1) + { + qDebug() << "sysctl KERN_ARGMAX" << errno; + return ret; + } + arglist.resize(maxarg); + for (int i = 0; i < numproc; i++) + { + size_t maxarg_ = (size_t)maxarg; + int mib[3] { CTL_KERN, KERN_PROCARGS2, vec[i] }; + if (sysctl(mib, 3, &arglist[0], &maxarg_, NULL, 0) == -1) + { + //qDebug() << "sysctl KERN_PROCARGS2" << vec[i] << errno; + continue; + } + QStringList cmdline; + for (unsigned j = sizeof(int) + strlen(&arglist[sizeof(int)]); j < maxarg_; j++) + { + QString arg(&arglist[j]); + if (arg.size() != 0) + { + cmdline << arg; + j += arg.size(); + } + } + if (cmdline.size() > 0) + { + int idx = cmdline[0].lastIndexOf('/'); + if (idx != -1) + { + QString tmp = cmdline[0].mid(idx+1); + if (cmdline.size() > 1 && (tmp == "wine.bin" || tmp == "wine")) + { + idx = cmdline[1].lastIndexOf('/'); + if (idx == -1) + idx = cmdline[1].lastIndexOf('\\'); + if (idx != -1) + { + ret.append(cmdline[1].mid(idx+1)); + } + else + ret.append(cmdline[1]); + } + else + { + ret.append(tmp); + } + } + else + ret.append(cmdline[0]); + } + } + return ret; + } + } +} + +#elif defined __linux + +#include <proc/readproc.h> +#include <cerrno> +template<typename = void> +static QStringList get_all_executable_names() +{ + QStringList ret; + proc_t** procs = readproctab(PROC_FILLCOM); + if (procs == nullptr) + { + qDebug() << "readproctab" << errno; + return ret; + } + for (int i = 0; procs[i]; i++) + { + // note, wine sets argv[0] so no parsing like in OSX case + auto proc = procs[i]; + if (proc->cmdline && proc->cmdline[0]) + { + QString tmp(proc->cmdline[0]); + const int idx = std::max(tmp.lastIndexOf('\\'), tmp.lastIndexOf('/')); + tmp = tmp.mid(idx == -1 ? 0 : idx+1); + ret.append(tmp); + } + freeproc(procs[i]); + } + free(procs); + return ret; +} + +#else +template<typename = void> +static QStringList get_all_executable_names() +{ + return QStringList(); +} +#endif diff --git a/compat/qcopyable-mutex.hpp b/compat/qcopyable-mutex.hpp new file mode 100644 index 00000000..57b0030d --- /dev/null +++ b/compat/qcopyable-mutex.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include <QMutex> + +class MyMutex { +private: + QMutex inner; + +public: + QMutex* operator->() { return &inner; } + QMutex* operator->() const { return &const_cast<MyMutex*>(this)->inner; } + + MyMutex operator=(const MyMutex& datum) + { + auto mode = + datum->isRecursive() + ? QMutex::Recursive + : QMutex::NonRecursive; + + return MyMutex(mode); + } + + MyMutex(const MyMutex& datum) + { + *this = datum; + } + + MyMutex(QMutex::RecursionMode mode = QMutex::NonRecursive) : + inner(mode) + { + } + + QMutex* operator&() const + { + return const_cast<QMutex*>(&inner); + } +}; diff --git a/compat/shm.cpp b/compat/shm.cpp new file mode 100644 index 00000000..83a3260c --- /dev/null +++ b/compat/shm.cpp @@ -0,0 +1,199 @@ +/* Copyright (c) 2013 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. + */ + +#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) +{ + 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, + 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() +{ + UnmapViewOfFile(mem); + CloseHandle(hMapFile); + CloseHandle(hMutex); +} + +void PortableLockedShm::lock() +{ + (void) WaitForSingleObject(hMutex, INFINITE); +} + +void PortableLockedShm::unlock() +{ + (void) ReleaseMutex(hMutex); +} +#else + +#include <limits.h> + +#pragma GCC diagnostic ignored "-Wunused-result" +PortableLockedShm::PortableLockedShm(const char *shmName, const char* /*mutexName*/, int mapSize) : size(mapSize) +{ + char filename[PATH_MAX+2] = {0}; + strcpy(filename, "/"); + strcat(filename, shmName); + fd = shm_open(filename, O_RDWR | O_CREAT, 0600); + (void) ftruncate(fd, mapSize); + mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)0); +} + +PortableLockedShm::~PortableLockedShm() +{ + (void) munmap(mem, size); + (void) close(fd); +} + +void PortableLockedShm::lock() +{ + flock(fd, LOCK_EX); +} + +void PortableLockedShm::unlock() +{ + flock(fd, LOCK_UN); +} +#endif + +bool PortableLockedShm::success() +{ +#ifndef _WIN32 + return mem != (void*) -1; +#else + return mem != NULL; +#endif +} diff --git a/compat/shm.h b/compat/shm.h new file mode 100644 index 00000000..f212dc17 --- /dev/null +++ b/compat/shm.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2013 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 + +#if defined(_WIN32) +#include <windows.h> +#else +#include <stdio.h> +#include <string.h> +#include <sys/file.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <limits.h> +#include <unistd.h> +#include <sys/types.h> +#endif + +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wattributes" +#endif + +#include "export.hpp" + +class OPENTRACK_COMPAT_EXPORT PortableLockedShm { +public: + PortableLockedShm(const char *shmName, const char *mutexName, int mapSize); + ~PortableLockedShm(); + void lock(); + void unlock(); + bool success(); + inline void* ptr() { return mem; } +private: + void* mem; +#if defined(_WIN32) + HANDLE hMutex, hMapFile; +#else + int fd, size; +#endif +}; + +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif diff --git a/compat/sleep.hpp b/compat/sleep.hpp new file mode 100644 index 00000000..fab27286 --- /dev/null +++ b/compat/sleep.hpp @@ -0,0 +1,22 @@ +#pragma once + +#ifdef _WIN32 +# include <windows.h> +#else +# include <unistd.h> +#endif + +namespace portable +{ +#ifdef _WIN32 + inline void sleep(unsigned milliseconds) + { + Sleep(milliseconds); + } +#else + inline void sleep(unsigned milliseconds) + { + usleep(milliseconds * 1000U); // takes microseconds + } +#endif +} diff --git a/compat/slider.cpp b/compat/slider.cpp new file mode 100644 index 00000000..be1aaeb8 --- /dev/null +++ b/compat/slider.cpp @@ -0,0 +1,73 @@ +#include "slider.hpp" +#include <cmath> + +namespace options { + +slider_value::slider_value(double cur, double min, double max) : + cur_(cur), + min_(min), + max_(max) +{ + if (min_ > max_) + min_ = max_; + if (cur_ > max_) + cur_ = max; + if (cur_ < min_) + cur_ = min_; +} + +slider_value::slider_value(const slider_value& v) : slider_value(v.cur(), v.min(), v.max()) +{ +} + +slider_value::slider_value() : slider_value(0, 0, 0) +{ +} + +slider_value& slider_value::operator=(const slider_value& v) +{ + cur_ = v.cur_; + + min_ = v.min_; + max_ = v.max_; + + return *this; +} + +bool slider_value::operator==(const slider_value& v) const +{ + using std::fabs; + + static constexpr double eps = 1e-3; + + return (fabs(v.cur_ - cur_) < eps && + fabs(v.min_ - min_) < eps && + fabs(v.max_ - max_) < eps); +} + +slider_value slider_value::update_from_slider(int pos, int q_min, int q_max) const +{ + slider_value v(*this); + + const int q_diff = q_max - q_min; + const double sv_pos = q_diff == 0 + ? -1e6 + : (((pos - q_min) * (v.max() - v.min())) / q_diff + v.min()); + + if (sv_pos < v.min()) + v = slider_value(v.min(), v.min(), v.max()); + else if (sv_pos > v.max()) + v = slider_value(v.max(), v.min(), v.max()); + else + v = slider_value(sv_pos, v.min(), v.max()); + return v; +} + +int slider_value::to_slider_pos(int q_min, int q_max) const +{ + const int q_diff = q_max - q_min; + + return int(std::round(((cur() - min() * q_diff) / (max() - min())) + q_min)); +} + +} // end ns options diff --git a/compat/slider.hpp b/compat/slider.hpp new file mode 100644 index 00000000..7d54c650 --- /dev/null +++ b/compat/slider.hpp @@ -0,0 +1,62 @@ +/* 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. + */ + +#pragma once + +#include "export.hpp" +#include <QMetaType> +#include <QDataStream> +#include <QDebug> + +namespace options +{ + class OPENTRACK_COMPAT_EXPORT slider_value final + { + double cur_, min_, max_; + public: + slider_value(double cur, double min, double max); + slider_value(const slider_value& v); + slider_value(); + slider_value& operator=(const slider_value& v); + bool operator==(const slider_value& v) const; + operator double() const { return cur_; } + double cur() const { return cur_; } + double min() const { return min_; } + double max() const { return max_; } + slider_value update_from_slider(int pos, int q_min, int q_max) const; + int to_slider_pos(int q_min, int q_max) const; + }; +} + +QT_BEGIN_NAMESPACE + +inline QDebug operator << (QDebug dbg, const options::slider_value& val) +{ + return dbg << val.cur(); +} + +inline QDataStream& operator << (QDataStream& out, const options::slider_value& v) +{ + out << v.cur() + << v.min() + << v.max(); + return out; +} + +inline QDataStream& operator >> (QDataStream& in, options::slider_value& v) +{ + double cur, min, max; + in >> cur; + in >> min; + in >> max; + v = options::slider_value(cur, min, max); + return in; +} + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(options::slider_value) diff --git a/compat/timer.hpp b/compat/timer.hpp new file mode 100644 index 00000000..300a883c --- /dev/null +++ b/compat/timer.hpp @@ -0,0 +1,100 @@ +/* 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 <ctime> + +#include "export.hpp" + +#if defined (_WIN32) +# include <windows.h> +# ifndef CLOCK_MONOTONIC +# define CLOCK_MONOTONIC -1 +# endif +static inline void opentrack_clock_gettime(int, struct timespec* ts) +{ + static LARGE_INTEGER freq; + + if (!freq.QuadPart) + (void) QueryPerformanceFrequency(&freq); + + LARGE_INTEGER d; + + (void) QueryPerformanceCounter(&d); + + using ll = long long; + using ld = long double; + const long long part = ll(d.QuadPart / ld(freq.QuadPart) * 1000000000.L); + using t_s = decltype(ts->tv_sec); + using t_ns = decltype(ts->tv_nsec); + + ts->tv_sec = t_s(part / 1000000000LL); + ts->tv_nsec = t_ns(part % 1000000000LL); +} +# define clock_gettime opentrack_clock_gettime +#else +# if defined(__MACH__) +# define CLOCK_MONOTONIC 0 +# include <inttypes.h> +# include <mach/mach_time.h> +static inline void clock_gettime(int, struct timespec* ts) +{ + static mach_timebase_info_data_t sTimebaseInfo; + uint64_t state, nsec; + if ( sTimebaseInfo.denom == 0 ) { + (void) mach_timebase_info(&sTimebaseInfo); + } + state = mach_absolute_time(); + nsec = state * sTimebaseInfo.numer / sTimebaseInfo.denom; + ts->tv_sec = nsec / 1000000000L; + ts->tv_nsec = nsec % 1000000000L; +} +# endif +#endif +class Timer +{ +private: + struct timespec state; + long long conv_nsecs(const struct timespec& cur) const + { + return (cur.tv_sec - state.tv_sec) * 1000000000LL + (cur.tv_nsec - state.tv_nsec); + } + long conv_usecs(const struct timespec& cur) const + { + return long(cur.tv_sec - state.tv_sec) * 1000000L + long(cur.tv_nsec - state.tv_nsec) / 1000l; + } +public: + Timer() + { + start(); + } + void start() + { + clock_gettime(CLOCK_MONOTONIC, &state); + } + long long elapsed_nsecs() const + { + struct timespec cur; + clock_gettime(CLOCK_MONOTONIC, &cur); + return conv_nsecs(cur); + } + long elapsed_usecs() const + { + struct timespec cur; + clock_gettime(CLOCK_MONOTONIC, &cur); + return long(conv_usecs(cur)); + } + long elapsed_ms() const + { + return elapsed_usecs() / 1000L; + } + double elapsed_seconds() const + { + return double(elapsed_nsecs() * 1e-9L); + } +}; diff --git a/compat/util.hpp b/compat/util.hpp new file mode 100644 index 00000000..1217e654 --- /dev/null +++ b/compat/util.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include "make-unique.hpp" + +#include <memory> +#include <utility> +#include <type_traits> +#include <thread> +#include <condition_variable> + +#include <QDebug> + +#define progn(...) ([&]() { __VA_ARGS__ }()) +template<typename t> using mem = std::shared_ptr<t>; +template<typename t> using ptr = std::unique_ptr<t>; + +template<typename F> +void run_in_thread_async(QObject* obj, F&& fun) +{ + QObject src; + src.moveToThread(obj->thread()); + QObject::connect(&src, &QObject::destroyed, obj, std::move(fun), Qt::AutoConnection); +} + +namespace detail { + +template<typename t> +struct run_in_thread_traits +{ + using type = t; + using ret_type = t&&; + static inline void assign(t& lvalue, t&& rvalue) { lvalue = rvalue; } + static inline ret_type&& pass(ret_type&& val) { return std::move(val); } + template<typename F> static ret_type call(F& fun) { return std::move(fun()); } +}; + +template<> +struct run_in_thread_traits<void> +{ + using type = unsigned char; + using ret_type = void; + static inline void assign(unsigned char&, unsigned char&&) {} + static inline void pass(type&&) {} + template<typename F> static type&& call(F& fun) { fun(); return std::move(type(0)); } +}; + +} + +template<typename F> +auto run_in_thread_sync(QObject* obj, F&& fun) + -> typename detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>::ret_type +{ + using lock_guard = std::unique_lock<std::mutex>; + + std::mutex mtx; + lock_guard guard(mtx); + std::condition_variable cvar; + + std::thread::id waiting_thread = std::this_thread::get_id(); + + using traits = detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>; + + typename traits::type ret; + + bool skip_wait = false; + + { + QObject src; + src.moveToThread(obj->thread()); + QObject::connect(&src, + &QObject::destroyed, + obj, + [&]() { + std::thread::id calling_thread = std::this_thread::get_id(); + if (waiting_thread == calling_thread) + { + skip_wait = true; + traits::assign(ret, traits::call(fun)); + } + else + { + lock_guard guard(mtx); + traits::assign(ret, traits::call(fun)); + cvar.notify_one(); + } + }, + Qt::AutoConnection); + } + + if (!skip_wait) + cvar.wait(guard); + return traits::pass(std::move(ret)); +} diff --git a/compat/win32-com.cpp b/compat/win32-com.cpp new file mode 100644 index 00000000..dd7c24a8 --- /dev/null +++ b/compat/win32-com.cpp @@ -0,0 +1,60 @@ +#ifdef _WIN32 + +#include "win32-com.hpp" + +#include <QString> +#include <QThread> +#include <QDebug> + +bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t) +{ + static thread_local com_type initialized = com_type(-1); + + if (initialized != com_type(-1)) + { + if (t != initialized) + { + QString tp("invalid type"); + switch (t) + { + case com_apartment: + tp = "apartment threaded"; + break; + case com_multithreaded: + tp = "multithreaded"; + break; + } + + qDebug() << "COM for thread" + << QThread::currentThread() << QThread::currentThreadId() + << "already initialized to" << tp; + + return false; + } + + return true; + } + + HRESULT ret = CoInitializeEx(0, t); + + if (ret != S_OK && ret != S_FALSE) + { + qDebug() << "CoInitializeEx failed:" << ret << GetLastError(); + return false; + } + + if (t == com_apartment) + { + ret = OleInitialize(nullptr); + + if (ret != S_OK && ret != S_FALSE) + qDebug() << "OleInitialize() failed:" << ret << GetLastError(); + + return false; + } + + initialized = t; + + return true; +} +#endif diff --git a/compat/win32-com.hpp b/compat/win32-com.hpp new file mode 100644 index 00000000..dcbea089 --- /dev/null +++ b/compat/win32-com.hpp @@ -0,0 +1,18 @@ +#pragma once + +#ifdef _WIN32 + +#include "export.hpp" + +#include <objbase.h> +#include <ole2.h> + +enum com_type : int +{ + com_multithreaded = COINIT_MULTITHREADED, + com_apartment = COINIT_APARTMENTTHREADED, +}; + +bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t = com_multithreaded); + +#endif diff --git a/cv/camera-dialog.hpp b/cv/camera-dialog.hpp index 3fd853c3..c5896ca3 100644 --- a/cv/camera-dialog.hpp +++ b/cv/camera-dialog.hpp @@ -8,9 +8,9 @@ #pragma once -#include "opentrack-compat/camera-names.hpp" -#include "opentrack-compat/sleep.hpp" -#include "opentrack-compat/win32-com.hpp" +#include "compat/camera-names.hpp" +#include "compat/sleep.hpp" +#include "compat/win32-com.hpp" #ifdef __linux # include <QProcess> diff --git a/cv/camera-dialog.hpp.OO4364 b/cv/camera-dialog.hpp.OO4364 index e99b5f6e..6f4c7966 100644 --- a/cv/camera-dialog.hpp.OO4364 +++ b/cv/camera-dialog.hpp.OO4364 @@ -9,8 +9,8 @@ #pragma once #include "export.hpp" -#include "opentrack-compat/camera-names.hpp" -#include "opentrack-compat/sleep.hpp" +#include "compat/camera-names.hpp" +#include "compat/sleep.hpp" #ifdef __linux # include <QProcess> diff --git a/cv/video-widget.cpp b/cv/video-widget.cpp index b514dc8f..bc143378 100644 --- a/cv/video-widget.cpp +++ b/cv/video-widget.cpp @@ -9,7 +9,7 @@ #include "video-widget.hpp" #include <opencv2/imgproc.hpp> -#include "opentrack/is-window-visible.hpp" +#include "api/is-window-visible.hpp" cv_video_widget::cv_video_widget(QWidget* parent) : QWidget(parent), diff --git a/cv/video-widget.hpp b/cv/video-widget.hpp index 2d5d673f..46332afe 100644 --- a/cv/video-widget.hpp +++ b/cv/video-widget.hpp @@ -8,7 +8,7 @@ #pragma once -#include "opentrack-compat/timer.hpp" +#include "compat/timer.hpp" #include <opencv2/core/core.hpp> #include <memory> #include <QObject> diff --git a/dinput/CMakeLists.txt b/dinput/CMakeLists.txt new file mode 100644 index 00000000..ed0b5990 --- /dev/null +++ b/dinput/CMakeLists.txt @@ -0,0 +1,4 @@ +if(WIN32) + opentrack_boilerplate(opentrack-dinput BIN) + target_link_libraries(opentrack-dinput dinput) +endif() diff --git a/dinput/dinput.cpp b/dinput/dinput.cpp new file mode 100644 index 00000000..d408ff2f --- /dev/null +++ b/dinput/dinput.cpp @@ -0,0 +1,98 @@ +#ifdef _WIN32 + +#include "dinput.hpp" +#include "compat/win32-com.hpp" +#include <QDebug> + +std::atomic<int> dinput_handle::refcnt; +std::atomic_flag dinput_handle::init_lock = ATOMIC_FLAG_INIT; +dinput_handle::di_t dinput_handle::handle(dinput_handle::make_di()); + +LPDIRECTINPUT8& dinput_handle::init_di() +{ + init_com_threading(com_multithreaded); + + static LPDIRECTINPUT8 di_ = nullptr; + if (di_ == nullptr) + { + if (!SUCCEEDED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di_, NULL))) + { + di_ = nullptr; + } + } + return di_; +} + +dinput_handle::di_t dinput_handle::make_di() +{ + while (init_lock.test_and_set()) { /* busy loop */ } + + LPDIRECTINPUT8& ret = init_di(); + + init_lock.clear(); + + return di_t(ret); +} + +void dinput_handle::di_t::free_di() +{ + if (handle && *handle) + (*handle)->Release(); + *handle = nullptr; + handle = nullptr; +} + +void dinput_handle::di_t::ref_di() +{ + while (init_lock.test_and_set()) { /* busy loop */ } + + const int refcnt_ = refcnt.fetch_add(1) + 1; + qDebug() << "start: dinput refcount now" << (refcnt_); + + init_lock.clear(); +} + +dinput_handle::di_t& dinput_handle::di_t::operator=(const di_t& new_di) +{ + if (handle) + unref_di(); + + handle = new_di.handle; + + if (handle) + ref_di(); + + return *this; +} + +void dinput_handle::di_t::unref_di() +{ + while (init_lock.test_and_set()) { /* busy loop */ } + + const int refcnt_ = refcnt.fetch_sub(1) - 1; + + qDebug() << "exit: dinput refcount now" << refcnt_; + + if (refcnt_ == 0) + { + qDebug() << "exit: deleting di handle"; + free_di(); + } + + init_lock.clear(); +} + +dinput_handle::di_t::di_t(LPDIRECTINPUT8& handle) : handle(&handle) +{ + ref_di(); +} + +dinput_handle::di_t::di_t() : handle(nullptr) {} + +dinput_handle::di_t::~di_t() +{ + if (handle) + unref_di(); +} + +#endif diff --git a/dinput/dinput.hpp b/dinput/dinput.hpp new file mode 100644 index 00000000..53f1c4af --- /dev/null +++ b/dinput/dinput.hpp @@ -0,0 +1,58 @@ +/* Copyright (c) 2016, 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 + +#ifdef _WIN32 + +#include "export.hpp" + +#ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +#endif +#include <dinput.h> + +#include <atomic> + +class OPENTRACK_DINPUT_EXPORT dinput_handle final +{ +public: + class di_t; + +private: + static std::atomic<int> refcnt; + static std::atomic_flag init_lock; + static di_t handle; + + static LPDIRECTINPUT8& init_di(); +public: + class di_t final + { + friend class dinput_handle; + + LPDIRECTINPUT8* handle; + + di_t(LPDIRECTINPUT8& handle); + void free_di(); + void unref_di(); + void ref_di(); + + public: + LPDIRECTINPUT8 operator->() { return *handle; } + operator LPDIRECTINPUT8() { return *handle; } + LPDIRECTINPUT8 di() { return *handle; } + di_t& operator=(const di_t& new_di); + di_t(); + ~di_t(); + }; + + static di_t make_di(); + dinput_handle() = delete; +}; + +#endif diff --git a/dinput/export.hpp b/dinput/export.hpp new file mode 100644 index 00000000..51ee4531 --- /dev/null +++ b/dinput/export.hpp @@ -0,0 +1,28 @@ +#pragma once + +#ifdef BUILD_dinput +# ifdef _WIN32 +# define OPENTRACK_DINPUT_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_DINPUT_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_DINPUT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_DINPUT_LINKAGE +# else +# define OPENTRACK_DINPUT_EXPORT OPENTRACK_DINPUT_LINKAGE +# endif + +#else +#ifdef _WIN32 +# define OPENTRACK_DINPUT_LINKAGE __declspec(dllimport) +#else +# define OPENTRACK_DINPUT_LINKAGE +#endif + +#ifndef _MSC_VER +# define OPENTRACK_DINPUT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_DINPUT_LINKAGE +#else +# define OPENTRACK_DINPUT_EXPORT OPENTRACK_DINPUT_LINKAGE +#endif +#endif diff --git a/dinput/keybinding-worker.cpp b/dinput/keybinding-worker.cpp new file mode 100644 index 00000000..32bfc6f0 --- /dev/null +++ b/dinput/keybinding-worker.cpp @@ -0,0 +1,201 @@ +/* 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. + */ + +#ifdef _WIN32 + +#include "keybinding-worker.hpp" +#include <functional> +#include <windows.h> +#include <QDebug> +#include <QMutexLocker> + +bool Key::should_process() +{ + if (!enabled || (keycode == 0 && guid == "")) + return false; + bool ret = timer.elapsed_ms() > 100; + timer.start(); + return ret; +} + +KeybindingWorker::~KeybindingWorker() +{ + qDebug() << "exit: destroying keybinding worker"; + + should_quit = true; + wait(); + if (dinkeyboard) { + dinkeyboard->Unacquire(); + dinkeyboard->Release(); + } +} + +void KeybindingWorker::init() +{ + din = dinput_handle::make_di(); + + if (!din) + { + qDebug() << "can't create dinput handle"; + return; + } + + if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { + qDebug() << "setup CreateDevice function failed!" << GetLastError(); + return; + } + + if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { + qDebug() << "setup SetDataFormat function failed!" << GetLastError(); + dinkeyboard->Release(); + dinkeyboard = 0; + return; + } + + if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + dinkeyboard->Release(); + dinkeyboard = 0; + qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); + return; + } + + if (dinkeyboard->Acquire() != DI_OK) + { + dinkeyboard->Release(); + dinkeyboard = 0; + qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); + return; + } +} + +KeybindingWorker::KeybindingWorker() : should_quit(false) +{ + start(); +} + +KeybindingWorker& KeybindingWorker::make() +{ + static KeybindingWorker k; + return k; +} + +void KeybindingWorker::run() +{ + init(); + + BYTE keystate[256] = {0}; + BYTE old_keystate[256] = {0}; + + while (!should_quit) + { + { + QMutexLocker l(&mtx); + + if (receivers.size()) + { + { + const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); + + if (hr != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + } + + { + using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; + + joy_fn f = [&](const QString& guid, int idx, bool held) -> void { + Key k; + k.keycode = idx; + k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); + k.guid = guid; + k.held = held; + + for (auto& r : receivers) + r->operator()(k); + }; + + joy_ctx.poll(f); + } + + for (int i = 0; i < 256; i++) + { + Key k; + if (old_keystate[i] != keystate[i]) + { + const bool held = keystate[i] & 0x80; + switch (i) + { + case DIK_LCONTROL: + case DIK_LSHIFT: + case DIK_LALT: + case DIK_RCONTROL: + case DIK_RSHIFT: + case DIK_RALT: + break; + default: + k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); + k.keycode = i; + k.held = held; + + for (auto& r : receivers) + r->operator()(k); + break; + } + } + old_keystate[i] = keystate[i]; + } + } + } + + // keypresses get dropped with high values + Sleep(4); + } +} + +KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) +{ + QMutexLocker l(&mtx); + receivers.push_back(std::unique_ptr<fun>(new fun(receiver))); + fun* f = receivers[receivers.size() - 1].get(); + //qDebug() << "add receiver" << (long) f; + joy_ctx.refresh(); + return f; +} + +void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) +{ + QMutexLocker l(&mtx); + bool ok = false; + + using s = int; + + for (int i = s(receivers.size()) - 1; i >= 0; i--) + { + using u = unsigned; + if (receivers[u(i)].get() == pos) + { + ok = true; + //qDebug() << "remove receiver" << (long) pos; + receivers.erase(receivers.begin() + i); + break; + } + } + if (!ok) + { + qDebug() << "bad remove receiver" << (long) pos; + } +} + +#endif diff --git a/dinput/keybinding-worker.hpp b/dinput/keybinding-worker.hpp new file mode 100644 index 00000000..39b850e0 --- /dev/null +++ b/dinput/keybinding-worker.hpp @@ -0,0 +1,80 @@ +/* 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 "export.hpp" + +#include "compat/timer.hpp" +#include "win32-joystick.hpp" +#include "dinput.hpp" +#include <QThread> +#include <QMutex> +#include <QWidget> +#include <QMainWindow> +#include <QDebug> +#include <functional> +#include <vector> + +struct OPENTRACK_DINPUT_EXPORT Key +{ + BYTE keycode; + QString guid; + bool shift; + bool ctrl; + bool alt; + bool held; + bool enabled; + Timer timer; +public: + Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true), enabled(true) {} + + bool should_process(); +}; + +struct OPENTRACK_DINPUT_EXPORT KeybindingWorker : private QThread +{ + using fun = std::function<void(const Key&)>; + +private: + LPDIRECTINPUTDEVICE8 dinkeyboard; + win32_joy_ctx joy_ctx; + std::vector<std::unique_ptr<fun>> receivers; + QMutex mtx; + QMainWindow fake_main_window; + dinput_handle::di_t din; + volatile bool should_quit; + + void run() override; + void init(); + KeybindingWorker(); + + static KeybindingWorker& make(); + fun* _add_receiver(fun &receiver); + void remove_receiver(fun* pos); + ~KeybindingWorker(); + + KeybindingWorker(const KeybindingWorker&) = delete; + KeybindingWorker& operator=(KeybindingWorker&) = delete; +public: + class Token + { + fun* pos; + Token(const Token&) = delete; + Token& operator=(Token&) = delete; + public: + ~Token() + { + make().remove_receiver(pos); + } + Token(fun receiver) + { + pos = make()._add_receiver(receiver); + } + }; +}; diff --git a/dinput/win32-joystick.cpp b/dinput/win32-joystick.cpp new file mode 100644 index 00000000..9502bcd2 --- /dev/null +++ b/dinput/win32-joystick.cpp @@ -0,0 +1,359 @@ +#ifdef _WIN32 + +#undef NDEBUG +#include "win32-joystick.hpp" +#include "compat/sleep.hpp" +#include <cassert> +#include <cstring> +#include <algorithm> +#include <cmath> +#include <objbase.h> + +#include <QDebug> + +QMutex win32_joy_ctx::enum_state::mtx; +win32_joy_ctx::enum_state win32_joy_ctx::enumerator; + +void win32_joy_ctx::poll(fn f) +{ + //refresh(false); + + QMutexLocker l(&enumerator.mtx); + + auto& joys = enumerator.get_joys(); + + for (auto& j : joys) + { + j.second->poll(f); + } +} + +bool win32_joy_ctx::poll_axis(const QString &guid, int* axes) +{ + QMutexLocker l(&enumerator.mtx); + + for (int k = 0; k < 10; k++) + { + if (k > 0) + enumerator.refresh(); + + const joys_t& joys = enumerator.get_joys(); + auto iter = joys.find(guid); + + if (iter == joys.end()) + return false; + + auto& j = iter->second; + + auto& joy_handle = j->joy_handle; + bool ok = false; + HRESULT hr; + + if (!FAILED(hr = joy_handle->Poll())) + { + ok = true; + } + + if (!ok && FAILED(hr = joy_handle->Acquire())) + { + //qDebug() << "joy acquire failed" << hr; + } + + if (!ok) + { + portable::sleep(25); + (void) joy_handle->Unacquire(); + continue; + } + + DIJOYSTATE2 js; + std::memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + //qDebug() << "joy get state failed" << guid << hr; + portable::sleep(50); + continue; + } + + const int values[] = + { + js.lX, + js.lY, + js.lZ, + js.lRx, + js.lRy, + js.lRz, + js.rglSlider[0], + js.rglSlider[1] + }; + + for (int i = 0; i < 8; i++) + axes[i] = values[i]; + + return true; + } + + return false; +} + +std::vector<win32_joy_ctx::joy_info> win32_joy_ctx::get_joy_info() +{ + std::vector<joy_info> ret; + QMutexLocker l(&enumerator.mtx); + auto& joys = enumerator.get_joys(); + ret.reserve(joys.size()); + + for (auto& j : joys) + ret.push_back(joy_info { j.second->name, j.first }); + + std::sort(ret.begin(), ret.end(), [&](const joy_info& fst, const joy_info& snd) -> bool { return fst.name < snd.name; }); + + return ret; +} + +win32_joy_ctx::win32_joy_ctx() +{ + refresh(); +} + +void win32_joy_ctx::refresh() +{ + QMutexLocker l(&enumerator.mtx); + enumerator.refresh(); +} + +QString win32_joy_ctx::guid_to_string(const GUID& guid) +{ + char buf[40] = {0}; + wchar_t szGuidW[40] = {0}; + + StringFromGUID2(guid, szGuidW, 40); + WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); + + return QString(buf); +} + +using fn = win32_joy_ctx::fn; + +void win32_joy_ctx::joy::release() +{ + if (joy_handle) + { + (void) joy_handle->Unacquire(); + joy_handle->Release(); + joy_handle = nullptr; + } +} + +bool win32_joy_ctx::joy::poll(fn f) +{ + HRESULT hr; + bool ok = false; + + (void) joy_handle->Acquire(); + + if (!FAILED(hr = joy_handle->Poll())) + ok = true; + + if (!ok) + { + qDebug() << "joy acquire failed" << guid << hr; + (void) joy_handle->Unacquire(); + return false; + } + + DIJOYSTATE2 js; + std::memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + for (unsigned i = 0; i < 4; i++) + { + using std::round; + + unsigned char pos; + unsigned pos_ = js.rgdwPOV[i]; + if ((pos_ & 0xffff) == 0xffff) + pos = 0; + else if (pos_ == ~0u) + pos = 0; + else + { + using uc = unsigned char; + pos = uc(((pos_ / 9000u) % 4u) + 1u); + } + + const bool state[] = + { + pos == 1, + pos == 2, + pos == 3, + pos == 4 + }; + + unsigned idx = 128u + i * 4u; + + for (unsigned j = 0; j < 4; j++, idx++) + { + if (state[j] != pressed[idx]) + { + f(guid, int(idx), state[j]); + pressed[idx] = state[j]; + } + } + } + + for (int i = 0; i < 128; i++) + { + const bool state = !!(js.rgbButtons[i] & 0x80); + if (state != pressed[i]) + { + f(guid, i, state); + } + pressed[i] = state; + } + + return true; +} + +win32_joy_ctx::enum_state::enum_state() : di(dinput_handle::make_di()) +{ +} + +win32_joy_ctx::enum_state::~enum_state() +{ + QMutexLocker l(&mtx); + + joys = std::unordered_map<QString, std::shared_ptr<joy>>(); +} + +void win32_joy_ctx::enum_state::refresh() +{ + all.clear(); + + if (!di) + { + qDebug() << "can't create dinput"; + return; + } + + HRESULT hr; + + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "failed enum joysticks" << hr; + return; + } + + for (auto it = joys.begin(); it != joys.end(); ) + { + if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.end()) + { + it = joys.erase(it); + } + else + { + ++it; + } + } +} + +const win32_joy_ctx::joys_t& win32_joy_ctx::enum_state::get_joys() const { return joys; } + +BOOL CALLBACK win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) +{ + enum_state& state = *reinterpret_cast<enum_state*>(pContext); + const QString guid = guid_to_string(pdidInstance->guidInstance); + const QString name = QString(pdidInstance->tszInstanceName); + + const bool exists = state.joys.find(guid) != state.joys.end(); + + state.all.push_back(guid); + + if (exists) + goto end; + + { + HRESULT hr; + LPDIRECTINPUTDEVICE8 h; + if (FAILED(hr = state.di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + { + qDebug() << "createdevice" << guid << hr; + goto end; + } + if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) + { + qDebug() << "format"; + h->Release(); + goto end; + } + + // not a static member - need main() to run for some time first + static const QWidget fake_window; + + if (FAILED(h->SetCooperativeLevel(reinterpret_cast<HWND>(fake_window.winId()), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + { + qDebug() << "coop"; + h->Release(); + goto end; + } + if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) + { + qDebug() << "enum-objects"; + h->Release(); + goto end; + } + + state.joys[guid] = std::make_shared<joy>(h, guid, name); + } +end: + return DIENUM_CONTINUE; +} + +BOOL CALLBACK win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx) +{ + if (pdidoi->dwType & DIDFT_AXIS) + { + DIPROPRANGE diprg; + std::memset(&diprg, 0, sizeof(diprg)); + diprg.diph.dwSize = sizeof( DIPROPRANGE ); + diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; + diprg.lMax = joy_axis_size; + diprg.lMin = -joy_axis_size; + + HRESULT hr; + + if (FAILED(hr = reinterpret_cast<LPDIRECTINPUTDEVICE8>(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) + { + qDebug() << "DIPROP_RANGE" << hr; + return DIENUM_STOP; + } + } + + return DIENUM_CONTINUE; +} + +win32_joy_ctx::joy::joy(LPDIRECTINPUTDEVICE8 handle, const QString &guid, const QString &name) + : joy_handle(handle), guid(guid), name(name) +{ + qDebug() << "make joy" << guid << name << joy_handle; + std::memset(pressed, 0, sizeof(pressed)); +} + +win32_joy_ctx::joy::~joy() +{ + qDebug() << "nix joy" << guid; + release(); +} + +#endif diff --git a/dinput/win32-joystick.hpp b/dinput/win32-joystick.hpp new file mode 100644 index 00000000..4b48d4a1 --- /dev/null +++ b/dinput/win32-joystick.hpp @@ -0,0 +1,101 @@ +/* Copyright (c) 2015-2016, 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 + +#ifdef _WIN32 + +#include "dinput.hpp" +#include "compat/timer.hpp" +#include "export.hpp" +#include <cstring> +#include <memory> +#include <vector> +#include <functional> +#include <algorithm> +#include <unordered_map> +#include <QString> +#include <QDebug> +#include <QMutex> +#include <QMutexLocker> +#include <QWidget> + +namespace std { +template<> +struct hash<QString> +{ + inline std::size_t operator()(const QString& value) const + { + return qHash(value); + } +}; +} + +struct OPENTRACK_DINPUT_EXPORT win32_joy_ctx +{ + using fn = std::function<void(const QString& guid, int btn, bool held)>; + + struct joy + { + LPDIRECTINPUTDEVICE8 joy_handle; + QString guid, name; + bool pressed[128 + 4 * 4]; + Timer first_timer; + + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name); + ~joy(); + + void release(); + bool poll(fn f); + }; + + using joys_t = std::unordered_map<QString, std::shared_ptr<joy>>; + + static constexpr int joy_axis_size = 65535; + + struct joy_info + { + QString name, guid; + }; + + void poll(fn f); + bool poll_axis(const QString& guid, int* axes); + std::vector<joy_info> get_joy_info(); + + win32_joy_ctx(const win32_joy_ctx&) = delete; + win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; + + win32_joy_ctx(); + void refresh(); + + using di_t = dinput_handle::di_t; + +private: + static QString guid_to_string(const GUID& guid); + + class OPENTRACK_DINPUT_EXPORT enum_state final + { + std::vector<QString> all; + joys_t joys; + dinput_handle::di_t di; + + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); + static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); + + public: + static QMutex mtx; + + enum_state(); + ~enum_state(); + void refresh(); + const joys_t& get_joys() const; + }; + + static enum_state enumerator; +}; + +#endif diff --git a/filter-accela/ftnoir_filter_accela.cpp b/filter-accela/ftnoir_filter_accela.cpp index f05b8f41..526b2da6 100644 --- a/filter-accela/ftnoir_filter_accela.cpp +++ b/filter-accela/ftnoir_filter_accela.cpp @@ -9,7 +9,7 @@ #include <cmath> #include <QDebug> #include <QMutexLocker> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" static constexpr double rot_gains[][2] = { { 6, 200 }, diff --git a/filter-accela/ftnoir_filter_accela.h b/filter-accela/ftnoir_filter_accela.h index eb1a30a4..828b78a0 100644 --- a/filter-accela/ftnoir_filter_accela.h +++ b/filter-accela/ftnoir_filter_accela.h @@ -6,15 +6,15 @@ */ #pragma once #include "ui_ftnoir_accela_filtercontrols.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "spline-widget/spline.hpp" #include <atomic> #include <QMutex> #include <QTimer> -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; -#include "opentrack-compat/timer.hpp" +#include "compat/timer.hpp" struct settings_accela : opts { diff --git a/filter-accela/ftnoir_filter_accela_dialog.cpp b/filter-accela/ftnoir_filter_accela_dialog.cpp index 7d257711..83114b20 100644 --- a/filter-accela/ftnoir_filter_accela_dialog.cpp +++ b/filter-accela/ftnoir_filter_accela_dialog.cpp @@ -9,7 +9,7 @@ #include <QDebug> #include <algorithm> #include <QDoubleSpinBox> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "spline-widget/spline-widget.hpp" #include <QDialog> diff --git a/filter-ewma2/ftnoir_filter_ewma2.cpp b/filter-ewma2/ftnoir_filter_ewma2.cpp index 7229c6d6..beceb4c2 100644 --- a/filter-ewma2/ftnoir_filter_ewma2.cpp +++ b/filter-ewma2/ftnoir_filter_ewma2.cpp @@ -8,7 +8,7 @@ #include <cmath> #include <QDebug> #include <QWidget> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <algorithm> #include <QMutexLocker> diff --git a/filter-ewma2/ftnoir_filter_ewma2.h b/filter-ewma2/ftnoir_filter_ewma2.h index 589b7910..e7fdd49e 100644 --- a/filter-ewma2/ftnoir_filter_ewma2.h +++ b/filter-ewma2/ftnoir_filter_ewma2.h @@ -1,11 +1,11 @@ #pragma once -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ui_ftnoir_ewma_filtercontrols.h" #include <QWidget> #include <QMutex> -#include "opentrack-compat/options.hpp" -#include "opentrack-compat/timer.hpp" +#include "compat/options.hpp" +#include "compat/timer.hpp" using namespace options; struct settings : opts { diff --git a/filter-ewma2/ftnoir_filter_ewma2_dialog.cpp b/filter-ewma2/ftnoir_filter_ewma2_dialog.cpp index 8e69573e..79fcd959 100644 --- a/filter-ewma2/ftnoir_filter_ewma2_dialog.cpp +++ b/filter-ewma2/ftnoir_filter_ewma2_dialog.cpp @@ -2,7 +2,7 @@ #include <cmath> #include <QDebug> #include <QString> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ui_ftnoir_ewma_filtercontrols.h" FilterControls::FilterControls() diff --git a/filter-kalman/kalman.h b/filter-kalman/kalman.h index aaed3bc1..d28557c6 100644 --- a/filter-kalman/kalman.h +++ b/filter-kalman/kalman.h @@ -7,10 +7,10 @@ */ #include "ui_ftnoir_kalman_filtercontrols.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" using namespace options; -#include "opentrack-compat/timer.hpp" +#include "compat/timer.hpp" #include <Eigen/Core> #include <Eigen/LU> diff --git a/gui/keyboard.h b/gui/keyboard.h index 27300690..d35fe675 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -1,8 +1,8 @@ #pragma once #include "ui_keyboard_listener.h" #ifdef _WIN32 -#include "opentrack-logic/win32-shortcuts.h" -#include "opentrack-dinput/keybinding-worker.hpp" +#include "logic/win32-shortcuts.h" +#include "dinput/keybinding-worker.hpp" #endif #include <QLabel> #include <QKeyEvent> diff --git a/gui/main-window.cpp b/gui/main-window.cpp index 667c3032..70652201 100644 --- a/gui/main-window.cpp +++ b/gui/main-window.cpp @@ -7,8 +7,8 @@ */ #include "main-window.hpp" -#include "opentrack-logic/tracker.h" -#include "opentrack-compat/options.hpp" +#include "logic/tracker.h" +#include "compat/options.hpp" #include "opentrack-library-path.h" #include "new_file_dialog.h" #include <QFile> diff --git a/gui/main-window.hpp b/gui/main-window.hpp index b068d158..e05ee9cc 100644 --- a/gui/main-window.hpp +++ b/gui/main-window.hpp @@ -8,16 +8,16 @@ #pragma once -#include "opentrack/plugin-support.hpp" +#include "api/plugin-support.hpp" #include "mapping-window.hpp" #include "options-dialog.hpp" #include "process_detector.h" -#include "opentrack-logic/main-settings.hpp" -#include "opentrack-logic/tracker.h" -#include "opentrack-logic/shortcuts.h" -#include "opentrack-logic/work.hpp" -#include "opentrack-logic/state.hpp" -#include "opentrack-compat/options.hpp" +#include "logic/main-settings.hpp" +#include "logic/tracker.h" +#include "logic/shortcuts.h" +#include "logic/work.hpp" +#include "logic/state.hpp" +#include "compat/options.hpp" #include <QMainWindow> #include <QKeySequence> diff --git a/gui/main.cpp b/gui/main.cpp index a9252c4d..43fd4539 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -9,8 +9,8 @@ #endif #include "main-window.hpp" -#include "opentrack-compat/options.hpp" -#include "opentrack-compat/win32-com.hpp" +#include "compat/options.hpp" +#include "compat/win32-com.hpp" using namespace options; #include <QApplication> #include <QCommandLineParser> diff --git a/gui/mapping-window.cpp b/gui/mapping-window.cpp index 108e1354..12b36e2a 100644 --- a/gui/mapping-window.cpp +++ b/gui/mapping-window.cpp @@ -7,7 +7,7 @@ */ #include "mapping-window.hpp" -#include "opentrack-logic/main-settings.hpp" +#include "logic/main-settings.hpp" #include "spline-widget/spline-widget.hpp" MapWidget::MapWidget(Mappings& m) : m(m) diff --git a/gui/mapping-window.hpp b/gui/mapping-window.hpp index e70a27c6..aeaed211 100644 --- a/gui/mapping-window.hpp +++ b/gui/mapping-window.hpp @@ -1,6 +1,6 @@ #pragma once #include <QWidget> -#include "opentrack-logic/mappings.hpp" +#include "logic/mappings.hpp" #include "ui_mapping-window.h" class MapWidget final : public QWidget diff --git a/gui/new_file_dialog.h b/gui/new_file_dialog.h index 5fdabb3a..8cb971c3 100644 --- a/gui/new_file_dialog.h +++ b/gui/new_file_dialog.h @@ -1,7 +1,7 @@ #pragma once #include "ui_new_config.h" -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" #include <QFile> #include <QRegExp> #include <QString> diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 1e8faa1c..6854107e 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -1,7 +1,7 @@ #pragma once #include "ui_options-dialog.h" -#include "opentrack-logic/shortcuts.h" +#include "logic/shortcuts.h" #include <QObject> #include <QWidget> #include <functional> diff --git a/gui/process_detector.cpp b/gui/process_detector.cpp index 9c12f783..7df8e980 100644 --- a/gui/process_detector.cpp +++ b/gui/process_detector.cpp @@ -8,7 +8,7 @@ #include "process_detector.h" #include "main-window.hpp" -#include "opentrack-compat/process-list.hpp" +#include "compat/process-list.hpp" #include <QList> #include <QFileDialog> #include <QComboBox> diff --git a/gui/process_detector.h b/gui/process_detector.h index e395e1a2..e081fa27 100644 --- a/gui/process_detector.h +++ b/gui/process_detector.h @@ -13,7 +13,7 @@ #include <QTableWidget> #include <QResizeEvent> -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; class FancyTable : public QTableWidget @@ -47,10 +47,10 @@ struct settings class process_detector : public QWidget { Q_OBJECT - + Ui_Dialog ui; settings s; - + int add_row(QString exe_name = "...", QString profile = ""); void add_items(); public: diff --git a/logic/CMakeLists.txt b/logic/CMakeLists.txt new file mode 100644 index 00000000..88b0240f --- /dev/null +++ b/logic/CMakeLists.txt @@ -0,0 +1,7 @@ +opentrack_boilerplate(opentrack-logic BIN) +target_link_libraries(opentrack-logic opentrack-spline-widget) +if(NOT WIN32) + target_link_libraries(opentrack-logic opentrack-qxt-mini) +else() + target_link_libraries(opentrack-logic opentrack-dinput winmm) +endif() diff --git a/logic/export.hpp b/logic/export.hpp new file mode 100644 index 00000000..2503f3a6 --- /dev/null +++ b/logic/export.hpp @@ -0,0 +1,28 @@ +#pragma once + +#ifdef BUILD_logic +# ifdef _WIN32 +# define OPENTRACK_LOGIC_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_LOGIC_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_LOGIC_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LOGIC_LINKAGE +# else +# define OPENTRACK_LOGIC_EXPORT OPENTRACK_LOGIC_LINKAGE +# endif + +#else +#ifdef _WIN32 +# define OPENTRACK_LOGIC_LINKAGE __declspec(dllimport) +#else +# define OPENTRACK_LOGIC_LINKAGE +#endif + +#ifndef _MSC_VER +# define OPENTRACK_LOGIC_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LOGIC_LINKAGE +#else +# define OPENTRACK_LOGIC_EXPORT OPENTRACK_LOGIC_LINKAGE +#endif +#endif diff --git a/logic/main-settings.hpp b/logic/main-settings.hpp new file mode 100644 index 00000000..26313a26 --- /dev/null +++ b/logic/main-settings.hpp @@ -0,0 +1,109 @@ +/* Copyright (c) 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 <QString> +#include "compat/options.hpp" +#include "api/plugin-api.hpp" + +using namespace options; + +#include "export.hpp" + +struct axis_opts +{ + pbundle b; + value<double> zero; + value<bool> invert, altp; + value<int> src; + axis_opts(pbundle b, QString pfx, int idx) : + b(b), + zero(b, n(pfx, "zero-pos"), 0), + invert(b, n(pfx, "invert-sign"), false), + altp(b, n(pfx, "alt-axis-sign"), false), + src(b, n(pfx, "source-index"), idx) + {} +private: + static inline QString n(QString pfx, QString name) { + return QString("%1-%2").arg(pfx, name); + } +}; + +struct key_opts +{ + value<QString> keycode, guid; + value<int> button; + + key_opts(pbundle b, const QString& name) : + keycode(b, QString("keycode-%1").arg(name), ""), + guid(b, QString("guid-%1").arg(name), ""), + button(b, QString("button-%1").arg(name), -1) + {} +}; + +struct module_settings +{ + pbundle b; + value<QString> tracker_dll, filter_dll, protocol_dll; + module_settings() : + b(bundle("modules")), + tracker_dll(b, "tracker-dll", ""), + filter_dll(b, "filter-dll", "Accela"), + protocol_dll(b, "protocol-dll", "freetrack 2.0 Enhanced") + { + } +}; + +struct main_settings +{ + pbundle b, b_map; + axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll; + value<bool> tcomp_p, tcomp_tz; + value<bool> tray_enabled; + value<int> camera_yaw, camera_pitch, camera_roll; + value<bool> use_camera_offset_from_centering; + value<bool> center_at_startup; + value<int> center_method; + key_opts key_start_tracking, key_stop_tracking, key_toggle_tracking, key_restart_tracking; + key_opts key_center, key_toggle, key_zero; + key_opts key_toggle_press, key_zero_press; + value<bool> tracklogging_enabled; + value<QString> tracklogging_filename; + main_settings() : + b(bundle("opentrack-ui")), + b_map(bundle("opentrack-mappings")), + a_x(b_map, "x", TX), + a_y(b_map, "y", TY), + a_z(b_map, "z", TZ), + a_yaw(b_map, "yaw", Yaw), + a_pitch(b_map, "pitch", Pitch), + a_roll(b_map, "roll", Roll), + tcomp_p(b, "compensate-translation", true), + tcomp_tz(b, "compensate-translation-disable-z-axis", false), + tray_enabled(b, "use-system-tray", false), + camera_yaw(b, "camera-yaw", 0), + camera_pitch(b, "camera-pitch", 0), + camera_roll(b, "camera-roll", 0), + use_camera_offset_from_centering(b, "use-camera-offset-from-centering", false), + center_at_startup(b, "center-at-startup", true), + center_method(b, "centering-method", true), + key_start_tracking(b, "start-tracking"), + key_stop_tracking(b, "stop-tracking"), + key_toggle_tracking(b, "toggle-tracking"), + key_restart_tracking(b, "restart-tracking"), + key_center(b, "center"), + key_toggle(b, "toggle"), + key_zero(b, "zero"), + key_toggle_press(b, "toggle-press"), + key_zero_press(b, "zero-press"), + tracklogging_enabled(b, "tracklogging-enabled", false), + tracklogging_filename(b, "tracklogging-filename", QString()) + { + } +}; diff --git a/logic/mappings.hpp b/logic/mappings.hpp new file mode 100644 index 00000000..0b9373c0 --- /dev/null +++ b/logic/mappings.hpp @@ -0,0 +1,89 @@ +/* Copyright (c) 2014-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 <QSettings> +#include "compat/options.hpp" +using namespace options; +#include "spline-widget/spline.hpp" +#include "main-settings.hpp" + +class Map { +public: + Map(QString primary, + QString secondary, + int max_x, + int max_y, + axis_opts& opts) : + spline_main(max_x, max_y), + spline_alt(max_x, max_y), + opts(opts), + name1(primary), + name2(secondary) + { + mem<QSettings> iniFile = group::ini_file(); + spline_main.loadSettings(*iniFile, primary); + spline_alt.loadSettings(*iniFile, secondary); + } + spline spline_main; + spline spline_alt; + axis_opts& opts; + QString name1, name2; +}; + +class Mappings { +private: + Map axes[6]; +public: + Mappings(std::vector<axis_opts*> opts) : + axes { + Map("tx","tx_alt", 30, 75, *opts[TX]), + Map("ty","ty_alt", 30, 75, *opts[TY]), + Map("tz","tz_alt", 30, 75, *opts[TZ]), + Map("rx", "rx_alt", 180, 180, *opts[Yaw]), + Map("ry", "ry_alt", 180, 180, *opts[Pitch]), + Map("rz", "rz_alt", 180, 180, *opts[Roll]) + } + {} + + inline Map& operator()(int i) { return axes[i]; } + inline const Map& operator()(int i) const { return axes[i]; } + + void load_mappings() + { + mem<QSettings> iniFile = group::ini_file(); + + for (int i = 0; i < 6; i++) + { + axes[i].spline_main.loadSettings(*iniFile, axes[i].name1); + axes[i].spline_alt.loadSettings(*iniFile, axes[i].name2); + axes[i].opts.b->reload(); + } + } + void save_mappings() + { + mem<QSettings> iniFile = group::ini_file(); + + for (int i = 0; i < 6; i++) + { + axes[i].spline_main.saveSettings(*iniFile, axes[i].name1); + axes[i].spline_alt.saveSettings(*iniFile, axes[i].name2); + axes[i].opts.b->save(); + } + } + + void invalidate_unsaved() + { + for (int i = 0; i < 6; i++) + { + axes[i].spline_main.invalidate_unsaved_settings(); + axes[i].spline_alt.invalidate_unsaved_settings(); + axes[i].opts.b->reload(); + } + } +}; diff --git a/logic/selected-libraries.cpp b/logic/selected-libraries.cpp new file mode 100644 index 00000000..4a1a9f09 --- /dev/null +++ b/logic/selected-libraries.cpp @@ -0,0 +1,37 @@ +#include "selected-libraries.hpp" +#include <QDebug> + +SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) : + pTracker(nullptr), + pFilter(nullptr), + pProtocol(nullptr), + correct(false) +{ + pProtocol = make_dylib_instance<IProtocol>(p); + + if (!pProtocol) + { + qDebug() << "protocol dylib load failure"; + return; + } + + if(!pProtocol->correct()) + { + qDebug() << "protocol load failure"; + pProtocol = nullptr; + return; + } + + pTracker = make_dylib_instance<ITracker>(t); + pFilter = make_dylib_instance<IFilter>(f); + + if (!pTracker) + { + qDebug() << "tracker dylib load failure"; + return; + } + + pTracker->start_tracker(frame); + + correct = true; +} diff --git a/logic/selected-libraries.hpp b/logic/selected-libraries.hpp new file mode 100644 index 00000000..d782374c --- /dev/null +++ b/logic/selected-libraries.hpp @@ -0,0 +1,25 @@ +/* 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 "api/plugin-support.hpp" +#include <QFrame> + +#include "export.hpp" + +struct OPENTRACK_LOGIC_EXPORT SelectedLibraries +{ + using dylibptr = mem<dylib>; + mem<ITracker> pTracker; + mem<IFilter> pFilter; + mem<IProtocol> pProtocol; + SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f); + SelectedLibraries() : pTracker(nullptr), pFilter(nullptr), pProtocol(nullptr), correct(false) {} + bool correct; +}; diff --git a/logic/shortcuts.cpp b/logic/shortcuts.cpp new file mode 100644 index 00000000..8d818180 --- /dev/null +++ b/logic/shortcuts.cpp @@ -0,0 +1,130 @@ +/* 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. + */ + +#include "shortcuts.h" +#include "win32-shortcuts.h" + +void Shortcuts::free_binding(K& key) +{ +#ifndef _WIN32 + if (key) + { + key->setEnabled(false); + key->setShortcut(QKeySequence::UnknownKey); + std::shared_ptr<QxtGlobalShortcut> tmp(nullptr); + key.swap(tmp); + } +#else + key.keycode = 0; + key.guid = ""; +#endif +} + +void Shortcuts::bind_shortcut(K &key, const key_opts& k, unused_on_unix(bool, held)) +{ +#if !defined(_WIN32) + using sh = QxtGlobalShortcut; + if (key) + { + free_binding(key); + } + + key = std::make_shared<sh>(); + + if (k.keycode != "") + { + key->setShortcut(QKeySequence::fromString(k.keycode, QKeySequence::PortableText)); + key->setEnabled(); + } +} +#else + key = K(); + int idx = 0; + QKeySequence code; + + if (k.guid != "") + { + key.guid = k.guid; + key.keycode = k.button & ~Qt::KeyboardModifierMask; + key.ctrl = !!(k.button & Qt::ControlModifier); + key.alt = !!(k.button & Qt::AltModifier); + key.shift = !!(k.button & Qt::ShiftModifier); + } + else + { + if (k.keycode == "") + code = QKeySequence(Qt::Key_unknown); + else + code = QKeySequence::fromString(k.keycode, QKeySequence::PortableText); + + Qt::KeyboardModifiers mods = Qt::NoModifier; + if (code != Qt::Key_unknown) + win_key::from_qt(code, idx, mods); + key.shift = !!(mods & Qt::ShiftModifier); + key.alt = !!(mods & Qt::AltModifier); + key.ctrl = !!(mods & Qt::ControlModifier); + key.keycode = idx; + key.held = held; + } +} +#endif + +#ifdef _WIN32 +void Shortcuts::receiver(const Key& k) +{ + const unsigned sz = keys.size(); + for (unsigned i = 0; i < sz; i++) + { + K& k_ = std::get<0>(keys[i]); + auto& fun = std::get<1>(keys[i]); + if (k.guid != k_.guid) + continue; + if (k.keycode != k_.keycode) + continue; + if (k_.held && !k.held) continue; + if (k_.alt != k.alt) continue; + if (k_.ctrl != k.ctrl) continue; + if (k_.shift != k.shift) continue; + if (!k_.should_process()) + continue; + + fun(k.held); + } +} +#endif + +void Shortcuts::reload(const t_keys& keys_) +{ + const unsigned sz = keys_.size(); + keys = std::vector<tt>(); + + for (unsigned i = 0; i < sz; i++) + { + const auto& kk = keys_[i]; + const key_opts& opts = std::get<0>(kk); + const bool held = std::get<2>(kk); + auto fun = std::get<1>(kk); + K k; + bind_shortcut(k, opts, held); + keys.push_back(tt(k, [=](unused_on_unix(bool, flag)) -> void + { +#ifdef _WIN32 + fun(flag); +#else + fun(true); +#endif + }, + held)); +#ifndef _WIN32 + const int idx = keys.size() - 1; + tt& kk_ = keys[idx]; + auto& fn = std::get<1>(kk_); + connect(k.get(), &QxtGlobalShortcut::activated, [=]() -> void { fn(true); }); +#endif + } +} diff --git a/logic/shortcuts.h b/logic/shortcuts.h new file mode 100644 index 00000000..d5dfd394 --- /dev/null +++ b/logic/shortcuts.h @@ -0,0 +1,68 @@ +/* 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 <QObject> +#include <tuple> +#include <vector> +#include <functional> + +#include "export.hpp" + +#include "qxt-mini/QxtGlobalShortcut" +#include "compat/options.hpp" +#include "main-settings.hpp" + +#ifdef _WIN32 +# include "dinput/keybinding-worker.hpp" +#endif + +#if defined(__GNUC__) && !defined(_WIN32) +# define unused_on_unix(t, i) t __attribute__((unused)) i +#else +# define unused_on_unix(t, i) t i +#endif + +using namespace options; + +struct OPENTRACK_LOGIC_EXPORT Shortcuts : public QObject +{ + Q_OBJECT + +public: + using K = +#ifndef _WIN32 + mem<QxtGlobalShortcut> +#else + Key +#endif + ; + + using fun = std::function<void(bool)>; + using tt = std::tuple<K, fun, bool>; + using t_key = std::tuple<key_opts&, fun, bool>; + using t_keys = std::vector<t_key>; + std::vector<tt> keys; +#ifdef _WIN32 + KeybindingWorker::Token key_token; +#endif + + Shortcuts() +#ifdef _WIN32 + : key_token([&](const Key& k) { receiver(k); }) +#endif + {} + + void reload(const t_keys& keys_); +private: + void free_binding(K& key); + void bind_shortcut(K &key, const key_opts& k, bool held); +#ifdef _WIN32 + void receiver(const Key& k); +#endif +}; diff --git a/logic/simple-mat.cpp b/logic/simple-mat.cpp new file mode 100644 index 00000000..f9ed8613 --- /dev/null +++ b/logic/simple-mat.cpp @@ -0,0 +1,97 @@ +#include "simple-mat.hpp" +#include "compat/pi-constant.hpp" +#include <cmath> + +namespace euler { + +euler_t OPENTRACK_LOGIC_EXPORT rmat_to_euler(const rmat& R) +{ + using std::atan2; + using std::sqrt; + + const double cy = sqrt(R(2,2)*R(2, 2) + R(2, 1)*R(2, 1)); + const bool large_enough = cy > 1e-10; + if (large_enough) + return euler_t(atan2(-R(1, 0), R(0, 0)), + atan2(R(2, 0), cy), + atan2(-R(2, 1), R(2, 2))); + else + return euler_t(atan2(R(0, 1), R(1, 1)), + atan2(R(2, 0), cy), + 0); +} + +// tait-bryan angles, not euler +rmat OPENTRACK_LOGIC_EXPORT euler_to_rmat(const euler_t& input) +{ + const double H = -input(0); + const double P = -input(1); + const double B = -input(2); + + using std::cos; + using std::sin; + + const auto c1 = cos(H); + const auto s1 = sin(H); + const auto c2 = cos(P); + const auto s2 = sin(P); + const auto c3 = cos(B); + const auto s3 = sin(B); + + return rmat( + // z + c1 * c2, + c1 * s2 * s3 - c3 * s1, + s1 * s3 + c1 * c3 * s2, + // y + c2 * s1, + c1 * c3 + s1 * s2 * s3, + c3 * s1 * s2 - c1 * s3, + // x + -s2, + c2 * s3, + c2 * c3 + ); +} + +// https://en.wikipedia.org/wiki/Davenport_chained_rotations#Tait.E2.80.93Bryan_chained_rotations +void OPENTRACK_LOGIC_EXPORT tait_bryan_to_matrices(const euler_t& input, + rmat& r_roll, + rmat& r_pitch, + rmat& r_yaw) +{ + using std::cos; + using std::sin; + + { + const double phi = -input(2); + const double sin_phi = sin(phi); + const double cos_phi = cos(phi); + + r_roll = rmat(1, 0, 0, + 0, cos_phi, -sin_phi, + 0, sin_phi, cos_phi); + } + + { + const double theta = -input(1); + const double sin_theta = sin(theta); + const double cos_theta = cos(theta); + + r_pitch = rmat(cos_theta, 0, -sin_theta, + 0, 1, 0, + sin_theta, 0, cos_theta); + } + + { + const double psi = -input(0); + const double sin_psi = sin(psi); + const double cos_psi = cos(psi); + + r_yaw = rmat(cos_psi, -sin_psi, 0, + sin_psi, cos_psi, 0, + 0, 0, 1); + } +} + +} // end ns euler diff --git a/logic/simple-mat.hpp b/logic/simple-mat.hpp new file mode 100644 index 00000000..514e845f --- /dev/null +++ b/logic/simple-mat.hpp @@ -0,0 +1,279 @@ +/* Copyright (c) 2014-2016, 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 "export.hpp" + +#include <initializer_list> +#include <type_traits> +#include <utility> + +namespace { + // last param to fool SFINAE into overloading + template<int i, int j, int> + struct equals + { + enum { value = i == j }; + }; + template<int i, int j, int min> + struct maybe_add_swizzle + { + enum { value = (i == 1 || j == 1) && (i >= min || j >= min) }; + }; + template<int i1, int j1, int i2, int j2> + struct is_vector_pair + { + enum { value = (i1 == i2 && j1 == 1 && j2 == 1) || (j1 == j2 && i1 == 1 && i2 == 1) }; + }; + template<int i, int j> + struct vector_len + { + enum { value = i > j ? i : j }; + }; + template<int a, int b, int c, int d> + struct is_dim3 + { + enum { value = (a == 1 && c == 1 && b == 3 && d == 3) || (a == 3 && c == 3 && b == 1 && d == 1) }; + enum { P = a == 1 ? 1 : 3 }; + enum { Q = a == 1 ? 3 : 1 }; + }; + + template<typename num, int h, int w, typename...ts> + struct is_arglist_correct + { + enum { value = h * w == sizeof...(ts) }; + }; +} + +template<typename num, int h_, int w_> +class Mat +{ + static_assert(h_ > 0 && w_ > 0, "must have positive mat dimensions"); + num data[h_][w_]; + +public: + template<int Q = w_> typename std::enable_if<equals<Q, 1, 0>::value, num>::type + inline operator()(int i) const { return data[i][0]; } + + template<int P = h_> typename std::enable_if<equals<P, 1, 1>::value, num>::type + inline operator()(int i) const { return data[0][i]; } + + template<int Q = w_> typename std::enable_if<equals<Q, 1, 2>::value, num&>::type + inline operator()(int i) { return data[i][0]; } + + template<int P = h_> typename std::enable_if<equals<P, 1, 3>::value, num&>::type + inline operator()(int i) { return data[0][i]; } + +#define OPENTRACK_ASSERT_SWIZZLE static_assert(P == h_ && Q == w_, "") + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 1>::value, num>::type + x() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(0); } + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 2>::value, num>::type + y() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(1); } + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 3>::value, num>::type + z() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(2); } + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 4>::value, num>::type + w() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(3); } + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 1>::value, num&>::type + x() { OPENTRACK_ASSERT_SWIZZLE; return operator()(0); } + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 2>::value, num&>::type + y() { OPENTRACK_ASSERT_SWIZZLE; return operator()(1); } + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 3>::value, num&>::type + z() { OPENTRACK_ASSERT_SWIZZLE; return operator()(2); } + + template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 4>::value, num&>::type + w() { OPENTRACK_ASSERT_SWIZZLE; return operator()(3); } + // parameters w_ and h_ are rebound so that SFINAE occurs + // removing them causes a compile-time error -sh 20150811 + + template<int R, int S, int P = h_, int Q = w_> + typename std::enable_if<is_vector_pair<R, S, P, Q>::value, num>::type + dot(const Mat<num, R, S>& p2) const + { + static_assert(P == h_ && Q == w_, ""); + + num ret = 0; + constexpr int len = vector_len<R, S>::value; + for (int i = 0; i < len; i++) + ret += operator()(i) * p2(i); + return ret; + } + + template<int R, int S, int P = h_, int Q = w_> + typename std::enable_if<is_dim3<P, Q, R, S>::value, Mat<num, is_dim3<P, Q, R, S>::P, is_dim3<P, Q, R, S>::Q>>::type + cross(const Mat<num, R, S>& p2) const + { + static_assert(P == h_ && Q == w_, ""); + decltype(*this)& p1 = *this; + + return Mat<num, R, S>(p1.y() * p2.z() - p2.y() * p1.z(), + p2.x() * p1.z() - p1.x() * p2.z(), + p1.x() * p2.y() - p1.y() * p2.x()); + } + + Mat<num, h_, w_> operator+(const Mat<num, h_, w_>& other) const + { + Mat<num, h_, w_> ret; + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + ret(j, i) = data[j][i] + other.data[j][i]; + return ret; + } + + Mat<num, h_, w_> operator-(const Mat<num, h_, w_>& other) const + { + Mat<num, h_, w_> ret; + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + ret(j, i) = data[j][i] - other.data[j][i]; + return ret; + } + + Mat<num, h_, w_> operator+(const num& other) const + { + Mat<num, h_, w_> ret; + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + ret(j, i) = data[j][i] + other; + return ret; + } + + Mat<num, h_, w_> operator-(const num& other) const + { + Mat<num, h_, w_> ret; + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + ret(j, i) = data[j][i] - other; + return ret; + } + + template<int p> + Mat<num, h_, p> operator*(const Mat<num, w_, p>& other) const + { + Mat<num, h_, p> ret; + for (int k = 0; k < h_; k++) + for (int i = 0; i < p; i++) + { + ret(k, i) = 0; + for (int j = 0; j < w_; j++) + ret(k, i) += data[k][j] * other(j, i); + } + return ret; + } + + inline num operator()(int j, int i) const { return data[j][i]; } + inline num& operator()(int j, int i) { return data[j][i]; } + + template<typename... ts, int h__ = h_, int w__ = w_, + typename = typename std::enable_if<is_arglist_correct<num, h__, w__, ts...>::value>::type> + Mat(const ts... xs) + { + static_assert(h__ == h_ && w__ == w_, ""); + + std::initializer_list<num> init = { static_cast<num>(xs)... }; + + *this = Mat(std::move(init)); + } + + Mat() + { + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + data[j][i] = num(0); + } + + Mat(const num* mem) + { + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + data[j][i] = mem[i*h_+j]; + } + + Mat(std::initializer_list<num>&& init) + { + auto iter = init.begin(); + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + data[j][i] = *iter++; + } + + operator num*() { return reinterpret_cast<num*>(data); } + operator const num*() const { return reinterpret_cast<const num*>(data); } + + // XXX add more operators as needed, third-party dependencies mostly + // not needed merely for matrix algebra -sh 20141030 + + template<int h__ = h_> + static typename std::enable_if<h_ == w_, Mat<num, h__, h__>>::type eye() + { + static_assert(h_ == h__, ""); + + Mat<num, h_, h_> ret; + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + ret.data[j][i] = 0; + + for (int i = 0; i < h_; i++) + ret.data[i][i] = 1; + + return ret; + } + + Mat<num, w_, h_> t() const + { + Mat<num, w_, h_> ret; + + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + ret(i, j) = data[j][i]; + + return ret; + } +}; + +template<int h_, int w_> using dmat = Mat<double, h_, w_>; + +template<typename num, int h, int w> +Mat<num, h, w> operator*(num scalar, const Mat<num, h, w>& mat) +{ + return mat * scalar; +} + +template<typename num, int h_, int w_> +Mat<num, h_, w_> operator*(const Mat<num, h_, w_>& self, num other) +{ + Mat<num, h_, w_> ret; + for (int j = 0; j < h_; j++) + for (int i = 0; i < w_; i++) + ret(j, i) = self(j, i) * other; + return ret; +} + +namespace euler { + +template<int y, int x> using dmat = Mat<double, y, x>; +using rmat = dmat<3, 3>; +using euler_t = dmat<3, 1>; + +rmat OPENTRACK_LOGIC_EXPORT euler_to_rmat(const euler_t& input); + +euler_t OPENTRACK_LOGIC_EXPORT rmat_to_euler(const rmat& R); + +void OPENTRACK_LOGIC_EXPORT tait_bryan_to_matrices(const euler_t& input, + rmat& r_roll, + rmat& r_pitch, + rmat& r_yaw); + +} // end ns euler diff --git a/logic/state.hpp b/logic/state.hpp new file mode 100644 index 00000000..4c3bb7a0 --- /dev/null +++ b/logic/state.hpp @@ -0,0 +1,32 @@ +/* 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 "compat/options.hpp" +using namespace options; +#include "api/plugin-support.hpp" +#include "main-settings.hpp" +#include "mappings.hpp" +#include "selected-libraries.hpp" +#include "work.hpp" +#include <vector> +#include <QString> + +struct State +{ + State(const QString& library_path) : + modules(library_path), + pose(std::vector<axis_opts*>{&s.a_x, &s.a_y, &s.a_z, &s.a_yaw, &s.a_pitch, &s.a_roll}) + {} + Modules modules; + SelectedLibraries libs; + main_settings s; + Mappings pose; + mem<Work> work; +}; diff --git a/logic/tracker.cpp b/logic/tracker.cpp new file mode 100644 index 00000000..c7580500 --- /dev/null +++ b/logic/tracker.cpp @@ -0,0 +1,385 @@ +/* Copyright (c) 2012-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. + */ + +/* + * this file appeared originally in facetracknoir, was rewritten completely + * following opentrack fork. + * + * originally written by Wim Vriend. + */ + +#include "compat/sleep.hpp" + +#include "tracker.h" +#include <cmath> +#include <algorithm> +#include <cstdio> + +#if defined(_WIN32) +# include <windows.h> +#endif + +Tracker::Tracker(Mappings &m, SelectedLibraries &libs, TrackLogger &logger) : + m(m), + newpose {0,0,0, 0,0,0}, + libs(libs), + logger(logger), + r_b(get_camera_offset_matrix(c_div).t()), + r_b_real(get_camera_offset_matrix(1).t()), + t_b {0,0,0}, + centerp(s.center_at_startup), + enabledp(true), + zero_(false), + should_quit(false) +{ +} + +Tracker::~Tracker() +{ + should_quit = true; + wait(); +} + +Tracker::rmat Tracker::get_camera_offset_matrix(double c) +{ + const double off[] = + { + d2r * c * (double)-s.camera_yaw, + d2r * c * (double)-s.camera_pitch, + d2r * c * (double)-s.camera_roll + }; + + return euler::euler_to_rmat(off); +} + +double Tracker::map(double pos, Map& axis) +{ + bool altp = (pos < 0) && axis.opts.altp; + axis.spline_main.setTrackingActive( !altp ); + axis.spline_alt.setTrackingActive( altp ); + auto& fc = altp ? axis.spline_alt : axis.spline_main; + return fc.getValue(pos); +} + +void Tracker::t_compensate(const rmat& rmat, const euler_t& xyz_, euler_t& output, bool rz) +{ + // TY is really yaw axis. need swapping accordingly. + const euler_t ret = rmat * euler_t(xyz_(TZ), -xyz_(TX), -xyz_(TY)); + if (!rz) + output(2) = ret(0); + else + output(2) = xyz_(2); + output(1) = -ret(2); + output(0) = -ret(1); +} + +#include "compat/nan.hpp" + +static inline double elide_nan(double value, double def) +{ + if (nanp(value)) + { + if (nanp(def)) + return 0; + return def; + } + return value; +} + +static bool is_nan(const dmat<3,3>& r, const dmat<3, 1>& t) +{ + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + if (nanp(r(i, j))) + return true; + + for (int i = 0; i < 3; i++) + if (nanp(t(i))) + return true; + + return false; +} + +static bool is_nan(const Pose& value) +{ + for (int i = 0; i < 6; i++) + if (nanp(value(i))) + return true; + return false; +} + +constexpr double Tracker::c_mult; +constexpr double Tracker::c_div; + +void Tracker::logic() +{ + using namespace euler; + + logger.write_dt(); + logger.reset_dt(); + + Pose value, raw; + + for (int i = 0; i < 6; i++) + { + auto& axis = m(i); + int k = axis.opts.src; + if (k < 0 || k >= 6) + value(i) = 0; + else + value(i) = newpose[k]; + raw(i) = newpose[i]; + } + + logger.write_pose(raw); // raw + + if (is_nan(raw)) + raw = last_raw; + + // TODO fix gimbal lock by dividing euler angle input by >=3. + // maintain the real rmat separately for translation compensation + // TODO split this function, it's too big + rmat r, r_real; + + { + euler_t tmp = d2r * euler_t(&value[Yaw]); + r = euler_to_rmat(c_div * tmp); + r_real = euler_to_rmat(tmp); + } + + euler_t t(value(0), value(1), value(2)); + + bool do_center_now = false; + bool nan = is_nan(r, t); + + if (centerp && !nan) + { + for (int i = 0; i < 6; i++) + if (fabs(newpose[i]) != 0) + { + do_center_now = true; + break; + } + } + + const rmat cam = get_camera_offset_matrix(c_div); + const rmat cam_real = get_camera_offset_matrix(1); + + r = r * cam; + r_real = r_real * cam_real; + + if (do_center_now) + { + centerp = false; + + if (libs.pFilter) + libs.pFilter->center(); + + if (libs.pTracker->center()) + { + r_b = cam.t(); + r_b_real = cam_real.t(); + r = rmat::eye(); + r_real = rmat::eye(); + } + else + { + r_b = r.t(); + r_b_real = r_real.t(); + } + + for (int i = 0; i < 3; i++) + t_b[i] = t(i); + } + + { + switch (s.center_method) + { + // inertial + case 0: + default: + r = r_b * r; + break; + // camera + case 1: + r = r * r_b; + break; + } + + const euler_t rot = r2d * c_mult * rmat_to_euler(r); + euler_t pos(t(0) - t_b[0], t(1) - t_b[1], t(2) - t_b[2]); + + if (s.use_camera_offset_from_centering) + t_compensate(r_b_real.t() * cam_real.t(), pos, pos, false); + else + t_compensate(cam_real.t(), pos, pos, false); + + for (int i = 0; i < 3; i++) + { + value(i) = pos(i); + value(i+3) = rot(i); + } + } + + logger.write_pose(value); // "corrected" - after various transformations to account for camera position + + // whenever something can corrupt its internal state due to nan/inf, elide the call + if (is_nan(value)) + { + nan = true; + logger.write_pose(value); // "filtered" + } + else + { + { + Pose tmp = value; + + if (libs.pFilter) + libs.pFilter->filter(tmp, value); + } + logger.write_pose(value); // "filtered" + + // CAVEAT rotation only, due to tcomp + for (int i = 3; i < 6; i++) + value(i) = map(value(i), m(i)); + + for (int i = 0; i < 6; i++) + value(i) += m(i).opts.zero; + + for (int i = 0; i < 6; i++) + value(i) *= int(m(i).opts.invert) * -2 + 1; + + if (zero_) + for (int i = 0; i < 6; i++) + value(i) = 0; + + if (is_nan(value)) + nan = true; + } + + if (s.tcomp_p) + { + euler_t value_(value(TX), value(TY), value(TZ)); + t_compensate(euler_to_rmat(euler_t(value(Yaw) * d2r, value(Pitch) * d2r, value(Roll) * d2r)), + value_, + value_, + s.tcomp_tz); + if (is_nan(r, value_)) + nan = true; + for (int i = 0; i < 3; i++) + value(i) = value_(i); + } + + // CAVEAT translation only, due to tcomp + for (int i = 0; i < 3; i++) + value(i) = map(value(i), m(i)); + + logger.write_pose(value); // "mapped" + + if (nan) + { + value = last_mapped; + + // for widget last value display + for (int i = 0; i < 6; i++) + (void) map(value(i), m(i)); + } + + libs.pProtocol->pose(value); + + last_mapped = value; + last_raw = raw; + + QMutexLocker foo(&mtx); + output_pose = value; + raw_6dof = raw; + + logger.reset_dt(); + logger.next_line(); +} + +void Tracker::run() +{ +#if defined(_WIN32) + (void) timeBeginPeriod(1); +#endif + + setPriority(QThread::HighPriority); + + { + static constexpr const char* posechannels[6] = { "TX", "TY", "TZ", "Yaw", "Pitch", "Roll" }; + static constexpr const char* datachannels[5] = { "dt", "raw", "corrected", "filtered", "mapped" }; + logger.write(datachannels[0]); + char buffer[128]; + for (unsigned j = 1; j < 5; ++j) + { + for (unsigned i = 0; i < 6; ++i) + { + std::sprintf(buffer, "%s%s", datachannels[j], posechannels[i]); + logger.write(buffer); + } + } + logger.next_line(); + } + + t.start(); + logger.reset_dt(); + + while (!should_quit) + { + double tmp[6] {0,0,0, 0,0,0}; + libs.pTracker->data(tmp); + + if (enabledp) + for (int i = 0; i < 6; i++) + newpose[i] = elide_nan(tmp[i], newpose[i]); + + logic(); + + static constexpr long const_sleep_us = 4000; + + using std::max; + using std::min; + + const long elapsed_usecs = t.elapsed_usecs(); + const long sleep_us = const_sleep_us * 2 - elapsed_usecs; + + const unsigned sleep_time = unsigned(max(1l, min(const_sleep_us * 4, max(1l, (sleep_us + 200l)/1000l)))); + + t.start(); + + portable::sleep(unsigned(max(1u, sleep_time))); + } + + { + // filter may inhibit exact origin + Pose p; + libs.pProtocol->pose(p); + } + +#if defined(_WIN32) + (void) timeEndPeriod(1); +#endif + + for (int i = 0; i < 6; i++) + { + m(i).spline_main.setTrackingActive(false); + m(i).spline_alt.setTrackingActive(false); + } +} + +void Tracker::get_raw_and_mapped_poses(double* mapped, double* raw) const +{ + QMutexLocker foo(&const_cast<Tracker&>(*this).mtx); + + for (int i = 0; i < 6; i++) + { + raw[i] = raw_6dof(i); + mapped[i] = output_pose(i); + } +} + diff --git a/logic/tracker.h b/logic/tracker.h new file mode 100644 index 00000000..15fb9701 --- /dev/null +++ b/logic/tracker.h @@ -0,0 +1,85 @@ +/* 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 <vector> + +#include "compat/pi-constant.hpp" +#include "compat/timer.hpp" +#include "api/plugin-support.hpp" +#include "mappings.hpp" +#include "simple-mat.hpp" +#include "selected-libraries.hpp" + +#include "spline-widget/spline.hpp" +#include "main-settings.hpp" +#include "compat/options.hpp" +#include "tracklogger.hpp" + +#include <QMutex> +#include <QThread> + +#include "export.hpp" + +using Pose = Mat<double, 6, 1>; + +class OPENTRACK_LOGIC_EXPORT Tracker : private QThread +{ + Q_OBJECT +private: + using rmat = euler::rmat; + using euler_t = euler::euler_t; + + QMutex mtx; + main_settings s; + Mappings& m; + + Timer t; + Pose output_pose, raw_6dof, last_mapped, last_raw; + + double newpose[6]; + SelectedLibraries const& libs; + // The owner of the reference is the main window. + // This design might be usefull if we decide later on to swap out + // the logger while the tracker is running. + TrackLogger &logger; + + rmat r_b, r_b_real; + double t_b[3]; + + volatile bool centerp; + volatile bool enabledp; + volatile bool zero_; + volatile bool should_quit; + + double map(double pos, Map& axis); + void logic(); + void t_compensate(const rmat& rmat, const euler_t& ypr, euler_t& output, bool rz); + void run() override; + + static constexpr double pi = OPENTRACK_PI; + static constexpr double r2d = 180. / OPENTRACK_PI; + static constexpr double d2r = OPENTRACK_PI / 180.; + + // note: float exponent base is 2 + static constexpr double c_mult = 4; + static constexpr double c_div = 1./c_mult; +public: + Tracker(Mappings& m, SelectedLibraries& libs, TrackLogger &logger); + ~Tracker(); + + rmat get_camera_offset_matrix(double c); + void get_raw_and_mapped_poses(double* mapped, double* raw) const; + void start() { QThread::start(); } + void toggle_enabled() { enabledp = !enabledp; } + void set_toggle(bool value) { enabledp = value; } + void set_zero(bool value) { zero_ = value; } + void center() { centerp = !centerp; } + void zero() { zero_ = !zero_; } +}; diff --git a/logic/tracklogger.cpp b/logic/tracklogger.cpp new file mode 100644 index 00000000..64dda579 --- /dev/null +++ b/logic/tracklogger.cpp @@ -0,0 +1,47 @@ +#include "tracklogger.hpp" +#include "tracker.h" + +TrackLogger::~TrackLogger() {} + +void TrackLogger::reset_dt() +{ + t.start(); +} + +void TrackLogger::write_dt() +{ + const double dt = t.elapsed_seconds(); + write(&dt, 1); +} + +void TrackLoggerCSV::handle_first_col_sep() +{ + if (!first_col) + out.put(','); + first_col = false; +} + +void TrackLoggerCSV::write(const char *s) +{ + handle_first_col_sep(); + out << s; +} + + +void TrackLoggerCSV::write(const double *p, int n) +{ + handle_first_col_sep(); + for (int i = 0; i < n-1; ++i) + { + out << p[i]; + out.put(','); + } + out << p[n-1]; +} + +void TrackLoggerCSV::next_line() +{ + out << std::endl; + first_col = true; +} + diff --git a/logic/tracklogger.hpp b/logic/tracklogger.hpp new file mode 100644 index 00000000..52ab35bc --- /dev/null +++ b/logic/tracklogger.hpp @@ -0,0 +1,65 @@ +#pragma once +#include "main-settings.hpp" +#include "compat/options.hpp" +#include "compat/timer.hpp" + +#include <fstream> +#include <QString> +#include <QMessageBox> +#include <QWidget> + +class OPENTRACK_LOGIC_EXPORT TrackLogger +{ + TrackLogger(TrackLogger&&) = delete; + TrackLogger(const TrackLogger&) = delete; + TrackLogger& operator=(const TrackLogger&) = delete; + TrackLogger& operator=(TrackLogger&&) = delete; + + Timer t; + +public: + TrackLogger() + { + } + + virtual ~TrackLogger(); + + virtual void write(const char *) + { + } + + virtual void write(const double *, int) + { + } + + virtual void next_line() + { + } + + void write_pose(const double *p) + { + write(p, 6); + } + + void reset_dt(); + void write_dt(); +}; + + +class OPENTRACK_LOGIC_EXPORT TrackLoggerCSV : public TrackLogger +{ + std::ofstream out; + bool first_col; + inline void handle_first_col_sep(); +public: + TrackLoggerCSV(const QString &filename) : first_col(true) + { + out.open(filename.toStdString()); + } + + bool is_open() const { return out.is_open(); } + void write(const char *s) override; + void write(const double *p, int n) override; + void next_line() override; +}; + diff --git a/logic/win32-shortcuts.cpp b/logic/win32-shortcuts.cpp new file mode 100644 index 00000000..df9145a0 --- /dev/null +++ b/logic/win32-shortcuts.cpp @@ -0,0 +1,196 @@ +/* Copyright (c) 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. + */ + +#if defined(_WIN32) +# ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +# endif +# include <dinput.h> + +#include "win32-shortcuts.h" +#include <QList> +#include <QVariant> +#include <QDebug> + +QList<win_key> windows_key_mods = + QList<win_key>({ + win_key(DIK_LCONTROL, Qt::Key::Key_Control), + win_key(DIK_RCONTROL, Qt::Key::Key_Control), + win_key(DIK_LALT, Qt::Key::Key_Alt), + win_key(DIK_RALT, Qt::Key::Key_Alt), + win_key(DIK_LSHIFT, Qt::Key::Key_Shift), + win_key(DIK_RSHIFT, Qt::Key::Key_Shift), + win_key(DIK_LWIN, Qt::Key::Key_unknown), + win_key(DIK_RWIN, Qt::Key::Key_unknown) + }); + +QList<win_key> windows_key_sequences = + QList<win_key>({ + win_key(DIK_F1, Qt::Key::Key_F1 ), + win_key(DIK_F2, Qt::Key::Key_F2 ), + win_key(DIK_F3, Qt::Key::Key_F3 ), + win_key(DIK_F4, Qt::Key::Key_F4 ), + win_key(DIK_F5, Qt::Key::Key_F5 ), + win_key(DIK_F6, Qt::Key::Key_F6 ), + win_key(DIK_F7, Qt::Key::Key_F7 ), + win_key(DIK_F8, Qt::Key::Key_F8 ), + win_key(DIK_F9, Qt::Key::Key_F9 ), + win_key(DIK_F10, Qt::Key::Key_F10 ), + win_key(DIK_F11, Qt::Key::Key_F11 ), + win_key(DIK_F12, Qt::Key::Key_F12 ), + win_key(DIK_LEFT, Qt::Key::Key_Left ), + win_key(DIK_RIGHT, Qt::Key::Key_Right ), + win_key(DIK_UP, Qt::Key::Key_Up ), + win_key(DIK_DOWN, Qt::Key::Key_Down ), + win_key(DIK_PRIOR, Qt::Key::Key_PageUp ), + win_key(DIK_NEXT, Qt::Key::Key_PageDown ), + win_key(DIK_HOME, Qt::Key::Key_Home ), + win_key(DIK_END, Qt::Key::Key_End ), + win_key(DIK_BACK, Qt::Key::Key_Backspace ), + win_key(DIK_COMMA, Qt::Key::Key_Comma ), + win_key(DIK_PERIOD, Qt::Key::Key_Period ), + win_key(DIK_LBRACKET, Qt::Key::Key_BracketLeft ), + win_key(DIK_RBRACKET, Qt::Key::Key_BracketRight ), + win_key(DIK_SEMICOLON, Qt::Key::Key_Semicolon ), + win_key(DIK_SLASH, Qt::Key::Key_Slash ), + win_key(DIK_BACKSLASH, Qt::Key::Key_Backslash ), + win_key(DIK_BACKSPACE, Qt::Key::Key_Backspace ), + win_key(DIK_APOSTROPHE, Qt::Key::Key_Apostrophe ), + win_key(DIK_GRAVE, Qt::Key::Key_QuoteLeft ), + win_key(DIK_MINUS, Qt::Key::Key_Minus ), + win_key(DIK_EQUALS, Qt::Key::Key_Equal ), + win_key(DIK_PERIOD, Qt::Key::Key_Period ), + win_key(DIK_F1, Qt::Key::Key_F1 ), + win_key(DIK_F2, Qt::Key::Key_F2 ), + win_key(DIK_F3, Qt::Key::Key_F3 ), + win_key(DIK_F4, Qt::Key::Key_F4 ), + win_key(DIK_F5, Qt::Key::Key_F5 ), + win_key(DIK_F6, Qt::Key::Key_F6 ), + win_key(DIK_F7, Qt::Key::Key_F7 ), + win_key(DIK_F8, Qt::Key::Key_F8 ), + win_key(DIK_F9, Qt::Key::Key_F9 ), + win_key(DIK_F10, Qt::Key::Key_F10 ), + win_key(DIK_F11, Qt::Key::Key_F11 ), + win_key(DIK_F12, Qt::Key::Key_F12 ), + win_key(DIK_0, Qt::Key::Key_0 ), + win_key(DIK_1, Qt::Key::Key_1 ), + win_key(DIK_2, Qt::Key::Key_2 ), + win_key(DIK_3, Qt::Key::Key_3 ), + win_key(DIK_4, Qt::Key::Key_4 ), + win_key(DIK_5, Qt::Key::Key_5 ), + win_key(DIK_6, Qt::Key::Key_6 ), + win_key(DIK_7, Qt::Key::Key_7 ), + win_key(DIK_8, Qt::Key::Key_8 ), + win_key(DIK_9, Qt::Key::Key_9 ), + win_key(DIK_A, Qt::Key::Key_A ), + win_key(DIK_B, Qt::Key::Key_B ), + win_key(DIK_C, Qt::Key::Key_C ), + win_key(DIK_D, Qt::Key::Key_D ), + win_key(DIK_E, Qt::Key::Key_E ), + win_key(DIK_F, Qt::Key::Key_F ), + win_key(DIK_G, Qt::Key::Key_G ), + win_key(DIK_H, Qt::Key::Key_H ), + win_key(DIK_I, Qt::Key::Key_I ), + win_key(DIK_J, Qt::Key::Key_J ), + win_key(DIK_K, Qt::Key::Key_K ), + win_key(DIK_L, Qt::Key::Key_L ), + win_key(DIK_M, Qt::Key::Key_M ), + win_key(DIK_N, Qt::Key::Key_N ), + win_key(DIK_O, Qt::Key::Key_O ), + win_key(DIK_P, Qt::Key::Key_P ), + win_key(DIK_Q, Qt::Key::Key_Q ), + win_key(DIK_R, Qt::Key::Key_R ), + win_key(DIK_S, Qt::Key::Key_S ), + win_key(DIK_T, Qt::Key::Key_T ), + win_key(DIK_U, Qt::Key::Key_U ), + win_key(DIK_V, Qt::Key::Key_V ), + win_key(DIK_W, Qt::Key::Key_W ), + win_key(DIK_X, Qt::Key::Key_X ), + win_key(DIK_Y, Qt::Key::Key_Y ), + win_key(DIK_Z, Qt::Key::Key_Z ), + win_key(DIK_RETURN, Qt::Key::Key_Return), + win_key(DIK_INSERT, Qt::Key::Key_Insert), + win_key(DIK_DELETE, Qt::Key::Key_Delete), + win_key(DIK_SPACE, Qt::Key::Key_Space), + win_key(DIK_SYSRQ, Qt::Key::Key_Print), + win_key(DIK_SCROLL, Qt::Key::Key_ScrollLock), + win_key(DIK_PAUSE, Qt::Key::Key_Pause), + win_key(DIK_NUMLOCK, Qt::Key::Key_NumLock), +#define mod(x, y) static_cast<Qt::Key>(x | y) + win_key(DIK_NUMPAD0, mod(Qt::Key::Key_0, Qt::KeypadModifier)), + win_key(DIK_NUMPAD0, mod(Qt::Key::Key_0, Qt::KeypadModifier)), + win_key(DIK_NUMPAD1, mod(Qt::Key::Key_1, Qt::KeypadModifier)), + win_key(DIK_NUMPAD2, mod(Qt::Key::Key_2, Qt::KeypadModifier)), + win_key(DIK_NUMPAD3, mod(Qt::Key::Key_3, Qt::KeypadModifier)), + win_key(DIK_NUMPAD4, mod(Qt::Key::Key_4, Qt::KeypadModifier)), + win_key(DIK_NUMPAD5, mod(Qt::Key::Key_5, Qt::KeypadModifier)), + win_key(DIK_NUMPAD6, mod(Qt::Key::Key_6, Qt::KeypadModifier)), + win_key(DIK_NUMPAD7, mod(Qt::Key::Key_7, Qt::KeypadModifier)), + win_key(DIK_NUMPAD8, mod(Qt::Key::Key_8, Qt::KeypadModifier)), + win_key(DIK_NUMPAD9, mod(Qt::Key::Key_9, Qt::KeypadModifier)), + win_key(DIK_NUMPADCOMMA, mod(Qt::Key::Key_Comma, Qt::KeypadModifier)), + win_key(DIK_NUMPADENTER, mod(Qt::Key::Key_Enter, Qt::KeypadModifier)), + win_key(DIK_NUMPADEQUALS, mod(Qt::Key::Key_Equal, Qt::KeypadModifier)), + win_key(DIK_NUMPADMINUS, mod(Qt::Key::Key_Minus, Qt::KeypadModifier)), + win_key(DIK_NUMPADPERIOD, mod(Qt::Key::Key_Period, Qt::KeypadModifier)), + win_key(DIK_NUMPADPLUS, mod(Qt::Key::Key_Plus, Qt::KeypadModifier)), + win_key(DIK_NUMPADSLASH, mod(Qt::Key::Key_Slash, Qt::KeypadModifier)), + win_key(DIK_NUMPADSTAR, mod(Qt::Key::Key_multiply, Qt::KeypadModifier)), + }); + +bool win_key::to_qt(const Key& k, QKeySequence& qt_, Qt::KeyboardModifiers &mods) +{ + for (auto& wk : windows_key_sequences) + { + if (wk.win == k.keycode) + { + qt_ = wk.qt; + mods = Qt::NoModifier; + if (k.ctrl) mods |= Qt::ControlModifier; + if (k.shift) mods |= Qt::ShiftModifier; + if (k.alt) mods |= Qt::AltModifier; + return true; + } + } + return false; +} + +bool win_key::from_qt(QKeySequence qt_, int& dik, Qt::KeyboardModifiers& mods) +{ + // CAVEAT don't use QVariant::toUInt() or conversion fails + const unsigned qt = static_cast<unsigned>(QVariant(qt_).toInt()); + const unsigned our_mods = qt & Qt::KeyboardModifierMask; + + { + const auto key_ = qt; + for (auto& wk : windows_key_sequences) + { + if (wk.qt == key_) + { + dik = wk.win; + mods = Qt::NoModifier; + return true; + } + } + } + { + const unsigned key = qt & ~Qt::KeyboardModifierMask; + for (auto& wk : windows_key_sequences) + { + if (wk.qt == key) + { + dik = wk.win; + mods = static_cast<Qt::KeyboardModifiers>(our_mods); + return true; + } + } + } + return false; +} + +#endif diff --git a/logic/win32-shortcuts.h b/logic/win32-shortcuts.h new file mode 100644 index 00000000..7626a31f --- /dev/null +++ b/logic/win32-shortcuts.h @@ -0,0 +1,24 @@ +#pragma once + +#ifdef _WIN32 + +#include <QKeySequence> +#include "shortcuts.h" + +struct win_key; + +extern QList<win_key> windows_key_mods; +extern QList<win_key> windows_key_sequences; + +#include "export.hpp" + +struct OPENTRACK_LOGIC_EXPORT win_key +{ + win_key(int win, Qt::Key qt) : win(win), qt(qt) {} + int win; + Qt::Key qt; + static bool from_qt(QKeySequence qt_, int& dik, Qt::KeyboardModifiers &mods); + static bool to_qt(const Key& k, QKeySequence& qt_, Qt::KeyboardModifiers &mods); +}; + +#endif diff --git a/logic/work.cpp b/logic/work.cpp new file mode 100644 index 00000000..8d00270b --- /dev/null +++ b/logic/work.cpp @@ -0,0 +1,73 @@ +#include "work.hpp" + +#include <QMessageBox> + + +std::shared_ptr<TrackLogger> Work::make_logger(const main_settings &s) +{ + if (s.tracklogging_enabled) + { + if (static_cast<QString>(s.tracklogging_filename).isEmpty()) + { + QMessageBox::warning(nullptr, "Logging Error", + "No filename given for track logging. Proceeding without logging.", + QMessageBox::Ok, + QMessageBox::NoButton); + } + else + { + auto logger = std::make_shared<TrackLoggerCSV>(s.tracklogging_filename); + if (!logger->is_open()) + { + logger = nullptr; + QMessageBox::warning(nullptr, "Logging Error", + "Unable to open file: " + s.tracklogging_filename + ". Proceeding without logging.", + QMessageBox::Ok, + QMessageBox::NoButton); + } + else + { + /* As this function has the potential to fill up the hard drive + of the unwary with junk data, a warning is in order. */ + QMessageBox::warning(nullptr, "Logging Active", + "Just a heads up. You are recoding pose data to " + s.tracklogging_filename + "!", + QMessageBox::Ok, + QMessageBox::NoButton); + return logger; + } + } + } + return std::make_shared<TrackLogger>(); +} + + +Work::Work(Mappings& m, SelectedLibraries& libs, WId handle) : + libs(libs), + logger(make_logger(s)), + tracker(std::make_shared<Tracker>(m, libs, *logger)), + sc(std::make_shared<Shortcuts>()), + handle(handle), + keys { + key_tuple(s.key_center, [&](bool) -> void { tracker->center(); }, true), + key_tuple(s.key_toggle, [&](bool) -> void { tracker->toggle_enabled(); }, true), + key_tuple(s.key_zero, [&](bool) -> void { tracker->zero(); }, true), + key_tuple(s.key_toggle_press, [&](bool x) -> void { tracker->set_toggle(!x); }, false), + key_tuple(s.key_zero_press, [&](bool x) -> void { tracker->set_zero(x); }, false), + } +{ + reload_shortcuts(); + tracker->start(); +} + +void Work::reload_shortcuts() +{ + sc->reload(keys); +} + +Work::~Work() +{ + sc = nullptr; + // order matters, otherwise use-after-free -sh + tracker = nullptr; + libs = SelectedLibraries(); +} diff --git a/logic/work.hpp b/logic/work.hpp new file mode 100644 index 00000000..b20b1824 --- /dev/null +++ b/logic/work.hpp @@ -0,0 +1,43 @@ +/* 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 "main-settings.hpp" +#include "api/plugin-support.hpp" +#include "tracker.h" +#include "shortcuts.h" +#include "export.hpp" +#include "tracklogger.hpp" + +#include <QObject> +#include <QFrame> +#include <memory> +#include <vector> +#include <tuple> +#include <functional> + +struct OPENTRACK_LOGIC_EXPORT Work +{ + using fn_t = std::function<void(bool)>; + using key_tuple = std::tuple<key_opts&, fn_t, bool>; + main_settings s; // tracker needs settings, so settings must come before it + SelectedLibraries& libs; + std::shared_ptr<TrackLogger> logger; // must come before tracker, since tracker depends on it + std::shared_ptr<Tracker> tracker; + std::shared_ptr<Shortcuts> sc; + WId handle; + std::vector<key_tuple> keys; + + Work(Mappings& m, SelectedLibraries& libs, WId handle); + ~Work(); + void reload_shortcuts(); + +private: + std::shared_ptr<TrackLogger> make_logger(const main_settings &s); +}; diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt deleted file mode 100644 index 2bbb496c..00000000 --- a/opentrack-compat/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -opentrack_boilerplate(opentrack-compat NO-COMPAT BIN) -if(NOT WIN32 AND NOT APPLE) - target_link_libraries(opentrack-compat rt) -endif() -if(CMAKE_COMPILER_IS_GNUCXX) - set_source_files_properties(nan.cpp PROPERTIES - COMPILE_FLAGS "-fno-fast-math -fno-finite-math-only -O0") -endif() diff --git a/opentrack-compat/camera-names.cpp b/opentrack-compat/camera-names.cpp deleted file mode 100644 index 21ff3b52..00000000 --- a/opentrack-compat/camera-names.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "camera-names.hpp" - -#ifdef _WIN32 -# define NO_DSHOW_STRSAFE -# include <dshow.h> -# include "win32-com.hpp" -# include <cwchar> -#elif 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; - init_com_threading(com_apartment); - 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, int(std::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; -} diff --git a/opentrack-compat/camera-names.hpp b/opentrack-compat/camera-names.hpp deleted file mode 100644 index ae0c6b25..00000000 --- a/opentrack-compat/camera-names.hpp +++ /dev/null @@ -1,18 +0,0 @@ -/* 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> - -#include "export.hpp" - -OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names(); -OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name); - diff --git a/opentrack-compat/export.hpp b/opentrack-compat/export.hpp deleted file mode 100644 index ba10f131..00000000 --- a/opentrack-compat/export.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#ifdef BUILD_compat -# 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 -#else - #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/make-unique.hpp b/opentrack-compat/make-unique.hpp deleted file mode 100644 index bb5315c5..00000000 --- a/opentrack-compat/make-unique.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -// GNU 5.4.0 doesn't have std::make_unique in -std=c++14 mode - -// this implementation was taken from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm - -#include <memory> -#include <utility> -#include <cstddef> - -namespace detail { -template<class T> struct Unique_if -{ - typedef std::unique_ptr<T> Single_object; -}; - -template<class T> struct Unique_if<T[]> -{ - typedef std::unique_ptr<T[]> Unknown_bound; -}; - -template<class T, size_t N> struct Unique_if<T[N]> -{ - typedef void Known_bound; -}; -} - -template<class T, class... Args> - typename detail::Unique_if<T>::Single_object - make_unique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); - } - -template<class T> - typename detail::Unique_if<T>::Unknown_bound - make_unique(std::size_t n) { - typedef typename std::remove_extent<T>::type U; - return std::unique_ptr<T>(new U[n]()); - } - -template<class T, class... Args> - typename detail::Unique_if<T>::Known_bound - make_unique(Args&&...) = delete; diff --git a/opentrack-compat/nan.cpp b/opentrack-compat/nan.cpp deleted file mode 100644 index 899b907a..00000000 --- a/opentrack-compat/nan.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include <cmath> -#include "export.hpp" - -#if defined(__GNUC__) -extern "C" OPENTRACK_COMPAT_EXPORT bool __attribute__ ((noinline)) nanp(double value) -#elif defined(_WIN32) -extern "C" OPENTRACK_COMPAT_EXPORT __declspec(noinline) bool nanp(double value) -#else -extern "C" OPENTRACK_COMPAT_EXPORT bool nanp(double value) -#endif -{ - using std::isnan; - using std::isinf; - - const volatile double x = value; - return isnan(x) || isinf(x); -} diff --git a/opentrack-compat/nan.hpp b/opentrack-compat/nan.hpp deleted file mode 100644 index 9926da13..00000000 --- a/opentrack-compat/nan.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "export.hpp" - -#if defined(__GNUC__) -extern "C" OPENTRACK_COMPAT_EXPORT bool __attribute__ ((noinline)) nanp(double value); -#elif defined(_WIN32) -extern "C" OPENTRACK_COMPAT_EXPORT __declspec(noinline) bool nanp(double value); -#else -extern "C" OPENTRACK_COMPAT_EXPORT bool nanp(double value); -#endif diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp deleted file mode 100644 index 8c6e6c65..00000000 --- a/opentrack-compat/options.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include "options.hpp" - -namespace options -{ - -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() const -{ - auto s = ini_file(); - s->beginGroup(name); - for (auto& i : kvs) - s->setValue(i.first, i.second); - s->endGroup(); -} - -void group::put(const QString &s, const QVariant &d) -{ - kvs[s] = d; -} - -bool group::contains(const QString &s) const -{ - 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 ""; - return dir + "/" + ini_filename(); -} - -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>(); -} - -bool group::operator==(const group& other) const -{ - for (const auto& kv : kvs) - { - const QVariant val = other.get<QVariant>(kv.first); - if (!other.contains(kv.first) || kv.second != val) - { - qDebug() << "bundle" << name << "modified" << "key" << kv.first << "-" << val << "<>" << kv.second; - return false; - } - } - - for (const auto& kv : other.kvs) - { - const QVariant val = get<QVariant>(kv.first); - if (!contains(kv.first) || kv.second != val) - { - qDebug() << "bundle" << name << "modified" << "key" << kv.first << "-" << kv.second << "<>" << val; - return false; - } - } - return true; -} - -impl_bundle::impl_bundle(const QString& group_name) - : - mtx(QMutex::Recursive), - group_name(group_name), - saved(group_name), - transient(saved) -{ -} - -void impl_bundle::reload() -{ - { - QMutexLocker l(&mtx); - saved = group(group_name); - transient = saved; - } - emit reloading(); -} - -void impl_bundle::store_kv(const QString& name, const QVariant& datum) -{ - QMutexLocker l(&mtx); - - transient.put(name, datum); -} - -bool impl_bundle::contains(const QString &name) const -{ - QMutexLocker l(const_cast<QMutex*>(&mtx)); - return transient.contains(name); -} - -void impl_bundle::save() -{ - bool modified_ = false; - - { - QMutexLocker l(&mtx); - if (saved != transient) - { - qDebug() << "bundle" << group_name << "changed, saving"; - modified_ = true; - saved = transient; - saved.save(); - } - } - - if (modified_) - emit saving(); -} - -bool impl_bundle::modifiedp() const // XXX unused -{ - QMutexLocker l(const_cast<QMutex*>(&mtx)); - return transient != saved; -} - -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)) -{ -} - -custom_type_initializer::custom_type_initializer() -{ - qRegisterMetaTypeStreamOperators<slider_value>("slider_value"); - QMetaType::registerDebugStreamOperator<slider_value>(); -} - -custom_type_initializer custom_type_initializer::singleton; - -namespace detail { - -opt_bundle::opt_bundle(const QString& group_name) - : impl_bundle(group_name) -{ -} - -opt_bundle::~opt_bundle() -{ - detail::singleton().bundle_decf(group_name); -} - -void opt_singleton::bundle_decf(const opt_singleton::k& key) -{ - QMutexLocker l(&implsgl_mtx); - - if (--std::get<0>(implsgl_data[key]) == 0) - { - qDebug() << "bundle -" << key; - - implsgl_data.erase(key); - } -} - -opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) -{ -} - -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(1, shr); - return shr; -} - -OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() -{ - static opt_singleton ret; - return ret; -} - - -} // end options::detail - -} // end options - diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp deleted file mode 100644 index 40aca2de..00000000 --- a/opentrack-compat/options.hpp +++ /dev/null @@ -1,481 +0,0 @@ -/* Copyright (c) 2013-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. - */ - -#pragma once - -#include <memory> -#include <tuple> -#include <map> -#include <cinttypes> -#include <vector> -#include <memory> - -#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 <QApplication> - -#include <QMetaType> -#include <QDataStream> - -#include <QDebug> - -#include "export.hpp" -#include "slider.hpp" - -#include "util.hpp" - -#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" -#define OPENTRACK_DEFAULT_CONFIG "default.ini" -#define OPENTRACK_ORG "opentrack-2.3" - -namespace options { - namespace { - class custom_type_initializer - { - custom_type_initializer(); - static custom_type_initializer singleton; - }; - } - - template<typename k, typename v> using map = std::map<k, v>; - - // 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() const; - void put(const QString& s, const QVariant& d); - bool contains(const QString& s) const; - static QString ini_directory(); - static QString ini_filename(); - static QString ini_pathname(); - static const QStringList ini_list(); - static const mem<QSettings> ini_file(); - bool operator==(const group& other) const; - bool operator!=(const group& other) const { return !(*this == other); } - - template<typename t> - t get(const QString& k) const - { - auto value = kvs.find(k); - if (value != kvs.cend()) - return value->second.value<t>(); - return t(); - } - }; - - class OPENTRACK_COMPAT_EXPORT impl_bundle : public QObject - { - Q_OBJECT - protected: - QMutex mtx; - const QString group_name; - group saved; - group transient; - impl_bundle(const impl_bundle&) = delete; - impl_bundle& operator=(const impl_bundle&) = delete; - signals: - void reloading(); - void saving() const; - 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) const; - void save(); - bool modifiedp() const; - - template<typename t> - t get(const QString& name) const - { - QMutexLocker l(const_cast<QMutex*>(&mtx)); - return transient.get<t>(name); - } - }; - - namespace detail - { - class OPENTRACK_COMPAT_EXPORT opt_bundle final : public impl_bundle - { - public: - opt_bundle(const QString& group_name); - ~opt_bundle(); - }; - - 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<detail::opt_bundle>; - - inline pbundle bundle(const QString& name) - { - return detail::singleton().bundle(name); - } - -#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); } -#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) - - class OPENTRACK_COMPAT_EXPORT base_value : public QObject - { - Q_OBJECT - public: - QString name() const { return self_name; } - base_value(pbundle b, const QString& name); - signals: - OPENTRACK_DEFINE_SIGNAL(double); - OPENTRACK_DEFINE_SIGNAL(float); - OPENTRACK_DEFINE_SIGNAL(int); - OPENTRACK_DEFINE_SIGNAL(bool); - OPENTRACK_DEFINE_SIGNAL(const QString&); - OPENTRACK_DEFINE_SIGNAL(const slider_value&); - protected: - pbundle b; - QString self_name; - - template<typename t> - void store(const t& datum) - { - b->store_kv(self_name, QVariant::fromValue(datum)); - emit valueChanged(static_cast<t>(datum)); - } - void store(float datum) - { - store(double(datum)); - } - - public slots: - OPENTRACK_DEFINE_SLOT(double) - OPENTRACK_DEFINE_SLOT(int) - OPENTRACK_DEFINE_SLOT(bool) - OPENTRACK_DEFINE_SLOT(const QString&) - OPENTRACK_DEFINE_SLOT(const slider_value&) - public slots: - virtual void reload() = 0; - }; - - namespace detail { - template<typename t> - struct value_get_traits - { - static inline t get(const t& val, const t&) - { - return val; - } - }; - - template<> - struct value_get_traits<slider_value> - { - using t = slider_value; - static inline t get(const t& val, const t& def) - { - return t(val.cur(), def.min(), def.max()); - } - }; - } - - template<typename t_> - class value : public base_value - { - template<typename t__, typename Enable = void> - struct get_t - { using t = t__; }; - - // Qt uses int a lot in slots so use it for all enums - template<typename t__> - struct get_t<t__, typename std::enable_if<std::is_enum<t__>::value>::type> - //{ using t = typename std::underlying_type<t__>::type; }; - { using t = int; }; - - using t = t_; - public: - using underlying_t = typename get_t<t_>::t; - - t operator=(const t& datum) - { - store(static_cast<underlying_t>(datum)); - return datum; - } - - static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::AutoConnection; - static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection; - - 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) - { - } - - t get() const - { - t val = b->contains(self_name) - ? static_cast<t>(b->get<underlying_t>(self_name)) - : def; - return detail::value_get_traits<t>::get(val, def); - } - - operator t() const { return get(); } - - void reload() override - { - *this = static_cast<t>(*this); - } - - private: - t def; - }; - - struct OPENTRACK_COMPAT_EXPORT opts - { - pbundle b; - opts(const QString& name); - opts& operator=(const opts&) = delete; - opts(const opts&) = delete; - ~opts(); - }; - - template<typename t, typename q> - inline void tie_setting(value<t>&, q*); - - template<typename t> - inline - typename std::enable_if<std::is_enum<t>::value>::type - tie_setting(value<t>& v, QComboBox* cb) - { - cb->setCurrentIndex(cb->findData((unsigned)static_cast<t>(v))); - v = static_cast<t>(cb->currentData().toInt()); - - // QObject::connect plays badly with std::bind of std::shared_ptr. Data seems to get freed. - // Direct accesses of cb->currentData within arbitrary thread context cause crashes as well. - // Hence we go for a verbose implementation. - - std::vector<int> enum_cases; - enum_cases.reserve(unsigned(cb->count())); - - for (int i = 0; i < cb->count(); i++) - enum_cases.push_back(cb->itemData(i).toInt()); - - struct fn1 - { - value<t>& v; - QComboBox* cb; - std::vector<int> enum_cases; - - fn1(value<t>& v, QComboBox* cb, const std::vector<int>& enum_cases) : - v(v), - cb(cb), - enum_cases(enum_cases) - { - } - - void operator()(int idx) - { - if (idx < 0 || idx >= (int)enum_cases.size()) - v = static_cast<t>(-1); - else - v = static_cast<t>(t(std::intptr_t(enum_cases[idx]))); - } - }; - - struct fn2 - { - value<t>& v; - QComboBox* cb; - std::vector<int> enum_cases; - - fn2(value<t>& v, QComboBox* cb, const std::vector<int>& enum_cases) : - v(v), - cb(cb), - enum_cases(enum_cases) - { - } - - void operator()(int val) - { - for (unsigned i = 0; i < enum_cases.size(); i++) - { - if (val == enum_cases[i]) - { - cb->setCurrentIndex(i); - return; - } - } - cb->setCurrentIndex(-1); - } - }; - - base_value::connect(cb, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), - &v, - fn1(v, cb, enum_cases), - v.DIRECT_CONNTYPE); - base_value::connect(&v, - static_cast<void (base_value::*)(int)>(&base_value::valueChanged), - cb, - fn2(v, cb, enum_cases), - v.DIRECT_CONNTYPE); - } - - 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.DIRECT_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); - } - - template<> - inline void tie_setting(value<slider_value>& v, QSlider* w) - { - // we can't get these at runtime since signals cross threads - const int q_min = w->minimum(); - const int q_max = w->maximum(); - const int q_diff = q_max - q_min; - - slider_value sv(v); - - const double sv_max = sv.max(); - const double sv_min = sv.min(); - const double sv_c = sv_max - sv_min; - - w->setValue(int((sv.cur() - sv_min) / sv_c * q_diff + q_min)); - v = slider_value(q_diff <= 0 ? 0 : (w->value() - q_min) * sv_c / (double)q_diff + sv_min, sv_min, sv_max); - - base_value::connect(w, - &QSlider::valueChanged, - &v, - [=, &v](int pos) -> void - { - if (q_diff <= 0 || pos <= 0) - v = slider_value(sv_min, sv_min, sv_max); - else - v = slider_value((pos - q_min) * sv_c / (double)q_diff + sv_min, sv_min, sv_max); - }, - v.DIRECT_CONNTYPE); - base_value::connect(&v, - static_cast<void(base_value::*)(double)>(&base_value::valueChanged), - w, - [=](double value) -> void - { - w->setValue(int(value * q_diff) + q_min); - }, - v.SAFE_CONNTYPE); - } -} - diff --git a/opentrack-compat/pi-constant.hpp b/opentrack-compat/pi-constant.hpp deleted file mode 100644 index 52b98a7f..00000000 --- a/opentrack-compat/pi-constant.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define OPENTRACK_PI 3.14159265358979323846 diff --git a/opentrack-compat/process-list.hpp b/opentrack-compat/process-list.hpp deleted file mode 100644 index 10613791..00000000 --- a/opentrack-compat/process-list.hpp +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright (c) 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 <QDebug> -#include <QStringList> - -#if defined _WIN32 - -#include <windows.h> -#include <tlhelp32.h> - -template<typename = void> -static QStringList get_all_executable_names() -{ - QStringList ret; - HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (h == INVALID_HANDLE_VALUE) - return ret; - - PROCESSENTRY32 e; - e.dwSize = sizeof(e); - - if (Process32First(h, &e) != TRUE) - { - CloseHandle(h); - return ret; - } - - do { - ret.append(e.szExeFile); - } while (Process32Next(h, &e) == TRUE); - - CloseHandle(h); - - return ret; -} -#elif defined __APPLE__ -#include <libproc.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/sysctl.h> -#include <cerrno> -#include <cstring> -#include <vector> - -template<typename = void> -static QStringList get_all_executable_names() -{ - QStringList ret; - std::vector<int> vec; - - while (true) - { - int numproc = proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0); - if (numproc == -1) - { - qDebug() << "proc_listpids numproc failed" << errno; - return ret; - } - vec.resize(numproc); - int cnt = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(int) * numproc); - - if (cnt <= numproc) - { - std::vector<char> arglist; - int mib[2] { CTL_KERN, KERN_ARGMAX }; - size_t sz = sizeof(int); - int maxarg = 0; - if (sysctl(mib, 2, &maxarg, &sz, NULL, 0) == -1) - { - qDebug() << "sysctl KERN_ARGMAX" << errno; - return ret; - } - arglist.resize(maxarg); - for (int i = 0; i < numproc; i++) - { - size_t maxarg_ = (size_t)maxarg; - int mib[3] { CTL_KERN, KERN_PROCARGS2, vec[i] }; - if (sysctl(mib, 3, &arglist[0], &maxarg_, NULL, 0) == -1) - { - //qDebug() << "sysctl KERN_PROCARGS2" << vec[i] << errno; - continue; - } - QStringList cmdline; - for (unsigned j = sizeof(int) + strlen(&arglist[sizeof(int)]); j < maxarg_; j++) - { - QString arg(&arglist[j]); - if (arg.size() != 0) - { - cmdline << arg; - j += arg.size(); - } - } - if (cmdline.size() > 0) - { - int idx = cmdline[0].lastIndexOf('/'); - if (idx != -1) - { - QString tmp = cmdline[0].mid(idx+1); - if (cmdline.size() > 1 && (tmp == "wine.bin" || tmp == "wine")) - { - idx = cmdline[1].lastIndexOf('/'); - if (idx == -1) - idx = cmdline[1].lastIndexOf('\\'); - if (idx != -1) - { - ret.append(cmdline[1].mid(idx+1)); - } - else - ret.append(cmdline[1]); - } - else - { - ret.append(tmp); - } - } - else - ret.append(cmdline[0]); - } - } - return ret; - } - } -} - -#elif defined __linux - -#include <proc/readproc.h> -#include <cerrno> -template<typename = void> -static QStringList get_all_executable_names() -{ - QStringList ret; - proc_t** procs = readproctab(PROC_FILLCOM); - if (procs == nullptr) - { - qDebug() << "readproctab" << errno; - return ret; - } - for (int i = 0; procs[i]; i++) - { - // note, wine sets argv[0] so no parsing like in OSX case - auto proc = procs[i]; - if (proc->cmdline && proc->cmdline[0]) - { - QString tmp(proc->cmdline[0]); - const int idx = std::max(tmp.lastIndexOf('\\'), tmp.lastIndexOf('/')); - tmp = tmp.mid(idx == -1 ? 0 : idx+1); - ret.append(tmp); - } - freeproc(procs[i]); - } - free(procs); - return ret; -} - -#else -template<typename = void> -static QStringList get_all_executable_names() -{ - return QStringList(); -} -#endif diff --git a/opentrack-compat/qcopyable-mutex.hpp b/opentrack-compat/qcopyable-mutex.hpp deleted file mode 100644 index 57b0030d..00000000 --- a/opentrack-compat/qcopyable-mutex.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include <QMutex> - -class MyMutex { -private: - QMutex inner; - -public: - QMutex* operator->() { return &inner; } - QMutex* operator->() const { return &const_cast<MyMutex*>(this)->inner; } - - MyMutex operator=(const MyMutex& datum) - { - auto mode = - datum->isRecursive() - ? QMutex::Recursive - : QMutex::NonRecursive; - - return MyMutex(mode); - } - - MyMutex(const MyMutex& datum) - { - *this = datum; - } - - MyMutex(QMutex::RecursionMode mode = QMutex::NonRecursive) : - inner(mode) - { - } - - QMutex* operator&() const - { - return const_cast<QMutex*>(&inner); - } -}; diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp deleted file mode 100644 index 83a3260c..00000000 --- a/opentrack-compat/shm.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright (c) 2013 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. - */ - -#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) -{ - 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, - 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() -{ - UnmapViewOfFile(mem); - CloseHandle(hMapFile); - CloseHandle(hMutex); -} - -void PortableLockedShm::lock() -{ - (void) WaitForSingleObject(hMutex, INFINITE); -} - -void PortableLockedShm::unlock() -{ - (void) ReleaseMutex(hMutex); -} -#else - -#include <limits.h> - -#pragma GCC diagnostic ignored "-Wunused-result" -PortableLockedShm::PortableLockedShm(const char *shmName, const char* /*mutexName*/, int mapSize) : size(mapSize) -{ - char filename[PATH_MAX+2] = {0}; - strcpy(filename, "/"); - strcat(filename, shmName); - fd = shm_open(filename, O_RDWR | O_CREAT, 0600); - (void) ftruncate(fd, mapSize); - mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)0); -} - -PortableLockedShm::~PortableLockedShm() -{ - (void) munmap(mem, size); - (void) close(fd); -} - -void PortableLockedShm::lock() -{ - flock(fd, LOCK_EX); -} - -void PortableLockedShm::unlock() -{ - flock(fd, LOCK_UN); -} -#endif - -bool PortableLockedShm::success() -{ -#ifndef _WIN32 - return mem != (void*) -1; -#else - return mem != NULL; -#endif -} diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h deleted file mode 100644 index f212dc17..00000000 --- a/opentrack-compat/shm.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (c) 2013 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 - -#if defined(_WIN32) -#include <windows.h> -#else -#include <stdio.h> -#include <string.h> -#include <sys/file.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <limits.h> -#include <unistd.h> -#include <sys/types.h> -#endif - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wattributes" -#endif - -#include "export.hpp" - -class OPENTRACK_COMPAT_EXPORT PortableLockedShm { -public: - PortableLockedShm(const char *shmName, const char *mutexName, int mapSize); - ~PortableLockedShm(); - void lock(); - void unlock(); - bool success(); - inline void* ptr() { return mem; } -private: - void* mem; -#if defined(_WIN32) - HANDLE hMutex, hMapFile; -#else - int fd, size; -#endif -}; - -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif diff --git a/opentrack-compat/sleep.hpp b/opentrack-compat/sleep.hpp deleted file mode 100644 index fab27286..00000000 --- a/opentrack-compat/sleep.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#ifdef _WIN32 -# include <windows.h> -#else -# include <unistd.h> -#endif - -namespace portable -{ -#ifdef _WIN32 - inline void sleep(unsigned milliseconds) - { - Sleep(milliseconds); - } -#else - inline void sleep(unsigned milliseconds) - { - usleep(milliseconds * 1000U); // takes microseconds - } -#endif -} diff --git a/opentrack-compat/slider.cpp b/opentrack-compat/slider.cpp deleted file mode 100644 index be1aaeb8..00000000 --- a/opentrack-compat/slider.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "slider.hpp" -#include <cmath> - -namespace options { - -slider_value::slider_value(double cur, double min, double max) : - cur_(cur), - min_(min), - max_(max) -{ - if (min_ > max_) - min_ = max_; - if (cur_ > max_) - cur_ = max; - if (cur_ < min_) - cur_ = min_; -} - -slider_value::slider_value(const slider_value& v) : slider_value(v.cur(), v.min(), v.max()) -{ -} - -slider_value::slider_value() : slider_value(0, 0, 0) -{ -} - -slider_value& slider_value::operator=(const slider_value& v) -{ - cur_ = v.cur_; - - min_ = v.min_; - max_ = v.max_; - - return *this; -} - -bool slider_value::operator==(const slider_value& v) const -{ - using std::fabs; - - static constexpr double eps = 1e-3; - - return (fabs(v.cur_ - cur_) < eps && - fabs(v.min_ - min_) < eps && - fabs(v.max_ - max_) < eps); -} - -slider_value slider_value::update_from_slider(int pos, int q_min, int q_max) const -{ - slider_value v(*this); - - const int q_diff = q_max - q_min; - const double sv_pos = q_diff == 0 - ? -1e6 - : (((pos - q_min) * (v.max() - v.min())) / q_diff + v.min()); - - if (sv_pos < v.min()) - v = slider_value(v.min(), v.min(), v.max()); - else if (sv_pos > v.max()) - v = slider_value(v.max(), v.min(), v.max()); - else - v = slider_value(sv_pos, v.min(), v.max()); - return v; -} - -int slider_value::to_slider_pos(int q_min, int q_max) const -{ - const int q_diff = q_max - q_min; - - return int(std::round(((cur() - min() * q_diff) / (max() - min())) + q_min)); -} - -} // end ns options diff --git a/opentrack-compat/slider.hpp b/opentrack-compat/slider.hpp deleted file mode 100644 index 7d54c650..00000000 --- a/opentrack-compat/slider.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* 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. - */ - -#pragma once - -#include "export.hpp" -#include <QMetaType> -#include <QDataStream> -#include <QDebug> - -namespace options -{ - class OPENTRACK_COMPAT_EXPORT slider_value final - { - double cur_, min_, max_; - public: - slider_value(double cur, double min, double max); - slider_value(const slider_value& v); - slider_value(); - slider_value& operator=(const slider_value& v); - bool operator==(const slider_value& v) const; - operator double() const { return cur_; } - double cur() const { return cur_; } - double min() const { return min_; } - double max() const { return max_; } - slider_value update_from_slider(int pos, int q_min, int q_max) const; - int to_slider_pos(int q_min, int q_max) const; - }; -} - -QT_BEGIN_NAMESPACE - -inline QDebug operator << (QDebug dbg, const options::slider_value& val) -{ - return dbg << val.cur(); -} - -inline QDataStream& operator << (QDataStream& out, const options::slider_value& v) -{ - out << v.cur() - << v.min() - << v.max(); - return out; -} - -inline QDataStream& operator >> (QDataStream& in, options::slider_value& v) -{ - double cur, min, max; - in >> cur; - in >> min; - in >> max; - v = options::slider_value(cur, min, max); - return in; -} - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(options::slider_value) diff --git a/opentrack-compat/timer.hpp b/opentrack-compat/timer.hpp deleted file mode 100644 index 300a883c..00000000 --- a/opentrack-compat/timer.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/* 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 <ctime> - -#include "export.hpp" - -#if defined (_WIN32) -# include <windows.h> -# ifndef CLOCK_MONOTONIC -# define CLOCK_MONOTONIC -1 -# endif -static inline void opentrack_clock_gettime(int, struct timespec* ts) -{ - static LARGE_INTEGER freq; - - if (!freq.QuadPart) - (void) QueryPerformanceFrequency(&freq); - - LARGE_INTEGER d; - - (void) QueryPerformanceCounter(&d); - - using ll = long long; - using ld = long double; - const long long part = ll(d.QuadPart / ld(freq.QuadPart) * 1000000000.L); - using t_s = decltype(ts->tv_sec); - using t_ns = decltype(ts->tv_nsec); - - ts->tv_sec = t_s(part / 1000000000LL); - ts->tv_nsec = t_ns(part % 1000000000LL); -} -# define clock_gettime opentrack_clock_gettime -#else -# if defined(__MACH__) -# define CLOCK_MONOTONIC 0 -# include <inttypes.h> -# include <mach/mach_time.h> -static inline void clock_gettime(int, struct timespec* ts) -{ - static mach_timebase_info_data_t sTimebaseInfo; - uint64_t state, nsec; - if ( sTimebaseInfo.denom == 0 ) { - (void) mach_timebase_info(&sTimebaseInfo); - } - state = mach_absolute_time(); - nsec = state * sTimebaseInfo.numer / sTimebaseInfo.denom; - ts->tv_sec = nsec / 1000000000L; - ts->tv_nsec = nsec % 1000000000L; -} -# endif -#endif -class Timer -{ -private: - struct timespec state; - long long conv_nsecs(const struct timespec& cur) const - { - return (cur.tv_sec - state.tv_sec) * 1000000000LL + (cur.tv_nsec - state.tv_nsec); - } - long conv_usecs(const struct timespec& cur) const - { - return long(cur.tv_sec - state.tv_sec) * 1000000L + long(cur.tv_nsec - state.tv_nsec) / 1000l; - } -public: - Timer() - { - start(); - } - void start() - { - clock_gettime(CLOCK_MONOTONIC, &state); - } - long long elapsed_nsecs() const - { - struct timespec cur; - clock_gettime(CLOCK_MONOTONIC, &cur); - return conv_nsecs(cur); - } - long elapsed_usecs() const - { - struct timespec cur; - clock_gettime(CLOCK_MONOTONIC, &cur); - return long(conv_usecs(cur)); - } - long elapsed_ms() const - { - return elapsed_usecs() / 1000L; - } - double elapsed_seconds() const - { - return double(elapsed_nsecs() * 1e-9L); - } -}; diff --git a/opentrack-compat/util.hpp b/opentrack-compat/util.hpp deleted file mode 100644 index 1217e654..00000000 --- a/opentrack-compat/util.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include "make-unique.hpp" - -#include <memory> -#include <utility> -#include <type_traits> -#include <thread> -#include <condition_variable> - -#include <QDebug> - -#define progn(...) ([&]() { __VA_ARGS__ }()) -template<typename t> using mem = std::shared_ptr<t>; -template<typename t> using ptr = std::unique_ptr<t>; - -template<typename F> -void run_in_thread_async(QObject* obj, F&& fun) -{ - QObject src; - src.moveToThread(obj->thread()); - QObject::connect(&src, &QObject::destroyed, obj, std::move(fun), Qt::AutoConnection); -} - -namespace detail { - -template<typename t> -struct run_in_thread_traits -{ - using type = t; - using ret_type = t&&; - static inline void assign(t& lvalue, t&& rvalue) { lvalue = rvalue; } - static inline ret_type&& pass(ret_type&& val) { return std::move(val); } - template<typename F> static ret_type call(F& fun) { return std::move(fun()); } -}; - -template<> -struct run_in_thread_traits<void> -{ - using type = unsigned char; - using ret_type = void; - static inline void assign(unsigned char&, unsigned char&&) {} - static inline void pass(type&&) {} - template<typename F> static type&& call(F& fun) { fun(); return std::move(type(0)); } -}; - -} - -template<typename F> -auto run_in_thread_sync(QObject* obj, F&& fun) - -> typename detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>::ret_type -{ - using lock_guard = std::unique_lock<std::mutex>; - - std::mutex mtx; - lock_guard guard(mtx); - std::condition_variable cvar; - - std::thread::id waiting_thread = std::this_thread::get_id(); - - using traits = detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>; - - typename traits::type ret; - - bool skip_wait = false; - - { - QObject src; - src.moveToThread(obj->thread()); - QObject::connect(&src, - &QObject::destroyed, - obj, - [&]() { - std::thread::id calling_thread = std::this_thread::get_id(); - if (waiting_thread == calling_thread) - { - skip_wait = true; - traits::assign(ret, traits::call(fun)); - } - else - { - lock_guard guard(mtx); - traits::assign(ret, traits::call(fun)); - cvar.notify_one(); - } - }, - Qt::AutoConnection); - } - - if (!skip_wait) - cvar.wait(guard); - return traits::pass(std::move(ret)); -} diff --git a/opentrack-compat/win32-com.cpp b/opentrack-compat/win32-com.cpp deleted file mode 100644 index dd7c24a8..00000000 --- a/opentrack-compat/win32-com.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifdef _WIN32 - -#include "win32-com.hpp" - -#include <QString> -#include <QThread> -#include <QDebug> - -bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t) -{ - static thread_local com_type initialized = com_type(-1); - - if (initialized != com_type(-1)) - { - if (t != initialized) - { - QString tp("invalid type"); - switch (t) - { - case com_apartment: - tp = "apartment threaded"; - break; - case com_multithreaded: - tp = "multithreaded"; - break; - } - - qDebug() << "COM for thread" - << QThread::currentThread() << QThread::currentThreadId() - << "already initialized to" << tp; - - return false; - } - - return true; - } - - HRESULT ret = CoInitializeEx(0, t); - - if (ret != S_OK && ret != S_FALSE) - { - qDebug() << "CoInitializeEx failed:" << ret << GetLastError(); - return false; - } - - if (t == com_apartment) - { - ret = OleInitialize(nullptr); - - if (ret != S_OK && ret != S_FALSE) - qDebug() << "OleInitialize() failed:" << ret << GetLastError(); - - return false; - } - - initialized = t; - - return true; -} -#endif diff --git a/opentrack-compat/win32-com.hpp b/opentrack-compat/win32-com.hpp deleted file mode 100644 index dcbea089..00000000 --- a/opentrack-compat/win32-com.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#ifdef _WIN32 - -#include "export.hpp" - -#include <objbase.h> -#include <ole2.h> - -enum com_type : int -{ - com_multithreaded = COINIT_MULTITHREADED, - com_apartment = COINIT_APARTMENTTHREADED, -}; - -bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t = com_multithreaded); - -#endif diff --git a/opentrack-dinput/CMakeLists.txt b/opentrack-dinput/CMakeLists.txt deleted file mode 100644 index ed0b5990..00000000 --- a/opentrack-dinput/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -if(WIN32) - opentrack_boilerplate(opentrack-dinput BIN) - target_link_libraries(opentrack-dinput dinput) -endif() diff --git a/opentrack-dinput/dinput.cpp b/opentrack-dinput/dinput.cpp deleted file mode 100644 index ae132e70..00000000 --- a/opentrack-dinput/dinput.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifdef _WIN32 - -#include "dinput.hpp" -#include "opentrack-compat/win32-com.hpp" -#include <QDebug> - -std::atomic<int> dinput_handle::refcnt; -std::atomic_flag dinput_handle::init_lock = ATOMIC_FLAG_INIT; -dinput_handle::di_t dinput_handle::handle(dinput_handle::make_di()); - -LPDIRECTINPUT8& dinput_handle::init_di() -{ - init_com_threading(com_multithreaded); - - static LPDIRECTINPUT8 di_ = nullptr; - if (di_ == nullptr) - { - if (!SUCCEEDED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di_, NULL))) - { - di_ = nullptr; - } - } - return di_; -} - -dinput_handle::di_t dinput_handle::make_di() -{ - while (init_lock.test_and_set()) { /* busy loop */ } - - LPDIRECTINPUT8& ret = init_di(); - - init_lock.clear(); - - return di_t(ret); -} - -void dinput_handle::di_t::free_di() -{ - if (handle && *handle) - (*handle)->Release(); - *handle = nullptr; - handle = nullptr; -} - -void dinput_handle::di_t::ref_di() -{ - while (init_lock.test_and_set()) { /* busy loop */ } - - const int refcnt_ = refcnt.fetch_add(1) + 1; - qDebug() << "start: dinput refcount now" << (refcnt_); - - init_lock.clear(); -} - -dinput_handle::di_t& dinput_handle::di_t::operator=(const di_t& new_di) -{ - if (handle) - unref_di(); - - handle = new_di.handle; - - if (handle) - ref_di(); - - return *this; -} - -void dinput_handle::di_t::unref_di() -{ - while (init_lock.test_and_set()) { /* busy loop */ } - - const int refcnt_ = refcnt.fetch_sub(1) - 1; - - qDebug() << "exit: dinput refcount now" << refcnt_; - - if (refcnt_ == 0) - { - qDebug() << "exit: deleting di handle"; - free_di(); - } - - init_lock.clear(); -} - -dinput_handle::di_t::di_t(LPDIRECTINPUT8& handle) : handle(&handle) -{ - ref_di(); -} - -dinput_handle::di_t::di_t() : handle(nullptr) {} - -dinput_handle::di_t::~di_t() -{ - if (handle) - unref_di(); -} - -#endif diff --git a/opentrack-dinput/dinput.hpp b/opentrack-dinput/dinput.hpp deleted file mode 100644 index 53f1c4af..00000000 --- a/opentrack-dinput/dinput.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2016, 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 - -#ifdef _WIN32 - -#include "export.hpp" - -#ifndef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x800 -#endif -#include <dinput.h> - -#include <atomic> - -class OPENTRACK_DINPUT_EXPORT dinput_handle final -{ -public: - class di_t; - -private: - static std::atomic<int> refcnt; - static std::atomic_flag init_lock; - static di_t handle; - - static LPDIRECTINPUT8& init_di(); -public: - class di_t final - { - friend class dinput_handle; - - LPDIRECTINPUT8* handle; - - di_t(LPDIRECTINPUT8& handle); - void free_di(); - void unref_di(); - void ref_di(); - - public: - LPDIRECTINPUT8 operator->() { return *handle; } - operator LPDIRECTINPUT8() { return *handle; } - LPDIRECTINPUT8 di() { return *handle; } - di_t& operator=(const di_t& new_di); - di_t(); - ~di_t(); - }; - - static di_t make_di(); - dinput_handle() = delete; -}; - -#endif diff --git a/opentrack-dinput/export.hpp b/opentrack-dinput/export.hpp deleted file mode 100644 index 51ee4531..00000000 --- a/opentrack-dinput/export.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#ifdef BUILD_dinput -# ifdef _WIN32 -# define OPENTRACK_DINPUT_LINKAGE __declspec(dllexport) -# else -# define OPENTRACK_DINPUT_LINKAGE -# endif - -# ifndef _MSC_VER -# define OPENTRACK_DINPUT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_DINPUT_LINKAGE -# else -# define OPENTRACK_DINPUT_EXPORT OPENTRACK_DINPUT_LINKAGE -# endif - -#else -#ifdef _WIN32 -# define OPENTRACK_DINPUT_LINKAGE __declspec(dllimport) -#else -# define OPENTRACK_DINPUT_LINKAGE -#endif - -#ifndef _MSC_VER -# define OPENTRACK_DINPUT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_DINPUT_LINKAGE -#else -# define OPENTRACK_DINPUT_EXPORT OPENTRACK_DINPUT_LINKAGE -#endif -#endif diff --git a/opentrack-dinput/keybinding-worker.cpp b/opentrack-dinput/keybinding-worker.cpp deleted file mode 100644 index 32bfc6f0..00000000 --- a/opentrack-dinput/keybinding-worker.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* 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. - */ - -#ifdef _WIN32 - -#include "keybinding-worker.hpp" -#include <functional> -#include <windows.h> -#include <QDebug> -#include <QMutexLocker> - -bool Key::should_process() -{ - if (!enabled || (keycode == 0 && guid == "")) - return false; - bool ret = timer.elapsed_ms() > 100; - timer.start(); - return ret; -} - -KeybindingWorker::~KeybindingWorker() -{ - qDebug() << "exit: destroying keybinding worker"; - - should_quit = true; - wait(); - if (dinkeyboard) { - dinkeyboard->Unacquire(); - dinkeyboard->Release(); - } -} - -void KeybindingWorker::init() -{ - din = dinput_handle::make_di(); - - if (!din) - { - qDebug() << "can't create dinput handle"; - return; - } - - if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { - qDebug() << "setup CreateDevice function failed!" << GetLastError(); - return; - } - - if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { - qDebug() << "setup SetDataFormat function failed!" << GetLastError(); - dinkeyboard->Release(); - dinkeyboard = 0; - return; - } - - if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { - dinkeyboard->Release(); - dinkeyboard = 0; - qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); - return; - } - - if (dinkeyboard->Acquire() != DI_OK) - { - dinkeyboard->Release(); - dinkeyboard = 0; - qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); - return; - } -} - -KeybindingWorker::KeybindingWorker() : should_quit(false) -{ - start(); -} - -KeybindingWorker& KeybindingWorker::make() -{ - static KeybindingWorker k; - return k; -} - -void KeybindingWorker::run() -{ - init(); - - BYTE keystate[256] = {0}; - BYTE old_keystate[256] = {0}; - - while (!should_quit) - { - { - QMutexLocker l(&mtx); - - if (receivers.size()) - { - { - const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); - - if (hr != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - Sleep(25); - continue; - } - } - - { - using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; - - joy_fn f = [&](const QString& guid, int idx, bool held) -> void { - Key k; - k.keycode = idx; - k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); - k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); - k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); - k.guid = guid; - k.held = held; - - for (auto& r : receivers) - r->operator()(k); - }; - - joy_ctx.poll(f); - } - - for (int i = 0; i < 256; i++) - { - Key k; - if (old_keystate[i] != keystate[i]) - { - const bool held = keystate[i] & 0x80; - switch (i) - { - case DIK_LCONTROL: - case DIK_LSHIFT: - case DIK_LALT: - case DIK_RCONTROL: - case DIK_RSHIFT: - case DIK_RALT: - break; - default: - k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); - k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); - k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); - k.keycode = i; - k.held = held; - - for (auto& r : receivers) - r->operator()(k); - break; - } - } - old_keystate[i] = keystate[i]; - } - } - } - - // keypresses get dropped with high values - Sleep(4); - } -} - -KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) -{ - QMutexLocker l(&mtx); - receivers.push_back(std::unique_ptr<fun>(new fun(receiver))); - fun* f = receivers[receivers.size() - 1].get(); - //qDebug() << "add receiver" << (long) f; - joy_ctx.refresh(); - return f; -} - -void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) -{ - QMutexLocker l(&mtx); - bool ok = false; - - using s = int; - - for (int i = s(receivers.size()) - 1; i >= 0; i--) - { - using u = unsigned; - if (receivers[u(i)].get() == pos) - { - ok = true; - //qDebug() << "remove receiver" << (long) pos; - receivers.erase(receivers.begin() + i); - break; - } - } - if (!ok) - { - qDebug() << "bad remove receiver" << (long) pos; - } -} - -#endif diff --git a/opentrack-dinput/keybinding-worker.hpp b/opentrack-dinput/keybinding-worker.hpp deleted file mode 100644 index 623875ac..00000000 --- a/opentrack-dinput/keybinding-worker.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* 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 "export.hpp" - -#include "opentrack-compat/timer.hpp" -#include "win32-joystick.hpp" -#include "dinput.hpp" -#include <QThread> -#include <QMutex> -#include <QWidget> -#include <QMainWindow> -#include <QDebug> -#include <functional> -#include <vector> - -struct OPENTRACK_DINPUT_EXPORT Key -{ - BYTE keycode; - QString guid; - bool shift; - bool ctrl; - bool alt; - bool held; - bool enabled; - Timer timer; -public: - Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true), enabled(true) {} - - bool should_process(); -}; - -struct OPENTRACK_DINPUT_EXPORT KeybindingWorker : private QThread -{ - using fun = std::function<void(const Key&)>; - -private: - LPDIRECTINPUTDEVICE8 dinkeyboard; - win32_joy_ctx joy_ctx; - std::vector<std::unique_ptr<fun>> receivers; - QMutex mtx; - QMainWindow fake_main_window; - dinput_handle::di_t din; - volatile bool should_quit; - - void run() override; - void init(); - KeybindingWorker(); - - static KeybindingWorker& make(); - fun* _add_receiver(fun &receiver); - void remove_receiver(fun* pos); - ~KeybindingWorker(); - - KeybindingWorker(const KeybindingWorker&) = delete; - KeybindingWorker& operator=(KeybindingWorker&) = delete; -public: - class Token - { - fun* pos; - Token(const Token&) = delete; - Token& operator=(Token&) = delete; - public: - ~Token() - { - make().remove_receiver(pos); - } - Token(fun receiver) - { - pos = make()._add_receiver(receiver); - } - }; -}; diff --git a/opentrack-dinput/win32-joystick.cpp b/opentrack-dinput/win32-joystick.cpp deleted file mode 100644 index 18500a0d..00000000 --- a/opentrack-dinput/win32-joystick.cpp +++ /dev/null @@ -1,359 +0,0 @@ -#ifdef _WIN32 - -#undef NDEBUG -#include "win32-joystick.hpp" -#include "opentrack-compat/sleep.hpp" -#include <cassert> -#include <cstring> -#include <algorithm> -#include <cmath> -#include <objbase.h> - -#include <QDebug> - -QMutex win32_joy_ctx::enum_state::mtx; -win32_joy_ctx::enum_state win32_joy_ctx::enumerator; - -void win32_joy_ctx::poll(fn f) -{ - //refresh(false); - - QMutexLocker l(&enumerator.mtx); - - auto& joys = enumerator.get_joys(); - - for (auto& j : joys) - { - j.second->poll(f); - } -} - -bool win32_joy_ctx::poll_axis(const QString &guid, int* axes) -{ - QMutexLocker l(&enumerator.mtx); - - for (int k = 0; k < 10; k++) - { - if (k > 0) - enumerator.refresh(); - - const joys_t& joys = enumerator.get_joys(); - auto iter = joys.find(guid); - - if (iter == joys.end()) - return false; - - auto& j = iter->second; - - auto& joy_handle = j->joy_handle; - bool ok = false; - HRESULT hr; - - if (!FAILED(hr = joy_handle->Poll())) - { - ok = true; - } - - if (!ok && FAILED(hr = joy_handle->Acquire())) - { - //qDebug() << "joy acquire failed" << hr; - } - - if (!ok) - { - portable::sleep(25); - (void) joy_handle->Unacquire(); - continue; - } - - DIJOYSTATE2 js; - std::memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - //qDebug() << "joy get state failed" << guid << hr; - portable::sleep(50); - continue; - } - - const int values[] = - { - js.lX, - js.lY, - js.lZ, - js.lRx, - js.lRy, - js.lRz, - js.rglSlider[0], - js.rglSlider[1] - }; - - for (int i = 0; i < 8; i++) - axes[i] = values[i]; - - return true; - } - - return false; -} - -std::vector<win32_joy_ctx::joy_info> win32_joy_ctx::get_joy_info() -{ - std::vector<joy_info> ret; - QMutexLocker l(&enumerator.mtx); - auto& joys = enumerator.get_joys(); - ret.reserve(joys.size()); - - for (auto& j : joys) - ret.push_back(joy_info { j.second->name, j.first }); - - std::sort(ret.begin(), ret.end(), [&](const joy_info& fst, const joy_info& snd) -> bool { return fst.name < snd.name; }); - - return ret; -} - -win32_joy_ctx::win32_joy_ctx() -{ - refresh(); -} - -void win32_joy_ctx::refresh() -{ - QMutexLocker l(&enumerator.mtx); - enumerator.refresh(); -} - -QString win32_joy_ctx::guid_to_string(const GUID& guid) -{ - char buf[40] = {0}; - wchar_t szGuidW[40] = {0}; - - StringFromGUID2(guid, szGuidW, 40); - WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); - - return QString(buf); -} - -using fn = win32_joy_ctx::fn; - -void win32_joy_ctx::joy::release() -{ - if (joy_handle) - { - (void) joy_handle->Unacquire(); - joy_handle->Release(); - joy_handle = nullptr; - } -} - -bool win32_joy_ctx::joy::poll(fn f) -{ - HRESULT hr; - bool ok = false; - - (void) joy_handle->Acquire(); - - if (!FAILED(hr = joy_handle->Poll())) - ok = true; - - if (!ok) - { - qDebug() << "joy acquire failed" << guid << hr; - (void) joy_handle->Unacquire(); - return false; - } - - DIJOYSTATE2 js; - std::memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - qDebug() << "joy get state failed" << guid << hr; - return false; - } - - for (unsigned i = 0; i < 4; i++) - { - using std::round; - - unsigned char pos; - unsigned pos_ = js.rgdwPOV[i]; - if ((pos_ & 0xffff) == 0xffff) - pos = 0; - else if (pos_ == ~0u) - pos = 0; - else - { - using uc = unsigned char; - pos = uc(((pos_ / 9000u) % 4u) + 1u); - } - - const bool state[] = - { - pos == 1, - pos == 2, - pos == 3, - pos == 4 - }; - - unsigned idx = 128u + i * 4u; - - for (unsigned j = 0; j < 4; j++, idx++) - { - if (state[j] != pressed[idx]) - { - f(guid, int(idx), state[j]); - pressed[idx] = state[j]; - } - } - } - - for (int i = 0; i < 128; i++) - { - const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i]) - { - f(guid, i, state); - } - pressed[i] = state; - } - - return true; -} - -win32_joy_ctx::enum_state::enum_state() : di(dinput_handle::make_di()) -{ -} - -win32_joy_ctx::enum_state::~enum_state() -{ - QMutexLocker l(&mtx); - - joys = std::unordered_map<QString, std::shared_ptr<joy>>(); -} - -void win32_joy_ctx::enum_state::refresh() -{ - all.clear(); - - if (!di) - { - qDebug() << "can't create dinput"; - return; - } - - HRESULT hr; - - if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) - { - qDebug() << "failed enum joysticks" << hr; - return; - } - - for (auto it = joys.begin(); it != joys.end(); ) - { - if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.end()) - { - it = joys.erase(it); - } - else - { - ++it; - } - } -} - -const win32_joy_ctx::joys_t& win32_joy_ctx::enum_state::get_joys() const { return joys; } - -BOOL CALLBACK win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) -{ - enum_state& state = *reinterpret_cast<enum_state*>(pContext); - const QString guid = guid_to_string(pdidInstance->guidInstance); - const QString name = QString(pdidInstance->tszInstanceName); - - const bool exists = state.joys.find(guid) != state.joys.end(); - - state.all.push_back(guid); - - if (exists) - goto end; - - { - HRESULT hr; - LPDIRECTINPUTDEVICE8 h; - if (FAILED(hr = state.di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) - { - qDebug() << "createdevice" << guid << hr; - goto end; - } - if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) - { - qDebug() << "format"; - h->Release(); - goto end; - } - - // not a static member - need main() to run for some time first - static const QWidget fake_window; - - if (FAILED(h->SetCooperativeLevel(reinterpret_cast<HWND>(fake_window.winId()), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) - { - qDebug() << "coop"; - h->Release(); - goto end; - } - if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) - { - qDebug() << "enum-objects"; - h->Release(); - goto end; - } - - state.joys[guid] = std::make_shared<joy>(h, guid, name); - } -end: - return DIENUM_CONTINUE; -} - -BOOL CALLBACK win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx) -{ - if (pdidoi->dwType & DIDFT_AXIS) - { - DIPROPRANGE diprg; - std::memset(&diprg, 0, sizeof(diprg)); - diprg.diph.dwSize = sizeof( DIPROPRANGE ); - diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); - diprg.diph.dwHow = DIPH_BYID; - diprg.diph.dwObj = pdidoi->dwType; - diprg.lMax = joy_axis_size; - diprg.lMin = -joy_axis_size; - - HRESULT hr; - - if (FAILED(hr = reinterpret_cast<LPDIRECTINPUTDEVICE8>(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) - { - qDebug() << "DIPROP_RANGE" << hr; - return DIENUM_STOP; - } - } - - return DIENUM_CONTINUE; -} - -win32_joy_ctx::joy::joy(LPDIRECTINPUTDEVICE8 handle, const QString &guid, const QString &name) - : joy_handle(handle), guid(guid), name(name) -{ - qDebug() << "make joy" << guid << name << joy_handle; - std::memset(pressed, 0, sizeof(pressed)); -} - -win32_joy_ctx::joy::~joy() -{ - qDebug() << "nix joy" << guid; - release(); -} - -#endif diff --git a/opentrack-dinput/win32-joystick.hpp b/opentrack-dinput/win32-joystick.hpp deleted file mode 100644 index ef8f59b0..00000000 --- a/opentrack-dinput/win32-joystick.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (c) 2015-2016, 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 - -#ifdef _WIN32 - -#include "dinput.hpp" -#include "opentrack-compat/timer.hpp" -#include "export.hpp" -#include <cstring> -#include <memory> -#include <vector> -#include <functional> -#include <algorithm> -#include <unordered_map> -#include <QString> -#include <QDebug> -#include <QMutex> -#include <QMutexLocker> -#include <QWidget> - -namespace std { -template<> -struct hash<QString> -{ - inline std::size_t operator()(const QString& value) const - { - return qHash(value); - } -}; -} - -struct OPENTRACK_DINPUT_EXPORT win32_joy_ctx -{ - using fn = std::function<void(const QString& guid, int btn, bool held)>; - - struct joy - { - LPDIRECTINPUTDEVICE8 joy_handle; - QString guid, name; - bool pressed[128 + 4 * 4]; - Timer first_timer; - - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name); - ~joy(); - - void release(); - bool poll(fn f); - }; - - using joys_t = std::unordered_map<QString, std::shared_ptr<joy>>; - - static constexpr int joy_axis_size = 65535; - - struct joy_info - { - QString name, guid; - }; - - void poll(fn f); - bool poll_axis(const QString& guid, int* axes); - std::vector<joy_info> get_joy_info(); - - win32_joy_ctx(const win32_joy_ctx&) = delete; - win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; - - win32_joy_ctx(); - void refresh(); - - using di_t = dinput_handle::di_t; - -private: - static QString guid_to_string(const GUID& guid); - - class OPENTRACK_DINPUT_EXPORT enum_state final - { - std::vector<QString> all; - joys_t joys; - dinput_handle::di_t di; - - static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); - static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); - - public: - static QMutex mtx; - - enum_state(); - ~enum_state(); - void refresh(); - const joys_t& get_joys() const; - }; - - static enum_state enumerator; -}; - -#endif diff --git a/opentrack-logic/CMakeLists.txt b/opentrack-logic/CMakeLists.txt deleted file mode 100644 index 88b0240f..00000000 --- a/opentrack-logic/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -opentrack_boilerplate(opentrack-logic BIN) -target_link_libraries(opentrack-logic opentrack-spline-widget) -if(NOT WIN32) - target_link_libraries(opentrack-logic opentrack-qxt-mini) -else() - target_link_libraries(opentrack-logic opentrack-dinput winmm) -endif() diff --git a/opentrack-logic/export.hpp b/opentrack-logic/export.hpp deleted file mode 100644 index 2503f3a6..00000000 --- a/opentrack-logic/export.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#ifdef BUILD_logic -# ifdef _WIN32 -# define OPENTRACK_LOGIC_LINKAGE __declspec(dllexport) -# else -# define OPENTRACK_LOGIC_LINKAGE -# endif - -# ifndef _MSC_VER -# define OPENTRACK_LOGIC_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LOGIC_LINKAGE -# else -# define OPENTRACK_LOGIC_EXPORT OPENTRACK_LOGIC_LINKAGE -# endif - -#else -#ifdef _WIN32 -# define OPENTRACK_LOGIC_LINKAGE __declspec(dllimport) -#else -# define OPENTRACK_LOGIC_LINKAGE -#endif - -#ifndef _MSC_VER -# define OPENTRACK_LOGIC_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LOGIC_LINKAGE -#else -# define OPENTRACK_LOGIC_EXPORT OPENTRACK_LOGIC_LINKAGE -#endif -#endif diff --git a/opentrack-logic/main-settings.hpp b/opentrack-logic/main-settings.hpp deleted file mode 100644 index 29f7f62c..00000000 --- a/opentrack-logic/main-settings.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (c) 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 <QString> -#include "opentrack-compat/options.hpp" -#include "opentrack/plugin-api.hpp" - -using namespace options; - -#include "export.hpp" - -struct axis_opts -{ - pbundle b; - value<double> zero; - value<bool> invert, altp; - value<int> src; - axis_opts(pbundle b, QString pfx, int idx) : - b(b), - zero(b, n(pfx, "zero-pos"), 0), - invert(b, n(pfx, "invert-sign"), false), - altp(b, n(pfx, "alt-axis-sign"), false), - src(b, n(pfx, "source-index"), idx) - {} -private: - static inline QString n(QString pfx, QString name) { - return QString("%1-%2").arg(pfx, name); - } -}; - -struct key_opts -{ - value<QString> keycode, guid; - value<int> button; - - key_opts(pbundle b, const QString& name) : - keycode(b, QString("keycode-%1").arg(name), ""), - guid(b, QString("guid-%1").arg(name), ""), - button(b, QString("button-%1").arg(name), -1) - {} -}; - -struct module_settings -{ - pbundle b; - value<QString> tracker_dll, filter_dll, protocol_dll; - module_settings() : - b(bundle("modules")), - tracker_dll(b, "tracker-dll", ""), - filter_dll(b, "filter-dll", "Accela"), - protocol_dll(b, "protocol-dll", "freetrack 2.0 Enhanced") - { - } -}; - -struct main_settings -{ - pbundle b, b_map; - axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll; - value<bool> tcomp_p, tcomp_tz; - value<bool> tray_enabled; - value<int> camera_yaw, camera_pitch, camera_roll; - value<bool> use_camera_offset_from_centering; - value<bool> center_at_startup; - value<int> center_method; - key_opts key_start_tracking, key_stop_tracking, key_toggle_tracking, key_restart_tracking; - key_opts key_center, key_toggle, key_zero; - key_opts key_toggle_press, key_zero_press; - value<bool> tracklogging_enabled; - value<QString> tracklogging_filename; - main_settings() : - b(bundle("opentrack-ui")), - b_map(bundle("opentrack-mappings")), - a_x(b_map, "x", TX), - a_y(b_map, "y", TY), - a_z(b_map, "z", TZ), - a_yaw(b_map, "yaw", Yaw), - a_pitch(b_map, "pitch", Pitch), - a_roll(b_map, "roll", Roll), - tcomp_p(b, "compensate-translation", true), - tcomp_tz(b, "compensate-translation-disable-z-axis", false), - tray_enabled(b, "use-system-tray", false), - camera_yaw(b, "camera-yaw", 0), - camera_pitch(b, "camera-pitch", 0), - camera_roll(b, "camera-roll", 0), - use_camera_offset_from_centering(b, "use-camera-offset-from-centering", false), - center_at_startup(b, "center-at-startup", true), - center_method(b, "centering-method", true), - key_start_tracking(b, "start-tracking"), - key_stop_tracking(b, "stop-tracking"), - key_toggle_tracking(b, "toggle-tracking"), - key_restart_tracking(b, "restart-tracking"), - key_center(b, "center"), - key_toggle(b, "toggle"), - key_zero(b, "zero"), - key_toggle_press(b, "toggle-press"), - key_zero_press(b, "zero-press"), - tracklogging_enabled(b, "tracklogging-enabled", false), - tracklogging_filename(b, "tracklogging-filename", QString()) - { - } -}; diff --git a/opentrack-logic/mappings.hpp b/opentrack-logic/mappings.hpp deleted file mode 100644 index 3e396980..00000000 --- a/opentrack-logic/mappings.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright (c) 2014-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 <QSettings> -#include "opentrack-compat/options.hpp" -using namespace options; -#include "spline-widget/spline.hpp" -#include "main-settings.hpp" - -class Map { -public: - Map(QString primary, - QString secondary, - int max_x, - int max_y, - axis_opts& opts) : - spline_main(max_x, max_y), - spline_alt(max_x, max_y), - opts(opts), - name1(primary), - name2(secondary) - { - mem<QSettings> iniFile = group::ini_file(); - spline_main.loadSettings(*iniFile, primary); - spline_alt.loadSettings(*iniFile, secondary); - } - spline spline_main; - spline spline_alt; - axis_opts& opts; - QString name1, name2; -}; - -class Mappings { -private: - Map axes[6]; -public: - Mappings(std::vector<axis_opts*> opts) : - axes { - Map("tx","tx_alt", 30, 75, *opts[TX]), - Map("ty","ty_alt", 30, 75, *opts[TY]), - Map("tz","tz_alt", 30, 75, *opts[TZ]), - Map("rx", "rx_alt", 180, 180, *opts[Yaw]), - Map("ry", "ry_alt", 180, 180, *opts[Pitch]), - Map("rz", "rz_alt", 180, 180, *opts[Roll]) - } - {} - - inline Map& operator()(int i) { return axes[i]; } - inline const Map& operator()(int i) const { return axes[i]; } - - void load_mappings() - { - mem<QSettings> iniFile = group::ini_file(); - - for (int i = 0; i < 6; i++) - { - axes[i].spline_main.loadSettings(*iniFile, axes[i].name1); - axes[i].spline_alt.loadSettings(*iniFile, axes[i].name2); - axes[i].opts.b->reload(); - } - } - void save_mappings() - { - mem<QSettings> iniFile = group::ini_file(); - - for (int i = 0; i < 6; i++) - { - axes[i].spline_main.saveSettings(*iniFile, axes[i].name1); - axes[i].spline_alt.saveSettings(*iniFile, axes[i].name2); - axes[i].opts.b->save(); - } - } - - void invalidate_unsaved() - { - for (int i = 0; i < 6; i++) - { - axes[i].spline_main.invalidate_unsaved_settings(); - axes[i].spline_alt.invalidate_unsaved_settings(); - axes[i].opts.b->reload(); - } - } -}; diff --git a/opentrack-logic/selected-libraries.cpp b/opentrack-logic/selected-libraries.cpp deleted file mode 100644 index 4a1a9f09..00000000 --- a/opentrack-logic/selected-libraries.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "selected-libraries.hpp" -#include <QDebug> - -SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) : - pTracker(nullptr), - pFilter(nullptr), - pProtocol(nullptr), - correct(false) -{ - pProtocol = make_dylib_instance<IProtocol>(p); - - if (!pProtocol) - { - qDebug() << "protocol dylib load failure"; - return; - } - - if(!pProtocol->correct()) - { - qDebug() << "protocol load failure"; - pProtocol = nullptr; - return; - } - - pTracker = make_dylib_instance<ITracker>(t); - pFilter = make_dylib_instance<IFilter>(f); - - if (!pTracker) - { - qDebug() << "tracker dylib load failure"; - return; - } - - pTracker->start_tracker(frame); - - correct = true; -} diff --git a/opentrack-logic/selected-libraries.hpp b/opentrack-logic/selected-libraries.hpp deleted file mode 100644 index 2538adff..00000000 --- a/opentrack-logic/selected-libraries.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* 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 "opentrack/plugin-support.hpp" -#include <QFrame> - -#include "export.hpp" - -struct OPENTRACK_LOGIC_EXPORT SelectedLibraries -{ - using dylibptr = mem<dylib>; - mem<ITracker> pTracker; - mem<IFilter> pFilter; - mem<IProtocol> pProtocol; - SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f); - SelectedLibraries() : pTracker(nullptr), pFilter(nullptr), pProtocol(nullptr), correct(false) {} - bool correct; -}; diff --git a/opentrack-logic/shortcuts.cpp b/opentrack-logic/shortcuts.cpp deleted file mode 100644 index 8d818180..00000000 --- a/opentrack-logic/shortcuts.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* 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. - */ - -#include "shortcuts.h" -#include "win32-shortcuts.h" - -void Shortcuts::free_binding(K& key) -{ -#ifndef _WIN32 - if (key) - { - key->setEnabled(false); - key->setShortcut(QKeySequence::UnknownKey); - std::shared_ptr<QxtGlobalShortcut> tmp(nullptr); - key.swap(tmp); - } -#else - key.keycode = 0; - key.guid = ""; -#endif -} - -void Shortcuts::bind_shortcut(K &key, const key_opts& k, unused_on_unix(bool, held)) -{ -#if !defined(_WIN32) - using sh = QxtGlobalShortcut; - if (key) - { - free_binding(key); - } - - key = std::make_shared<sh>(); - - if (k.keycode != "") - { - key->setShortcut(QKeySequence::fromString(k.keycode, QKeySequence::PortableText)); - key->setEnabled(); - } -} -#else - key = K(); - int idx = 0; - QKeySequence code; - - if (k.guid != "") - { - key.guid = k.guid; - key.keycode = k.button & ~Qt::KeyboardModifierMask; - key.ctrl = !!(k.button & Qt::ControlModifier); - key.alt = !!(k.button & Qt::AltModifier); - key.shift = !!(k.button & Qt::ShiftModifier); - } - else - { - if (k.keycode == "") - code = QKeySequence(Qt::Key_unknown); - else - code = QKeySequence::fromString(k.keycode, QKeySequence::PortableText); - - Qt::KeyboardModifiers mods = Qt::NoModifier; - if (code != Qt::Key_unknown) - win_key::from_qt(code, idx, mods); - key.shift = !!(mods & Qt::ShiftModifier); - key.alt = !!(mods & Qt::AltModifier); - key.ctrl = !!(mods & Qt::ControlModifier); - key.keycode = idx; - key.held = held; - } -} -#endif - -#ifdef _WIN32 -void Shortcuts::receiver(const Key& k) -{ - const unsigned sz = keys.size(); - for (unsigned i = 0; i < sz; i++) - { - K& k_ = std::get<0>(keys[i]); - auto& fun = std::get<1>(keys[i]); - if (k.guid != k_.guid) - continue; - if (k.keycode != k_.keycode) - continue; - if (k_.held && !k.held) continue; - if (k_.alt != k.alt) continue; - if (k_.ctrl != k.ctrl) continue; - if (k_.shift != k.shift) continue; - if (!k_.should_process()) - continue; - - fun(k.held); - } -} -#endif - -void Shortcuts::reload(const t_keys& keys_) -{ - const unsigned sz = keys_.size(); - keys = std::vector<tt>(); - - for (unsigned i = 0; i < sz; i++) - { - const auto& kk = keys_[i]; - const key_opts& opts = std::get<0>(kk); - const bool held = std::get<2>(kk); - auto fun = std::get<1>(kk); - K k; - bind_shortcut(k, opts, held); - keys.push_back(tt(k, [=](unused_on_unix(bool, flag)) -> void - { -#ifdef _WIN32 - fun(flag); -#else - fun(true); -#endif - }, - held)); -#ifndef _WIN32 - const int idx = keys.size() - 1; - tt& kk_ = keys[idx]; - auto& fn = std::get<1>(kk_); - connect(k.get(), &QxtGlobalShortcut::activated, [=]() -> void { fn(true); }); -#endif - } -} diff --git a/opentrack-logic/shortcuts.h b/opentrack-logic/shortcuts.h deleted file mode 100644 index b44864ba..00000000 --- a/opentrack-logic/shortcuts.h +++ /dev/null @@ -1,68 +0,0 @@ -/* 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 <QObject> -#include <tuple> -#include <vector> -#include <functional> - -#include "export.hpp" - -#include "qxt-mini/QxtGlobalShortcut" -#include "opentrack-compat/options.hpp" -#include "main-settings.hpp" - -#ifdef _WIN32 -# include "opentrack-dinput/keybinding-worker.hpp" -#endif - -#if defined(__GNUC__) && !defined(_WIN32) -# define unused_on_unix(t, i) t __attribute__((unused)) i -#else -# define unused_on_unix(t, i) t i -#endif - -using namespace options; - -struct OPENTRACK_LOGIC_EXPORT Shortcuts : public QObject -{ - Q_OBJECT - -public: - using K = -#ifndef _WIN32 - mem<QxtGlobalShortcut> -#else - Key -#endif - ; - - using fun = std::function<void(bool)>; - using tt = std::tuple<K, fun, bool>; - using t_key = std::tuple<key_opts&, fun, bool>; - using t_keys = std::vector<t_key>; - std::vector<tt> keys; -#ifdef _WIN32 - KeybindingWorker::Token key_token; -#endif - - Shortcuts() -#ifdef _WIN32 - : key_token([&](const Key& k) { receiver(k); }) -#endif - {} - - void reload(const t_keys& keys_); -private: - void free_binding(K& key); - void bind_shortcut(K &key, const key_opts& k, bool held); -#ifdef _WIN32 - void receiver(const Key& k); -#endif -}; diff --git a/opentrack-logic/simple-mat.cpp b/opentrack-logic/simple-mat.cpp deleted file mode 100644 index 8c97f192..00000000 --- a/opentrack-logic/simple-mat.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "simple-mat.hpp" -#include "opentrack-compat/pi-constant.hpp" -#include <cmath> - -namespace euler { - -euler_t OPENTRACK_LOGIC_EXPORT rmat_to_euler(const rmat& R) -{ - using std::atan2; - using std::sqrt; - - const double cy = sqrt(R(2,2)*R(2, 2) + R(2, 1)*R(2, 1)); - const bool large_enough = cy > 1e-10; - if (large_enough) - return euler_t(atan2(-R(1, 0), R(0, 0)), - atan2(R(2, 0), cy), - atan2(-R(2, 1), R(2, 2))); - else - return euler_t(atan2(R(0, 1), R(1, 1)), - atan2(R(2, 0), cy), - 0); -} - -// tait-bryan angles, not euler -rmat OPENTRACK_LOGIC_EXPORT euler_to_rmat(const euler_t& input) -{ - const double H = -input(0); - const double P = -input(1); - const double B = -input(2); - - using std::cos; - using std::sin; - - const auto c1 = cos(H); - const auto s1 = sin(H); - const auto c2 = cos(P); - const auto s2 = sin(P); - const auto c3 = cos(B); - const auto s3 = sin(B); - - return rmat( - // z - c1 * c2, - c1 * s2 * s3 - c3 * s1, - s1 * s3 + c1 * c3 * s2, - // y - c2 * s1, - c1 * c3 + s1 * s2 * s3, - c3 * s1 * s2 - c1 * s3, - // x - -s2, - c2 * s3, - c2 * c3 - ); -} - -// https://en.wikipedia.org/wiki/Davenport_chained_rotations#Tait.E2.80.93Bryan_chained_rotations -void OPENTRACK_LOGIC_EXPORT tait_bryan_to_matrices(const euler_t& input, - rmat& r_roll, - rmat& r_pitch, - rmat& r_yaw) -{ - using std::cos; - using std::sin; - - { - const double phi = -input(2); - const double sin_phi = sin(phi); - const double cos_phi = cos(phi); - - r_roll = rmat(1, 0, 0, - 0, cos_phi, -sin_phi, - 0, sin_phi, cos_phi); - } - - { - const double theta = -input(1); - const double sin_theta = sin(theta); - const double cos_theta = cos(theta); - - r_pitch = rmat(cos_theta, 0, -sin_theta, - 0, 1, 0, - sin_theta, 0, cos_theta); - } - - { - const double psi = -input(0); - const double sin_psi = sin(psi); - const double cos_psi = cos(psi); - - r_yaw = rmat(cos_psi, -sin_psi, 0, - sin_psi, cos_psi, 0, - 0, 0, 1); - } -} - -} // end ns euler diff --git a/opentrack-logic/simple-mat.hpp b/opentrack-logic/simple-mat.hpp deleted file mode 100644 index 514e845f..00000000 --- a/opentrack-logic/simple-mat.hpp +++ /dev/null @@ -1,279 +0,0 @@ -/* Copyright (c) 2014-2016, 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 "export.hpp" - -#include <initializer_list> -#include <type_traits> -#include <utility> - -namespace { - // last param to fool SFINAE into overloading - template<int i, int j, int> - struct equals - { - enum { value = i == j }; - }; - template<int i, int j, int min> - struct maybe_add_swizzle - { - enum { value = (i == 1 || j == 1) && (i >= min || j >= min) }; - }; - template<int i1, int j1, int i2, int j2> - struct is_vector_pair - { - enum { value = (i1 == i2 && j1 == 1 && j2 == 1) || (j1 == j2 && i1 == 1 && i2 == 1) }; - }; - template<int i, int j> - struct vector_len - { - enum { value = i > j ? i : j }; - }; - template<int a, int b, int c, int d> - struct is_dim3 - { - enum { value = (a == 1 && c == 1 && b == 3 && d == 3) || (a == 3 && c == 3 && b == 1 && d == 1) }; - enum { P = a == 1 ? 1 : 3 }; - enum { Q = a == 1 ? 3 : 1 }; - }; - - template<typename num, int h, int w, typename...ts> - struct is_arglist_correct - { - enum { value = h * w == sizeof...(ts) }; - }; -} - -template<typename num, int h_, int w_> -class Mat -{ - static_assert(h_ > 0 && w_ > 0, "must have positive mat dimensions"); - num data[h_][w_]; - -public: - template<int Q = w_> typename std::enable_if<equals<Q, 1, 0>::value, num>::type - inline operator()(int i) const { return data[i][0]; } - - template<int P = h_> typename std::enable_if<equals<P, 1, 1>::value, num>::type - inline operator()(int i) const { return data[0][i]; } - - template<int Q = w_> typename std::enable_if<equals<Q, 1, 2>::value, num&>::type - inline operator()(int i) { return data[i][0]; } - - template<int P = h_> typename std::enable_if<equals<P, 1, 3>::value, num&>::type - inline operator()(int i) { return data[0][i]; } - -#define OPENTRACK_ASSERT_SWIZZLE static_assert(P == h_ && Q == w_, "") - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 1>::value, num>::type - x() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(0); } - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 2>::value, num>::type - y() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(1); } - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 3>::value, num>::type - z() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(2); } - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 4>::value, num>::type - w() const { OPENTRACK_ASSERT_SWIZZLE; return operator()(3); } - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 1>::value, num&>::type - x() { OPENTRACK_ASSERT_SWIZZLE; return operator()(0); } - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 2>::value, num&>::type - y() { OPENTRACK_ASSERT_SWIZZLE; return operator()(1); } - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 3>::value, num&>::type - z() { OPENTRACK_ASSERT_SWIZZLE; return operator()(2); } - - template<int P = h_, int Q = w_> typename std::enable_if<maybe_add_swizzle<P, Q, 4>::value, num&>::type - w() { OPENTRACK_ASSERT_SWIZZLE; return operator()(3); } - // parameters w_ and h_ are rebound so that SFINAE occurs - // removing them causes a compile-time error -sh 20150811 - - template<int R, int S, int P = h_, int Q = w_> - typename std::enable_if<is_vector_pair<R, S, P, Q>::value, num>::type - dot(const Mat<num, R, S>& p2) const - { - static_assert(P == h_ && Q == w_, ""); - - num ret = 0; - constexpr int len = vector_len<R, S>::value; - for (int i = 0; i < len; i++) - ret += operator()(i) * p2(i); - return ret; - } - - template<int R, int S, int P = h_, int Q = w_> - typename std::enable_if<is_dim3<P, Q, R, S>::value, Mat<num, is_dim3<P, Q, R, S>::P, is_dim3<P, Q, R, S>::Q>>::type - cross(const Mat<num, R, S>& p2) const - { - static_assert(P == h_ && Q == w_, ""); - decltype(*this)& p1 = *this; - - return Mat<num, R, S>(p1.y() * p2.z() - p2.y() * p1.z(), - p2.x() * p1.z() - p1.x() * p2.z(), - p1.x() * p2.y() - p1.y() * p2.x()); - } - - Mat<num, h_, w_> operator+(const Mat<num, h_, w_>& other) const - { - Mat<num, h_, w_> ret; - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - ret(j, i) = data[j][i] + other.data[j][i]; - return ret; - } - - Mat<num, h_, w_> operator-(const Mat<num, h_, w_>& other) const - { - Mat<num, h_, w_> ret; - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - ret(j, i) = data[j][i] - other.data[j][i]; - return ret; - } - - Mat<num, h_, w_> operator+(const num& other) const - { - Mat<num, h_, w_> ret; - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - ret(j, i) = data[j][i] + other; - return ret; - } - - Mat<num, h_, w_> operator-(const num& other) const - { - Mat<num, h_, w_> ret; - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - ret(j, i) = data[j][i] - other; - return ret; - } - - template<int p> - Mat<num, h_, p> operator*(const Mat<num, w_, p>& other) const - { - Mat<num, h_, p> ret; - for (int k = 0; k < h_; k++) - for (int i = 0; i < p; i++) - { - ret(k, i) = 0; - for (int j = 0; j < w_; j++) - ret(k, i) += data[k][j] * other(j, i); - } - return ret; - } - - inline num operator()(int j, int i) const { return data[j][i]; } - inline num& operator()(int j, int i) { return data[j][i]; } - - template<typename... ts, int h__ = h_, int w__ = w_, - typename = typename std::enable_if<is_arglist_correct<num, h__, w__, ts...>::value>::type> - Mat(const ts... xs) - { - static_assert(h__ == h_ && w__ == w_, ""); - - std::initializer_list<num> init = { static_cast<num>(xs)... }; - - *this = Mat(std::move(init)); - } - - Mat() - { - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - data[j][i] = num(0); - } - - Mat(const num* mem) - { - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - data[j][i] = mem[i*h_+j]; - } - - Mat(std::initializer_list<num>&& init) - { - auto iter = init.begin(); - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - data[j][i] = *iter++; - } - - operator num*() { return reinterpret_cast<num*>(data); } - operator const num*() const { return reinterpret_cast<const num*>(data); } - - // XXX add more operators as needed, third-party dependencies mostly - // not needed merely for matrix algebra -sh 20141030 - - template<int h__ = h_> - static typename std::enable_if<h_ == w_, Mat<num, h__, h__>>::type eye() - { - static_assert(h_ == h__, ""); - - Mat<num, h_, h_> ret; - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - ret.data[j][i] = 0; - - for (int i = 0; i < h_; i++) - ret.data[i][i] = 1; - - return ret; - } - - Mat<num, w_, h_> t() const - { - Mat<num, w_, h_> ret; - - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - ret(i, j) = data[j][i]; - - return ret; - } -}; - -template<int h_, int w_> using dmat = Mat<double, h_, w_>; - -template<typename num, int h, int w> -Mat<num, h, w> operator*(num scalar, const Mat<num, h, w>& mat) -{ - return mat * scalar; -} - -template<typename num, int h_, int w_> -Mat<num, h_, w_> operator*(const Mat<num, h_, w_>& self, num other) -{ - Mat<num, h_, w_> ret; - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - ret(j, i) = self(j, i) * other; - return ret; -} - -namespace euler { - -template<int y, int x> using dmat = Mat<double, y, x>; -using rmat = dmat<3, 3>; -using euler_t = dmat<3, 1>; - -rmat OPENTRACK_LOGIC_EXPORT euler_to_rmat(const euler_t& input); - -euler_t OPENTRACK_LOGIC_EXPORT rmat_to_euler(const rmat& R); - -void OPENTRACK_LOGIC_EXPORT tait_bryan_to_matrices(const euler_t& input, - rmat& r_roll, - rmat& r_pitch, - rmat& r_yaw); - -} // end ns euler diff --git a/opentrack-logic/state.hpp b/opentrack-logic/state.hpp deleted file mode 100644 index 1c608f7a..00000000 --- a/opentrack-logic/state.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* 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 "opentrack-compat/options.hpp" -using namespace options; -#include "opentrack/plugin-support.hpp" -#include "main-settings.hpp" -#include "mappings.hpp" -#include "selected-libraries.hpp" -#include "work.hpp" -#include <vector> -#include <QString> - -struct State -{ - State(const QString& library_path) : - modules(library_path), - pose(std::vector<axis_opts*>{&s.a_x, &s.a_y, &s.a_z, &s.a_yaw, &s.a_pitch, &s.a_roll}) - {} - Modules modules; - SelectedLibraries libs; - main_settings s; - Mappings pose; - mem<Work> work; -}; diff --git a/opentrack-logic/tracker.cpp b/opentrack-logic/tracker.cpp deleted file mode 100644 index d060fff1..00000000 --- a/opentrack-logic/tracker.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright (c) 2012-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. - */ - -/* - * this file appeared originally in facetracknoir, was rewritten completely - * following opentrack fork. - * - * originally written by Wim Vriend. - */ - -#include "opentrack-compat/sleep.hpp" - -#include "tracker.h" -#include <cmath> -#include <algorithm> -#include <cstdio> - -#if defined(_WIN32) -# include <windows.h> -#endif - -Tracker::Tracker(Mappings &m, SelectedLibraries &libs, TrackLogger &logger) : - m(m), - newpose {0,0,0, 0,0,0}, - libs(libs), - logger(logger), - r_b(get_camera_offset_matrix(c_div).t()), - r_b_real(get_camera_offset_matrix(1).t()), - t_b {0,0,0}, - centerp(s.center_at_startup), - enabledp(true), - zero_(false), - should_quit(false) -{ -} - -Tracker::~Tracker() -{ - should_quit = true; - wait(); -} - -Tracker::rmat Tracker::get_camera_offset_matrix(double c) -{ - const double off[] = - { - d2r * c * (double)-s.camera_yaw, - d2r * c * (double)-s.camera_pitch, - d2r * c * (double)-s.camera_roll - }; - - return euler::euler_to_rmat(off); -} - -double Tracker::map(double pos, Map& axis) -{ - bool altp = (pos < 0) && axis.opts.altp; - axis.spline_main.setTrackingActive( !altp ); - axis.spline_alt.setTrackingActive( altp ); - auto& fc = altp ? axis.spline_alt : axis.spline_main; - return fc.getValue(pos); -} - -void Tracker::t_compensate(const rmat& rmat, const euler_t& xyz_, euler_t& output, bool rz) -{ - // TY is really yaw axis. need swapping accordingly. - const euler_t ret = rmat * euler_t(xyz_(TZ), -xyz_(TX), -xyz_(TY)); - if (!rz) - output(2) = ret(0); - else - output(2) = xyz_(2); - output(1) = -ret(2); - output(0) = -ret(1); -} - -#include "opentrack-compat/nan.hpp" - -static inline double elide_nan(double value, double def) -{ - if (nanp(value)) - { - if (nanp(def)) - return 0; - return def; - } - return value; -} - -static bool is_nan(const dmat<3,3>& r, const dmat<3, 1>& t) -{ - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) - if (nanp(r(i, j))) - return true; - - for (int i = 0; i < 3; i++) - if (nanp(t(i))) - return true; - - return false; -} - -static bool is_nan(const Pose& value) -{ - for (int i = 0; i < 6; i++) - if (nanp(value(i))) - return true; - return false; -} - -constexpr double Tracker::c_mult; -constexpr double Tracker::c_div; - -void Tracker::logic() -{ - using namespace euler; - - logger.write_dt(); - logger.reset_dt(); - - Pose value, raw; - - for (int i = 0; i < 6; i++) - { - auto& axis = m(i); - int k = axis.opts.src; - if (k < 0 || k >= 6) - value(i) = 0; - else - value(i) = newpose[k]; - raw(i) = newpose[i]; - } - - logger.write_pose(raw); // raw - - if (is_nan(raw)) - raw = last_raw; - - // TODO fix gimbal lock by dividing euler angle input by >=3. - // maintain the real rmat separately for translation compensation - // TODO split this function, it's too big - rmat r, r_real; - - { - euler_t tmp = d2r * euler_t(&value[Yaw]); - r = euler_to_rmat(c_div * tmp); - r_real = euler_to_rmat(tmp); - } - - euler_t t(value(0), value(1), value(2)); - - bool do_center_now = false; - bool nan = is_nan(r, t); - - if (centerp && !nan) - { - for (int i = 0; i < 6; i++) - if (fabs(newpose[i]) != 0) - { - do_center_now = true; - break; - } - } - - const rmat cam = get_camera_offset_matrix(c_div); - const rmat cam_real = get_camera_offset_matrix(1); - - r = r * cam; - r_real = r_real * cam_real; - - if (do_center_now) - { - centerp = false; - - if (libs.pFilter) - libs.pFilter->center(); - - if (libs.pTracker->center()) - { - r_b = cam.t(); - r_b_real = cam_real.t(); - r = rmat::eye(); - r_real = rmat::eye(); - } - else - { - r_b = r.t(); - r_b_real = r_real.t(); - } - - for (int i = 0; i < 3; i++) - t_b[i] = t(i); - } - - { - switch (s.center_method) - { - // inertial - case 0: - default: - r = r_b * r; - break; - // camera - case 1: - r = r * r_b; - break; - } - - const euler_t rot = r2d * c_mult * rmat_to_euler(r); - euler_t pos(t(0) - t_b[0], t(1) - t_b[1], t(2) - t_b[2]); - - if (s.use_camera_offset_from_centering) - t_compensate(r_b_real.t() * cam_real.t(), pos, pos, false); - else - t_compensate(cam_real.t(), pos, pos, false); - - for (int i = 0; i < 3; i++) - { - value(i) = pos(i); - value(i+3) = rot(i); - } - } - - logger.write_pose(value); // "corrected" - after various transformations to account for camera position - - // whenever something can corrupt its internal state due to nan/inf, elide the call - if (is_nan(value)) - { - nan = true; - logger.write_pose(value); // "filtered" - } - else - { - { - Pose tmp = value; - - if (libs.pFilter) - libs.pFilter->filter(tmp, value); - } - logger.write_pose(value); // "filtered" - - // CAVEAT rotation only, due to tcomp - for (int i = 3; i < 6; i++) - value(i) = map(value(i), m(i)); - - for (int i = 0; i < 6; i++) - value(i) += m(i).opts.zero; - - for (int i = 0; i < 6; i++) - value(i) *= int(m(i).opts.invert) * -2 + 1; - - if (zero_) - for (int i = 0; i < 6; i++) - value(i) = 0; - - if (is_nan(value)) - nan = true; - } - - if (s.tcomp_p) - { - euler_t value_(value(TX), value(TY), value(TZ)); - t_compensate(euler_to_rmat(euler_t(value(Yaw) * d2r, value(Pitch) * d2r, value(Roll) * d2r)), - value_, - value_, - s.tcomp_tz); - if (is_nan(r, value_)) - nan = true; - for (int i = 0; i < 3; i++) - value(i) = value_(i); - } - - // CAVEAT translation only, due to tcomp - for (int i = 0; i < 3; i++) - value(i) = map(value(i), m(i)); - - logger.write_pose(value); // "mapped" - - if (nan) - { - value = last_mapped; - - // for widget last value display - for (int i = 0; i < 6; i++) - (void) map(value(i), m(i)); - } - - libs.pProtocol->pose(value); - - last_mapped = value; - last_raw = raw; - - QMutexLocker foo(&mtx); - output_pose = value; - raw_6dof = raw; - - logger.reset_dt(); - logger.next_line(); -} - -void Tracker::run() -{ -#if defined(_WIN32) - (void) timeBeginPeriod(1); -#endif - - setPriority(QThread::HighPriority); - - { - static constexpr const char* posechannels[6] = { "TX", "TY", "TZ", "Yaw", "Pitch", "Roll" }; - static constexpr const char* datachannels[5] = { "dt", "raw", "corrected", "filtered", "mapped" }; - logger.write(datachannels[0]); - char buffer[128]; - for (unsigned j = 1; j < 5; ++j) - { - for (unsigned i = 0; i < 6; ++i) - { - std::sprintf(buffer, "%s%s", datachannels[j], posechannels[i]); - logger.write(buffer); - } - } - logger.next_line(); - } - - t.start(); - logger.reset_dt(); - - while (!should_quit) - { - double tmp[6] {0,0,0, 0,0,0}; - libs.pTracker->data(tmp); - - if (enabledp) - for (int i = 0; i < 6; i++) - newpose[i] = elide_nan(tmp[i], newpose[i]); - - logic(); - - static constexpr long const_sleep_us = 4000; - - using std::max; - using std::min; - - const long elapsed_usecs = t.elapsed_usecs(); - const long sleep_us = const_sleep_us * 2 - elapsed_usecs; - - const unsigned sleep_time = unsigned(max(1l, min(const_sleep_us * 4, max(1l, (sleep_us + 200l)/1000l)))); - - t.start(); - - portable::sleep(unsigned(max(1u, sleep_time))); - } - - { - // filter may inhibit exact origin - Pose p; - libs.pProtocol->pose(p); - } - -#if defined(_WIN32) - (void) timeEndPeriod(1); -#endif - - for (int i = 0; i < 6; i++) - { - m(i).spline_main.setTrackingActive(false); - m(i).spline_alt.setTrackingActive(false); - } -} - -void Tracker::get_raw_and_mapped_poses(double* mapped, double* raw) const -{ - QMutexLocker foo(&const_cast<Tracker&>(*this).mtx); - - for (int i = 0; i < 6; i++) - { - raw[i] = raw_6dof(i); - mapped[i] = output_pose(i); - } -} - diff --git a/opentrack-logic/tracker.h b/opentrack-logic/tracker.h deleted file mode 100644 index 6dc48074..00000000 --- a/opentrack-logic/tracker.h +++ /dev/null @@ -1,85 +0,0 @@ -/* 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 <vector> - -#include "opentrack-compat/pi-constant.hpp" -#include "opentrack-compat/timer.hpp" -#include "opentrack/plugin-support.hpp" -#include "mappings.hpp" -#include "simple-mat.hpp" -#include "selected-libraries.hpp" - -#include "spline-widget/spline.hpp" -#include "main-settings.hpp" -#include "opentrack-compat/options.hpp" -#include "tracklogger.hpp" - -#include <QMutex> -#include <QThread> - -#include "export.hpp" - -using Pose = Mat<double, 6, 1>; - -class OPENTRACK_LOGIC_EXPORT Tracker : private QThread -{ - Q_OBJECT -private: - using rmat = euler::rmat; - using euler_t = euler::euler_t; - - QMutex mtx; - main_settings s; - Mappings& m; - - Timer t; - Pose output_pose, raw_6dof, last_mapped, last_raw; - - double newpose[6]; - SelectedLibraries const& libs; - // The owner of the reference is the main window. - // This design might be usefull if we decide later on to swap out - // the logger while the tracker is running. - TrackLogger &logger; - - rmat r_b, r_b_real; - double t_b[3]; - - volatile bool centerp; - volatile bool enabledp; - volatile bool zero_; - volatile bool should_quit; - - double map(double pos, Map& axis); - void logic(); - void t_compensate(const rmat& rmat, const euler_t& ypr, euler_t& output, bool rz); - void run() override; - - static constexpr double pi = OPENTRACK_PI; - static constexpr double r2d = 180. / OPENTRACK_PI; - static constexpr double d2r = OPENTRACK_PI / 180.; - - // note: float exponent base is 2 - static constexpr double c_mult = 4; - static constexpr double c_div = 1./c_mult; -public: - Tracker(Mappings& m, SelectedLibraries& libs, TrackLogger &logger); - ~Tracker(); - - rmat get_camera_offset_matrix(double c); - void get_raw_and_mapped_poses(double* mapped, double* raw) const; - void start() { QThread::start(); } - void toggle_enabled() { enabledp = !enabledp; } - void set_toggle(bool value) { enabledp = value; } - void set_zero(bool value) { zero_ = value; } - void center() { centerp = !centerp; } - void zero() { zero_ = !zero_; } -}; diff --git a/opentrack-logic/tracklogger.cpp b/opentrack-logic/tracklogger.cpp deleted file mode 100644 index 64dda579..00000000 --- a/opentrack-logic/tracklogger.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "tracklogger.hpp" -#include "tracker.h" - -TrackLogger::~TrackLogger() {} - -void TrackLogger::reset_dt() -{ - t.start(); -} - -void TrackLogger::write_dt() -{ - const double dt = t.elapsed_seconds(); - write(&dt, 1); -} - -void TrackLoggerCSV::handle_first_col_sep() -{ - if (!first_col) - out.put(','); - first_col = false; -} - -void TrackLoggerCSV::write(const char *s) -{ - handle_first_col_sep(); - out << s; -} - - -void TrackLoggerCSV::write(const double *p, int n) -{ - handle_first_col_sep(); - for (int i = 0; i < n-1; ++i) - { - out << p[i]; - out.put(','); - } - out << p[n-1]; -} - -void TrackLoggerCSV::next_line() -{ - out << std::endl; - first_col = true; -} - diff --git a/opentrack-logic/tracklogger.hpp b/opentrack-logic/tracklogger.hpp deleted file mode 100644 index c6c145cf..00000000 --- a/opentrack-logic/tracklogger.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -#include "main-settings.hpp" -#include "opentrack-compat/options.hpp" -#include "opentrack-compat/timer.hpp" - -#include <fstream> -#include <QString> -#include <QMessageBox> -#include <QWidget> - -class OPENTRACK_LOGIC_EXPORT TrackLogger -{ - TrackLogger(TrackLogger&&) = delete; - TrackLogger(const TrackLogger&) = delete; - TrackLogger& operator=(const TrackLogger&) = delete; - TrackLogger& operator=(TrackLogger&&) = delete; - - Timer t; - -public: - TrackLogger() - { - } - - virtual ~TrackLogger(); - - virtual void write(const char *) - { - } - - virtual void write(const double *, int) - { - } - - virtual void next_line() - { - } - - void write_pose(const double *p) - { - write(p, 6); - } - - void reset_dt(); - void write_dt(); -}; - - -class OPENTRACK_LOGIC_EXPORT TrackLoggerCSV : public TrackLogger -{ - std::ofstream out; - bool first_col; - inline void handle_first_col_sep(); -public: - TrackLoggerCSV(const QString &filename) : first_col(true) - { - out.open(filename.toStdString()); - } - - bool is_open() const { return out.is_open(); } - void write(const char *s) override; - void write(const double *p, int n) override; - void next_line() override; -}; - diff --git a/opentrack-logic/win32-shortcuts.cpp b/opentrack-logic/win32-shortcuts.cpp deleted file mode 100644 index df9145a0..00000000 --- a/opentrack-logic/win32-shortcuts.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (c) 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. - */ - -#if defined(_WIN32) -# ifndef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x800 -# endif -# include <dinput.h> - -#include "win32-shortcuts.h" -#include <QList> -#include <QVariant> -#include <QDebug> - -QList<win_key> windows_key_mods = - QList<win_key>({ - win_key(DIK_LCONTROL, Qt::Key::Key_Control), - win_key(DIK_RCONTROL, Qt::Key::Key_Control), - win_key(DIK_LALT, Qt::Key::Key_Alt), - win_key(DIK_RALT, Qt::Key::Key_Alt), - win_key(DIK_LSHIFT, Qt::Key::Key_Shift), - win_key(DIK_RSHIFT, Qt::Key::Key_Shift), - win_key(DIK_LWIN, Qt::Key::Key_unknown), - win_key(DIK_RWIN, Qt::Key::Key_unknown) - }); - -QList<win_key> windows_key_sequences = - QList<win_key>({ - win_key(DIK_F1, Qt::Key::Key_F1 ), - win_key(DIK_F2, Qt::Key::Key_F2 ), - win_key(DIK_F3, Qt::Key::Key_F3 ), - win_key(DIK_F4, Qt::Key::Key_F4 ), - win_key(DIK_F5, Qt::Key::Key_F5 ), - win_key(DIK_F6, Qt::Key::Key_F6 ), - win_key(DIK_F7, Qt::Key::Key_F7 ), - win_key(DIK_F8, Qt::Key::Key_F8 ), - win_key(DIK_F9, Qt::Key::Key_F9 ), - win_key(DIK_F10, Qt::Key::Key_F10 ), - win_key(DIK_F11, Qt::Key::Key_F11 ), - win_key(DIK_F12, Qt::Key::Key_F12 ), - win_key(DIK_LEFT, Qt::Key::Key_Left ), - win_key(DIK_RIGHT, Qt::Key::Key_Right ), - win_key(DIK_UP, Qt::Key::Key_Up ), - win_key(DIK_DOWN, Qt::Key::Key_Down ), - win_key(DIK_PRIOR, Qt::Key::Key_PageUp ), - win_key(DIK_NEXT, Qt::Key::Key_PageDown ), - win_key(DIK_HOME, Qt::Key::Key_Home ), - win_key(DIK_END, Qt::Key::Key_End ), - win_key(DIK_BACK, Qt::Key::Key_Backspace ), - win_key(DIK_COMMA, Qt::Key::Key_Comma ), - win_key(DIK_PERIOD, Qt::Key::Key_Period ), - win_key(DIK_LBRACKET, Qt::Key::Key_BracketLeft ), - win_key(DIK_RBRACKET, Qt::Key::Key_BracketRight ), - win_key(DIK_SEMICOLON, Qt::Key::Key_Semicolon ), - win_key(DIK_SLASH, Qt::Key::Key_Slash ), - win_key(DIK_BACKSLASH, Qt::Key::Key_Backslash ), - win_key(DIK_BACKSPACE, Qt::Key::Key_Backspace ), - win_key(DIK_APOSTROPHE, Qt::Key::Key_Apostrophe ), - win_key(DIK_GRAVE, Qt::Key::Key_QuoteLeft ), - win_key(DIK_MINUS, Qt::Key::Key_Minus ), - win_key(DIK_EQUALS, Qt::Key::Key_Equal ), - win_key(DIK_PERIOD, Qt::Key::Key_Period ), - win_key(DIK_F1, Qt::Key::Key_F1 ), - win_key(DIK_F2, Qt::Key::Key_F2 ), - win_key(DIK_F3, Qt::Key::Key_F3 ), - win_key(DIK_F4, Qt::Key::Key_F4 ), - win_key(DIK_F5, Qt::Key::Key_F5 ), - win_key(DIK_F6, Qt::Key::Key_F6 ), - win_key(DIK_F7, Qt::Key::Key_F7 ), - win_key(DIK_F8, Qt::Key::Key_F8 ), - win_key(DIK_F9, Qt::Key::Key_F9 ), - win_key(DIK_F10, Qt::Key::Key_F10 ), - win_key(DIK_F11, Qt::Key::Key_F11 ), - win_key(DIK_F12, Qt::Key::Key_F12 ), - win_key(DIK_0, Qt::Key::Key_0 ), - win_key(DIK_1, Qt::Key::Key_1 ), - win_key(DIK_2, Qt::Key::Key_2 ), - win_key(DIK_3, Qt::Key::Key_3 ), - win_key(DIK_4, Qt::Key::Key_4 ), - win_key(DIK_5, Qt::Key::Key_5 ), - win_key(DIK_6, Qt::Key::Key_6 ), - win_key(DIK_7, Qt::Key::Key_7 ), - win_key(DIK_8, Qt::Key::Key_8 ), - win_key(DIK_9, Qt::Key::Key_9 ), - win_key(DIK_A, Qt::Key::Key_A ), - win_key(DIK_B, Qt::Key::Key_B ), - win_key(DIK_C, Qt::Key::Key_C ), - win_key(DIK_D, Qt::Key::Key_D ), - win_key(DIK_E, Qt::Key::Key_E ), - win_key(DIK_F, Qt::Key::Key_F ), - win_key(DIK_G, Qt::Key::Key_G ), - win_key(DIK_H, Qt::Key::Key_H ), - win_key(DIK_I, Qt::Key::Key_I ), - win_key(DIK_J, Qt::Key::Key_J ), - win_key(DIK_K, Qt::Key::Key_K ), - win_key(DIK_L, Qt::Key::Key_L ), - win_key(DIK_M, Qt::Key::Key_M ), - win_key(DIK_N, Qt::Key::Key_N ), - win_key(DIK_O, Qt::Key::Key_O ), - win_key(DIK_P, Qt::Key::Key_P ), - win_key(DIK_Q, Qt::Key::Key_Q ), - win_key(DIK_R, Qt::Key::Key_R ), - win_key(DIK_S, Qt::Key::Key_S ), - win_key(DIK_T, Qt::Key::Key_T ), - win_key(DIK_U, Qt::Key::Key_U ), - win_key(DIK_V, Qt::Key::Key_V ), - win_key(DIK_W, Qt::Key::Key_W ), - win_key(DIK_X, Qt::Key::Key_X ), - win_key(DIK_Y, Qt::Key::Key_Y ), - win_key(DIK_Z, Qt::Key::Key_Z ), - win_key(DIK_RETURN, Qt::Key::Key_Return), - win_key(DIK_INSERT, Qt::Key::Key_Insert), - win_key(DIK_DELETE, Qt::Key::Key_Delete), - win_key(DIK_SPACE, Qt::Key::Key_Space), - win_key(DIK_SYSRQ, Qt::Key::Key_Print), - win_key(DIK_SCROLL, Qt::Key::Key_ScrollLock), - win_key(DIK_PAUSE, Qt::Key::Key_Pause), - win_key(DIK_NUMLOCK, Qt::Key::Key_NumLock), -#define mod(x, y) static_cast<Qt::Key>(x | y) - win_key(DIK_NUMPAD0, mod(Qt::Key::Key_0, Qt::KeypadModifier)), - win_key(DIK_NUMPAD0, mod(Qt::Key::Key_0, Qt::KeypadModifier)), - win_key(DIK_NUMPAD1, mod(Qt::Key::Key_1, Qt::KeypadModifier)), - win_key(DIK_NUMPAD2, mod(Qt::Key::Key_2, Qt::KeypadModifier)), - win_key(DIK_NUMPAD3, mod(Qt::Key::Key_3, Qt::KeypadModifier)), - win_key(DIK_NUMPAD4, mod(Qt::Key::Key_4, Qt::KeypadModifier)), - win_key(DIK_NUMPAD5, mod(Qt::Key::Key_5, Qt::KeypadModifier)), - win_key(DIK_NUMPAD6, mod(Qt::Key::Key_6, Qt::KeypadModifier)), - win_key(DIK_NUMPAD7, mod(Qt::Key::Key_7, Qt::KeypadModifier)), - win_key(DIK_NUMPAD8, mod(Qt::Key::Key_8, Qt::KeypadModifier)), - win_key(DIK_NUMPAD9, mod(Qt::Key::Key_9, Qt::KeypadModifier)), - win_key(DIK_NUMPADCOMMA, mod(Qt::Key::Key_Comma, Qt::KeypadModifier)), - win_key(DIK_NUMPADENTER, mod(Qt::Key::Key_Enter, Qt::KeypadModifier)), - win_key(DIK_NUMPADEQUALS, mod(Qt::Key::Key_Equal, Qt::KeypadModifier)), - win_key(DIK_NUMPADMINUS, mod(Qt::Key::Key_Minus, Qt::KeypadModifier)), - win_key(DIK_NUMPADPERIOD, mod(Qt::Key::Key_Period, Qt::KeypadModifier)), - win_key(DIK_NUMPADPLUS, mod(Qt::Key::Key_Plus, Qt::KeypadModifier)), - win_key(DIK_NUMPADSLASH, mod(Qt::Key::Key_Slash, Qt::KeypadModifier)), - win_key(DIK_NUMPADSTAR, mod(Qt::Key::Key_multiply, Qt::KeypadModifier)), - }); - -bool win_key::to_qt(const Key& k, QKeySequence& qt_, Qt::KeyboardModifiers &mods) -{ - for (auto& wk : windows_key_sequences) - { - if (wk.win == k.keycode) - { - qt_ = wk.qt; - mods = Qt::NoModifier; - if (k.ctrl) mods |= Qt::ControlModifier; - if (k.shift) mods |= Qt::ShiftModifier; - if (k.alt) mods |= Qt::AltModifier; - return true; - } - } - return false; -} - -bool win_key::from_qt(QKeySequence qt_, int& dik, Qt::KeyboardModifiers& mods) -{ - // CAVEAT don't use QVariant::toUInt() or conversion fails - const unsigned qt = static_cast<unsigned>(QVariant(qt_).toInt()); - const unsigned our_mods = qt & Qt::KeyboardModifierMask; - - { - const auto key_ = qt; - for (auto& wk : windows_key_sequences) - { - if (wk.qt == key_) - { - dik = wk.win; - mods = Qt::NoModifier; - return true; - } - } - } - { - const unsigned key = qt & ~Qt::KeyboardModifierMask; - for (auto& wk : windows_key_sequences) - { - if (wk.qt == key) - { - dik = wk.win; - mods = static_cast<Qt::KeyboardModifiers>(our_mods); - return true; - } - } - } - return false; -} - -#endif diff --git a/opentrack-logic/win32-shortcuts.h b/opentrack-logic/win32-shortcuts.h deleted file mode 100644 index 7626a31f..00000000 --- a/opentrack-logic/win32-shortcuts.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#ifdef _WIN32 - -#include <QKeySequence> -#include "shortcuts.h" - -struct win_key; - -extern QList<win_key> windows_key_mods; -extern QList<win_key> windows_key_sequences; - -#include "export.hpp" - -struct OPENTRACK_LOGIC_EXPORT win_key -{ - win_key(int win, Qt::Key qt) : win(win), qt(qt) {} - int win; - Qt::Key qt; - static bool from_qt(QKeySequence qt_, int& dik, Qt::KeyboardModifiers &mods); - static bool to_qt(const Key& k, QKeySequence& qt_, Qt::KeyboardModifiers &mods); -}; - -#endif diff --git a/opentrack-logic/work.cpp b/opentrack-logic/work.cpp deleted file mode 100644 index 8d00270b..00000000 --- a/opentrack-logic/work.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "work.hpp" - -#include <QMessageBox> - - -std::shared_ptr<TrackLogger> Work::make_logger(const main_settings &s) -{ - if (s.tracklogging_enabled) - { - if (static_cast<QString>(s.tracklogging_filename).isEmpty()) - { - QMessageBox::warning(nullptr, "Logging Error", - "No filename given for track logging. Proceeding without logging.", - QMessageBox::Ok, - QMessageBox::NoButton); - } - else - { - auto logger = std::make_shared<TrackLoggerCSV>(s.tracklogging_filename); - if (!logger->is_open()) - { - logger = nullptr; - QMessageBox::warning(nullptr, "Logging Error", - "Unable to open file: " + s.tracklogging_filename + ". Proceeding without logging.", - QMessageBox::Ok, - QMessageBox::NoButton); - } - else - { - /* As this function has the potential to fill up the hard drive - of the unwary with junk data, a warning is in order. */ - QMessageBox::warning(nullptr, "Logging Active", - "Just a heads up. You are recoding pose data to " + s.tracklogging_filename + "!", - QMessageBox::Ok, - QMessageBox::NoButton); - return logger; - } - } - } - return std::make_shared<TrackLogger>(); -} - - -Work::Work(Mappings& m, SelectedLibraries& libs, WId handle) : - libs(libs), - logger(make_logger(s)), - tracker(std::make_shared<Tracker>(m, libs, *logger)), - sc(std::make_shared<Shortcuts>()), - handle(handle), - keys { - key_tuple(s.key_center, [&](bool) -> void { tracker->center(); }, true), - key_tuple(s.key_toggle, [&](bool) -> void { tracker->toggle_enabled(); }, true), - key_tuple(s.key_zero, [&](bool) -> void { tracker->zero(); }, true), - key_tuple(s.key_toggle_press, [&](bool x) -> void { tracker->set_toggle(!x); }, false), - key_tuple(s.key_zero_press, [&](bool x) -> void { tracker->set_zero(x); }, false), - } -{ - reload_shortcuts(); - tracker->start(); -} - -void Work::reload_shortcuts() -{ - sc->reload(keys); -} - -Work::~Work() -{ - sc = nullptr; - // order matters, otherwise use-after-free -sh - tracker = nullptr; - libs = SelectedLibraries(); -} diff --git a/opentrack-logic/work.hpp b/opentrack-logic/work.hpp deleted file mode 100644 index 4afb1da4..00000000 --- a/opentrack-logic/work.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* 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 "main-settings.hpp" -#include "opentrack/plugin-support.hpp" -#include "tracker.h" -#include "shortcuts.h" -#include "export.hpp" -#include "tracklogger.hpp" - -#include <QObject> -#include <QFrame> -#include <memory> -#include <vector> -#include <tuple> -#include <functional> - -struct OPENTRACK_LOGIC_EXPORT Work -{ - using fn_t = std::function<void(bool)>; - using key_tuple = std::tuple<key_opts&, fn_t, bool>; - main_settings s; // tracker needs settings, so settings must come before it - SelectedLibraries& libs; - std::shared_ptr<TrackLogger> logger; // must come before tracker, since tracker depends on it - std::shared_ptr<Tracker> tracker; - std::shared_ptr<Shortcuts> sc; - WId handle; - std::vector<key_tuple> keys; - - Work(Mappings& m, SelectedLibraries& libs, WId handle); - ~Work(); - void reload_shortcuts(); - -private: - std::shared_ptr<TrackLogger> make_logger(const main_settings &s); -}; diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt deleted file mode 100644 index 5151cbf7..00000000 --- a/opentrack/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -opentrack_boilerplate(opentrack-api NO-COMPAT BIN) -target_link_libraries(opentrack-api opentrack-compat) -target_include_directories(opentrack-api PUBLIC ${CMAKE_BINARY_DIR}) diff --git a/opentrack/dtors.cpp b/opentrack/dtors.cpp deleted file mode 100644 index 5cc87187..00000000 --- a/opentrack/dtors.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "plugin-api.hpp" - -// these exist only so that vtable is emitted in a single compilation unit, not all of them. - -Metadata::~Metadata() {} -IFilter::~IFilter() {} -IFilterDialog::~IFilterDialog() {} -IProtocol::~IProtocol() {} -IProtocolDialog::~IProtocolDialog() {} -ITracker::~ITracker() {} -ITrackerDialog::~ITrackerDialog() {} diff --git a/opentrack/export.hpp b/opentrack/export.hpp deleted file mode 100644 index a9f3521e..00000000 --- a/opentrack/export.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#ifdef BUILD_api -# ifdef _WIN32 -# define OPENTRACK_API_LINKAGE __declspec(dllexport) -# else -# define OPENTRACK_API_LINKAGE -# endif - -# ifndef _MSC_VER -# define OPENTRACK_API_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_API_LINKAGE -# else -# define OPENTRACK_API_EXPORT OPENTRACK_API_LINKAGE -# endif - -#else - #ifdef _WIN32 - # define OPENTRACK_API_LINKAGE __declspec(dllimport) - #else - # define OPENTRACK_API_LINKAGE - #endif - - #ifndef _MSC_VER - # define OPENTRACK_API_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_API_LINKAGE - #else - # define OPENTRACK_API_EXPORT OPENTRACK_API_LINKAGE - #endif -#endif diff --git a/opentrack/is-window-visible.cpp b/opentrack/is-window-visible.cpp deleted file mode 100644 index fc25bb7d..00000000 --- a/opentrack/is-window-visible.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "is-window-visible.hpp" -#include <QPoint> - -#ifdef _WIN32 - -#include <windows.h> - -OPENTRACK_API_EXPORT bool is_window_visible(const QWidget* widget) -{ - const QPoint p = widget->mapToGlobal(QPoint(0, 0)); - const QSize s = widget->size(); - - const POINT points[] = - { - { p.x(), p.y() }, - { p.x() + s.width(), p.y() }, - { p.x() + s.width(), p.y() + s.height() }, - { p.x(), p.y() + s.height() }, - { p.x() + s.width()/2, p.y() + s.height()/2 }, - }; - - for (const POINT& pt : points) - if (WindowFromPoint(pt) == (HWND) widget->winId()) - return true; - return false; -} - -#else -OPENTRACK_API_EXPORT bool is_window_visible(const QWidget* widget) -{ - return true; -} -#endif diff --git a/opentrack/is-window-visible.hpp b/opentrack/is-window-visible.hpp deleted file mode 100644 index 18c9251a..00000000 --- a/opentrack/is-window-visible.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include <QWidget> -#include "export.hpp" - -OPENTRACK_API_EXPORT bool is_window_visible(const QWidget* widget); - diff --git a/opentrack/plugin-api.hpp b/opentrack/plugin-api.hpp deleted file mode 100644 index 1e5c0fe0..00000000 --- a/opentrack/plugin-api.hpp +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (c) 2013-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 <QString> -#include <QWidget> -#include <QFrame> -#include <QIcon> - -#include "export.hpp" - -#ifndef OPENTRACK_PLUGIN_EXPORT -# ifdef _WIN32 -# define OPENTRACK_PLUGIN_LINKAGE __declspec(dllexport) -# else -# define OPENTRACK_PLUGIN_LINKAGE -# endif -# ifndef _MSC_VER -# define OPENTRACK_PLUGIN_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_PLUGIN_LINKAGE -# else -# define OPENTRACK_PLUGIN_EXPORT OPENTRACK_PLUGIN_LINKAGE -# endif -#endif - -enum Axis { - TX, TY, TZ, Yaw, Pitch, Roll -}; - -namespace plugin_api { -namespace detail { - -class OPENTRACK_API_EXPORT BaseDialog : public QWidget -{ - Q_OBJECT -public: - void closeEvent(QCloseEvent *) override { emit closing(); } -signals: - void closing(); -}; - -} // ns -} // ns - -#define OPENTRACK_DECLARE_PLUGIN_INTERNAL(ctor_class, ctor_ret_class, metadata_class, dialog_class, dialog_ret_class) \ - extern "C" OPENTRACK_PLUGIN_EXPORT ctor_ret_class* GetConstructor(); \ - extern "C" OPENTRACK_PLUGIN_EXPORT Metadata* GetMetadata(); \ - extern "C" OPENTRACK_PLUGIN_EXPORT dialog_ret_class* GetDialog(); \ - \ - extern "C" OPENTRACK_PLUGIN_EXPORT ctor_ret_class* GetConstructor() \ - { \ - return new ctor_class; \ - } \ - extern "C" OPENTRACK_PLUGIN_EXPORT Metadata* GetMetadata() \ - { \ - return new metadata_class; \ - } \ - extern "C" OPENTRACK_PLUGIN_EXPORT dialog_ret_class* GetDialog() \ - { \ - return new dialog_class; \ - } - -// implement this in all plugins -// also you must link against "opentrack-api" in CMakeLists.txt to avoid vtable link errors -struct OPENTRACK_API_EXPORT Metadata -{ - Metadata(const Metadata&) = delete; - Metadata(Metadata&&) = delete; - Metadata& operator=(const Metadata&) = delete; - inline Metadata() {} - - // plugin name to be displayed in the interface - virtual QString name() = 0; - // plugin icon, you can return an empty QIcon() - virtual QIcon icon() = 0; - // optional destructor - virtual ~Metadata(); -}; - -// implement this in filters -struct OPENTRACK_API_EXPORT IFilter -{ - IFilter(const IFilter&) = delete; - IFilter(IFilter&&) = delete; - IFilter& operator=(const IFilter&) = delete; - inline IFilter() {} - - // optional destructor - virtual ~IFilter(); - // perform filtering step. - // you have to take care of dt on your own, try "opentrack-compat/timer.hpp" - virtual void filter(const double *input, double *output) = 0; - // optionally reset the filter when centering - virtual void center() {} -}; - -struct OPENTRACK_API_EXPORT IFilterDialog : public plugin_api::detail::BaseDialog -{ - // optional destructor - virtual ~IFilterDialog(); - // receive a pointer to the filter from ui thread - virtual void register_filter(IFilter* filter) = 0; - // received filter pointer is about to get deleted - virtual void unregister_filter() = 0; -}; - -// call once with your chosen class names in the plugin -#define OPENTRACK_DECLARE_FILTER(filter_class, dialog_class, metadata_class) \ - OPENTRACK_DECLARE_PLUGIN_INTERNAL(filter_class, IFilter, metadata_class, dialog_class, IFilterDialog) - -// implement this in protocols -struct OPENTRACK_API_EXPORT IProtocol -{ - IProtocol(const IProtocol&) = delete; - IProtocol(IProtocol&&) = delete; - IProtocol& operator=(const IProtocol&) = delete; - inline IProtocol() {} - - // optional destructor - virtual ~IProtocol(); - // return true if protocol was properly initialized - virtual bool correct() = 0; - // called 250 times a second with XYZ yaw pitch roll pose - // try not to perform intense computation here. if you must, use a thread. - virtual void pose(const double* headpose) = 0; - // return game name or placeholder text - virtual QString game_name() = 0; -}; - -struct OPENTRACK_API_EXPORT IProtocolDialog : public plugin_api::detail::BaseDialog -{ - // optional destructor - virtual ~IProtocolDialog(); - // receive a pointer to the protocol from ui thread - virtual void register_protocol(IProtocol *protocol) = 0; - // received protocol pointer is about to get deleted - virtual void unregister_protocol() = 0; -}; - -// call once with your chosen class names in the plugin -#define OPENTRACK_DECLARE_PROTOCOL(protocol_class, dialog_class, metadata_class) \ - OPENTRACK_DECLARE_PLUGIN_INTERNAL(protocol_class, IProtocol, metadata_class, dialog_class, IProtocolDialog) - -// implement this in trackers -struct OPENTRACK_API_EXPORT ITracker -{ - ITracker(const ITracker&) = delete; - ITracker(ITracker&&) = delete; - ITracker& operator=(const ITracker&) = delete; - inline ITracker() {} - - // optional destructor - virtual ~ITracker(); - // start tracking, and grab a frame to display webcam video in, optionally - virtual void start_tracker(QFrame* frame) = 0; - // return XYZ yaw pitch roll data. don't block here, use a separate thread for computation. - virtual void data(double *data) = 0; - // tracker notified of centering - // returning true makes identity the center pose - virtual bool center() { return false; } -}; - -struct OPENTRACK_API_EXPORT ITrackerDialog : public plugin_api::detail::BaseDialog -{ - // optional destructor - virtual ~ITrackerDialog(); - // receive a pointer to the tracker from ui thread - virtual void register_tracker(ITracker *tracker) = 0; - // received tracker pointer is about to get deleted - virtual void unregister_tracker() = 0; -}; - -// call once with your chosen class names in the plugin -#define OPENTRACK_DECLARE_TRACKER(tracker_class, dialog_class, metadata_class) \ - OPENTRACK_DECLARE_PLUGIN_INTERNAL(tracker_class, ITracker, metadata_class, dialog_class, ITrackerDialog) diff --git a/opentrack/plugin-support.hpp b/opentrack/plugin-support.hpp deleted file mode 100644 index a26d7f08..00000000 --- a/opentrack/plugin-support.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright (c) 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 "plugin-api.hpp" -#include "opentrack-compat/options.hpp" - -#include <QWidget> -#include <QDebug> -#include <QString> -#include <QLibrary> -#include <QFrame> -#include <QList> - -#include <cstdio> -#include <cinttypes> -#include <iostream> -#include <algorithm> - -#include <QCoreApplication> -#include <QFile> -#include <QDir> -#include <QList> -#include <QStringList> - -#if defined(__APPLE__) -# define OPENTRACK_SOLIB_EXT "dylib" -#elif defined(_WIN32) -# define OPENTRACK_SOLIB_EXT "dll" -#else -# define OPENTRACK_SOLIB_EXT "so" -#endif - -#include <iostream> - -#ifdef _MSC_VER -# define OPENTRACK_SOLIB_PREFIX "" -#else -# define OPENTRACK_SOLIB_PREFIX "lib" -#endif - -extern "C" typedef void* (*OPENTRACK_CTOR_FUNPTR)(void); -extern "C" typedef Metadata* (*OPENTRACK_METADATA_FUNPTR)(void); - -struct dylib final { - enum Type { Filter, Tracker, Protocol }; - - dylib(const QString& filename, Type t) : - type(t), - filename(filename), - Dialog(nullptr), - Constructor(nullptr), - Meta(nullptr), - handle(nullptr) - { - // otherwise dlopen opens the calling executable - if (filename.size() == 0) - return; - - handle = new QLibrary(filename); - handle->setLoadHints(QLibrary::PreventUnloadHint | handle->loadHints()); - - struct _foo { - static bool die(QLibrary*& l, bool failp) - { - if (failp) - { - qDebug() << "failed" << l->errorString(); - delete l; - l = nullptr; - } - return failp; - } - }; - - if (_foo::die(handle, !handle->load())) - return; - - Dialog = (OPENTRACK_CTOR_FUNPTR) handle->resolve("GetDialog"); - if (_foo::die(handle, !Dialog)) - return; - - Constructor = (OPENTRACK_CTOR_FUNPTR) handle->resolve("GetConstructor"); - if (_foo::die(handle, !Constructor)) - return; - - Meta = (OPENTRACK_METADATA_FUNPTR) handle->resolve("GetMetadata"); - if (_foo::die(handle, !Meta)) - return; - - auto m = mem<Metadata>(Meta()); - - icon = m->icon(); - name = m->name(); - } - ~dylib() - { - if (handle) - delete handle; - } - - static QList<mem<dylib>> enum_libraries(const QString& library_path) - { - const char* filters_n[] = { OPENTRACK_SOLIB_PREFIX "opentrack-filter-*." OPENTRACK_SOLIB_EXT, - OPENTRACK_SOLIB_PREFIX "opentrack-tracker-*." OPENTRACK_SOLIB_EXT, - OPENTRACK_SOLIB_PREFIX "opentrack-proto-*." OPENTRACK_SOLIB_EXT, - }; - const Type filters_t[] = { Filter, Tracker, Protocol }; - - QDir settingsDir(library_path); - - QList<mem<dylib>> ret; - - for (int i = 0; i < 3; i++) - { - QString glob = filters_n[i]; - Type t = filters_t[i]; - QStringList filenames = settingsDir.entryList(QStringList { glob }, QDir::Files, QDir::Name); - - for (const QString& filename : filenames) - { - QIcon icon; - QString longName; - auto lib = std::make_shared<dylib>(library_path + filename, t); - qDebug() << "Loading" << filename; - std::cout.flush(); - if (!get_metadata(lib, longName, icon)) - continue; - using d = const mem<dylib>&; - if (std::any_of(ret.cbegin(), - ret.cend(), - [&](d a) {return a->type == lib->type && a->name == lib->name;})) - { - qDebug() << "Duplicate lib" << lib->filename; - continue; - } - ret.push_back(lib); - } - } - - return ret; - } - - Type type; - QString filename; - - QIcon icon; - QString name; - - OPENTRACK_CTOR_FUNPTR Dialog; - OPENTRACK_CTOR_FUNPTR Constructor; - OPENTRACK_METADATA_FUNPTR Meta; -private: - QLibrary* handle; - - static bool get_metadata(mem<dylib> lib, QString& name, QIcon& icon) - { - Metadata* meta; - if (!lib->Meta || ((meta = lib->Meta()), !meta)) - return false; - name = meta->name(); - icon = meta->icon(); - delete meta; - return true; - } -}; - -struct Modules -{ - Modules(const QString& library_path) : - module_list(dylib::enum_libraries(library_path)), - filter_modules(filter(dylib::Filter)), - tracker_modules(filter(dylib::Tracker)), - protocol_modules(filter(dylib::Protocol)) - {} - QList<mem<dylib>>& filters() { return filter_modules; } - QList<mem<dylib>>& trackers() { return tracker_modules; } - QList<mem<dylib>>& protocols() { return protocol_modules; } -private: - QList<mem<dylib>> module_list; - QList<mem<dylib>> filter_modules; - QList<mem<dylib>> tracker_modules; - QList<mem<dylib>> protocol_modules; - - template<typename t> - static void sort(QList<t>& xs) - { - std::sort(xs.begin(), xs.end(), [&](const t& a, const t& b) { return a->name.toLower() < b->name.toLower(); }); - } - - QList<mem<dylib>> filter(dylib::Type t) - { - QList<mem<dylib>> ret; - for (auto x : module_list) - if (x->type == t) - ret.push_back(x); - - sort(ret); - - return ret; - } -}; - -template<typename t> -mem<t> make_dylib_instance(mem<dylib> lib) -{ - mem<t> ret; - if (lib != nullptr && lib->Constructor) - ret = mem<t>(reinterpret_cast<t*>(reinterpret_cast<OPENTRACK_CTOR_FUNPTR>(lib->Constructor)())); - return ret; -} diff --git a/opentrack/variance.hpp b/opentrack/variance.hpp deleted file mode 100644 index 55060b02..00000000 --- a/opentrack/variance.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include <cmath> - -// no copyright information other than the attribution below. - -// code shared as an example/tutorial of running variance -// written by John D. Cook on the website <http://www.johndcook.com/blog/standard_deviation> - -// following references in the site's article: - -// Chan, Tony F.; Golub, Gene H.; LeVeque, Randall J. (1983). -// Algorithms for Computing the Sample Variance: Analysis and Recommendations. -// The American Statistician 37, 242-247. - -// Ling, Robert F. (1974). -// Comparison of Several Algorithms for Computing Sample Means and Variances. -// Journal of the American Statistical Association, Vol. 69, No. 348, 859-866. - -class variance -{ - double m_old, m_new, s_old, s_new; - unsigned long cnt; - -public: - variance() : cnt(0) {} - - void clear() { *this = variance(); } - - void input(double x) - { - cnt++; - - if (cnt == 1) - { - m_old = m_new = x; - s_old = 0; - } - else - { - m_new = m_old + (x - m_old)/cnt; - s_new = s_old + (x - m_old)*(x - m_new); - - m_old = m_new; - s_old = s_new; - } - } - - double avg() const { return cnt > 0 ? m_new : 0; } - double Var() const { return cnt > 1 ? s_new/(cnt - 1) : 0; } - double stddev() const { return std::sqrt(Var()); } -}; diff --git a/pose-widget/glwidget.cpp b/pose-widget/glwidget.cpp index 2e36a095..a2a76726 100644 --- a/pose-widget/glwidget.cpp +++ b/pose-widget/glwidget.cpp @@ -6,8 +6,8 @@ */ #include "glwidget.h" -#include "opentrack/is-window-visible.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "api/is-window-visible.hpp" +#include "compat/pi-constant.hpp" #include <cmath> #include <algorithm> #include <QPainter> diff --git a/pose-widget/glwidget.h b/pose-widget/glwidget.h index 95be2914..7965130c 100644 --- a/pose-widget/glwidget.h +++ b/pose-widget/glwidget.h @@ -10,9 +10,9 @@ #include <QtGlobal> #include <QWidget> #include <QPixmap> -#include "opentrack/plugin-api.hpp" -#include "opentrack-logic/simple-mat.hpp" -#include "opentrack-compat/timer.hpp" +#include "api/plugin-api.hpp" +#include "logic/simple-mat.hpp" +#include "compat/timer.hpp" #ifdef BUILD_pose_widget # define POSE_WIDGET_EXPORT Q_DECL_EXPORT diff --git a/proto-fg/ftnoir_protocol_fg.cpp b/proto-fg/ftnoir_protocol_fg.cpp index 660a7352..599a4d2c 100644 --- a/proto-fg/ftnoir_protocol_fg.cpp +++ b/proto-fg/ftnoir_protocol_fg.cpp @@ -9,7 +9,7 @@ * copyright notice and this permission notice appear in all copies. * */ #include "ftnoir_protocol_fg.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" // For Todd and Arda Kutlu diff --git a/proto-fg/ftnoir_protocol_fg.h b/proto-fg/ftnoir_protocol_fg.h index 5b1cbc81..77cb73c8 100644 --- a/proto-fg/ftnoir_protocol_fg.h +++ b/proto-fg/ftnoir_protocol_fg.h @@ -14,8 +14,8 @@ #include <QThread> #include <QUdpSocket> #include <QMessageBox> -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/proto-fg/ftnoir_protocol_fg_dialog.cpp b/proto-fg/ftnoir_protocol_fg_dialog.cpp index 6a3463b4..50ca2a73 100644 --- a/proto-fg/ftnoir_protocol_fg_dialog.cpp +++ b/proto-fg/ftnoir_protocol_fg_dialog.cpp @@ -11,7 +11,7 @@ #include "ftnoir_protocol_fg.h" #include <QObject> #include <QFile> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. diff --git a/proto-fsuipc/ftnoir_protocol_fsuipc.cpp b/proto-fsuipc/ftnoir_protocol_fsuipc.cpp index cb289747..92d9bd88 100644 --- a/proto-fsuipc/ftnoir_protocol_fsuipc.cpp +++ b/proto-fsuipc/ftnoir_protocol_fsuipc.cpp @@ -9,7 +9,7 @@ * copyright notice and this permission notice appear in all copies. * */ #include "ftnoir_protocol_fsuipc.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <cmath> diff --git a/proto-fsuipc/ftnoir_protocol_fsuipc.h b/proto-fsuipc/ftnoir_protocol_fsuipc.h index 42f421ad..8207ac9f 100644 --- a/proto-fsuipc/ftnoir_protocol_fsuipc.h +++ b/proto-fsuipc/ftnoir_protocol_fsuipc.h @@ -15,7 +15,7 @@ #include <windows.h> #include <stdlib.h> #include "FSUIPC_User.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ui_ftnoir_fsuipccontrols.h" #include <QMessageBox> #include <QSettings> @@ -24,7 +24,7 @@ #include <QDebug> #include <QFile> #include <QFileDialog> -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; #define FSUIPC_FILENAME "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll" diff --git a/proto-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp b/proto-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp index 504b2dcb..07507cfb 100644 --- a/proto-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp +++ b/proto-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp @@ -9,7 +9,7 @@ * copyright notice and this permission notice appear in all copies. * */ #include "ftnoir_protocol_fsuipc.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" FSUIPCControls::FSUIPCControls() { diff --git a/proto-ft/ftnoir_protocol_ft.cpp b/proto-ft/ftnoir_protocol_ft.cpp index 851cd939..7cd0b5f7 100644 --- a/proto-ft/ftnoir_protocol_ft.cpp +++ b/proto-ft/ftnoir_protocol_ft.cpp @@ -9,7 +9,7 @@ #include "ftnoir_protocol_ft.h" #include "csv/csv.h" #include "opentrack-library-path.h" -#include "opentrack-compat/pi-constant.hpp" +#include "compat/pi-constant.hpp" check_for_first_run FTNoIR_Protocol::runonce_check = check_for_first_run(); diff --git a/proto-ft/ftnoir_protocol_ft.h b/proto-ft/ftnoir_protocol_ft.h index d90d916e..246a73c4 100644 --- a/proto-ft/ftnoir_protocol_ft.h +++ b/proto-ft/ftnoir_protocol_ft.h @@ -8,7 +8,7 @@ #pragma once #include "ui_ftnoir_ftcontrols.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <QMessageBox> #include <QSettings> #include <QLibrary> @@ -18,8 +18,8 @@ #include <QString> #include <QMutex> #include <QMutexLocker> -#include "opentrack-compat/shm.h" -#include "opentrack-compat/options.hpp" +#include "compat/shm.h" +#include "compat/options.hpp" #include "freetrackclient/fttypes.h" #include <memory> #include "mutex.hpp" diff --git a/proto-ftn/ftnoir_protocol_ftn.cpp b/proto-ftn/ftnoir_protocol_ftn.cpp index db852f55..51db0f9d 100644 --- a/proto-ftn/ftnoir_protocol_ftn.cpp +++ b/proto-ftn/ftnoir_protocol_ftn.cpp @@ -10,7 +10,7 @@ */ #include "ftnoir_protocol_ftn.h" #include <QFile> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" FTNoIR_Protocol::FTNoIR_Protocol() { diff --git a/proto-ftn/ftnoir_protocol_ftn.h b/proto-ftn/ftnoir_protocol_ftn.h index d8b8aff0..9e647980 100644 --- a/proto-ftn/ftnoir_protocol_ftn.h +++ b/proto-ftn/ftnoir_protocol_ftn.h @@ -15,8 +15,8 @@ #include <QUdpSocket> #include <QMessageBox> #include <cmath> -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/proto-ftn/ftnoir_protocol_ftn_dialog.cpp b/proto-ftn/ftnoir_protocol_ftn_dialog.cpp index 7e191336..70416a69 100644 --- a/proto-ftn/ftnoir_protocol_ftn_dialog.cpp +++ b/proto-ftn/ftnoir_protocol_ftn_dialog.cpp @@ -9,7 +9,7 @@ * copyright notice and this permission notice appear in all copies. * */ #include "ftnoir_protocol_ftn.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" FTNControls::FTNControls() { diff --git a/proto-libevdev/ftnoir_protocol_libevdev.cpp b/proto-libevdev/ftnoir_protocol_libevdev.cpp index 96805b39..96411ae3 100644 --- a/proto-libevdev/ftnoir_protocol_libevdev.cpp +++ b/proto-libevdev/ftnoir_protocol_libevdev.cpp @@ -1,5 +1,5 @@ #include "ftnoir_protocol_libevdev.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <cstdio> #include <algorithm> diff --git a/proto-libevdev/ftnoir_protocol_libevdev.h b/proto-libevdev/ftnoir_protocol_libevdev.h index ecb3b201..79be398b 100644 --- a/proto-libevdev/ftnoir_protocol_libevdev.h +++ b/proto-libevdev/ftnoir_protocol_libevdev.h @@ -8,7 +8,7 @@ #include "ui_ftnoir_libevdev_controls.h" #include <QMessageBox> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" extern "C" { # include <libevdev/libevdev.h> diff --git a/proto-libevdev/ftnoir_protocol_libevdev_dialog.cpp b/proto-libevdev/ftnoir_protocol_libevdev_dialog.cpp index bb63ba6a..afccf908 100644 --- a/proto-libevdev/ftnoir_protocol_libevdev_dialog.cpp +++ b/proto-libevdev/ftnoir_protocol_libevdev_dialog.cpp @@ -1,5 +1,5 @@ #include "ftnoir_protocol_libevdev.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" LibevdevControls::LibevdevControls() { diff --git a/proto-mouse/ftnoir_protocol_mouse.cpp b/proto-mouse/ftnoir_protocol_mouse.cpp index 73616785..ced53bc6 100644 --- a/proto-mouse/ftnoir_protocol_mouse.cpp +++ b/proto-mouse/ftnoir_protocol_mouse.cpp @@ -5,7 +5,7 @@ * copyright notice and this permission notice appear in all copies. */ #include "ftnoir_protocol_mouse.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <cmath> #include <algorithm> #include <windows.h> diff --git a/proto-mouse/ftnoir_protocol_mouse.h b/proto-mouse/ftnoir_protocol_mouse.h index 2d96915e..0781366c 100644 --- a/proto-mouse/ftnoir_protocol_mouse.h +++ b/proto-mouse/ftnoir_protocol_mouse.h @@ -9,8 +9,8 @@ #include "ui_ftnoir_mousecontrols.h" #include <QDebug> -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/proto-mouse/ftnoir_protocol_mouse_dialog.cpp b/proto-mouse/ftnoir_protocol_mouse_dialog.cpp index d8517487..77b1ff2e 100644 --- a/proto-mouse/ftnoir_protocol_mouse_dialog.cpp +++ b/proto-mouse/ftnoir_protocol_mouse_dialog.cpp @@ -1,5 +1,5 @@ #include "ftnoir_protocol_mouse.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" MOUSEControls::MOUSEControls() { diff --git a/proto-sc/ftnoir_protocol_sc.cpp b/proto-sc/ftnoir_protocol_sc.cpp index fb60cb01..cea064ea 100644 --- a/proto-sc/ftnoir_protocol_sc.cpp +++ b/proto-sc/ftnoir_protocol_sc.cpp @@ -10,7 +10,7 @@ * copyright notice and this permission notice appear in all copies. * */ #include "ftnoir_protocol_sc.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "opentrack-library-path.h" FTNoIR_Protocol::FTNoIR_Protocol() : should_stop(false), hSimConnect(nullptr) diff --git a/proto-sc/ftnoir_protocol_sc.h b/proto-sc/ftnoir_protocol_sc.h index dcc0ca77..0da6c242 100644 --- a/proto-sc/ftnoir_protocol_sc.h +++ b/proto-sc/ftnoir_protocol_sc.h @@ -10,7 +10,7 @@ * copyright notice and this permission notice appear in all copies. * */ #pragma once -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ui_ftnoir_sccontrols.h" #include <QThread> @@ -20,7 +20,7 @@ #include <QProcess> #include <QDebug> #include <QFile> -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; #include <windows.h> diff --git a/proto-sc/ftnoir_protocol_sc_dialog.cpp b/proto-sc/ftnoir_protocol_sc_dialog.cpp index e2ff82fc..a14c6b44 100644 --- a/proto-sc/ftnoir_protocol_sc_dialog.cpp +++ b/proto-sc/ftnoir_protocol_sc_dialog.cpp @@ -10,7 +10,7 @@ */ #include "ftnoir_protocol_sc.h" #include <QDebug> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" SCControls::SCControls() { diff --git a/proto-vjoystick/vjoystick.cpp b/proto-vjoystick/vjoystick.cpp index d14166be..ad582b6d 100644 --- a/proto-vjoystick/vjoystick.cpp +++ b/proto-vjoystick/vjoystick.cpp @@ -1,5 +1,5 @@ #include "vjoystick.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <cstring> #include <QDebug> diff --git a/proto-vjoystick/vjoystick.h b/proto-vjoystick/vjoystick.h index c4cb7e69..2d3fd378 100644 --- a/proto-vjoystick/vjoystick.h +++ b/proto-vjoystick/vjoystick.h @@ -7,7 +7,7 @@ */ #pragma once #include "ui_vjoystick.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <windows.h> diff --git a/proto-vjoystick/vjoystick_dialog.cpp b/proto-vjoystick/vjoystick_dialog.cpp index 136e898b..461230a6 100644 --- a/proto-vjoystick/vjoystick_dialog.cpp +++ b/proto-vjoystick/vjoystick_dialog.cpp @@ -1,5 +1,5 @@ #include "vjoystick.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" vjoystick_dialog::vjoystick_dialog() { diff --git a/proto-wine/ftnoir_protocol_wine.h b/proto-wine/ftnoir_protocol_wine.h index f78e1364..8b41824c 100644 --- a/proto-wine/ftnoir_protocol_wine.h +++ b/proto-wine/ftnoir_protocol_wine.h @@ -8,8 +8,8 @@ #include <QMutex> #include <QMutexLocker> #include <QFile> -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/shm.h" +#include "api/plugin-api.hpp" +#include "compat/shm.h" #include "wine-shm.h" class FTNoIR_Protocol : public IProtocol diff --git a/proto-wine/ftnoir_protocol_wine_dialog.cpp b/proto-wine/ftnoir_protocol_wine_dialog.cpp index d5cb4494..a388df70 100644 --- a/proto-wine/ftnoir_protocol_wine_dialog.cpp +++ b/proto-wine/ftnoir_protocol_wine_dialog.cpp @@ -1,6 +1,6 @@ #include "ftnoir_protocol_wine.h" #include <QDebug> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" FTControls::FTControls() { diff --git a/proto-wine/opentrack-wrapper-wine-main.cxx b/proto-wine/opentrack-wrapper-wine-main.cxx index 082e5dde..1c88755a 100644 --- a/proto-wine/opentrack-wrapper-wine-main.cxx +++ b/proto-wine/opentrack-wrapper-wine-main.cxx @@ -6,13 +6,13 @@ #include <cstdio> #include "freetrackclient/fttypes.h" #include "wine-shm.h" -#include "opentrack-compat/export.hpp" +#include "compat/export.hpp" enum Axis { TX = 0, TY, TZ, Yaw, Pitch, Roll }; -#include "opentrack-compat/shm.h" +#include "compat/shm.h" void create_registry_key(void); diff --git a/proto-wine/opentrack-wrapper-wine-posix.cxx b/proto-wine/opentrack-wrapper-wine-posix.cxx index 50cce728..21c7622b 100644 --- a/proto-wine/opentrack-wrapper-wine-posix.cxx +++ b/proto-wine/opentrack-wrapper-wine-posix.cxx @@ -3,5 +3,5 @@ #endif #define PortableLockedShm ShmPosix -#include "opentrack-compat/shm.h" -#include "opentrack-compat/shm.cpp" +#include "compat/shm.h" +#include "compat/shm.cpp" diff --git a/proto-wine/opentrack-wrapper-wine-windows.cxx b/proto-wine/opentrack-wrapper-wine-windows.cxx index cc8ae63a..698e3c3b 100644 --- a/proto-wine/opentrack-wrapper-wine-windows.cxx +++ b/proto-wine/opentrack-wrapper-wine-windows.cxx @@ -3,8 +3,8 @@ #endif #define PortableLockedShm ShmWine -#include "opentrack-compat/shm.h" -#include "opentrack-compat/shm.cpp" +#include "compat/shm.h" +#include "compat/shm.cpp" #include "wine-shm.h" #define OPENTRACK_NO_QT_PATH #include "opentrack-library-path.h" diff --git a/spline-widget/spline-widget.cpp b/spline-widget/spline-widget.cpp index 17dbe31d..1f049339 100644 --- a/spline-widget/spline-widget.cpp +++ b/spline-widget/spline-widget.cpp @@ -5,7 +5,7 @@ * copyright notice and this permission notice appear in all copies. */ -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; #include "spline-widget.hpp" #include <QPainter> diff --git a/spline-widget/spline-widget.hpp b/spline-widget/spline-widget.hpp index 577e6f7f..1dbdb8e1 100644 --- a/spline-widget/spline-widget.hpp +++ b/spline-widget/spline-widget.hpp @@ -13,7 +13,7 @@ #include <QtGui> #include <QPointF> #include "spline.hpp" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" class SPLINE_WIDGET_EXPORT spline_widget : public QWidget { diff --git a/spline-widget/spline.hpp b/spline-widget/spline.hpp index 6387c87a..26775402 100644 --- a/spline-widget/spline.hpp +++ b/spline-widget/spline.hpp @@ -16,7 +16,7 @@ #include <QMutex> #include <vector> #include <limits> -#include "opentrack-compat/qcopyable-mutex.hpp" +#include "compat/qcopyable-mutex.hpp" #ifdef BUILD_spline_widget # define SPLINE_WIDGET_EXPORT Q_DECL_EXPORT diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index a1ca0ac5..9af182e5 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -6,14 +6,14 @@ */ #include "ftnoir_tracker_aruco.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <opencv2/core.hpp> #include <opencv2/videoio.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/calib3d.hpp> -#include "opentrack-compat/camera-names.hpp" -#include "opentrack-compat/sleep.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "compat/camera-names.hpp" +#include "compat/sleep.hpp" +#include "compat/pi-constant.hpp" #include <QMutexLocker> #include <QDebug> diff --git a/tracker-aruco/ftnoir_tracker_aruco.h b/tracker-aruco/ftnoir_tracker_aruco.h index 6c28c7db..aeabd438 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.h +++ b/tracker-aruco/ftnoir_tracker_aruco.h @@ -8,7 +8,7 @@ #pragma once #include "ui_aruco-trackercontrols.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "include/markerdetector.h" #include "cv/camera-dialog.hpp" @@ -26,7 +26,7 @@ #include <cinttypes> -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp index 9a5697dd..800428aa 100644 --- a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp @@ -1,6 +1,6 @@ #include "ftnoir_tracker_freepie-udp.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "api/plugin-api.hpp" +#include "compat/pi-constant.hpp" #include <cinttypes> #include <algorithm> diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h index 9d18c7d1..05228006 100644 --- a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h @@ -9,8 +9,8 @@ #include <QUdpSocket> #include <QThread> #include "ui_freepie-udp-controls.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp b/tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp index 3ebe359f..42a8308b 100644 --- a/tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp @@ -1,5 +1,5 @@ #include "ftnoir_tracker_freepie-udp.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" TrackerDialog::TrackerDialog() { diff --git a/tracker-hatire/ftnoir_tracker_hat.h b/tracker-hatire/ftnoir_tracker_hat.h index 03d00205..0969fd9c 100644 --- a/tracker-hatire/ftnoir_tracker_hat.h +++ b/tracker-hatire/ftnoir_tracker_hat.h @@ -1,7 +1,7 @@ #pragma once #include "thread.hpp" -#include "opentrack/plugin-support.hpp" +#include "api/plugin-support.hpp" #include "ftnoir_tracker_hat_settings.h" #include "ftnoir_arduino_type.h" diff --git a/tracker-hatire/ftnoir_tracker_hat_dialog.h b/tracker-hatire/ftnoir_tracker_hat_dialog.h index b93c4301..82615d53 100644 --- a/tracker-hatire/ftnoir_tracker_hat_dialog.h +++ b/tracker-hatire/ftnoir_tracker_hat_dialog.h @@ -1,4 +1,4 @@ -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ftnoir_tracker_hat_settings.h" #include "ftnoir_tracker_hat.h" #include "ui_ftnoir_hatcontrols.h" diff --git a/tracker-hatire/ftnoir_tracker_hat_settings.h b/tracker-hatire/ftnoir_tracker_hat_settings.h index 0450856b..fa24996e 100644 --- a/tracker-hatire/ftnoir_tracker_hat_settings.h +++ b/tracker-hatire/ftnoir_tracker_hat_settings.h @@ -8,7 +8,7 @@ #pragma once #include <QSerialPort> -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; diff --git a/tracker-hatire/thread.cpp b/tracker-hatire/thread.cpp index 764bd875..4f5feae5 100644 --- a/tracker-hatire/thread.cpp +++ b/tracker-hatire/thread.cpp @@ -1,5 +1,5 @@ #include "thread.hpp" -#include "opentrack-compat/sleep.hpp" +#include "compat/sleep.hpp" #include <utility> #include <QTextStream> diff --git a/tracker-hatire/thread.hpp b/tracker-hatire/thread.hpp index 26491cfe..dcdc13ee 100644 --- a/tracker-hatire/thread.hpp +++ b/tracker-hatire/thread.hpp @@ -10,8 +10,8 @@ #include <QFile> #include <QCoreApplication> -#include "opentrack/variance.hpp" -#include "opentrack-compat/timer.hpp" +#include "api/variance.hpp" +#include "compat/timer.hpp" enum results { diff --git a/tracker-ht/ftnoir_tracker_ht.cpp b/tracker-ht/ftnoir_tracker_ht.cpp index 1ffc387e..045d05f8 100644 --- a/tracker-ht/ftnoir_tracker_ht.cpp +++ b/tracker-ht/ftnoir_tracker_ht.cpp @@ -1,21 +1,21 @@ #include "headtracker-ftnoir.h" #include "ftnoir_tracker_ht.h" #include "ui_ht-trackercontrols.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <cmath> -#include "opentrack/camera-names.hpp" -#include "opentrack-compat/sleep.hpp" +#include "api/camera-names.hpp" +#include "compat/sleep.hpp" typedef struct { - int width; - int height; + int width; + int height; } resolution_tuple; static resolution_tuple resolution_choices[] = { - { 640, 480 }, - { 320, 240 }, - { 320, 200 }, - { 0, 0 } + { 640, 480 }, + { 320, 240 }, + { 320, 200 }, + { 0, 0 } }; void Tracker::load_settings(ht_config_t* config) @@ -63,9 +63,9 @@ void Tracker::load_settings(ht_config_t* config) int res = s.resolution; if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple))) - res = 0; - resolution_tuple r = resolution_choices[res]; - config->force_width = r.width; + res = 0; + resolution_tuple r = resolution_choices[res]; + config->force_width = r.width; config->force_height = r.height; config->flandmark_delay = 50; for (int i = 0; i < 5; i++) @@ -86,10 +86,10 @@ Tracker::~Tracker() should_stop = true; wait(); ht_free_context(ht); - if (layout) - delete layout; - if (videoWidget) - delete videoWidget; + if (layout) + delete layout; + if (videoWidget) + delete videoWidget; } void Tracker::start_tracker(QFrame* videoframe) diff --git a/tracker-ht/ftnoir_tracker_ht.h b/tracker-ht/ftnoir_tracker_ht.h index 1ec3467a..96fd258d 100644 --- a/tracker-ht/ftnoir_tracker_ht.h +++ b/tracker-ht/ftnoir_tracker_ht.h @@ -10,11 +10,11 @@ #include "headtracker-ftnoir.h" #include "ui_ht-trackercontrols.h" #include "ht_video_widget.h" -#include "opentrack-compat/shm.h" +#include "compat/shm.h" #include <QObject> -#include "opentrack-compat/options.hpp" -#include "opentrack/plugin-api.hpp" -#include "opentrack/opencv-camera-dialog.hpp" +#include "compat/options.hpp" +#include "api/plugin-api.hpp" +#include "api/opencv-camera-dialog.hpp" #include <QThread> #include <QMutex> diff --git a/tracker-hydra/ftnoir_tracker_hydra.cpp b/tracker-hydra/ftnoir_tracker_hydra.cpp index 33156f85..6b52153f 100644 --- a/tracker-hydra/ftnoir_tracker_hydra.cpp +++ b/tracker-hydra/ftnoir_tracker_hydra.cpp @@ -1,7 +1,7 @@ /* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ #include "ftnoir_tracker_hydra.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "api/plugin-api.hpp" +#include "compat/pi-constant.hpp" #include <cstdio> #include <cmath> #ifdef _WIN32 diff --git a/tracker-hydra/ftnoir_tracker_hydra.h b/tracker-hydra/ftnoir_tracker_hydra.h index 94396b7c..d8fe6afb 100644 --- a/tracker-hydra/ftnoir_tracker_hydra.h +++ b/tracker-hydra/ftnoir_tracker_hydra.h @@ -1,6 +1,6 @@ #include "ui_ftnoir_hydra_clientcontrols.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-hydra/ftnoir_tracker_hydra_dialog.cpp b/tracker-hydra/ftnoir_tracker_hydra_dialog.cpp index 773f8b50..42019dfa 100644 --- a/tracker-hydra/ftnoir_tracker_hydra_dialog.cpp +++ b/tracker-hydra/ftnoir_tracker_hydra_dialog.cpp @@ -1,5 +1,5 @@ #include "ftnoir_tracker_hydra.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" TrackerControls::TrackerControls() { diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp index d10b15ca..263a5cb0 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -5,7 +5,7 @@ * copyright notice and this permission notice appear in all copies. */ #include "ftnoir_tracker_joystick.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <QMutexLocker> FTNoIR_Tracker::FTNoIR_Tracker() diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 2d776ebf..0cd26f36 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -15,10 +15,10 @@ #include <QFrame> #include <QStringList> #include <cmath> -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" -#include "opentrack-dinput/win32-joystick.hpp" -#include "opentrack-compat/options.hpp" +#include "dinput/win32-joystick.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp index 035beef6..1d67cdbb 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -1,5 +1,5 @@ #include "ftnoir_tracker_joystick.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" TrackerControls::TrackerControls() : tracker(nullptr) { diff --git a/tracker-pt/camera.cpp b/tracker-pt/camera.cpp index e5901da1..c15bb2be 100644 --- a/tracker-pt/camera.cpp +++ b/tracker-pt/camera.cpp @@ -6,8 +6,8 @@ */ #include "camera.h" -#include "opentrack-compat/sleep.hpp" -#include "opentrack-compat/camera-names.hpp" +#include "compat/sleep.hpp" +#include "compat/camera-names.hpp" #include <string> #include <QDebug> diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 429a0305..eaf1de0d 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -12,8 +12,8 @@ #include <QDebug> #include <QFile> #include <QCoreApplication> -#include "opentrack-compat/camera-names.hpp" -#include "opentrack-compat/sleep.hpp" +#include "compat/camera-names.hpp" +#include "compat/sleep.hpp" #include <functional> //#define PT_PERF_LOG //log performance diff --git a/tracker-pt/ftnoir_tracker_pt.h b/tracker-pt/ftnoir_tracker_pt.h index f515715e..04a6646f 100644 --- a/tracker-pt/ftnoir_tracker_pt.h +++ b/tracker-pt/ftnoir_tracker_pt.h @@ -9,15 +9,15 @@ #ifndef FTNOIR_TRACKER_PT_H #define FTNOIR_TRACKER_PT_H -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ftnoir_tracker_pt_settings.h" #include "camera.h" #include "point_extractor.h" #include "point_tracker.h" -#include "opentrack-compat/timer.hpp" +#include "compat/timer.hpp" #include "cv/camera-dialog.hpp" #include "cv/video-widget.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "compat/pi-constant.hpp" #include <QThread> #include <QMutex> diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp index 9b09722f..307be1f2 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -12,7 +12,7 @@ #include <QDebug> #include <opencv2/core/core.hpp> #include <memory> -#include "opentrack-compat/camera-names.hpp" +#include "compat/camera-names.hpp" #include <vector> //----------------------------------------------------------------------------- diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.h b/tracker-pt/ftnoir_tracker_pt_dialog.h index d2647a94..49e8f1b0 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.h +++ b/tracker-pt/ftnoir_tracker_pt_dialog.h @@ -8,7 +8,7 @@ #ifndef FTNOIR_TRACKER_PT_DIALOG_H #define FTNOIR_TRACKER_PT_DIALOG_H -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ftnoir_tracker_pt_settings.h" #include "ftnoir_tracker_pt.h" #include "ui_FTNoIR_PT_Controls.h" diff --git a/tracker-pt/ftnoir_tracker_pt_settings.h b/tracker-pt/ftnoir_tracker_pt_settings.h index f5256f18..c076082a 100644 --- a/tracker-pt/ftnoir_tracker_pt_settings.h +++ b/tracker-pt/ftnoir_tracker_pt_settings.h @@ -8,7 +8,7 @@ #pragma once -#include "opentrack-compat/pi-constant.hpp" +#include "compat/pi-constant.hpp" #include <limits> #include <opencv2/core.hpp> @@ -28,7 +28,7 @@ struct pt_types using mat22 = mat<2, 2>; }; -#include "opentrack-compat/options.hpp" +#include "compat/options.hpp" using namespace options; struct settings_pt : opts diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index e749934e..f4034b28 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -10,7 +10,7 @@ #include <QDebug> #ifdef DEBUG_EXTRACTION -# include "opentrack-compat/timer.hpp" +# include "compat/timer.hpp" #endif #include <opencv2/videoio.hpp> diff --git a/tracker-pt/point_extractor.h b/tracker-pt/point_extractor.h index 9ef2adb4..0a019ec0 100644 --- a/tracker-pt/point_extractor.h +++ b/tracker-pt/point_extractor.h @@ -13,7 +13,7 @@ #include <opencv2/imgproc/imgproc.hpp> #include "ftnoir_tracker_pt_settings.h" -#include "opentrack-compat/pi-constant.hpp" +#include "compat/pi-constant.hpp" #include <vector> diff --git a/tracker-pt/point_tracker.cpp b/tracker-pt/point_tracker.cpp index a2511118..fe8ff0f2 100644 --- a/tracker-pt/point_tracker.cpp +++ b/tracker-pt/point_tracker.cpp @@ -6,7 +6,7 @@ */ #include "point_tracker.h" -#include "opentrack-compat/nan.hpp" +#include "compat/nan.hpp" #include <vector> #include <algorithm> @@ -325,11 +325,17 @@ int PointTracker::POSIT(const PointModel& model, const PointOrder& order_, f foc for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (nanp(r(i, j))) + { + qDebug() << "posit nan"; return -1; + } for (unsigned i = 0; i < 3; i++) if (nanp(t[i])) + { + qDebug() << "posit nan"; return -1; + } // apply results X_CM.R = r; diff --git a/tracker-pt/point_tracker.h b/tracker-pt/point_tracker.h index 00e371f5..6ed91069 100644 --- a/tracker-pt/point_tracker.h +++ b/tracker-pt/point_tracker.h @@ -8,7 +8,7 @@ #ifndef POINTTRACKER_H #define POINTTRACKER_H -#include "opentrack-compat/timer.hpp" +#include "compat/timer.hpp" #include "ftnoir_tracker_pt_settings.h" #include <opencv2/core/core.hpp> #include <memory> diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.cpp b/tracker-rift-025/ftnoir_tracker_rift_025.cpp index e6cbe3de..feacf5b1 100644 --- a/tracker-rift-025/ftnoir_tracker_rift_025.cpp +++ b/tracker-rift-025/ftnoir_tracker_rift_025.cpp @@ -1,7 +1,7 @@ /* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ #include "ftnoir_tracker_rift_025.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "api/plugin-api.hpp" +#include "compat/pi-constant.hpp" #include <OVR.h> #include <cstdio> #include <cmath> diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.h b/tracker-rift-025/ftnoir_tracker_rift_025.h index ea4d224f..33f615ea 100644 --- a/tracker-rift-025/ftnoir_tracker_rift_025.h +++ b/tracker-rift-025/ftnoir_tracker_rift_025.h @@ -1,7 +1,7 @@ #pragma once #include "ui_ftnoir_rift_clientcontrols_025.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" #include <OVR.h> #include <cmath> #include <memory> diff --git a/tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp b/tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp index f13883e0..c3a6a198 100644 --- a/tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp +++ b/tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp @@ -1,5 +1,5 @@ #include "ftnoir_tracker_rift_025.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" TrackerControls::TrackerControls() { diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.cpp b/tracker-rift-042/ftnoir_tracker_rift_042.cpp index a49f7d23..901e4d1f 100644 --- a/tracker-rift-042/ftnoir_tracker_rift_042.cpp +++ b/tracker-rift-042/ftnoir_tracker_rift_042.cpp @@ -1,7 +1,7 @@ /* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ #include "ftnoir_tracker_rift_042.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "api/plugin-api.hpp" +#include "compat/pi-constant.hpp" #include <OVR_CAPI.h> #include <Kernel/OVR_Math.h> #include <cstdio> diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.h b/tracker-rift-042/ftnoir_tracker_rift_042.h index e39ac654..55a59f18 100644 --- a/tracker-rift-042/ftnoir_tracker_rift_042.h +++ b/tracker-rift-042/ftnoir_tracker_rift_042.h @@ -1,7 +1,7 @@ #pragma once #include "ui_ftnoir_rift_clientcontrols_042.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" #include <OVR.h> #include <QMessageBox> #include <QWaitCondition> diff --git a/tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp b/tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp index 3fcf632c..f520b4b5 100644 --- a/tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp +++ b/tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp @@ -1,5 +1,5 @@ #include "ftnoir_tracker_rift_042.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" TrackerControls::TrackerControls() { diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.cpp b/tracker-rift-080/ftnoir_tracker_rift_080.cpp index d3019ac5..ce1f741a 100644 --- a/tracker-rift-080/ftnoir_tracker_rift_080.cpp +++ b/tracker-rift-080/ftnoir_tracker_rift_080.cpp @@ -1,7 +1,7 @@ /* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ #include "ftnoir_tracker_rift_080.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "api/plugin-api.hpp" +#include "compat/pi-constant.hpp" #include <OVR_CAPI.h> #include <Extras/OVR_Math.h> #include <OVR_CAPI_0_8_0.h> diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.h b/tracker-rift-080/ftnoir_tracker_rift_080.h index 280a729c..6adf6bcf 100644 --- a/tracker-rift-080/ftnoir_tracker_rift_080.h +++ b/tracker-rift-080/ftnoir_tracker_rift_080.h @@ -1,7 +1,7 @@ #pragma once #include "ui_ftnoir_rift_clientcontrols_080.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" #include <OVR.h> #include <cmath> #include <QMessageBox> diff --git a/tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp b/tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp index fd28475d..aba4f6bf 100644 --- a/tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp +++ b/tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp @@ -1,5 +1,5 @@ #include "ftnoir_tracker_rift_080.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" TrackerControls::TrackerControls() { diff --git a/tracker-rs/ftnoir_tracker_rs.cpp b/tracker-rs/ftnoir_tracker_rs.cpp index 4a59d74a..1ab32992 100644 --- a/tracker-rs/ftnoir_tracker_rs.cpp +++ b/tracker-rs/ftnoir_tracker_rs.cpp @@ -8,7 +8,7 @@ #include "ftnoir_tracker_rs.h" #include "ftnoir_tracker_rs_controls.h" #include "imagewidget.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "opentrack-library-path.h" #include <QMessageBox> #include <QProcess> @@ -46,7 +46,7 @@ void RSTracker::configurePreviewFrame() void RSTracker::start_tracker(QFrame* previewFrame) { - qDebug() << "tracker_rs: starting tracker"; + qDebug() << "tracker_rs: starting tracker"; mPreviewFrame = previewFrame; @@ -58,20 +58,20 @@ void RSTracker::start_tracker(QFrame* previewFrame) } void RSTracker::startPreview(){ - qDebug() << "tracker_rs: starting preview"; + qDebug() << "tracker_rs: starting preview"; mPreviewUpdateTimer.start(kPreviewUpdateInterval); } void RSTracker::updatePreview(){ - if (mImageWidget != nullptr && mImageWidget->isEnabled() && mTrackerWorkerThread.isRunning()) - mImageWidget->setImage(mTrackerWorkerThread.getPreview()); - else - qDebug() << "tracker_rs: not updating preview. worker thread running: " << mTrackerWorkerThread.isRunning(); + if (mImageWidget != nullptr && mImageWidget->isEnabled() && mTrackerWorkerThread.isRunning()) + mImageWidget->setImage(mTrackerWorkerThread.getPreview()); + else + qDebug() << "tracker_rs: not updating preview. worker thread running: " << mTrackerWorkerThread.isRunning(); } void RSTracker::stopPreview(){ - mPreviewUpdateTimer.stop(); - qDebug() << "tracker_rs: stopped preview"; + mPreviewUpdateTimer.stop(); + qDebug() << "tracker_rs: stopped preview"; } void RSTracker::handleTrackingEnded(int exitCode){ @@ -98,17 +98,17 @@ void RSTracker::showRealSenseErrorMessageBox(int exitCode) msgBox.setIcon(QMessageBox::Critical); msgBox.setText("RealSense Tracking Error"); - switch(exitCode){ - case -101: //The implementation got an invalid handle from the RealSense SDK session/modules + switch(exitCode){ + case -101: //The implementation got an invalid handle from the RealSense SDK session/modules msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed."); - break; - case -301: //RealSense SDK runtime execution aborted. - msgBox.setInformativeText("Tracking stopped after the RealSense SDK Runtime execution has aborted."); - break; - case -601: //RealSense Camera stream configuration has changed. - msgBox.setInformativeText("Tracking stopped after another program changed camera streams configuration."); - break; - default: + break; + case -301: //RealSense SDK runtime execution aborted. + msgBox.setInformativeText("Tracking stopped after the RealSense SDK Runtime execution has aborted."); + break; + case -601: //RealSense Camera stream configuration has changed. + msgBox.setInformativeText("Tracking stopped after another program changed camera streams configuration."); + break; + default: msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime 2016 R2 to be installed."); } @@ -126,7 +126,7 @@ void RSTracker::data(double *data) } RSTracker::~RSTracker() { - qDebug() << "tracker is being destroyed."; + qDebug() << "tracker is being destroyed."; stopPreview(); diff --git a/tracker-rs/ftnoir_tracker_rs.h b/tracker-rs/ftnoir_tracker_rs.h index 845e0beb..083794ed 100644 --- a/tracker-rs/ftnoir_tracker_rs.h +++ b/tracker-rs/ftnoir_tracker_rs.h @@ -7,7 +7,7 @@ #pragma once -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include "ui_ftnoir_tracker_rs_controls.h" #include "ftnoir_tracker_rs_worker.h" #include <QTimer> diff --git a/tracker-test/test.cpp b/tracker-test/test.cpp index b6cc742e..3e0db547 100644 --- a/tracker-test/test.cpp +++ b/tracker-test/test.cpp @@ -7,7 +7,7 @@ */ #include "test.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" #include <cmath> #include <QDebug> diff --git a/tracker-test/test.h b/tracker-test/test.h index afb11f6f..786d7705 100644 --- a/tracker-test/test.h +++ b/tracker-test/test.h @@ -1,8 +1,8 @@ #pragma once #include "ui_test.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/timer.hpp" -#include "opentrack-compat/pi-constant.hpp" +#include "api/plugin-api.hpp" +#include "compat/timer.hpp" +#include "compat/pi-constant.hpp" class FTNoIR_Tracker : public ITracker { diff --git a/tracker-test/test_dialog.cpp b/tracker-test/test_dialog.cpp index 38578ffc..5d33555b 100644 --- a/tracker-test/test_dialog.cpp +++ b/tracker-test/test_dialog.cpp @@ -1,3 +1,3 @@ #include "test.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" diff --git a/tracker-udp/ftnoir_tracker_udp.cpp b/tracker-udp/ftnoir_tracker_udp.cpp index bc3bebc6..8438d48f 100644 --- a/tracker-udp/ftnoir_tracker_udp.cpp +++ b/tracker-udp/ftnoir_tracker_udp.cpp @@ -7,7 +7,7 @@ */ #include "ftnoir_tracker_udp.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" FTNoIR_Tracker::FTNoIR_Tracker() : last_recv_pose { 0,0,0, 0,0,0 }, should_quit(false) {} diff --git a/tracker-udp/ftnoir_tracker_udp.h b/tracker-udp/ftnoir_tracker_udp.h index 3f0e6d8c..292df1f5 100644 --- a/tracker-udp/ftnoir_tracker_udp.h +++ b/tracker-udp/ftnoir_tracker_udp.h @@ -3,8 +3,8 @@ #include <QUdpSocket> #include <QThread> #include <cmath> -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/options.hpp" +#include "api/plugin-api.hpp" +#include "compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-udp/ftnoir_tracker_udp_dialog.cpp b/tracker-udp/ftnoir_tracker_udp_dialog.cpp index df274541..af94183c 100644 --- a/tracker-udp/ftnoir_tracker_udp_dialog.cpp +++ b/tracker-udp/ftnoir_tracker_udp_dialog.cpp @@ -1,5 +1,5 @@ #include "ftnoir_tracker_udp.h" -#include "opentrack/plugin-api.hpp" +#include "api/plugin-api.hpp" TrackerControls::TrackerControls() { -- cgit v1.2.3