From 0760fe011114fa440275b487eaf766b015f40e5b Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 16 Jun 2016 12:34:31 +0200 Subject: all: split "api" into "api" and "logic" Here, the "logic" module has all the stuff for building one's own graphical user interface. The "api" module has stuff used by other trackers. While at it, each of "api", "logic", and "compat" need their own export headers. This is because of preprocessor symbol clashes. This is all because a change in the "gui"-only dependency required a relink of all the trackers, protocols, and flters. It takes too long when building in the release configuration. With the split, only the "gui" module gets rebuilt. Since it has close to no static dependencies, it's fast enough. --- cmake/opentrack-version.cmake | 3 +- gui/CMakeLists.txt | 1 + gui/curve-config.cpp | 6 +- gui/curve-config.h | 2 +- gui/keyboard.h | 4 +- gui/options-dialog.hpp | 2 +- gui/ui.cpp | 2 +- gui/ui.h | 10 +- opentrack-compat/camera-names.hpp | 6 +- opentrack-compat/export.hpp | 8 +- opentrack-compat/import.hpp | 20 +- opentrack-compat/options.hpp | 6 +- opentrack-compat/shm.h | 6 +- opentrack-compat/timer.hpp | 6 +- opentrack-logic/CMakeLists.txt | 10 + opentrack-logic/export.hpp | 18 ++ opentrack-logic/import.hpp | 13 ++ opentrack-logic/keybinding-worker.cpp | 194 ++++++++++++++++++ opentrack-logic/keybinding-worker.hpp | 78 ++++++++ opentrack-logic/main-settings.hpp | 92 +++++++++ opentrack-logic/mappings.hpp | 89 +++++++++ opentrack-logic/nan.cpp | 16 ++ opentrack-logic/selected-libraries.cpp | 37 ++++ opentrack-logic/selected-libraries.hpp | 25 +++ opentrack-logic/shortcuts.cpp | 130 ++++++++++++ opentrack-logic/shortcuts.h | 66 +++++++ opentrack-logic/state.hpp | 29 +++ opentrack-logic/tracker.cpp | 305 +++++++++++++++++++++++++++++ opentrack-logic/tracker.h | 85 ++++++++ opentrack-logic/win32-joystick.cpp | 297 ++++++++++++++++++++++++++++ opentrack-logic/win32-joystick.hpp | 96 +++++++++ opentrack-logic/win32-shortcuts.cpp | 197 +++++++++++++++++++ opentrack-logic/win32-shortcuts.h | 24 +++ opentrack-logic/work.hpp | 63 ++++++ opentrack/CMakeLists.txt | 10 +- opentrack/dtors.cpp | 1 - opentrack/export.hpp | 18 ++ opentrack/import.hpp | 13 ++ opentrack/keybinding-worker.cpp | 194 ------------------ opentrack/keybinding-worker.hpp | 82 -------- opentrack/main-settings.hpp | 87 -------- opentrack/mappings.hpp | 89 --------- opentrack/nan.cpp | 16 -- opentrack/plugin-api.hpp | 22 +-- opentrack/selected-libraries.cpp | 37 ---- opentrack/selected-libraries.hpp | 29 --- opentrack/shortcuts.cpp | 130 ------------ opentrack/shortcuts.h | 69 ------- opentrack/simple-mat.hpp | 6 +- opentrack/state.hpp | 29 --- opentrack/tracker.cpp | 305 ----------------------------- opentrack/tracker.h | 87 -------- opentrack/win32-joystick.cpp | 297 ---------------------------- opentrack/win32-joystick.hpp | 100 ---------- opentrack/win32-shortcuts.cpp | 197 ------------------- opentrack/win32-shortcuts.h | 28 --- opentrack/work.hpp | 63 ------ proto-wine/wine-shm.h | 4 +- tracker-joystick/CMakeLists.txt | 2 + tracker-joystick/ftnoir_tracker_joystick.h | 2 +- x-plane-plugin/plugin.c | 19 +- 61 files changed, 1962 insertions(+), 1920 deletions(-) create mode 100644 opentrack-logic/CMakeLists.txt create mode 100644 opentrack-logic/export.hpp create mode 100644 opentrack-logic/import.hpp create mode 100644 opentrack-logic/keybinding-worker.cpp create mode 100644 opentrack-logic/keybinding-worker.hpp create mode 100644 opentrack-logic/main-settings.hpp create mode 100644 opentrack-logic/mappings.hpp create mode 100644 opentrack-logic/nan.cpp create mode 100644 opentrack-logic/selected-libraries.cpp create mode 100644 opentrack-logic/selected-libraries.hpp create mode 100644 opentrack-logic/shortcuts.cpp create mode 100644 opentrack-logic/shortcuts.h create mode 100644 opentrack-logic/state.hpp create mode 100644 opentrack-logic/tracker.cpp create mode 100644 opentrack-logic/tracker.h create mode 100644 opentrack-logic/win32-joystick.cpp create mode 100644 opentrack-logic/win32-joystick.hpp create mode 100644 opentrack-logic/win32-shortcuts.cpp create mode 100644 opentrack-logic/win32-shortcuts.h create mode 100644 opentrack-logic/work.hpp create mode 100644 opentrack/export.hpp create mode 100644 opentrack/import.hpp delete mode 100644 opentrack/keybinding-worker.cpp delete mode 100644 opentrack/keybinding-worker.hpp delete mode 100644 opentrack/main-settings.hpp delete mode 100644 opentrack/mappings.hpp delete mode 100644 opentrack/nan.cpp delete mode 100644 opentrack/selected-libraries.cpp delete mode 100644 opentrack/selected-libraries.hpp delete mode 100644 opentrack/shortcuts.cpp delete mode 100644 opentrack/shortcuts.h delete mode 100644 opentrack/state.hpp delete mode 100644 opentrack/tracker.cpp delete mode 100644 opentrack/tracker.h delete mode 100644 opentrack/win32-joystick.cpp delete mode 100644 opentrack/win32-joystick.hpp delete mode 100644 opentrack/win32-shortcuts.cpp delete mode 100644 opentrack/win32-shortcuts.h delete mode 100644 opentrack/work.hpp diff --git a/cmake/opentrack-version.cmake b/cmake/opentrack-version.cmake index b5b18ff0..b1896b55 100644 --- a/cmake/opentrack-version.cmake +++ b/cmake/opentrack-version.cmake @@ -19,6 +19,7 @@ endif() file(WRITE ${CMAKE_BINARY_DIR}/opentrack-version.h "#define OPENTRACK_VERSION \"${_build_type}${OPENTRACK_COMMIT}\"") set(version-string " +#define BUILD_compat #include \"opentrack-compat/export.hpp\" #ifdef __cplusplus @@ -26,7 +27,7 @@ extern \"C\" #else extern #endif -OPENTRACK_EXPORT +OPENTRACK_COMPAT_EXPORT const char* opentrack_version; const char* opentrack_version = \"${_build_type}${OPENTRACK_COMMIT}\"; diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 08534795..b7448b4c 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -17,6 +17,7 @@ if(NOT WIN32) endif() target_link_libraries(opentrack + opentrack-logic opentrack-spline-widget opentrack-pose-widget opentrack-version diff --git a/gui/curve-config.cpp b/gui/curve-config.cpp index e4396e01..61459c1c 100644 --- a/gui/curve-config.cpp +++ b/gui/curve-config.cpp @@ -7,7 +7,7 @@ */ #include "curve-config.h" -#include "opentrack/main-settings.hpp" +#include "opentrack-logic/main-settings.hpp" MapWidget::MapWidget(Mappings& m, main_settings& s) : m(m) { @@ -54,12 +54,12 @@ MapWidget::MapWidget(Mappings& m, main_settings& s) : qfc.setEnabled(qfcs[i].checkbox->isChecked()); qfc.force_redraw(); } - + if (qfcs[i].axis >= 3) qfcs[i].qfc->set_snap(2, 5); else qfcs[i].qfc->set_snap(1, 5); - + qfcs[i].qfc->setConfig(conf, name); } } diff --git a/gui/curve-config.h b/gui/curve-config.h index 0cbc7055..9a9475b9 100644 --- a/gui/curve-config.h +++ b/gui/curve-config.h @@ -1,6 +1,6 @@ #pragma once #include -#include "opentrack/mappings.hpp" +#include "opentrack-logic/mappings.hpp" #include "ui_mapping.h" class MapWidget: public QWidget diff --git a/gui/keyboard.h b/gui/keyboard.h index 696df605..07f326ea 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -1,8 +1,8 @@ #pragma once #include "ui_keyboard_listener.h" #ifdef _WIN32 -#include "opentrack/win32-shortcuts.h" -#include "opentrack/keybinding-worker.hpp" +#include "opentrack-logic/win32-shortcuts.h" +#include "opentrack-logic/keybinding-worker.hpp" #endif #include #include diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index a879a208..eee9d090 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -1,7 +1,7 @@ #pragma once #include "ui_settings.h" -#include "opentrack/shortcuts.h" +#include "opentrack-logic/shortcuts.h" #include #include #include diff --git a/gui/ui.cpp b/gui/ui.cpp index fd86aca8..63f40cf8 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -7,7 +7,7 @@ */ #include "ui.h" -#include "opentrack/tracker.h" +#include "opentrack-logic/tracker.h" #include "opentrack-compat/options.hpp" #include "new_file_dialog.h" #include diff --git a/gui/ui.h b/gui/ui.h index 42c4630c..626b1bb3 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -23,12 +23,12 @@ #include "ui_main.h" #include "opentrack-compat/options.hpp" -#include "opentrack/main-settings.hpp" +#include "opentrack-logic/main-settings.hpp" #include "opentrack/plugin-support.hpp" -#include "opentrack/tracker.h" -#include "opentrack/shortcuts.h" -#include "opentrack/work.hpp" -#include "opentrack/state.hpp" +#include "opentrack-logic/tracker.h" +#include "opentrack-logic/shortcuts.h" +#include "opentrack-logic/work.hpp" +#include "opentrack-logic/state.hpp" #include "curve-config.h" #include "options-dialog.hpp" #include "process_detector.h" diff --git a/opentrack-compat/camera-names.hpp b/opentrack-compat/camera-names.hpp index c2879000..ae0c6b25 100644 --- a/opentrack-compat/camera-names.hpp +++ b/opentrack-compat/camera-names.hpp @@ -11,11 +11,7 @@ #include #include -#ifdef BUILD_compat -# include "compat-export.hpp" -#else -# include "compat-import.hpp" -#endif +#include "export.hpp" OPENTRACK_COMPAT_EXPORT QList 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 index 100950a0..fbb62e1f 100644 --- a/opentrack-compat/export.hpp +++ b/opentrack-compat/export.hpp @@ -1,6 +1,6 @@ #pragma once -#ifndef OPENTRACK_EXPORT +#ifdef BUILD_compat # ifdef _WIN32 # define OPENTRACK_LINKAGE __declspec(dllexport) # else @@ -8,8 +8,10 @@ # endif # ifndef _MSC_VER -# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +# define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE # else -# define OPENTRACK_EXPORT OPENTRACK_LINKAGE +# define OPENTRACK_COMPAT_EXPORT OPENTRACK_LINKAGE # endif +#else +# include "import.hpp" #endif diff --git a/opentrack-compat/import.hpp b/opentrack-compat/import.hpp index 3747b141..1b4aa8f1 100644 --- a/opentrack-compat/import.hpp +++ b/opentrack-compat/import.hpp @@ -1,15 +1,13 @@ #pragma once -#ifndef OPENTRACK_EXPORT -# ifdef _WIN32 -# define OPENTRACK_LINKAGE __declspec(dllimport) -# else -# define OPENTRACK_LINKAGE -# endif +#ifdef _WIN32 +# define OPENTRACK_LINKAGE __declspec(dllimport) +#else +# define OPENTRACK_LINKAGE +#endif -# ifndef _MSC_VER -# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE -# else -# define OPENTRACK_EXPORT OPENTRACK_LINKAGE -# endif +#ifndef _MSC_VER +# define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +#else +# define OPENTRACK_COMPAT_EXPORT OPENTRACK_LINKAGE #endif diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp index 17ab093c..b8db411a 100644 --- a/opentrack-compat/options.hpp +++ b/opentrack-compat/options.hpp @@ -42,11 +42,7 @@ #include -#ifdef BUILD_compat -# include "compat-export.hpp" -#else -# include "compat-import.hpp" -#endif +#include "export.hpp" template using mem = std::shared_ptr; diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h index 3edb0080..c7af4ac7 100644 --- a/opentrack-compat/shm.h +++ b/opentrack-compat/shm.h @@ -24,11 +24,7 @@ # pragma GCC diagnostic ignored "-Wattributes" #endif -#ifdef BUILD_compat -# include "compat-export.hpp" -#else -# include "compat-import.hpp" -#endif +#include "export.hpp" class OPENTRACK_COMPAT_EXPORT PortableLockedShm { public: diff --git a/opentrack-compat/timer.hpp b/opentrack-compat/timer.hpp index 4f7e8d2e..c048844c 100644 --- a/opentrack-compat/timer.hpp +++ b/opentrack-compat/timer.hpp @@ -8,6 +8,9 @@ #pragma once #include + +#include "export.hpp" + #if defined (_WIN32) # include # ifndef CLOCK_MONOTONIC @@ -52,7 +55,8 @@ static inline void clock_gettime(int, struct timespec* ts) } # endif #endif -class Timer { +class OPENTRACK_COMPAT_EXPORT Timer +{ private: struct timespec state; long long conv(const struct timespec& cur) const diff --git a/opentrack-logic/CMakeLists.txt b/opentrack-logic/CMakeLists.txt new file mode 100644 index 00000000..000276d5 --- /dev/null +++ b/opentrack-logic/CMakeLists.txt @@ -0,0 +1,10 @@ +opentrack_boilerplate(opentrack-logic) +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 winmm) +endif() +if(CMAKE_COMPILER_IS_GNUCXX) + set_source_files_properties(nan.cpp PROPERTIES COMPILE_FLAGS "-fno-fast-math -fno-finite-math-only -fno-fast-math -O2") +endif() diff --git a/opentrack-logic/export.hpp b/opentrack-logic/export.hpp new file mode 100644 index 00000000..699fdd6a --- /dev/null +++ b/opentrack-logic/export.hpp @@ -0,0 +1,18 @@ +#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_LINKAGE +# endif + +#else +# include "import.hpp" +#endif \ No newline at end of file diff --git a/opentrack-logic/import.hpp b/opentrack-logic/import.hpp new file mode 100644 index 00000000..8a3e80c1 --- /dev/null +++ b/opentrack-logic/import.hpp @@ -0,0 +1,13 @@ +#pragma once + +#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 diff --git a/opentrack-logic/keybinding-worker.cpp b/opentrack-logic/keybinding-worker.cpp new file mode 100644 index 00000000..a0c7178c --- /dev/null +++ b/opentrack-logic/keybinding-worker.cpp @@ -0,0 +1,194 @@ +/* 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. + */ + +#ifdef _WIN32 + +#include "keybinding-worker.hpp" +#include +#include +#include +#include + +bool Key::should_process() +{ + if (!enabled || (keycode == 0 && guid == "")) + return false; + bool ret = timer.elapsed_ms() > 100; + timer.start(); + return ret; +} + +KeybindingWorker::~KeybindingWorker() { + should_quit = true; + wait(); + if (dinkeyboard) { + dinkeyboard->Unacquire(); + dinkeyboard->Release(); + } + if (din) + din->Release(); +} + +KeybindingWorker::KeybindingWorker() : + should_quit(true) +{ + if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { + qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); + return; + } + if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { + din->Release(); + din = 0; + qDebug() << "setup CreateDevice function failed!" << GetLastError(); + return; + } + if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { + qDebug() << "setup SetDataFormat function failed!" << GetLastError(); + dinkeyboard->Release(); + dinkeyboard = 0; + din->Release(); + din = 0; + return; + } + + if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); + return; + } + if (dinkeyboard->Acquire() != DI_OK) + { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); + return; + } + should_quit = false; + start(); +} + +KeybindingWorker& KeybindingWorker::make() +{ + static KeybindingWorker k; + return k; +} + +void KeybindingWorker::run() { + 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; + + 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(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; + + for (int i = receivers.size() - 1; i >= 0; i--) + { + if (receivers[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-logic/keybinding-worker.hpp b/opentrack-logic/keybinding-worker.hpp new file mode 100644 index 00000000..12237ab0 --- /dev/null +++ b/opentrack-logic/keybinding-worker.hpp @@ -0,0 +1,78 @@ +/* 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 "export.hpp" + +#include "opentrack-compat/timer.hpp" +#include "win32-joystick.hpp" +#include +#include +#include +#include +#include +#include + +#undef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION 0x0800 +#include +#include +struct 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_LOGIC_EXPORT KeybindingWorker : private QThread +{ +private: + LPDIRECTINPUT8 din; + LPDIRECTINPUTDEVICE8 dinkeyboard; + win32_joy_ctx joy_ctx; + volatile bool should_quit; + using fun = std::function; + std::vector> receivers; + QMutex mtx; + QMainWindow fake_main_window; + + void run() override; + KeybindingWorker(); + + KeybindingWorker(const KeybindingWorker&) = delete; + KeybindingWorker& operator=(KeybindingWorker&) = delete; + static KeybindingWorker& make(); + fun* _add_receiver(fun &receiver); + void remove_receiver(fun* pos); + ~KeybindingWorker(); +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-logic/main-settings.hpp b/opentrack-logic/main-settings.hpp new file mode 100644 index 00000000..16ff59e4 --- /dev/null +++ b/opentrack-logic/main-settings.hpp @@ -0,0 +1,92 @@ +/* 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 +#include "opentrack-compat/options.hpp" +#include "opentrack/plugin-api.hpp" + +using namespace options; + +#include "export.hpp" + +struct axis_opts +{ + pbundle b; + value zero; + value invert, altp; + value 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 keycode, guid; + value 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 main_settings : opts +{ + value tracker_dll, filter_dll, protocol_dll; + axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll; + value tcomp_p, tcomp_tz; + value tray_enabled; + value camera_yaw, camera_pitch, camera_roll; + value center_at_startup; + value 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; + main_settings() : + opts("opentrack-ui"), + tracker_dll(b, "tracker-dll", ""), + filter_dll(b, "filter-dll", "Accela"), + protocol_dll(b, "protocol-dll", "freetrack 2.0 Enhanced"), + a_x(b, "x", TX), + a_y(b, "y", TY), + a_z(b, "z", TZ), + a_yaw(b, "yaw", Yaw), + a_pitch(b, "pitch", Pitch), + a_roll(b, "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), + 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") + { + } +}; diff --git a/opentrack-logic/mappings.hpp b/opentrack-logic/mappings.hpp new file mode 100644 index 00000000..087ea7f3 --- /dev/null +++ b/opentrack-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 +#include "opentrack-compat/options.hpp" +using namespace options; +#include "spline-widget/functionconfig.h" +#include "main-settings.hpp" + +class Mapping { +public: + Mapping(QString primary, + QString secondary, + int max_x, + int max_y, + axis_opts& opts) : + curve(max_x, max_y), + curveAlt(max_x, max_y), + opts(opts), + name1(primary), + name2(secondary) + { + mem iniFile = group::ini_file(); + curve.loadSettings(*iniFile, primary); + curveAlt.loadSettings(*iniFile, secondary); + } + Map curve; + Map curveAlt; + axis_opts& opts; + QString name1, name2; +}; + +class Mappings { +private: + Mapping axes[6]; +public: + Mappings(std::vector opts) : + axes { + Mapping("tx","tx_alt", 100, 100, *opts[TX]), + Mapping("ty","ty_alt", 100, 100, *opts[TY]), + Mapping("tz","tz_alt", 100, 100, *opts[TZ]), + Mapping("rx", "rx_alt", 180, 180, *opts[Yaw]), + Mapping("ry", "ry_alt", 180, 180, *opts[Pitch]), + Mapping("rz", "rz_alt", 180, 180, *opts[Roll]) + } + {} + + inline Mapping& operator()(int i) { return axes[i]; } + inline const Mapping& operator()(int i) const { return axes[i]; } + + void load_mappings() + { + mem iniFile = group::ini_file(); + + for (int i = 0; i < 6; i++) + { + axes[i].curve.loadSettings(*iniFile, axes[i].name1); + axes[i].curveAlt.loadSettings(*iniFile, axes[i].name2); + axes[i].opts.b->reload(); + } + } + void save_mappings() + { + mem iniFile = group::ini_file(); + + for (int i = 0; i < 6; i++) + { + axes[i].curve.saveSettings(*iniFile, axes[i].name1); + axes[i].curveAlt.saveSettings(*iniFile, axes[i].name2); + axes[i].opts.b->save(); + } + } + + void invalidate_unsaved() + { + for (int i = 0; i < 6; i++) + { + axes[i].curve.invalidate_unsaved_settings(); + axes[i].curveAlt.invalidate_unsaved_settings(); + axes[i].opts.b->reload(); + } + } +}; diff --git a/opentrack-logic/nan.cpp b/opentrack-logic/nan.cpp new file mode 100644 index 00000000..2522ba38 --- /dev/null +++ b/opentrack-logic/nan.cpp @@ -0,0 +1,16 @@ +#include + +#if defined(__GNUC__) +bool __attribute__ ((noinline)) nanp(double value) +#elif defined(_WIN32) +__declspec(noinline) bool nanp(double value) +#else +bool nanp(double value) +#endif +{ + using std::isnan; + using std::isinf; + + const volatile double x = value; + return isnan(x) || isinf(x); +} \ No newline at end of file diff --git a/opentrack-logic/selected-libraries.cpp b/opentrack-logic/selected-libraries.cpp new file mode 100644 index 00000000..4a1a9f09 --- /dev/null +++ b/opentrack-logic/selected-libraries.cpp @@ -0,0 +1,37 @@ +#include "selected-libraries.hpp" +#include + +SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) : + pTracker(nullptr), + pFilter(nullptr), + pProtocol(nullptr), + correct(false) +{ + pProtocol = make_dylib_instance(p); + + if (!pProtocol) + { + qDebug() << "protocol dylib load failure"; + return; + } + + if(!pProtocol->correct()) + { + qDebug() << "protocol load failure"; + pProtocol = nullptr; + return; + } + + pTracker = make_dylib_instance(t); + pFilter = make_dylib_instance(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 new file mode 100644 index 00000000..2538adff --- /dev/null +++ b/opentrack-logic/selected-libraries.hpp @@ -0,0 +1,25 @@ +/* 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 "opentrack/plugin-support.hpp" +#include + +#include "export.hpp" + +struct OPENTRACK_LOGIC_EXPORT SelectedLibraries +{ + using dylibptr = mem; + mem pTracker; + mem pFilter; + mem 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 new file mode 100644 index 00000000..06c246af --- /dev/null +++ b/opentrack-logic/shortcuts.cpp @@ -0,0 +1,130 @@ +/* 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. + */ + +#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 tmp(nullptr); + key.swap(tmp); + } +#else + key.keycode = 0; + key.guid = ""; +#endif +} + +void Shortcuts::bind_keyboard_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(); + + 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 std::vector> &keys_) +{ + const unsigned sz = keys_.size(); + keys = std::vector(); + + 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_keyboard_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 new file mode 100644 index 00000000..87e24d4f --- /dev/null +++ b/opentrack-logic/shortcuts.h @@ -0,0 +1,66 @@ +/* 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 +#include +#include +#include + +#include "export.hpp" + +#include "qxt-mini/QxtGlobalShortcut" +#include "opentrack-compat/options.hpp" +#include "main-settings.hpp" + +#ifdef _WIN32 +# include "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 +#else + Key +#endif + ; + + using fun = std::function; + using tt = std::tuple; + std::vector keys; +#ifdef _WIN32 + KeybindingWorker::Token key_token; +#endif + + Shortcuts() +#ifdef _WIN32 + : key_token([&](const Key& k) { receiver(k); }) +#endif + {} + + void reload(const std::vector> &keys_); +private: + void free_binding(K& key); + void bind_keyboard_shortcut(K &key, const key_opts& k, bool held); +#ifdef _WIN32 + void receiver(const Key& k); +#endif +}; diff --git a/opentrack-logic/state.hpp b/opentrack-logic/state.hpp new file mode 100644 index 00000000..ff46cc36 --- /dev/null +++ b/opentrack-logic/state.hpp @@ -0,0 +1,29 @@ +/* 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 +#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" + +struct State { + State() : + pose(std::vector{&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; +}; diff --git a/opentrack-logic/tracker.cpp b/opentrack-logic/tracker.cpp new file mode 100644 index 00000000..3b3f35e6 --- /dev/null +++ b/opentrack-logic/tracker.cpp @@ -0,0 +1,305 @@ +/* Copyright (c) 2012-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. + */ + +/* + * this file appeared originally in facetracknoir, was rewritten completely + * following opentrack fork. + * + * originally written by Wim Vriend. + */ + + +#include "tracker.h" +#include +#include + +#if defined(_WIN32) +# include +#endif + +Tracker::Tracker(main_settings& s, Mappings &m, SelectedLibraries &libs) : + s(s), + m(m), + newpose {0,0,0, 0,0,0}, + centerp(s.center_at_startup), + enabledp(true), + zero_(false), + should_quit(false), + libs(libs), + r_b(rmat::eye()), + t_b {0,0,0} +{ +} + +Tracker::~Tracker() +{ + should_quit = true; + wait(); +} + +double Tracker::map(double pos, Mapping& axis) +{ + bool altp = (pos < 0) && axis.opts.altp; + axis.curve.setTrackingActive( !altp ); + axis.curveAlt.setTrackingActive( altp ); + auto& fc = altp ? axis.curveAlt : axis.curve; + return fc.getValue(pos); +} + +void Tracker::t_compensate(const rmat& rmat, const double* xyz, double* output, bool rz) +{ + // TY is really yaw axis. need swapping accordingly. + dmat<3, 1> tvec( xyz[2], -xyz[0], -xyz[1] ); + const dmat<3, 1> ret = rmat * tvec; + if (!rz) + output[2] = ret(0); + else + output[2] = xyz[2]; + output[1] = -ret(2); + output[0] = -ret(1); +} + +#ifdef _WIN32 +__declspec(noinline) bool nanp(double value); +#elif defined(__GNUC__) +bool __attribute__ ((noinline)) nanp(double value); +#else +bool nanp(double value); +#endif + +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; +} + +void Tracker::logic() +{ + bool inverts[6] = { + m(0).opts.invert, + m(1).opts.invert, + m(2).opts.invert, + m(3).opts.invert, + m(4).opts.invert, + m(5).opts.invert, + }; + + static constexpr double pi = 3.141592653; + static constexpr double r2d = 180. / pi; + + using namespace euler; + + 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]; + } + + if (is_nan(raw)) + raw = last_raw; + + const double off[] = + { + (double)-s.camera_yaw, + (double)-s.camera_pitch, + (double)-s.camera_roll + }; + const rmat cam = euler_to_rmat(off); + rmat r = euler_to_rmat(&value[Yaw]); + euler_t t(value(0), value(1), value(2)); + + r = cam * r; + + bool can_center = false; + const bool nan = is_nan(r, t); + + if (centerp && !nan) + { + for (int i = 0; i < 6; i++) + if (fabs(newpose[i]) != 0) + { + can_center = true; + break; + } + } + + if (can_center) + { + if (libs.pFilter) + libs.pFilter->center(); + centerp = false; + for (int i = 0; i < 3; i++) + t_b[i] = t(i); + r_b = r; + } + + { + double tmp[3] = { t(0) - t_b[0], t(1) - t_b[1], t(2) - t_b[2] }; + rmat m_; + switch (s.center_method) + { + case 0: + default: + m_ = r * r_b.t(); + break; + case 1: + m_ = r_b.t() * r; + } + + const euler_t euler = rmat_to_euler(m_); + + for (int i = 0; i < 3; i++) + { + value(i) = tmp[i]; + value(i+3) = euler(i) * r2d; + } + } + + bool nan_ = false; + // whenever something can corrupt its internal state due to nan/inf, elide the call + if (is_nan(value)) + { + nan_ = true; + } + else + { + { + Pose tmp = value; + + if (libs.pFilter) + libs.pFilter->filter(tmp, value); + } + + for (int i = 0; i < 6; i++) + value(i) = map(value(i), m(i)); + + if (s.tcomp_p) + t_compensate(euler_to_rmat(&value[Yaw]), + value, + value, + s.tcomp_tz); + + for (int i = 0; i < 6; i++) + value(i) += m(i).opts.zero; + + for (int i = 0; i < 6; i++) + value[i] *= inverts[i] ? -1. : 1.; + + if (zero_) + for (int i = 0; i < 6; i++) + value(i) = 0; + + if (is_nan(value)) + nan_ = true; + } + + 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; +} + +void Tracker::run() +{ + const int sleep_ms = 3; + +#if defined(_WIN32) + (void) timeBeginPeriod(1); +#endif + + while (!should_quit) + { + t.start(); + + double tmp[6] {0,0,0, 0,0,0}; + t_compensate(cam, tmp, tmp, false); + libs.pTracker->data(tmp); + + if (enabledp) + for (int i = 0; i < 6; i++) + newpose[i] = elide_nan(tmp[i], newpose[i]); + + logic(); + + long q = sleep_ms * 1000L - t.elapsed()/1000L; + using std::max; + usleep(max(1L, q)); + } + + { + // 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).curve.setTrackingActive(false); + m(i).curveAlt.setTrackingActive(false); + } +} + +void Tracker::get_raw_and_mapped_poses(double* mapped, double* raw) const { + QMutexLocker foo(&const_cast(*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 new file mode 100644 index 00000000..591ca03c --- /dev/null +++ b/opentrack-logic/tracker.h @@ -0,0 +1,85 @@ +/* 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 + +#include "opentrack-compat/timer.hpp" +#include "opentrack/plugin-support.hpp" +#include "mappings.hpp" +#include "opentrack/simple-mat.hpp" +#include "selected-libraries.hpp" + +#include "spline-widget/functionconfig.h" +#include "main-settings.hpp" +#include "opentrack-compat/options.hpp" + +#include +#include + +#include "export.hpp" + +class Pose +{ +private: + static constexpr double pi = 3.141592653; + static constexpr double d2r = pi/180.0; + static constexpr double r2d = 180./pi; + + double axes[6]; +public: + Pose() : axes {0,0,0, 0,0,0} {} + + inline operator double*() { return axes; } + inline operator const double*() const { return axes; } + + inline double& operator()(int i) { return axes[i]; } + inline double operator()(int i) const { return axes[i]; } +}; + +class OPENTRACK_LOGIC_EXPORT Tracker : private QThread +{ + Q_OBJECT +private: + QMutex mtx; + main_settings& s; + Mappings& m; + + Timer t; + Pose output_pose, raw_6dof, last_mapped, last_raw; + + double newpose[6]; + volatile bool centerp; + volatile bool enabledp; + volatile bool zero_; + volatile bool should_quit; + SelectedLibraries const& libs; + + using rmat = dmat<3, 3>; + + rmat r_b; + double t_b[3]; + + double map(double pos, Mapping& axis); + void logic(); + + void t_compensate(const rmat& rmat, const double* ypr, double* output, bool rz); + void run() override; +public: + Tracker(main_settings& s, Mappings& m, SelectedLibraries& libs); + ~Tracker(); + + void get_raw_and_mapped_poses(double* mapped, double* raw) const; + void start() { QThread::start(); } + void toggle_enabled() { qDebug() << "toggle enabled"; enabledp = !enabledp; } + void set_toggle(bool value) { qDebug() << "enabled" << value; enabledp = value; } + void set_zero(bool value) { qDebug() << "zero" << value; zero_ = value; } + void center() { qDebug() << "toggle center"; centerp = !centerp; } + void zero() { qDebug() << "toggle zero"; zero_ = !zero_; } +}; diff --git a/opentrack-logic/win32-joystick.cpp b/opentrack-logic/win32-joystick.cpp new file mode 100644 index 00000000..bf919f4a --- /dev/null +++ b/opentrack-logic/win32-joystick.cpp @@ -0,0 +1,297 @@ +#undef NDEBUG +#include +#include "win32-joystick.hpp" + +#ifdef _WIN32 + +void win32_joy_ctx::poll(fn f) +{ + //refresh(false); + + QMutexLocker l(&mtx); + + for (auto& j : joys) + { + j.second->poll(f); + } +} + +bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) +{ + //refresh(false); + + QMutexLocker l(&mtx); + + 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; + + (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; + memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + 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; +} + +win32_joy_ctx::~win32_joy_ctx() +{ + release(); +} + +std::vector win32_joy_ctx::get_joy_info() +{ + QMutexLocker l(&mtx); + + std::vector ret; + + for (auto& j : joys) + ret.push_back(joy_info { j.second->name, j.first }); + + return ret; +} + +win32_joy_ctx::win32_joy_ctx() +{ + if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL) != DI_OK) { + qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); + assert(!"direct input handle can't be created"); + } + refresh(); +} + +void win32_joy_ctx::release() +{ + joys = std::unordered_map>(); + di->Release(); + di = nullptr; +} + +void win32_joy_ctx::refresh() +{ + QMutexLocker l(&mtx); + + qDebug() << "joy list refresh"; + enum_state st(joys, fake_main_window, di); +} + +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; + memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + for (int i = 0; i < 128; i++) + { + const bool state = !!(js.rgbButtons[i] & 0x80) && js.rgbButtons[i] != js_old.rgbButtons[i]; + if (state != pressed[i]) + { + f(guid, i, state); + qDebug() << "btn" << guid << i << state; + } + pressed[i] = state; + } + + js_old = js; + + return true; +} + +win32_joy_ctx::enum_state::enum_state(std::unordered_map> &joys_, + QMainWindow &fake_main_window, + LPDIRECTINPUT8 di) : + fake_main_window(fake_main_window), + di(di) +{ + joys = joys_; + + 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.cend()) + it = joys.erase(it); + else + it++; + } + + joys_ = joys; +} + +win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) +{ + enum_state& state = *reinterpret_cast(pContext); + const QString guid = guid_to_string(pdidInstance->guidInstance); + const QString name = QString(pdidInstance->tszInstanceName); + + auto it = state.joys.find(guid); + const bool exists = it != state.joys.end(); + + state.all.push_back(guid); + + if (!exists) + { + 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; + } + + if (FAILED(h->SetCooperativeLevel((HWND) state.fake_main_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; + } + + qDebug() << "add joy" << guid; + state.joys[guid] = std::make_shared(h, guid, name); + } +end: + return DIENUM_CONTINUE; +} + +win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx) +{ + if (pdidoi->dwType & DIDFT_AXIS) + { + DIPROPRANGE diprg; + 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(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() << "got joy" << guid; + for (int i = 0; i < 128; i++) + pressed[i] = false; + memset(&js_old, 0, sizeof(js_old)); +} + +win32_joy_ctx::joy::~joy() +{ + qDebug() << "nix joy" << guid; + release(); +} + +#endif diff --git a/opentrack-logic/win32-joystick.hpp b/opentrack-logic/win32-joystick.hpp new file mode 100644 index 00000000..d9b62e45 --- /dev/null +++ b/opentrack-logic/win32-joystick.hpp @@ -0,0 +1,96 @@ +#pragma once + +#ifdef _WIN32 + +#include "export.hpp" + +#include +#include +#include +#include +#include +#include +#ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +#endif +#include +#include +#include "opentrack-compat/timer.hpp" +#include +#include +#include +#include +#include + +namespace std { +template<> +struct hash +{ + inline std::size_t operator()(const QString& value) const + { + return qHash(value); + } +}; +} + +struct OPENTRACK_LOGIC_EXPORT win32_joy_ctx +{ + using fn = std::function; + + enum { joy_axis_size = 65535 }; + + struct joy_info + { + QString name, guid; + }; + + void poll(fn f); + bool poll_axis(const QString& guid, int axes[8]); + std::vector get_joy_info(); + + win32_joy_ctx(const win32_joy_ctx&) = delete; + win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; + + win32_joy_ctx(); + ~win32_joy_ctx(); + void refresh(); +private: + QMutex mtx; + QMainWindow fake_main_window; + LPDIRECTINPUT8 di; + + static QString guid_to_string(const GUID guid); + void release(); + + struct joy + { + LPDIRECTINPUTDEVICE8 joy_handle; + QString guid, name; + bool pressed[128]; + Timer first_timer; + DIJOYSTATE2 js_old; + + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name); + ~joy(); + + void release(); + bool poll(fn f); + }; + + std::unordered_map> joys; + + class enum_state + { + std::unordered_map> joys; + QMainWindow& fake_main_window; + LPDIRECTINPUT8 di; + + std::vector all; + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); + static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); + public: + enum_state(std::unordered_map>& joys, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); + }; +}; + +#endif diff --git a/opentrack-logic/win32-shortcuts.cpp b/opentrack-logic/win32-shortcuts.cpp new file mode 100644 index 00000000..a93803a3 --- /dev/null +++ b/opentrack-logic/win32-shortcuts.cpp @@ -0,0 +1,197 @@ +/* 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. + */ + +#if defined(_WIN32) +# ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +# endif +# include +# include + +#include +#include +#include +#include "win32-shortcuts.h" + +QList windows_key_mods = + QList({ + 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 windows_key_sequences = + QList({ + 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(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(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(our_mods); + return true; + } + } + } + return false; +} + +#endif diff --git a/opentrack-logic/win32-shortcuts.h b/opentrack-logic/win32-shortcuts.h new file mode 100644 index 00000000..7626a31f --- /dev/null +++ b/opentrack-logic/win32-shortcuts.h @@ -0,0 +1,24 @@ +#pragma once + +#ifdef _WIN32 + +#include +#include "shortcuts.h" + +struct win_key; + +extern QList windows_key_mods; +extern QList 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.hpp b/opentrack-logic/work.hpp new file mode 100644 index 00000000..2377be5a --- /dev/null +++ b/opentrack-logic/work.hpp @@ -0,0 +1,63 @@ +/* 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 "main-settings.hpp" +#include "opentrack/plugin-support.hpp" +#include "tracker.h" +#include "shortcuts.h" + +#include +#include +#include +#include +#include +#include + +struct Work +{ + main_settings& s; + SelectedLibraries& libs; + mem tracker; + mem sc; + WId handle; + using fn = std::function; + using tt = std::tuple; + std::vector keys; + + Work(main_settings& s, Mappings& m, SelectedLibraries& libs, WId handle) : + s(s), libs(libs), + tracker(std::make_shared(s, m, libs)), + sc(std::make_shared()), + handle(handle), + keys { + tt(s.key_center, [&](bool) -> void { tracker->center(); }, true), + tt(s.key_toggle, [&](bool) -> void { tracker->toggle_enabled(); }, true), + tt(s.key_zero, [&](bool) -> void { tracker->zero(); }, true), + tt(s.key_toggle_press, [&](bool x) -> void { tracker->set_toggle(!x); }, false), + tt(s.key_zero_press, [&](bool x) -> void { tracker->set_zero(x); }, false), + } + { + reload_shortcuts(); + tracker->start(); + } + + void reload_shortcuts() + { + sc->reload(keys); + } + + ~Work() + { + sc = nullptr; + // order matters, otherwise use-after-free -sh + tracker = nullptr; + libs = SelectedLibraries(); + } +}; diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt index dd90bda6..6dc6a96d 100644 --- a/opentrack/CMakeLists.txt +++ b/opentrack/CMakeLists.txt @@ -1,10 +1,2 @@ opentrack_boilerplate(opentrack-api NO-COMPAT) -target_link_libraries(opentrack-api opentrack-spline-widget opentrack-compat) -if(NOT WIN32) - target_link_libraries(opentrack-api opentrack-qxt-mini) -else() - target_link_libraries(opentrack-api winmm) -endif() -if(CMAKE_COMPILER_IS_GNUCXX) - set_source_files_properties(nan.cpp PROPERTIES COMPILE_FLAGS "-fno-fast-math -fno-finite-math-only -fno-fast-math -O2") -endif() +target_link_libraries(opentrack-api opentrack-compat) diff --git a/opentrack/dtors.cpp b/opentrack/dtors.cpp index 578d067a..5cc87187 100644 --- a/opentrack/dtors.cpp +++ b/opentrack/dtors.cpp @@ -1,5 +1,4 @@ #include "plugin-api.hpp" -#include "main-settings.hpp" // these exist only so that vtable is emitted in a single compilation unit, not all of them. diff --git a/opentrack/export.hpp b/opentrack/export.hpp new file mode 100644 index 00000000..2dab8bef --- /dev/null +++ b/opentrack/export.hpp @@ -0,0 +1,18 @@ +#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_LINKAGE +# endif + +#else +# include "import.hpp" +#endif diff --git a/opentrack/import.hpp b/opentrack/import.hpp new file mode 100644 index 00000000..7448416a --- /dev/null +++ b/opentrack/import.hpp @@ -0,0 +1,13 @@ +#pragma once + +#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 diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp deleted file mode 100644 index a0c7178c..00000000 --- a/opentrack/keybinding-worker.cpp +++ /dev/null @@ -1,194 +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. - */ - -#ifdef _WIN32 - -#include "keybinding-worker.hpp" -#include -#include -#include -#include - -bool Key::should_process() -{ - if (!enabled || (keycode == 0 && guid == "")) - return false; - bool ret = timer.elapsed_ms() > 100; - timer.start(); - return ret; -} - -KeybindingWorker::~KeybindingWorker() { - should_quit = true; - wait(); - if (dinkeyboard) { - dinkeyboard->Unacquire(); - dinkeyboard->Release(); - } - if (din) - din->Release(); -} - -KeybindingWorker::KeybindingWorker() : - should_quit(true) -{ - if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { - qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); - return; - } - if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { - din->Release(); - din = 0; - qDebug() << "setup CreateDevice function failed!" << GetLastError(); - return; - } - if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { - qDebug() << "setup SetDataFormat function failed!" << GetLastError(); - dinkeyboard->Release(); - dinkeyboard = 0; - din->Release(); - din = 0; - return; - } - - if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { - dinkeyboard->Release(); - din->Release(); - din = 0; - dinkeyboard = 0; - qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); - return; - } - if (dinkeyboard->Acquire() != DI_OK) - { - dinkeyboard->Release(); - din->Release(); - din = 0; - dinkeyboard = 0; - qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); - return; - } - should_quit = false; - start(); -} - -KeybindingWorker& KeybindingWorker::make() -{ - static KeybindingWorker k; - return k; -} - -void KeybindingWorker::run() { - 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; - - 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(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; - - for (int i = receivers.size() - 1; i >= 0; i--) - { - if (receivers[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/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp deleted file mode 100644 index 19db0fa9..00000000 --- a/opentrack/keybinding-worker.hpp +++ /dev/null @@ -1,82 +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 - -#ifdef BUILD_api -# include "opentrack-compat/export.hpp" -#else -# include "opentrack-compat/import.hpp" -#endif - -#include "opentrack-compat/timer.hpp" -#include "opentrack/win32-joystick.hpp" -#include -#include -#include -#include -#include -#include - -#undef DIRECTINPUT_VERSION -#define DIRECTINPUT_VERSION 0x0800 -#include -#include -struct 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_EXPORT KeybindingWorker : private QThread -{ -private: - LPDIRECTINPUT8 din; - LPDIRECTINPUTDEVICE8 dinkeyboard; - win32_joy_ctx joy_ctx; - volatile bool should_quit; - using fun = std::function; - std::vector> receivers; - QMutex mtx; - QMainWindow fake_main_window; - - void run() override; - KeybindingWorker(); - - KeybindingWorker(const KeybindingWorker&) = delete; - KeybindingWorker& operator=(KeybindingWorker&) = delete; - static KeybindingWorker& make(); - fun* _add_receiver(fun &receiver); - void remove_receiver(fun* pos); - ~KeybindingWorker(); -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/main-settings.hpp b/opentrack/main-settings.hpp deleted file mode 100644 index 7c04fd6d..00000000 --- a/opentrack/main-settings.hpp +++ /dev/null @@ -1,87 +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 -#include "opentrack-compat/options.hpp" -#include "opentrack/plugin-api.hpp" - -using namespace options; - -struct axis_opts { - pbundle b; - value zero; - value invert, altp; - value 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 keycode, guid; - value 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 main_settings : opts { - value tracker_dll, filter_dll, protocol_dll; - axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll; - value tcomp_p, tcomp_tz; - value tray_enabled; - value camera_yaw, camera_pitch, camera_roll; - value center_at_startup; - value 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; - main_settings() : - opts("opentrack-ui"), - tracker_dll(b, "tracker-dll", ""), - filter_dll(b, "filter-dll", "Accela"), - protocol_dll(b, "protocol-dll", "freetrack 2.0 Enhanced"), - a_x(b, "x", TX), - a_y(b, "y", TY), - a_z(b, "z", TZ), - a_yaw(b, "yaw", Yaw), - a_pitch(b, "pitch", Pitch), - a_roll(b, "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), - 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") - { - } -}; diff --git a/opentrack/mappings.hpp b/opentrack/mappings.hpp deleted file mode 100644 index 087ea7f3..00000000 --- a/opentrack/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 -#include "opentrack-compat/options.hpp" -using namespace options; -#include "spline-widget/functionconfig.h" -#include "main-settings.hpp" - -class Mapping { -public: - Mapping(QString primary, - QString secondary, - int max_x, - int max_y, - axis_opts& opts) : - curve(max_x, max_y), - curveAlt(max_x, max_y), - opts(opts), - name1(primary), - name2(secondary) - { - mem iniFile = group::ini_file(); - curve.loadSettings(*iniFile, primary); - curveAlt.loadSettings(*iniFile, secondary); - } - Map curve; - Map curveAlt; - axis_opts& opts; - QString name1, name2; -}; - -class Mappings { -private: - Mapping axes[6]; -public: - Mappings(std::vector opts) : - axes { - Mapping("tx","tx_alt", 100, 100, *opts[TX]), - Mapping("ty","ty_alt", 100, 100, *opts[TY]), - Mapping("tz","tz_alt", 100, 100, *opts[TZ]), - Mapping("rx", "rx_alt", 180, 180, *opts[Yaw]), - Mapping("ry", "ry_alt", 180, 180, *opts[Pitch]), - Mapping("rz", "rz_alt", 180, 180, *opts[Roll]) - } - {} - - inline Mapping& operator()(int i) { return axes[i]; } - inline const Mapping& operator()(int i) const { return axes[i]; } - - void load_mappings() - { - mem iniFile = group::ini_file(); - - for (int i = 0; i < 6; i++) - { - axes[i].curve.loadSettings(*iniFile, axes[i].name1); - axes[i].curveAlt.loadSettings(*iniFile, axes[i].name2); - axes[i].opts.b->reload(); - } - } - void save_mappings() - { - mem iniFile = group::ini_file(); - - for (int i = 0; i < 6; i++) - { - axes[i].curve.saveSettings(*iniFile, axes[i].name1); - axes[i].curveAlt.saveSettings(*iniFile, axes[i].name2); - axes[i].opts.b->save(); - } - } - - void invalidate_unsaved() - { - for (int i = 0; i < 6; i++) - { - axes[i].curve.invalidate_unsaved_settings(); - axes[i].curveAlt.invalidate_unsaved_settings(); - axes[i].opts.b->reload(); - } - } -}; diff --git a/opentrack/nan.cpp b/opentrack/nan.cpp deleted file mode 100644 index 2522ba38..00000000 --- a/opentrack/nan.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include - -#if defined(__GNUC__) -bool __attribute__ ((noinline)) nanp(double value) -#elif defined(_WIN32) -__declspec(noinline) bool nanp(double value) -#else -bool nanp(double value) -#endif -{ - using std::isnan; - using std::isinf; - - const volatile double x = value; - return isnan(x) || isinf(x); -} \ No newline at end of file diff --git a/opentrack/plugin-api.hpp b/opentrack/plugin-api.hpp index e715780e..6cd76a16 100644 --- a/opentrack/plugin-api.hpp +++ b/opentrack/plugin-api.hpp @@ -13,11 +13,7 @@ #include #include -#ifdef BUILD_api -# include "opentrack-compat/export.hpp" -#else -# include "opentrack-compat/import.hpp" -#endif +#include "export.hpp" #ifndef OPENTRACK_PLUGIN_EXPORT # ifdef _WIN32 @@ -39,7 +35,7 @@ enum Axis { namespace plugin_api { namespace detail { -class OPENTRACK_EXPORT BaseDialog : public QWidget +class OPENTRACK_API_EXPORT BaseDialog : public QWidget { Q_OBJECT public: @@ -67,7 +63,7 @@ signals: // implement this in all plugins // also you must link against "opentrack-api" in CMakeLists.txt to avoid vtable link errors -struct OPENTRACK_EXPORT Metadata +struct OPENTRACK_API_EXPORT Metadata { Metadata(const Metadata&) = delete; Metadata(Metadata&&) = delete; @@ -83,7 +79,7 @@ struct OPENTRACK_EXPORT Metadata }; // implement this in filters -struct OPENTRACK_EXPORT IFilter +struct OPENTRACK_API_EXPORT IFilter { IFilter(const IFilter&) = delete; IFilter(IFilter&&) = delete; @@ -99,7 +95,7 @@ struct OPENTRACK_EXPORT IFilter virtual void center() {} }; -struct OPENTRACK_EXPORT IFilterDialog : public plugin_api::detail::BaseDialog +struct OPENTRACK_API_EXPORT IFilterDialog : public plugin_api::detail::BaseDialog { // optional destructor virtual ~IFilterDialog(); @@ -114,7 +110,7 @@ struct OPENTRACK_EXPORT IFilterDialog : public plugin_api::detail::BaseDialog OPENTRACK_DECLARE_PLUGIN_INTERNAL(filter_class, IFilter, metadata_class, dialog_class, IFilterDialog) // implement this in protocols -struct OPENTRACK_EXPORT IProtocol +struct OPENTRACK_API_EXPORT IProtocol { IProtocol(const IProtocol&) = delete; IProtocol(IProtocol&&) = delete; @@ -132,7 +128,7 @@ struct OPENTRACK_EXPORT IProtocol virtual QString game_name() = 0; }; -struct OPENTRACK_EXPORT IProtocolDialog : public plugin_api::detail::BaseDialog +struct OPENTRACK_API_EXPORT IProtocolDialog : public plugin_api::detail::BaseDialog { // optional destructor virtual ~IProtocolDialog(); @@ -147,7 +143,7 @@ struct OPENTRACK_EXPORT IProtocolDialog : public plugin_api::detail::BaseDialog OPENTRACK_DECLARE_PLUGIN_INTERNAL(protocol_class, IProtocol, metadata_class, dialog_class, IProtocolDialog) // implement this in trackers -struct OPENTRACK_EXPORT ITracker +struct OPENTRACK_API_EXPORT ITracker { ITracker(const ITracker&) = delete; ITracker(ITracker&&) = delete; @@ -162,7 +158,7 @@ struct OPENTRACK_EXPORT ITracker virtual void data(double *data) = 0; }; -struct OPENTRACK_EXPORT ITrackerDialog : public plugin_api::detail::BaseDialog +struct OPENTRACK_API_EXPORT ITrackerDialog : public plugin_api::detail::BaseDialog { // optional destructor virtual ~ITrackerDialog(); diff --git a/opentrack/selected-libraries.cpp b/opentrack/selected-libraries.cpp deleted file mode 100644 index 63517774..00000000 --- a/opentrack/selected-libraries.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "opentrack/selected-libraries.hpp" -#include - -SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) : - pTracker(nullptr), - pFilter(nullptr), - pProtocol(nullptr), - correct(false) -{ - pProtocol = make_dylib_instance(p); - - if (!pProtocol) - { - qDebug() << "protocol dylib load failure"; - return; - } - - if(!pProtocol->correct()) - { - qDebug() << "protocol load failure"; - pProtocol = nullptr; - return; - } - - pTracker = make_dylib_instance(t); - pFilter = make_dylib_instance(f); - - if (!pTracker) - { - qDebug() << "tracker dylib load failure"; - return; - } - - pTracker->start_tracker(frame); - - correct = true; -} diff --git a/opentrack/selected-libraries.hpp b/opentrack/selected-libraries.hpp deleted file mode 100644 index b396b5ec..00000000 --- a/opentrack/selected-libraries.hpp +++ /dev/null @@ -1,29 +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 "opentrack/plugin-support.hpp" -#include - - -#ifdef BUILD_api -# include "opentrack-compat/export.hpp" -#else -# include "opentrack-compat/import.hpp" -#endif - -struct OPENTRACK_EXPORT SelectedLibraries { - using dylibptr = mem; - mem pTracker; - mem pFilter; - mem 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/shortcuts.cpp b/opentrack/shortcuts.cpp deleted file mode 100644 index 06c246af..00000000 --- a/opentrack/shortcuts.cpp +++ /dev/null @@ -1,130 +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. - */ - -#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 tmp(nullptr); - key.swap(tmp); - } -#else - key.keycode = 0; - key.guid = ""; -#endif -} - -void Shortcuts::bind_keyboard_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(); - - 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 std::vector> &keys_) -{ - const unsigned sz = keys_.size(); - keys = std::vector(); - - 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_keyboard_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/shortcuts.h b/opentrack/shortcuts.h deleted file mode 100644 index 2362c88b..00000000 --- a/opentrack/shortcuts.h +++ /dev/null @@ -1,69 +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 -#include -#include -#include - -#ifdef BUILD_api -# include "opentrack-compat/export.hpp" -#else -# include "opentrack-compat/import.hpp" -#endif - -#include "qxt-mini/QxtGlobalShortcut" -#include "opentrack-compat/options.hpp" -#include "opentrack/main-settings.hpp" - -#ifdef _WIN32 -# include "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_EXPORT Shortcuts : public QObject { - Q_OBJECT - -public: - using K = -#ifndef _WIN32 - mem -#else - Key -#endif - ; - - using fun = std::function; - using tt = std::tuple; - std::vector keys; -#ifdef _WIN32 - KeybindingWorker::Token key_token; -#endif - - Shortcuts() -#ifdef _WIN32 - : key_token([&](const Key& k) { receiver(k); }) -#endif - {} - - void reload(const std::vector> &keys_); -private: - void free_binding(K& key); - void bind_keyboard_shortcut(K &key, const key_opts& k, bool held); -#ifdef _WIN32 - void receiver(const Key& k); -#endif -}; diff --git a/opentrack/simple-mat.hpp b/opentrack/simple-mat.hpp index 54ebb920..ce2bccc5 100644 --- a/opentrack/simple-mat.hpp +++ b/opentrack/simple-mat.hpp @@ -242,16 +242,18 @@ public: } }; +#include "export.hpp" + namespace euler { template using dmat = Mat; using rmat = dmat<3, 3>; using euler_t = dmat<3, 1>; -rmat euler_to_rmat(const double* input); +rmat OPENTRACK_API_EXPORT euler_to_rmat(const double* input); // http://stackoverflow.com/a/18436193 -euler_t rmat_to_euler(const dmat<3, 3>& R); +euler_t OPENTRACK_API_EXPORT rmat_to_euler(const dmat<3, 3>& R); } // end ns euler diff --git a/opentrack/state.hpp b/opentrack/state.hpp deleted file mode 100644 index dcb18293..00000000 --- a/opentrack/state.hpp +++ /dev/null @@ -1,29 +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 -#include "opentrack-compat/options.hpp" -using namespace options; -#include "opentrack/plugin-support.hpp" -#include "opentrack/main-settings.hpp" -#include "opentrack/mappings.hpp" -#include "opentrack/selected-libraries.hpp" -#include "opentrack/work.hpp" - -struct State { - State() : - pose(std::vector{&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; -}; diff --git a/opentrack/tracker.cpp b/opentrack/tracker.cpp deleted file mode 100644 index 9d754324..00000000 --- a/opentrack/tracker.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* Copyright (c) 2012-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. - */ - -/* - * this file appeared originally in facetracknoir, was rewritten completely - * following opentrack fork. - * - * originally written by Wim Vriend. - */ - - -#include "tracker.h" -#include -#include - -#if defined(_WIN32) -# include -#endif - -Tracker::Tracker(main_settings& s, Mappings &m, SelectedLibraries &libs) : - s(s), - m(m), - newpose {0,0,0, 0,0,0}, - centerp(s.center_at_startup), - enabledp(true), - zero_(false), - should_quit(false), - libs(libs), - r_b(dmat<3,3>::eye()), - t_b {0,0,0} -{ -} - -Tracker::~Tracker() -{ - should_quit = true; - wait(); -} - -double Tracker::map(double pos, Mapping& axis) -{ - bool altp = (pos < 0) && axis.opts.altp; - axis.curve.setTrackingActive( !altp ); - axis.curveAlt.setTrackingActive( altp ); - auto& fc = altp ? axis.curveAlt : axis.curve; - return fc.getValue(pos); -} - -void Tracker::t_compensate(const rmat& rmat, const double* xyz, double* output, bool rz) -{ - // TY is really yaw axis. need swapping accordingly. - dmat<3, 1> tvec( xyz[2], -xyz[0], -xyz[1] ); - const dmat<3, 1> ret = rmat * tvec; - if (!rz) - output[2] = ret(0); - else - output[2] = xyz[2]; - output[1] = -ret(2); - output[0] = -ret(1); -} - -#ifdef _WIN32 -__declspec(noinline) bool nanp(double value); -#elif defined(__GNUC__) -bool __attribute__ ((noinline)) nanp(double value); -#else -bool nanp(double value); -#endif - -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; -} - -void Tracker::logic() -{ - bool inverts[6] = { - m(0).opts.invert, - m(1).opts.invert, - m(2).opts.invert, - m(3).opts.invert, - m(4).opts.invert, - m(5).opts.invert, - }; - - static constexpr double pi = 3.141592653; - static constexpr double r2d = 180. / pi; - - using namespace euler; - - 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]; - } - - if (is_nan(raw)) - raw = last_raw; - - const double off[] = - { - (double)-s.camera_yaw, - (double)-s.camera_pitch, - (double)-s.camera_roll - }; - const rmat cam = euler_to_rmat(off); - rmat r = euler_to_rmat(&value[Yaw]); - euler_t t(value(0), value(1), value(2)); - - r = cam * r; - - bool can_center = false; - const bool nan = is_nan(r, t); - - if (centerp && !nan) - { - for (int i = 0; i < 6; i++) - if (fabs(newpose[i]) != 0) - { - can_center = true; - break; - } - } - - if (can_center) - { - if (libs.pFilter) - libs.pFilter->center(); - centerp = false; - for (int i = 0; i < 3; i++) - t_b[i] = t(i); - r_b = r; - } - - { - double tmp[3] = { t(0) - t_b[0], t(1) - t_b[1], t(2) - t_b[2] }; - t_compensate(cam, tmp, tmp, false); - rmat m_; - switch (s.center_method) - { - case 0: - default: - m_ = r * r_b.t(); - break; - case 1: - m_ = r_b.t() * r; - } - - const euler_t euler = rmat_to_euler(m_); - - for (int i = 0; i < 3; i++) - { - value(i) = tmp[i]; - value(i+3) = euler(i) * r2d; - } - } - - bool nan_ = false; - // whenever something can corrupt its internal state due to nan/inf, elide the call - if (is_nan(value)) - { - nan_ = true; - } - else - { - { - Pose tmp = value; - - if (libs.pFilter) - libs.pFilter->filter(tmp, value); - } - - for (int i = 0; i < 6; i++) - value(i) = map(value(i), m(i)); - - if (s.tcomp_p) - t_compensate(euler_to_rmat(&value[Yaw]), - value, - value, - s.tcomp_tz); - - for (int i = 0; i < 6; i++) - value(i) += m(i).opts.zero; - - for (int i = 0; i < 6; i++) - value[i] *= inverts[i] ? -1. : 1.; - - if (zero_) - for (int i = 0; i < 6; i++) - value(i) = 0; - - if (is_nan(value)) - nan_ = true; - } - - 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; -} - -void Tracker::run() -{ - const int sleep_ms = 3; - -#if defined(_WIN32) - (void) timeBeginPeriod(1); -#endif - - while (!should_quit) - { - t.start(); - - 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(); - - long q = sleep_ms * 1000L - t.elapsed()/1000L; - using std::max; - usleep(max(1L, q)); - } - - { - // 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).curve.setTrackingActive(false); - m(i).curveAlt.setTrackingActive(false); - } -} - -void Tracker::get_raw_and_mapped_poses(double* mapped, double* raw) const { - QMutexLocker foo(&const_cast(*this).mtx); - for (int i = 0; i < 6; i++) - { - raw[i] = raw_6dof(i); - mapped[i] = output_pose(i); - } -} - diff --git a/opentrack/tracker.h b/opentrack/tracker.h deleted file mode 100644 index ea831eb0..00000000 --- a/opentrack/tracker.h +++ /dev/null @@ -1,87 +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 - -#include "opentrack-compat/timer.hpp" -#include "plugin-support.hpp" -#include "mappings.hpp" -#include "simple-mat.hpp" -#include "selected-libraries.hpp" - -#include "spline-widget/functionconfig.h" -#include "main-settings.hpp" -#include "opentrack-compat/options.hpp" - -#include -#include - -class Pose { -private: - static constexpr double pi = 3.141592653; - static constexpr double d2r = pi/180.0; - static constexpr double r2d = 180./pi; - - double axes[6]; -public: - Pose() : axes {0,0,0, 0,0,0} {} - - inline operator double*() { return axes; } - inline operator const double*() const { return axes; } - - inline double& operator()(int i) { return axes[i]; } - inline double operator()(int i) const { return axes[i]; } -}; - -#ifdef BUILD_api -# include "opentrack-compat/export.hpp" -#else -# include "opentrack-compat/import.hpp" -#endif - -class OPENTRACK_EXPORT Tracker : private QThread { - Q_OBJECT -private: - QMutex mtx; - main_settings& s; - Mappings& m; - - Timer t; - Pose output_pose, raw_6dof, last_mapped, last_raw; - - double newpose[6]; - volatile bool centerp; - volatile bool enabledp; - volatile bool zero_; - volatile bool should_quit; - SelectedLibraries const& libs; - - using rmat = dmat<3, 3>; - - dmat<3, 3> r_b; - double t_b[3]; - - double map(double pos, Mapping& axis); - void logic(); - - void t_compensate(const rmat& rmat, const double* ypr, double* output, bool rz); - void run() override; -public: - Tracker(main_settings& s, Mappings& m, SelectedLibraries& libs); - ~Tracker(); - - void get_raw_and_mapped_poses(double* mapped, double* raw) const; - void start() { QThread::start(); } - void toggle_enabled() { qDebug() << "toggle enabled"; enabledp = !enabledp; } - void set_toggle(bool value) { qDebug() << "enabled" << value; enabledp = value; } - void set_zero(bool value) { qDebug() << "zero" << value; zero_ = value; } - void center() { qDebug() << "toggle center"; centerp = !centerp; } - void zero() { qDebug() << "toggle zero"; zero_ = !zero_; } -}; diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp deleted file mode 100644 index bf919f4a..00000000 --- a/opentrack/win32-joystick.cpp +++ /dev/null @@ -1,297 +0,0 @@ -#undef NDEBUG -#include -#include "win32-joystick.hpp" - -#ifdef _WIN32 - -void win32_joy_ctx::poll(fn f) -{ - //refresh(false); - - QMutexLocker l(&mtx); - - for (auto& j : joys) - { - j.second->poll(f); - } -} - -bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) -{ - //refresh(false); - - QMutexLocker l(&mtx); - - 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; - - (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; - memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - qDebug() << "joy get state failed" << guid << hr; - return false; - } - - 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; -} - -win32_joy_ctx::~win32_joy_ctx() -{ - release(); -} - -std::vector win32_joy_ctx::get_joy_info() -{ - QMutexLocker l(&mtx); - - std::vector ret; - - for (auto& j : joys) - ret.push_back(joy_info { j.second->name, j.first }); - - return ret; -} - -win32_joy_ctx::win32_joy_ctx() -{ - if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL) != DI_OK) { - qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); - assert(!"direct input handle can't be created"); - } - refresh(); -} - -void win32_joy_ctx::release() -{ - joys = std::unordered_map>(); - di->Release(); - di = nullptr; -} - -void win32_joy_ctx::refresh() -{ - QMutexLocker l(&mtx); - - qDebug() << "joy list refresh"; - enum_state st(joys, fake_main_window, di); -} - -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; - memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - qDebug() << "joy get state failed" << guid << hr; - return false; - } - - for (int i = 0; i < 128; i++) - { - const bool state = !!(js.rgbButtons[i] & 0x80) && js.rgbButtons[i] != js_old.rgbButtons[i]; - if (state != pressed[i]) - { - f(guid, i, state); - qDebug() << "btn" << guid << i << state; - } - pressed[i] = state; - } - - js_old = js; - - return true; -} - -win32_joy_ctx::enum_state::enum_state(std::unordered_map> &joys_, - QMainWindow &fake_main_window, - LPDIRECTINPUT8 di) : - fake_main_window(fake_main_window), - di(di) -{ - joys = joys_; - - 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.cend()) - it = joys.erase(it); - else - it++; - } - - joys_ = joys; -} - -win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) -{ - enum_state& state = *reinterpret_cast(pContext); - const QString guid = guid_to_string(pdidInstance->guidInstance); - const QString name = QString(pdidInstance->tszInstanceName); - - auto it = state.joys.find(guid); - const bool exists = it != state.joys.end(); - - state.all.push_back(guid); - - if (!exists) - { - 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; - } - - if (FAILED(h->SetCooperativeLevel((HWND) state.fake_main_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; - } - - qDebug() << "add joy" << guid; - state.joys[guid] = std::make_shared(h, guid, name); - } -end: - return DIENUM_CONTINUE; -} - -win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx) -{ - if (pdidoi->dwType & DIDFT_AXIS) - { - DIPROPRANGE diprg; - 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(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() << "got joy" << guid; - for (int i = 0; i < 128; i++) - pressed[i] = false; - memset(&js_old, 0, sizeof(js_old)); -} - -win32_joy_ctx::joy::~joy() -{ - qDebug() << "nix joy" << guid; - release(); -} - -#endif diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp deleted file mode 100644 index 9c888326..00000000 --- a/opentrack/win32-joystick.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#ifdef _WIN32 - -#include -#include -#include -#include -#include -#include -#ifndef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x800 -#endif -#include -#include -#include "opentrack-compat/timer.hpp" -#include -#include -#include -#include -#include - -namespace std { -template<> -struct hash -{ - inline std::size_t operator()(const QString& value) const - { - return qHash(value); - } -}; -} - -#ifdef BUILD_api -# include "opentrack-compat/export.hpp" -#else -# include "opentrack-compat/import.hpp" -#endif - -struct OPENTRACK_EXPORT win32_joy_ctx -{ - using fn = std::function; - - enum { joy_axis_size = 65535 }; - - struct joy_info - { - QString name, guid; - }; - - void poll(fn f); - bool poll_axis(const QString& guid, int axes[8]); - std::vector get_joy_info(); - - win32_joy_ctx(const win32_joy_ctx&) = delete; - win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; - - win32_joy_ctx(); - ~win32_joy_ctx(); - void refresh(); -private: - QMutex mtx; - QMainWindow fake_main_window; - LPDIRECTINPUT8 di; - - static QString guid_to_string(const GUID guid); - void release(); - - struct joy - { - LPDIRECTINPUTDEVICE8 joy_handle; - QString guid, name; - bool pressed[128]; - Timer first_timer; - DIJOYSTATE2 js_old; - - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name); - ~joy(); - - void release(); - bool poll(fn f); - }; - - std::unordered_map> joys; - - class enum_state - { - std::unordered_map> joys; - QMainWindow& fake_main_window; - LPDIRECTINPUT8 di; - - std::vector all; - static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); - static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); - public: - enum_state(std::unordered_map>& joys, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); - }; -}; - -#endif diff --git a/opentrack/win32-shortcuts.cpp b/opentrack/win32-shortcuts.cpp deleted file mode 100644 index a93803a3..00000000 --- a/opentrack/win32-shortcuts.cpp +++ /dev/null @@ -1,197 +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. - */ - -#if defined(_WIN32) -# ifndef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x800 -# endif -# include -# include - -#include -#include -#include -#include "win32-shortcuts.h" - -QList windows_key_mods = - QList({ - 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 windows_key_sequences = - QList({ - 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(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(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(our_mods); - return true; - } - } - } - return false; -} - -#endif diff --git a/opentrack/win32-shortcuts.h b/opentrack/win32-shortcuts.h deleted file mode 100644 index 9b2c6121..00000000 --- a/opentrack/win32-shortcuts.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#ifdef _WIN32 - -#include -#include "opentrack/shortcuts.h" - -struct win_key; - -extern QList windows_key_mods; -extern QList windows_key_sequences; - -#ifdef BUILD_api -# include "opentrack-compat/export.hpp" -#else -# include "opentrack-compat/import.hpp" -#endif - -struct OPENTRACK_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/work.hpp b/opentrack/work.hpp deleted file mode 100644 index 3b65ba52..00000000 --- a/opentrack/work.hpp +++ /dev/null @@ -1,63 +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 "opentrack/main-settings.hpp" -#include "opentrack/plugin-support.hpp" -#include "opentrack/tracker.h" -#include "opentrack/shortcuts.h" - -#include -#include -#include -#include -#include -#include - -struct Work -{ - main_settings& s; - SelectedLibraries& libs; - mem tracker; - mem sc; - WId handle; - using fn = std::function; - using tt = std::tuple; - std::vector keys; - - Work(main_settings& s, Mappings& m, SelectedLibraries& libs, WId handle) : - s(s), libs(libs), - tracker(std::make_shared(s, m, libs)), - sc(std::make_shared()), - handle(handle), - keys { - tt(s.key_center, [&](bool) -> void { tracker->center(); }, true), - tt(s.key_toggle, [&](bool) -> void { tracker->toggle_enabled(); }, true), - tt(s.key_zero, [&](bool) -> void { tracker->zero(); }, true), - tt(s.key_toggle_press, [&](bool x) -> void { tracker->set_toggle(!x); }, false), - tt(s.key_zero_press, [&](bool x) -> void { tracker->set_zero(x); }, false), - } - { - reload_shortcuts(); - tracker->start(); - } - - void reload_shortcuts() - { - sc->reload(keys); - } - - ~Work() - { - sc = nullptr; - // order matters, otherwise use-after-free -sh - tracker = nullptr; - libs = SelectedLibraries(); - } -}; diff --git a/proto-wine/wine-shm.h b/proto-wine/wine-shm.h index c7e29abb..a717dcc8 100644 --- a/proto-wine/wine-shm.h +++ b/proto-wine/wine-shm.h @@ -4,9 +4,7 @@ #define WINE_MTX_NAME "facetracknoir-wine-mtx" // OSX sdk 10.8 build error otherwise -#ifdef _LIBCPP_MSVCRT -# undef _LIBCPP_MSVCRT -#endif +#undef _LIBCPP_MSVCRT #include diff --git a/tracker-joystick/CMakeLists.txt b/tracker-joystick/CMakeLists.txt index b5fbcf75..e0b6f281 100644 --- a/tracker-joystick/CMakeLists.txt +++ b/tracker-joystick/CMakeLists.txt @@ -1,3 +1,5 @@ if(WIN32) opentrack_boilerplate(opentrack-tracker-joystick) + target_link_libraries(opentrack-tracker-joystick opentrack-logic) endif() + diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 1f940b63..31f1dee7 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -17,7 +17,7 @@ #include #include "opentrack/plugin-api.hpp" -#include "opentrack/win32-joystick.hpp" +#include "opentrack-logic/win32-joystick.hpp" #include "opentrack-compat/options.hpp" using namespace options; diff --git a/x-plane-plugin/plugin.c b/x-plane-plugin/plugin.c index 4d4c6c92..b0a41414 100644 --- a/x-plane-plugin/plugin.c +++ b/x-plane-plugin/plugin.c @@ -22,18 +22,21 @@ #define WINE_SHM_NAME "facetracknoir-wine-shm" #define WINE_MTX_NAME "facetracknoir-wine-mtx" +#define BUILD_compat #include "../opentrack-compat/export.hpp" enum Axis { TX = 0, TY, TZ, Yaw, Pitch, Roll }; -typedef struct PortableLockedShm { +typedef struct PortableLockedShm +{ void* mem; int fd, size; } PortableLockedShm; -typedef struct WineSHM { +typedef struct WineSHM +{ double data[6]; int gameid, gameid2; unsigned char table[8]; @@ -68,7 +71,7 @@ PortableLockedShm* PortableLockedShm_init(const char *shmName, const char *OT_UN strncpy(shm_filename+1, shmName, NAME_MAX-2); shm_filename[NAME_MAX-1] = '\0'; /* (void) shm_unlink(shm_filename); */ - + self->fd = shm_open(shm_filename, O_RDWR | O_CREAT, 0600); (void) ftruncate(self->fd, mapSize); self->mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, self->fd, (off_t)0); @@ -149,7 +152,7 @@ static int TranslationToggleHandler( XPLMCommandRef inCommand, return 0; } -PLUGIN_API OPENTRACK_EXPORT int XPluginStart ( char * outName, char * outSignature, char * outDescription ) { +PLUGIN_API OPENTRACK_COMPAT_EXPORT int XPluginStart ( char * outName, char * outSignature, char * outDescription ) { view_x = XPLMFindDataRef("sim/aircraft/view/acf_peX"); view_y = XPLMFindDataRef("sim/aircraft/view/acf_peY"); view_z = XPLMFindDataRef("sim/aircraft/view/acf_peZ"); @@ -187,7 +190,7 @@ PLUGIN_API OPENTRACK_EXPORT int XPluginStart ( char * outName, char * outSignatu return 0; } -PLUGIN_API OPENTRACK_EXPORT void XPluginStop ( void ) { +PLUGIN_API OPENTRACK_COMPAT_EXPORT void XPluginStop ( void ) { if (lck_posix) { PortableLockedShm_free(lck_posix); @@ -196,17 +199,17 @@ PLUGIN_API OPENTRACK_EXPORT void XPluginStop ( void ) { } } -PLUGIN_API OPENTRACK_EXPORT void XPluginEnable ( void ) { +PLUGIN_API OPENTRACK_COMPAT_EXPORT void XPluginEnable ( void ) { XPLMRegisterFlightLoopCallback(write_head_position, -1.0, NULL); track_disabled = 0; } -PLUGIN_API OPENTRACK_EXPORT void XPluginDisable ( void ) { +PLUGIN_API OPENTRACK_COMPAT_EXPORT void XPluginDisable ( void ) { XPLMUnregisterFlightLoopCallback(write_head_position, NULL); track_disabled = 1; } -PLUGIN_API OPENTRACK_EXPORT void XPluginReceiveMessage( +PLUGIN_API OPENTRACK_COMPAT_EXPORT void XPluginReceiveMessage( XPLMPluginID OT_UNUSED(inFromWho), int OT_UNUSED(inMessage), void * OT_UNUSED(inParam)) -- cgit v1.2.3