From f90b77dd5e342ebc45259051d23d6396f37c660d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 09:01:57 +0100 Subject: cmake: fix spline widget linkage --- opentrack/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'opentrack') diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt index 590eaca5..c3676979 100644 --- a/opentrack/CMakeLists.txt +++ b/opentrack/CMakeLists.txt @@ -4,3 +4,5 @@ if(NOT WIN32) else() target_link_libraries(opentrack-api winmm) endif() +link_with_dinput8(opentrack-api) +target_link_libraries(opentrack-api opentrack-spline-widget) -- cgit v1.2.3 From 0424a2802aec3600774ba9347c49312bb09b8cfe Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:28:17 +0100 Subject: all: adjust options.hpp move to compat --- filter-accela/ftnoir_filter_accela.h | 2 +- filter-ewma2/ftnoir_filter_ewma2.h | 2 +- filter-kalman/ftnoir_filter_kalman.h | 2 +- gui/main.cpp | 2 +- gui/new_file_dialog.h | 2 +- gui/process_detector.h | 2 +- gui/ui.cpp | 4 +-- gui/ui.h | 2 +- opentrack-compat/compat-export.hpp | 15 +++++++++ opentrack-compat/compat-import.hpp | 15 +++++++++ opentrack-compat/export.hpp | 22 +++++++------ opentrack-compat/import.hpp | 15 +++++++++ opentrack-compat/shm.h | 22 ++----------- opentrack/CMakeLists.txt | 2 +- opentrack/main-settings.hpp | 2 +- opentrack/mappings.hpp | 2 +- opentrack/plugin-api.hpp | 40 +++++++++++++++++++----- opentrack/plugin-support.hpp | 2 +- opentrack/selected-libraries.hpp | 9 +++++- opentrack/shortcuts.h | 14 ++++++--- opentrack/state.hpp | 2 +- opentrack/tracker.h | 10 ++++-- opentrack/win32-shortcuts.h | 8 ++++- proto-fg/ftnoir_protocol_fg.h | 2 +- proto-fsuipc/ftnoir_protocol_fsuipc.h | 2 +- proto-ft/ftnoir_protocol_ft.h | 2 +- proto-ftn/ftnoir_protocol_ftn.h | 2 +- proto-mouse/ftnoir_protocol_mouse.h | 2 +- proto-sc/ftnoir_protocol_sc.h | 2 +- spline-widget/CMakeLists.txt | 1 + spline-widget/qfunctionconfigurator.cpp | 2 +- tracker-aruco/ftnoir_tracker_aruco.h | 2 +- tracker-freepie-udp/ftnoir_tracker_freepie-udp.h | 2 +- tracker-hatire/ftnoir_tracker_hat_settings.cpp | 2 +- tracker-ht/ftnoir_tracker_ht.h | 2 +- tracker-hydra/ftnoir_tracker_hydra.h | 2 +- tracker-joystick/ftnoir_tracker_joystick.h | 2 +- tracker-pt/ftnoir_tracker_pt_settings.h | 2 +- tracker-rift-025/ftnoir_tracker_rift_025.h | 2 +- tracker-rift-042/ftnoir_tracker_rift_042.h | 2 +- tracker-rift-080/ftnoir_tracker_rift_080.h | 2 +- tracker-udp/ftnoir_tracker_udp.h | 2 +- 42 files changed, 157 insertions(+), 78 deletions(-) create mode 100644 opentrack-compat/compat-export.hpp create mode 100644 opentrack-compat/compat-import.hpp create mode 100644 opentrack-compat/import.hpp (limited to 'opentrack') diff --git a/filter-accela/ftnoir_filter_accela.h b/filter-accela/ftnoir_filter_accela.h index b15e0cea..289b84f0 100644 --- a/filter-accela/ftnoir_filter_accela.h +++ b/filter-accela/ftnoir_filter_accela.h @@ -12,7 +12,7 @@ #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; #include "opentrack-compat/timer.hpp" diff --git a/filter-ewma2/ftnoir_filter_ewma2.h b/filter-ewma2/ftnoir_filter_ewma2.h index bf4e83ad..bdb9cedc 100644 --- a/filter-ewma2/ftnoir_filter_ewma2.h +++ b/filter-ewma2/ftnoir_filter_ewma2.h @@ -5,7 +5,7 @@ #include #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/filter-kalman/ftnoir_filter_kalman.h b/filter-kalman/ftnoir_filter_kalman.h index a6f40bb7..773f61d5 100644 --- a/filter-kalman/ftnoir_filter_kalman.h +++ b/filter-kalman/ftnoir_filter_kalman.h @@ -16,7 +16,7 @@ #include #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/gui/main.cpp b/gui/main.cpp index a63fe54a..3ae01404 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -3,7 +3,7 @@ #endif #include "ui.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; #include #include diff --git a/gui/new_file_dialog.h b/gui/new_file_dialog.h index 3a35cf71..5fdabb3a 100644 --- a/gui/new_file_dialog.h +++ b/gui/new_file_dialog.h @@ -1,7 +1,7 @@ #pragma once #include "ui_new_config.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include #include #include diff --git a/gui/process_detector.h b/gui/process_detector.h index f6497c90..e395e1a2 100644 --- a/gui/process_detector.h +++ b/gui/process_detector.h @@ -13,7 +13,7 @@ #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; class FancyTable : public QTableWidget diff --git a/gui/ui.cpp b/gui/ui.cpp index 5ea5dbfa..fc6d4754 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -8,7 +8,7 @@ #include "ui.h" #include "opentrack/tracker.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include "new_file_dialog.h" #include #include @@ -411,7 +411,7 @@ bool mk_dialog(mem lib, mem& orig) dialog->show(); dialog->raise(); - QObject::connect(dialog.get(), &BaseDialog::closing, [&]() -> void { orig = nullptr; }); + QObject::connect(dialog.get(), &plugin_api::detail::BaseDialog::closing, [&]() -> void { orig = nullptr; }); return true; } diff --git a/gui/ui.h b/gui/ui.h index 91e4ebbf..44bcde0c 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -19,7 +19,7 @@ #include "ui_main.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include "opentrack/main-settings.hpp" #include "opentrack/plugin-support.hpp" #include "opentrack/tracker.h" diff --git a/opentrack-compat/compat-export.hpp b/opentrack-compat/compat-export.hpp new file mode 100644 index 00000000..2d6f1d3d --- /dev/null +++ b/opentrack-compat/compat-export.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +# ifdef _WIN32 +# define OPENTRACK_COMPAT_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_COMPAT_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +# else +# define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +# endif +#endif diff --git a/opentrack-compat/compat-import.hpp b/opentrack-compat/compat-import.hpp new file mode 100644 index 00000000..161ccc5d --- /dev/null +++ b/opentrack-compat/compat-import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +# ifdef _WIN32 +# define OPENTRACK_COMPAT_LINKAGE __declspec(dllimport) +# else +# define OPENTRACK_COMPAT_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +# else +# define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +# endif +#endif diff --git a/opentrack-compat/export.hpp b/opentrack-compat/export.hpp index f0983b75..100950a0 100644 --- a/opentrack-compat/export.hpp +++ b/opentrack-compat/export.hpp @@ -1,13 +1,15 @@ #pragma once -#ifdef _WIN32 -# define OPENTRACK_LINKAGE __declspec(dllexport) -#else -# define OPENTRACK_LINKAGE -#endif +#ifndef OPENTRACK_EXPORT +# ifdef _WIN32 +# define OPENTRACK_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_LINKAGE +# endif -#ifndef _MSC_VER -# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE -#else -# define OPENTRACK_EXPORT OPENTRACK_LINKAGE -#endif \ No newline at end of file +# ifndef _MSC_VER +# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +# else +# define OPENTRACK_EXPORT OPENTRACK_LINKAGE +# endif +#endif diff --git a/opentrack-compat/import.hpp b/opentrack-compat/import.hpp new file mode 100644 index 00000000..3747b141 --- /dev/null +++ b/opentrack-compat/import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_EXPORT +# ifdef _WIN32 +# define OPENTRACK_LINKAGE __declspec(dllimport) +# else +# define OPENTRACK_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +# else +# define OPENTRACK_EXPORT OPENTRACK_LINKAGE +# endif +#endif diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h index 28bda986..c62976bd 100644 --- a/opentrack-compat/shm.h +++ b/opentrack-compat/shm.h @@ -22,29 +22,13 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wattributes" -#ifdef __GNUC__ -# define COMPAT_GNUC_VISIBILITY __attribute__ ((visibility ("default"))) -#else -# define COMPAT_GNUC_VISIBILITY -#endif - #ifdef BUILD_compat -# ifdef _WIN32 -# define COMPAT_WIN32_EXPORT __declspec(dllexport) -# else -# define COMPAT_WIN32_EXPORT -# endif +# include "compat-export.hpp" #else -# ifdef _WIN32 -# define COMPAT_WIN32_EXPORT __declspec(dllimport) -# else -# define COMPAT_WIN32_EXPORT -# endif +# include "compat-import.hpp" #endif -#define COMPAT_EXPORT COMPAT_WIN32_EXPORT COMPAT_GNUC_VISIBILITY - -class COMPAT_EXPORT PortableLockedShm { +class OPENTRACK_COMPAT_EXPORT PortableLockedShm { public: PortableLockedShm(const char *shmName, const char *mutexName, int mapSize); ~PortableLockedShm(); diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt index c3676979..de5975e2 100644 --- a/opentrack/CMakeLists.txt +++ b/opentrack/CMakeLists.txt @@ -1,4 +1,4 @@ -opentrack_boilerplate(opentrack-api NO-LINKER-SCRIPT NO-COMPAT) +opentrack_boilerplate(opentrack-api NO-LINKER-SCRIPT NO-COMPAT LINKAGE) if(NOT WIN32) target_link_libraries(opentrack-api opentrack-qxt-mini opentrack-compat dl) else() diff --git a/opentrack/main-settings.hpp b/opentrack/main-settings.hpp index 613223ce..b7b086ad 100644 --- a/opentrack/main-settings.hpp +++ b/opentrack/main-settings.hpp @@ -9,7 +9,7 @@ #pragma once #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include "opentrack/plugin-api.hpp" using namespace options; diff --git a/opentrack/mappings.hpp b/opentrack/mappings.hpp index bb38a3ca..087ea7f3 100644 --- a/opentrack/mappings.hpp +++ b/opentrack/mappings.hpp @@ -8,7 +8,7 @@ #pragma once #include -#include "options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; #include "spline-widget/functionconfig.h" #include "main-settings.hpp" diff --git a/opentrack/plugin-api.hpp b/opentrack/plugin-api.hpp index a57077ab..5fdc3bcb 100644 --- a/opentrack/plugin-api.hpp +++ b/opentrack/plugin-api.hpp @@ -8,17 +8,38 @@ #pragma once -#include "../opentrack-compat/export.hpp" #include #include #include #include +#ifdef BUILD_api +# include "opentrack-compat/export.hpp" +#else +# include "opentrack-compat/import.hpp" +#endif + +#ifndef OPENTRACK_PLUGIN_EXPORT +# ifdef _WIN32 +# define OPENTRACK_PLUGIN_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_PLUGIN_LINKAGE +# endif +# ifndef _MSC_VER +# define OPENTRACK_PLUGIN_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_PLUGIN_LINKAGE +# else +# define OPENTRACK_PLUGIN_EXPORT OPENTRACK_PLUGIN_LINKAGE +# endif +#endif + enum Axis { TX = 0, TY, TZ, Yaw, Pitch, Roll }; -class BaseDialog : public QWidget +namespace plugin_api { +namespace detail { + +class OPENTRACK_EXPORT BaseDialog : public QWidget { Q_OBJECT public: @@ -27,16 +48,19 @@ signals: void closing(); }; +} // ns +} // ns + #define OPENTRACK_DECLARE_PLUGIN_INTERNAL(ctor_class, ctor_ret_class, metadata_class, dialog_class, dialog_ret_class) \ - extern "C" OPENTRACK_EXPORT ctor_ret_class* GetConstructor() \ + extern "C" OPENTRACK_PLUGIN_EXPORT ctor_ret_class* GetConstructor() \ { \ return new ctor_class; \ } \ - extern "C" OPENTRACK_EXPORT Metadata* GetMetadata() \ + extern "C" OPENTRACK_PLUGIN_EXPORT Metadata* GetMetadata() \ { \ return new metadata_class; \ } \ - extern "C" OPENTRACK_EXPORT dialog_ret_class* GetDialog() \ + extern "C" OPENTRACK_PLUGIN_EXPORT dialog_ret_class* GetDialog() \ { \ return new dialog_class; \ } @@ -65,7 +89,7 @@ struct IFilter virtual void center() {} }; -struct IFilterDialog : public BaseDialog +struct IFilterDialog : public plugin_api::detail::BaseDialog { // optional destructor virtual ~IFilterDialog() {} @@ -93,7 +117,7 @@ struct IProtocol virtual QString game_name() = 0; }; -struct IProtocolDialog : public BaseDialog +struct IProtocolDialog : public plugin_api::detail::BaseDialog { // optional destructor virtual ~IProtocolDialog() {} @@ -118,7 +142,7 @@ struct ITracker virtual void data(double *data) = 0; }; -struct ITrackerDialog : public BaseDialog +struct ITrackerDialog : public plugin_api::detail::BaseDialog { // optional destructor virtual ~ITrackerDialog() {} diff --git a/opentrack/plugin-support.hpp b/opentrack/plugin-support.hpp index 102d11c4..650eec10 100644 --- a/opentrack/plugin-support.hpp +++ b/opentrack/plugin-support.hpp @@ -8,7 +8,7 @@ #pragma once #include "plugin-api.hpp" -#include "options.hpp" +#include "opentrack-compat/options.hpp" #include #include diff --git a/opentrack/selected-libraries.hpp b/opentrack/selected-libraries.hpp index 3719b109..b396b5ec 100644 --- a/opentrack/selected-libraries.hpp +++ b/opentrack/selected-libraries.hpp @@ -11,7 +11,14 @@ #include "opentrack/plugin-support.hpp" #include -struct SelectedLibraries { + +#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; diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 63d91829..03adc1ab 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -17,9 +17,15 @@ #include #include +#ifdef BUILD_api +# include "opentrack-compat/export.hpp" +#else +# include "opentrack-compat/import.hpp" +#endif + #include "qxt-mini/QxtGlobalShortcut" #include "opentrack/plugin-support.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include "opentrack/main-settings.hpp" using namespace options; @@ -66,9 +72,7 @@ typedef unsigned char BYTE; struct Key { int foo; }; #endif -struct Shortcuts; - -struct KeybindingWorker : public QThread { +struct OPENTRACK_EXPORT KeybindingWorker : public QThread { #ifdef _WIN32 private: LPDIRECTINPUT8 din; @@ -87,7 +91,7 @@ public: #endif }; -struct Shortcuts : public QObject { +struct OPENTRACK_EXPORT Shortcuts : public QObject { Q_OBJECT public: diff --git a/opentrack/state.hpp b/opentrack/state.hpp index e4cb0f04..dcb18293 100644 --- a/opentrack/state.hpp +++ b/opentrack/state.hpp @@ -9,7 +9,7 @@ #pragma once #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; #include "opentrack/plugin-support.hpp" #include "opentrack/main-settings.hpp" diff --git a/opentrack/tracker.h b/opentrack/tracker.h index 890660e1..e26c3f7a 100644 --- a/opentrack/tracker.h +++ b/opentrack/tracker.h @@ -18,7 +18,7 @@ #include "spline-widget/functionconfig.h" #include "main-settings.hpp" -#include "options.hpp" +#include "opentrack-compat/options.hpp" #include #include @@ -40,7 +40,13 @@ public: inline double operator()(int i) const { return axes[i]; } }; -class Tracker : private QThread { +#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; diff --git a/opentrack/win32-shortcuts.h b/opentrack/win32-shortcuts.h index fe92ae53..9b2c6121 100644 --- a/opentrack/win32-shortcuts.h +++ b/opentrack/win32-shortcuts.h @@ -10,7 +10,13 @@ struct win_key; extern QList windows_key_mods; extern QList windows_key_sequences; -struct win_key +#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; diff --git a/proto-fg/ftnoir_protocol_fg.h b/proto-fg/ftnoir_protocol_fg.h index de528270..5b1cbc81 100644 --- a/proto-fg/ftnoir_protocol_fg.h +++ b/proto-fg/ftnoir_protocol_fg.h @@ -15,7 +15,7 @@ #include #include #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/proto-fsuipc/ftnoir_protocol_fsuipc.h b/proto-fsuipc/ftnoir_protocol_fsuipc.h index c8e91a42..af59e988 100644 --- a/proto-fsuipc/ftnoir_protocol_fsuipc.h +++ b/proto-fsuipc/ftnoir_protocol_fsuipc.h @@ -24,7 +24,7 @@ #include #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; #define FSUIPC_FILENAME "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll" diff --git a/proto-ft/ftnoir_protocol_ft.h b/proto-ft/ftnoir_protocol_ft.h index 8e50f1cb..9cf16f03 100644 --- a/proto-ft/ftnoir_protocol_ft.h +++ b/proto-ft/ftnoir_protocol_ft.h @@ -19,7 +19,7 @@ #include #include #include "opentrack-compat/shm.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include "freetrackclient/fttypes.h" using namespace options; diff --git a/proto-ftn/ftnoir_protocol_ftn.h b/proto-ftn/ftnoir_protocol_ftn.h index 7fe6c225..d8b8aff0 100644 --- a/proto-ftn/ftnoir_protocol_ftn.h +++ b/proto-ftn/ftnoir_protocol_ftn.h @@ -16,7 +16,7 @@ #include #include #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/proto-mouse/ftnoir_protocol_mouse.h b/proto-mouse/ftnoir_protocol_mouse.h index 595be393..f1730777 100644 --- a/proto-mouse/ftnoir_protocol_mouse.h +++ b/proto-mouse/ftnoir_protocol_mouse.h @@ -10,7 +10,7 @@ #include "ui_ftnoir_mousecontrols.h" #include #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/proto-sc/ftnoir_protocol_sc.h b/proto-sc/ftnoir_protocol_sc.h index 671a3500..dcc0ca77 100644 --- a/proto-sc/ftnoir_protocol_sc.h +++ b/proto-sc/ftnoir_protocol_sc.h @@ -20,7 +20,7 @@ #include #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; #include diff --git a/spline-widget/CMakeLists.txt b/spline-widget/CMakeLists.txt index 4d951f92..651a7874 100644 --- a/spline-widget/CMakeLists.txt +++ b/spline-widget/CMakeLists.txt @@ -1 +1,2 @@ opentrack_boilerplate(opentrack-spline-widget NO-LINKER-SCRIPT NO-COMPAT LINKAGE) +target_link_libraries(opentrack-spline-widget opentrack-compat) diff --git a/spline-widget/qfunctionconfigurator.cpp b/spline-widget/qfunctionconfigurator.cpp index 7ab1e360..5d910826 100644 --- a/spline-widget/qfunctionconfigurator.cpp +++ b/spline-widget/qfunctionconfigurator.cpp @@ -5,7 +5,7 @@ * copyright notice and this permission notice appear in all copies. */ -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; #include "spline-widget/qfunctionconfigurator.h" #include diff --git a/tracker-aruco/ftnoir_tracker_aruco.h b/tracker-aruco/ftnoir_tracker_aruco.h index f827da77..018f69ea 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.h +++ b/tracker-aruco/ftnoir_tracker_aruco.h @@ -15,7 +15,7 @@ #include #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include "trans_calib.h" #include "opentrack/plugin-api.hpp" #include "opentrack/opencv-camera-dialog.hpp" diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h index 7cff2ec9..9d18c7d1 100644 --- a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h @@ -10,7 +10,7 @@ #include #include "ui_freepie-udp-controls.h" #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-hatire/ftnoir_tracker_hat_settings.cpp b/tracker-hatire/ftnoir_tracker_hat_settings.cpp index e6b32047..df0480a1 100644 --- a/tracker-hatire/ftnoir_tracker_hat_settings.cpp +++ b/tracker-hatire/ftnoir_tracker_hat_settings.cpp @@ -14,7 +14,7 @@ #include "ftnoir_tracker_hat_settings.h" #ifdef OPENTRACK_API -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #endif void TrackerSettings::load_ini() diff --git a/tracker-ht/ftnoir_tracker_ht.h b/tracker-ht/ftnoir_tracker_ht.h index 1e364456..0563fe1c 100644 --- a/tracker-ht/ftnoir_tracker_ht.h +++ b/tracker-ht/ftnoir_tracker_ht.h @@ -12,7 +12,7 @@ #include "ht_video_widget.h" #include "opentrack-compat/shm.h" #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" #include "opentrack/plugin-api.hpp" #include "opentrack/opencv-camera-dialog.hpp" diff --git a/tracker-hydra/ftnoir_tracker_hydra.h b/tracker-hydra/ftnoir_tracker_hydra.h index 47a1eb9a..94396b7c 100644 --- a/tracker-hydra/ftnoir_tracker_hydra.h +++ b/tracker-hydra/ftnoir_tracker_hydra.h @@ -1,6 +1,6 @@ #include "ui_ftnoir_hydra_clientcontrols.h" #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 75305f07..29e65af1 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -27,7 +27,7 @@ #include #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-pt/ftnoir_tracker_pt_settings.h b/tracker-pt/ftnoir_tracker_pt_settings.h index 85eec8f9..e4bfa371 100644 --- a/tracker-pt/ftnoir_tracker_pt_settings.h +++ b/tracker-pt/ftnoir_tracker_pt_settings.h @@ -9,7 +9,7 @@ #ifndef FTNOIR_TRACKER_PT_SETTINGS_H #define FTNOIR_TRACKER_PT_SETTINGS_H -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings_pt : opts diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.h b/tracker-rift-025/ftnoir_tracker_rift_025.h index 2bd5024b..8333e092 100644 --- a/tracker-rift-025/ftnoir_tracker_rift_025.h +++ b/tracker-rift-025/ftnoir_tracker_rift_025.h @@ -6,7 +6,7 @@ #include "opentrack/plugin-api.hpp" #include "OVR.h" #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.h b/tracker-rift-042/ftnoir_tracker_rift_042.h index 437a2a39..77e7ffa6 100644 --- a/tracker-rift-042/ftnoir_tracker_rift_042.h +++ b/tracker-rift-042/ftnoir_tracker_rift_042.h @@ -6,7 +6,7 @@ #include "opentrack/plugin-api.hpp" #include "OVR.h" #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.h b/tracker-rift-080/ftnoir_tracker_rift_080.h index 08684dd2..879d31d2 100644 --- a/tracker-rift-080/ftnoir_tracker_rift_080.h +++ b/tracker-rift-080/ftnoir_tracker_rift_080.h @@ -6,7 +6,7 @@ #include "opentrack/plugin-api.hpp" #include "OVR.h" #include -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { diff --git a/tracker-udp/ftnoir_tracker_udp.h b/tracker-udp/ftnoir_tracker_udp.h index 6de5b295..3f0e6d8c 100644 --- a/tracker-udp/ftnoir_tracker_udp.h +++ b/tracker-udp/ftnoir_tracker_udp.h @@ -4,7 +4,7 @@ #include #include #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp" using namespace options; struct settings : opts { -- cgit v1.2.3 From be36337e46218c6f843a478036497a3f494502ed Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:29:24 +0100 Subject: options: don't define options singleton in every module Instead, define in opentrack-api.so only. Also, move to opentrack-compat to break a circular dependency --- opentrack-compat/options.cpp | 16 ++ opentrack-compat/options.hpp | 485 +++++++++++++++++++++++++++++++++++++++++++ opentrack/options.hpp | 481 ------------------------------------------ 3 files changed, 501 insertions(+), 481 deletions(-) create mode 100644 opentrack-compat/options.cpp create mode 100644 opentrack-compat/options.hpp delete mode 100644 opentrack/options.hpp (limited to 'opentrack') diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp new file mode 100644 index 00000000..91cd3664 --- /dev/null +++ b/opentrack-compat/options.cpp @@ -0,0 +1,16 @@ +#include "options.hpp" + +namespace options +{ + +namespace detail +{ +OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() +{ + static auto ret = std::make_shared(); + return *ret; +} + +} + +} diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp new file mode 100644 index 00000000..be8c688c --- /dev/null +++ b/opentrack-compat/options.hpp @@ -0,0 +1,485 @@ +/* Copyright (c) 2013-2015 Stanislaw Halik + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#ifdef BUILD_compat +# include "compat-export.hpp" +#else +# include "compat-import.hpp" +#endif + +template using mem = std::shared_ptr; + +#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" +#define OPENTRACK_DEFAULT_CONFIG "default.ini" +#define OPENTRACK_ORG "opentrack-2.3" + +namespace options { + template + using map = std::map; + using std::string; + + template + // don't elide usages of the function, qvariant default implicit + // conversion results in nonsensical runtime behavior -sh + inline t qcruft_to_t (const QVariant& datum); + + template<> + inline int qcruft_to_t(const QVariant& t) + { + return t.toInt(); + } + + template<> + inline QString qcruft_to_t(const QVariant& t) + { + return t.toString(); + } + + template<> + inline bool qcruft_to_t(const QVariant& t) + { + return t.toBool(); + } + + template<> + inline double qcruft_to_t(const QVariant& t) + { + return t.toDouble(); + } + + template<> + inline QVariant qcruft_to_t(const QVariant& t) + { + return t; + } + + // snapshot of qsettings group at given time + class group { + private: + map kvs; + string name; + public: + group(const string& name) : name(name) + { + auto conf = ini_file(); + auto q_name = QString::fromStdString(name); + conf->beginGroup(q_name); + for (auto& k_ : conf->childKeys()) + { + auto tmp = k_.toUtf8(); + string k(tmp); + kvs[k] = conf->value(k_); + } + conf->endGroup(); + } + + void save() + { + auto s = ini_file(); + auto q_name = QString::fromStdString(name); + s->beginGroup(q_name); + for (auto& i : kvs) + { + auto k = QString::fromStdString(i.first); + s->setValue(k, i.second); + } + s->endGroup(); + s->sync(); + } + + template + t get(const string& k) + { + return qcruft_to_t(kvs[k]); + } + + void put(const string& s, const QVariant& d) + { + kvs[s] = d; + } + + bool contains(const string& s) + { + return kvs.count(s) != 0; + } + + static QString ini_directory() + { + const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + if (dirs.size() == 0) + return ""; + if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) + return dirs[0] + "/" OPENTRACK_ORG; + return ""; + } + + static QString ini_filename() + { + QSettings settings(OPENTRACK_ORG); + return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); + } + + static QString ini_pathname() + { + const auto dir = ini_directory(); + if (dir == "") + return ""; + QSettings settings(OPENTRACK_ORG); + return dir + "/" + settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); + } + + static const QStringList ini_list() + { + const auto dirname = ini_directory(); + if (dirname == "") + return QStringList(); + QDir settings_dir(dirname); + return settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); + } + + static const mem ini_file() + { + const auto pathname = ini_pathname(); + if (pathname != "") + return std::make_shared(ini_pathname(), QSettings::IniFormat); + return std::make_shared(); + } + }; + + class OPENTRACK_COMPAT_EXPORT impl_bundle : public QObject { + Q_OBJECT + protected: + QMutex mtx; + const string group_name; + group saved; + group transient; + bool modified; + impl_bundle(const impl_bundle&) = delete; + impl_bundle& operator=(const impl_bundle&) = delete; + signals: + void reloading(); + void saving(); + public: + impl_bundle(const string& group_name) : + mtx(QMutex::Recursive), + group_name(group_name), + saved(group_name), + transient(saved), + modified(false) + { + } + + string name() { return group_name; } + + void reload() { + { + QMutexLocker l(&mtx); + saved = group(group_name); + transient = saved; + modified = false; + } + emit reloading(); + } + + void store_kv(const string& name, const QVariant& datum) + { + QMutexLocker l(&mtx); + + auto old = transient.get(name); + if (!transient.contains(name) || datum != old) + { + modified = true; + transient.put(name, datum); + } + } + bool contains(const string& name) + { + QMutexLocker l(&mtx); + return transient.contains(name); + } + template + t get(const string& name) + { + QMutexLocker l(&mtx); + return transient.get(name); + } + void save() + { + { + QMutexLocker l(&mtx); + modified = false; + saved = transient; + transient.save(); + } + emit saving(); + } + + bool modifiedp() { + QMutexLocker l(&mtx); + return modified; + } + }; + + class opt_bundle; + + namespace detail + { + struct OPENTRACK_COMPAT_EXPORT opt_singleton + { + public: + using k = std::string; + using v = opt_bundle; + using cnt = int; + using pbundle = std::shared_ptr; + using tt = std::tuple>; + private: + QMutex implsgl_mtx; + map implsgl_data; + public: + opt_singleton() : implsgl_mtx(QMutex::Recursive) {} + + pbundle bundle(const k& key) + { + QMutexLocker l(&implsgl_mtx); + + if (implsgl_data.count(key) != 0) + { + auto shared = std::get<1>(implsgl_data[key]).lock(); + if (shared != nullptr) + return shared; + } + + qDebug() << "bundle +" << QString::fromStdString(key); + + auto shr = std::make_shared(key); + implsgl_data[key] = tt(cnt(1), shr); + return shr; + } + + void bundle_decf(const k& key) + { + QMutexLocker l(&implsgl_mtx); + + if (--std::get<0>(implsgl_data[key]) == 0) + implsgl_data.erase(key); + } + }; + + OPENTRACK_COMPAT_EXPORT opt_singleton& singleton(); + } + + using pbundle = std::shared_ptr; + + static inline pbundle bundle(const string name) { return detail::singleton().bundle(name); } + + class opt_bundle : public impl_bundle + { + public: + opt_bundle() : impl_bundle("i-have-no-name") {} + opt_bundle(const string& group_name) : impl_bundle(group_name) + { + } + + ~opt_bundle() + { + qDebug() << "bundle -" << QString::fromStdString(group_name); + detail::singleton().bundle_decf(group_name); + } + }; + + class OPENTRACK_COMPAT_EXPORT base_value : public QObject + { + Q_OBJECT +#define DEFINE_SLOT(t) void setValue(t datum) { store(datum); } +#define DEFINE_SIGNAL(t) void valueChanged(t) + public: + string name() { return self_name; } + base_value(pbundle b, const string& name) : b(b), self_name(name) {} + signals: + DEFINE_SIGNAL(double); + DEFINE_SIGNAL(int); + DEFINE_SIGNAL(bool); + DEFINE_SIGNAL(QString); + protected: + pbundle b; + string self_name; + + template + void store(const t& datum) + { + b->store_kv(self_name, datum); + emit valueChanged(static_cast(datum)); + } + public slots: + DEFINE_SLOT(double) + DEFINE_SLOT(int) + DEFINE_SLOT(QString) + DEFINE_SLOT(bool) + public slots: + virtual void reload() = 0; + }; + + static inline string string_from_qstring(const QString& datum) + { + auto tmp = datum.toUtf8(); + return string(tmp.constData()); + } + + template + class value : public base_value { + public: + t operator=(const t datum) + { + store(datum); + return datum; + } + static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; + static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection; + value(pbundle b, const string& name, t def) : base_value(b, name), def(def) + { + QObject::connect(b.get(), SIGNAL(reloading()), + this, SLOT(reload()), + DIRECT_CONNTYPE); + if (!b->contains(name) || b->get(name).type() == QVariant::Invalid) + *this = def; + } + value(pbundle b, const QString& name, t def) : value(b, string_from_qstring(name), def) {} + value(pbundle b, const char* name, t def) : value(b, string(name), def) {} + + operator t() + { + return b->contains(self_name) ? b->get(self_name) : def; + } + void reload() override { + *this = static_cast(*this); + } + private: + t def; + }; + + struct opts + { + pbundle b; + + opts(const std::string& name) : b(bundle(name)) {} + + ~opts() + { + b->reload(); + } + }; + + template + inline void tie_setting(value&, q*); + + template<> + inline void tie_setting(value& v, QComboBox* cb) + { + cb->setCurrentIndex(v); + v = cb->currentIndex(); + base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QComboBox* cb) + { + cb->setCurrentText(v); + v = cb->currentText(); + base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QCheckBox* cb) + { + cb->setChecked(v); + base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QDoubleSpinBox* dsb) + { + dsb->setValue(v); + base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QSpinBox* sb) + { + sb->setValue(v); + base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QSlider* sl) + { + sl->setValue(v); + v = sl->value(); + base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QLineEdit* le) + { + le->setText(v); + base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QLabel* lb) + { + lb->setText(v); + base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value& v, QTabWidget* t) + { + t->setCurrentIndex(v); + base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); + } +} diff --git a/opentrack/options.hpp b/opentrack/options.hpp deleted file mode 100644 index f8475877..00000000 --- a/opentrack/options.hpp +++ /dev/null @@ -1,481 +0,0 @@ -/* Copyright (c) 2013-2015 Stanislaw Halik - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - */ - -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -template using mem = std::shared_ptr; - -#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" -#define OPENTRACK_DEFAULT_CONFIG "default.ini" -#define OPENTRACK_ORG "opentrack-2.3" - -namespace options { - template - using map = std::map; - using std::string; - - template - // don't elide usages of the function, qvariant default implicit - // conversion results in nonsensical runtime behavior -sh - inline t qcruft_to_t (const QVariant& datum); - - template<> - inline int qcruft_to_t(const QVariant& t) - { - return t.toInt(); - } - - template<> - inline QString qcruft_to_t(const QVariant& t) - { - return t.toString(); - } - - template<> - inline bool qcruft_to_t(const QVariant& t) - { - return t.toBool(); - } - - template<> - inline double qcruft_to_t(const QVariant& t) - { - return t.toDouble(); - } - - template<> - inline QVariant qcruft_to_t(const QVariant& t) - { - return t; - } - - // snapshot of qsettings group at given time - class group { - private: - map kvs; - string name; - public: - group(const string& name) : name(name) - { - auto conf = ini_file(); - auto q_name = QString::fromStdString(name); - conf->beginGroup(q_name); - for (auto& k_ : conf->childKeys()) - { - auto tmp = k_.toUtf8(); - string k(tmp); - kvs[k] = conf->value(k_); - } - conf->endGroup(); - } - - void save() - { - auto s = ini_file(); - auto q_name = QString::fromStdString(name); - s->beginGroup(q_name); - for (auto& i : kvs) - { - auto k = QString::fromStdString(i.first); - s->setValue(k, i.second); - } - s->endGroup(); - s->sync(); - } - - template - t get(const string& k) - { - return qcruft_to_t(kvs[k]); - } - - void put(const string& s, const QVariant& d) - { - kvs[s] = d; - } - - bool contains(const string& s) - { - return kvs.count(s) != 0; - } - - static QString ini_directory() - { - const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - if (dirs.size() == 0) - return ""; - if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) - return dirs[0] + "/" OPENTRACK_ORG; - return ""; - } - - static QString ini_filename() - { - QSettings settings(OPENTRACK_ORG); - return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); - } - - static QString ini_pathname() - { - const auto dir = ini_directory(); - if (dir == "") - return ""; - QSettings settings(OPENTRACK_ORG); - return dir + "/" + settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); - } - - static const QStringList ini_list() - { - const auto dirname = ini_directory(); - if (dirname == "") - return QStringList(); - QDir settings_dir(dirname); - return settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); - } - - static const mem ini_file() - { - const auto pathname = ini_pathname(); - if (pathname != "") - return std::make_shared(ini_pathname(), QSettings::IniFormat); - return std::make_shared(); - } - }; - - class impl_bundle : public QObject { - Q_OBJECT - protected: - QMutex mtx; - const string group_name; - group saved; - group transient; - bool modified; - impl_bundle(const impl_bundle&) = delete; - impl_bundle& operator=(const impl_bundle&) = delete; - signals: - void reloading(); - void saving(); - public: - impl_bundle(const string& group_name) : - mtx(QMutex::Recursive), - group_name(group_name), - saved(group_name), - transient(saved), - modified(false) - { - } - - string name() { return group_name; } - - void reload() { - { - QMutexLocker l(&mtx); - saved = group(group_name); - transient = saved; - modified = false; - } - emit reloading(); - } - - void store_kv(const string& name, const QVariant& datum) - { - QMutexLocker l(&mtx); - - auto old = transient.get(name); - if (!transient.contains(name) || datum != old) - { - modified = true; - transient.put(name, datum); - } - } - bool contains(const string& name) - { - QMutexLocker l(&mtx); - return transient.contains(name); - } - template - t get(const string& name) - { - QMutexLocker l(&mtx); - return transient.get(name); - } - void save() - { - { - QMutexLocker l(&mtx); - modified = false; - saved = transient; - transient.save(); - } - emit saving(); - } - - bool modifiedp() { - QMutexLocker l(&mtx); - return modified; - } - }; - - class opt_bundle; - - namespace - { - template - struct opt_singleton - { - public: - using pbundle = std::shared_ptr; - using tt = std::tuple>; - private: - QMutex implsgl_mtx; - map implsgl_data; - public: - opt_singleton() : implsgl_mtx(QMutex::Recursive) {} - - static opt_singleton& datum() - { - static auto ret = std::make_shared>(); - return *ret; - } - - pbundle bundle(const k& key) - { - QMutexLocker l(&implsgl_mtx); - - if (implsgl_data.count(key) != 0) - { - auto shared = std::get<1>(implsgl_data[key]).lock(); - if (shared != nullptr) - return shared; - } - - qDebug() << "bundle +" << QString::fromStdString(key); - - auto shr = std::make_shared(key); - implsgl_data[key] = tt(cnt(1), shr); - return shr; - } - - void bundle_decf(const k& key) - { - QMutexLocker l(&implsgl_mtx); - - if (--std::get<0>(implsgl_data[key]) == 0) - implsgl_data.erase(key); - } - }; - - using pbundle = std::shared_ptr; - using t_fact = opt_singleton; - } - - static inline t_fact::pbundle bundle(const string name) { return t_fact::datum().bundle(name); } - - class opt_bundle : public impl_bundle - { - public: - opt_bundle() : impl_bundle("i-have-no-name") {} - opt_bundle(const string& group_name) : impl_bundle(group_name) - { - } - - ~opt_bundle() - { - qDebug() << "bundle -" << QString::fromStdString(group_name); - t_fact::datum().bundle_decf(group_name); - } - }; - - class base_value : public QObject - { - Q_OBJECT -#define DEFINE_SLOT(t) void setValue(t datum) { store(datum); } -#define DEFINE_SIGNAL(t) void valueChanged(t) - public: - string name() { return self_name; } - base_value(pbundle b, const string& name) : b(b), self_name(name) {} - signals: - DEFINE_SIGNAL(double); - DEFINE_SIGNAL(int); - DEFINE_SIGNAL(bool); - DEFINE_SIGNAL(QString); - protected: - pbundle b; - string self_name; - - template - void store(const t& datum) - { - b->store_kv(self_name, datum); - emit valueChanged(static_cast(datum)); - } - public slots: - DEFINE_SLOT(double) - DEFINE_SLOT(int) - DEFINE_SLOT(QString) - DEFINE_SLOT(bool) - public slots: - virtual void reload() = 0; - }; - - static inline string string_from_qstring(const QString& datum) - { - auto tmp = datum.toUtf8(); - return string(tmp.constData()); - } - - template - class value : public base_value { - public: - t operator=(const t datum) - { - store(datum); - return datum; - } - static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; - static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection; - value(pbundle b, const string& name, t def) : base_value(b, name), def(def) - { - QObject::connect(b.get(), SIGNAL(reloading()), - this, SLOT(reload()), - DIRECT_CONNTYPE); - if (!b->contains(name) || b->get(name).type() == QVariant::Invalid) - *this = def; - } - value(pbundle b, const QString& name, t def) : value(b, string_from_qstring(name), def) {} - value(pbundle b, const char* name, t def) : value(b, string(name), def) {} - - operator t() - { - return b->contains(self_name) ? b->get(self_name) : def; - } - void reload() override { - *this = static_cast(*this); - } - private: - t def; - }; - - struct opts - { - pbundle b; - - opts(const std::string& name) : b(bundle(name)) {} - - ~opts() - { - b->reload(); - } - }; - - template - inline void tie_setting(value&, q*); - - template<> - inline void tie_setting(value& v, QComboBox* cb) - { - cb->setCurrentIndex(v); - v = cb->currentIndex(); - base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QComboBox* cb) - { - cb->setCurrentText(v); - v = cb->currentText(); - base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QCheckBox* cb) - { - cb->setChecked(v); - base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QDoubleSpinBox* dsb) - { - dsb->setValue(v); - base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QSpinBox* sb) - { - sb->setValue(v); - base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QSlider* sl) - { - sl->setValue(v); - v = sl->value(); - base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QLineEdit* le) - { - le->setText(v); - base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QLabel* lb) - { - lb->setText(v); - base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE); - } - - template<> - inline void tie_setting(value& v, QTabWidget* t) - { - t->setCurrentIndex(v); - base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); - } -} -- cgit v1.2.3 From 712f2e6c09713024d0d92f129577b498d5945fb7 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:29:48 +0100 Subject: shortcuts: cleanup --- opentrack/shortcuts.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'opentrack') diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 03adc1ab..81c1bb80 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -30,18 +30,15 @@ using namespace options; -extern QList global_key_sequences; - -struct key_opts { - value keycode; - - key_opts(pbundle b, const QString& name) : - keycode(b, QString("keycode-%1").arg(name), "") - {} -}; +namespace { + extern QList global_key_sequences; +} #if defined(_WIN32) -extern QList global_windows_key_sequences; + +namespace { + extern QList global_windows_key_sequences; +} # undef DIRECTINPUT_VERSION # define DIRECTINPUT_VERSION 0x0800 # include @@ -111,6 +108,14 @@ public: #ifdef _WIN32 mem keybindingWorker; #endif + + struct key_opts { + value keycode; + + key_opts(pbundle b, const QString& name) : + keycode(b, QString("keycode-%1").arg(name), "") + {} + }; struct settings : opts { key_opts center, toggle, zero; @@ -136,5 +141,3 @@ signals: void toggle(); void zero(); }; - - -- cgit v1.2.3 From 8dca727968bf64c8aa89cce09172f101c2ade069 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:44:42 +0100 Subject: shortcuts: separate keybinding worker to another file --- opentrack/keybinding-worker.cpp | 112 ++++++++++++++++++++++++++++++++++++++++ opentrack/keybinding-worker.hpp | 70 +++++++++++++++++++++++++ opentrack/shortcuts.cpp | 104 +------------------------------------ opentrack/shortcuts.h | 69 ++----------------------- 4 files changed, 186 insertions(+), 169 deletions(-) create mode 100644 opentrack/keybinding-worker.cpp create mode 100644 opentrack/keybinding-worker.hpp (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp new file mode 100644 index 00000000..29b2cf9f --- /dev/null +++ b/opentrack/keybinding-worker.cpp @@ -0,0 +1,112 @@ +/* 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 "keybinding-worker.hpp" + +#if defined(_WIN32) +# include +# include +# include + +KeybindingWorker::~KeybindingWorker() { + should_quit = true; + wait(); + if (dinkeyboard) { + dinkeyboard->Unacquire(); + dinkeyboard->Release(); + } + if (din) + din->Release(); +} + +KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : + should_quit(true), receiver(receiver) +{ + HWND handle = reinterpret_cast(h); + + 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) handle, 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; +} + +void KeybindingWorker::run() { + BYTE keystate[256]; + + while (!should_quit) + { + if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + + QMutexLocker l(&mtx); + + for (int i = 0; i < 256; i++) + { + Key k; + if (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; + receiver(k); + break; + } + } + } + + // keypresses get dropped with high values + Sleep(4); + } +} +#endif \ No newline at end of file diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp new file mode 100644 index 00000000..e720ffdc --- /dev/null +++ b/opentrack/keybinding-worker.hpp @@ -0,0 +1,70 @@ +/* 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 +#include +#include +#include + +#ifdef _WIN32 +# undef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x0800 +# include +# include +struct Key { + BYTE keycode; + bool shift; + bool ctrl; + bool alt; + Timer timer; +public: + Key() : keycode(0), shift(false), ctrl(false), alt(false) + { + } + + bool should_process() + { + if (keycode == 0) + return false; + bool ret = timer.elapsed_ms() > 100; + timer.start(); + return ret; + } +}; +#else +typedef unsigned char BYTE; +struct Key { int foo; }; +#endif + +struct OPENTRACK_EXPORT KeybindingWorker : public QThread { +#ifdef _WIN32 +private: + LPDIRECTINPUT8 din; + LPDIRECTINPUTDEVICE8 dinkeyboard; + QMutex mtx; +public: + volatile bool should_quit; + std::function receiver; + ~KeybindingWorker(); + KeybindingWorker(std::function receiver, WId h); + void run(); +#else +public: + KeybindingWorker(Key, Key, Key, WId) {} + void run() {} +#endif +}; \ No newline at end of file diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index a33cf088..5f5ad922 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -7,110 +7,8 @@ */ #include "shortcuts.h" -#include - -#if defined(_WIN32) -#include -#include #include "win32-shortcuts.h" - -KeybindingWorker::~KeybindingWorker() { - should_quit = true; - wait(); - if (dinkeyboard) { - dinkeyboard->Unacquire(); - dinkeyboard->Release(); - } - if (din) - din->Release(); -} - -KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : - should_quit(true), receiver(receiver) -{ - HWND handle = reinterpret_cast(h); - - 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) handle, 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; -} - -void KeybindingWorker::run() { - BYTE keystate[256]; - - while (!should_quit) - { - if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - Sleep(25); - continue; - } - - QMutexLocker l(&mtx); - - for (int i = 0; i < 256; i++) - { - Key k; - if (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; - receiver(k); - break; - } - } - } - - // keypresses get dropped with high values - Sleep(4); - } -} -#endif +#include void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) { diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 81c1bb80..84231850 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -8,14 +8,6 @@ #pragma once #include -#include -#include "opentrack-compat/timer.hpp" -#include -#include -#include -#include -#include -#include #ifdef BUILD_api # include "opentrack-compat/export.hpp" @@ -24,69 +16,14 @@ #endif #include "qxt-mini/QxtGlobalShortcut" -#include "opentrack/plugin-support.hpp" #include "opentrack-compat/options.hpp" #include "opentrack/main-settings.hpp" -using namespace options; - -namespace { - extern QList global_key_sequences; -} - -#if defined(_WIN32) - -namespace { - extern QList global_windows_key_sequences; -} -# undef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x0800 -# include -# include - -struct Key { - BYTE keycode; - bool shift; - bool ctrl; - bool alt; - Timer timer; -public: - Key() : keycode(0), shift(false), ctrl(false), alt(false) - { - } - - bool should_process() - { - if (keycode == 0) - return false; - bool ret = timer.elapsed_ms() > 100; - timer.start(); - return ret; - } -}; -#else -typedef unsigned char BYTE; -struct Key { int foo; }; -#endif - -struct OPENTRACK_EXPORT KeybindingWorker : public QThread { #ifdef _WIN32 -private: - LPDIRECTINPUT8 din; - LPDIRECTINPUTDEVICE8 dinkeyboard; - QMutex mtx; -public: - volatile bool should_quit; - std::function receiver; - ~KeybindingWorker(); - KeybindingWorker(std::function receiver, WId h); - void run(); -#else -public: - KeybindingWorker(Key, Key, Key, WId) {} - void run() {} +# include "keybinding-worker.hpp" #endif -}; + +using namespace options; struct OPENTRACK_EXPORT Shortcuts : public QObject { Q_OBJECT -- cgit v1.2.3 From e138d155d2f2cfb7e87c353f98ffea0e2592483f Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 17:09:52 +0100 Subject: simple-mat: nix porked ctor --- opentrack/simple-mat.hpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'opentrack') diff --git a/opentrack/simple-mat.hpp b/opentrack/simple-mat.hpp index e462812b..59afbbf0 100644 --- a/opentrack/simple-mat.hpp +++ b/opentrack/simple-mat.hpp @@ -198,14 +198,6 @@ public: data[j][i] = *iter++; } - template - Mat(const t* xs) - { - for (int j = 0; j < h_; j++) - for (int i = 0; i < w_; i++) - data[j][i] = num(*xs++); - } - Mat() { for (int j = 0; j < h_; j++) -- cgit v1.2.3 From 2d90e4039c6dd1aab00c738f9bbc70a4949cd583 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 06:14:00 +0100 Subject: allow for binding joystick buttons to shortcut functions Win32 only Issue: #118 --- gui/keyboard.h | 16 +- gui/options-dialog.cpp | 44 ++++-- gui/options-dialog.hpp | 2 +- opentrack/keybinding-worker.cpp | 13 ++ opentrack/keybinding-worker.hpp | 5 +- opentrack/shortcuts.cpp | 34 +++-- opentrack/shortcuts.h | 7 +- opentrack/win32-joystick-shortcuts.hpp | 264 +++++++++++++++++++++++++++++++++ 8 files changed, 354 insertions(+), 31 deletions(-) create mode 100644 opentrack/win32-joystick-shortcuts.hpp (limited to 'opentrack') diff --git a/gui/keyboard.h b/gui/keyboard.h index 03edacc7..aa4b4a24 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -20,10 +20,17 @@ public: #ifdef _WIN32 , w([&](Key& k) { - Qt::KeyboardModifiers m; - QKeySequence k_; - if (win_key::to_qt(k, k_, m)) - key_pressed(static_cast(k_).toInt() | m); + if(k.guid != "") + { + joystick_button_pressed(k.guid, k.keycode); + } + else + { + Qt::KeyboardModifiers m; + QKeySequence k_; + if (win_key::to_qt(k, k_, m)) + key_pressed(static_cast(k_).toInt() | m); + } }, this->winId()) #endif { @@ -47,4 +54,5 @@ public: #endif signals: void key_pressed(QKeySequence k); + void joystick_button_pressed(QString guid, int idx); }; diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 2778be0f..c8bf668d 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -12,9 +12,18 @@ #include #include +static QString kopts_to_string(const Shortcuts::key_opts& kopts) +{ + if (static_cast(kopts.guid) != "") + return "Joystick button " + QString::number(kopts.button); + if (static_cast(kopts.keycode) == "") + return "None"; + return kopts.keycode; +} + OptionsDialog::OptionsDialog() { - ui.setupUi( this ); + ui.setupUi(this); connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); @@ -53,18 +62,20 @@ OptionsDialog::OptionsDialog() tie_setting(s.s_main.center_method, ui.center_method); - connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center.keycode, ui.center_text); }); - connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero.keycode, ui.zero_text); }); - connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle.keycode, ui.toggle_text); }); + connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center, ui.center_text); }); + connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero, ui.zero_text); }); + connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle, ui.toggle_text); }); - ui.center_text->setText(s.center.keycode == "" ? "None" : static_cast(s.center.keycode)); - ui.toggle_text->setText(s.toggle.keycode == "" ? "None" : static_cast(s.toggle.keycode)); - ui.zero_text->setText(s.zero.keycode == "" ? "None" : static_cast(s.zero.keycode)); + ui.center_text->setText(kopts_to_string(s.center)); + ui.toggle_text->setText(kopts_to_string(s.toggle)); + ui.zero_text->setText(kopts_to_string(s.zero)); } -void OptionsDialog::bind_key(value& ret, QLabel* label) +void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) { - ret = ""; + kopts.button = -1; + kopts.guid = ""; + kopts.keycode = ""; QDialog d; auto l = new QHBoxLayout; l->setMargin(0); @@ -73,9 +84,20 @@ void OptionsDialog::bind_key(value& ret, QLabel* label) d.setLayout(l); d.setFixedSize(QSize(500, 300)); d.setWindowFlags(Qt::Dialog); - connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { ret = s.toString(QKeySequence::PortableText); d.close(); }); + connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { + kopts.keycode = s.toString(QKeySequence::PortableText); + kopts.guid = ""; + kopts.button = -1; + d.close(); + }); + connect(k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx) -> void { + kopts.guid = guid; + kopts.keycode = ""; + kopts.button = idx; + d.close(); + }); d.exec(); - label->setText(ret == "" ? "None" : static_cast(ret)); + label->setText(kopts_to_string(kopts)); delete k; delete l; } diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 3ef99d06..308b5b0f 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -19,5 +19,5 @@ private: private slots: void doOK(); void doCancel(); - void bind_key(value& ret, QLabel* label); + void bind_key(Shortcuts::key_opts &kopts, QLabel* label); }; diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 29b2cf9f..e6c023ef 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -72,6 +72,19 @@ void KeybindingWorker::run() { while (!should_quit) { + { + using joy_fn = std::function; + + joy_fn f = [&](const QString& guid, int idx) -> void { + Key k; + k.keycode = idx; + k.guid = guid; + receiver(k); + }; + + joy_ctx.poll(f); + } + if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); Sleep(25); diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index e720ffdc..8cf59d65 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -15,6 +15,7 @@ #endif #include "opentrack-compat/timer.hpp" +#include "opentrack/win32-joystick-shortcuts.hpp" #include #include #include @@ -27,6 +28,7 @@ # include struct Key { BYTE keycode; + QString guid; bool shift; bool ctrl; bool alt; @@ -38,7 +40,7 @@ public: bool should_process() { - if (keycode == 0) + if (keycode == 0 && guid == "") return false; bool ret = timer.elapsed_ms() > 100; timer.start(); @@ -56,6 +58,7 @@ private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; QMutex mtx; + win32_joy_ctx joy_ctx; public: volatile bool should_quit; std::function receiver; diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 5f5ad922..0d7f79b9 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -34,19 +34,27 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) key = K(); int idx = 0; QKeySequence code; - - if (k.keycode == "") - code = QKeySequence(Qt::Key_unknown); + + if (k.guid != "") + { + key.guid = k.guid; + key.keycode = k.button; + } 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; + { + 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; + } } #endif @@ -56,6 +64,8 @@ void Shortcuts::receiver(Key &k) std::vector ks { &keyCenter, &keyToggle, &keyZero }; for (K* k_ : ks) { + if (k.guid != k_->guid) + continue; if (k.keycode != k_->keycode) continue; if (!k_->should_process()) diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 84231850..1643485e 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -47,10 +47,13 @@ public: #endif struct key_opts { - value keycode; + value keycode, guid; + value button; key_opts(pbundle b, const QString& name) : - keycode(b, QString("keycode-%1").arg(name), "") + keycode(b, QString("keycode-%1").arg(name), ""), + guid(b, QString("guid-%1").arg(name), ""), + button(b, QString("button-%1").arg(name), -1) {} }; diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp new file mode 100644 index 00000000..67465bce --- /dev/null +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -0,0 +1,264 @@ +#pragma once + +#include +#include +#include +#include +#include +#ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +#endif +#include +#include +#include "opentrack-compat/timer.hpp" +#include +#include + +struct win32_joy_ctx +{ + using fn = std::function; + + void poll(fn f) + { + refresh(); + for (int i = joys.size() - 1; i >= 0; i--) + { + if (!joys[i]->poll(f)) + joys.erase(joys.begin() + i); + } + } + + struct joy + { + LPDIRECTINPUTDEVICE8 joy_handle; + QString guid; + + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid) + { + qDebug() << "got joy" << guid; + } + + ~joy() + { + qDebug() << "nix joy" << guid; + release(); + } + + void release() + { + if (joy_handle) + { + (void) joy_handle->Unacquire(); + joy_handle->Release(); + joy_handle = nullptr; + } + } + + bool poll(fn f) + { + HRESULT hr; + bool ok = false; + + for (int i = 0; i < 5; i++) + { + if (!FAILED(joy_handle->Poll())) + { + ok = true; + break; + } + if ((hr = joy_handle->Acquire()) != DI_OK) + continue; + else + ok = true; + break; + } + + if (!ok) + { + qDebug() << "joy acquire failed" << guid << hr; + return false; + } + + DIJOYSTATE2 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++) + if (js.rgbButtons[i] & 0x80) + f(guid, i); + + return true; + } + }; + + static QString 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); + } + + win32_joy_ctx() : dinput_handle(nullptr) + { + (void) CoInitialize(nullptr); + + HRESULT hr; + + if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (void**) &dinput_handle, + nullptr))) + goto fail; + + return; +fail: + qDebug() << "dinput8 failed for shortcuts" << hr; + + release(); + } + + ~win32_joy_ctx() + { + release(); + } + + void release() + { + joys = std::vector>(); + if (dinput_handle) + { + dinput_handle->Release(); + dinput_handle = nullptr; + } + } + + void refresh() + { + if (!dinput_handle) + return; + + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + + timer_joylist.start(); + + enum_state st(dinput_handle, joys); + } + + struct enum_state + { + std::vector>& joys; + std::vector all; + LPDIRECTINPUT8 dinput_handle; + + enum_state(LPDIRECTINPUT8 di, std::vector>& joys) : joys(joys), dinput_handle(di) + { + HRESULT hr; + + if(FAILED(hr = dinput_handle->EnumDevices(DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "failed enum joysticks" << hr; + return; + } + + for (int i = joys.size() - 1; i >= 0; i--) + { + const auto& guid = joys[i]->guid; + if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return guid == guid2; }) == all.cend()) + joys.erase(joys.begin() + i); + } + } + + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) + { + enum_state& state = *reinterpret_cast(pContext); + const QString guid = guid_to_string(pdidInstance->guidInstance); +#if 0 + const QString name = QString(pdidInstance->tszInstanceName); + // the logic here is that iff multiple joysticks of same name exist, then take guids into account at all + const int cnt_names = std::count_if(state.joys.begin(), state.joys.end(), [&](const joy& j) -> bool { return j.name == name; }); + // this is potentially bad since replugged sticks can change guids (?) +#endif + + const bool exists = std::find_if(state.joys.cbegin(), + state.joys.cend(), + [&](const std::shared_ptr& j) -> bool { return j->guid == guid; }) != state.joys.cend(); + + state.all.push_back(guid); + + if (!exists) + { + HRESULT hr; + LPDIRECTINPUTDEVICE8 h; + if (FAILED(hr = state.dinput_handle->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + { + qDebug() << "create joystick breakage" << guid << hr; + goto end; + } + if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) + { + qDebug() << "format"; + h->Release(); + goto end; + } + + if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + { + qDebug() << "coop"; + h->Release(); + goto end; + } +#if 0 + if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) + { + qDebug() << "enum-objects"; + h->Release(); + goto end; + } +#endif + state.joys.push_back(std::make_shared(h, guid)); + } + +end: return DIENUM_CONTINUE; + } + +#if 0 + static BOOL CALLBACK 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 = 32; + diprg.lMin = -32; + + if (FAILED(reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) + return DIENUM_STOP; + } + + return DIENUM_CONTINUE; + } +#endif + }; + + LPDIRECTINPUT8 dinput_handle; + std::vector> joys; + Timer timer_joylist; + enum { joylist_refresh_ms = 2000 }; +}; \ No newline at end of file -- cgit v1.2.3 From 17849b12f232c89bdae16f7e179d3a92a32280ad Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 13:44:45 +0100 Subject: shortcuts: map joystick buttons on depress only Some buttons like the X65 mode switch are held all the time. Prevent them from hogging all the keybindings. Issue: #118 --- gui/keyboard.h | 4 ++-- gui/options-dialog.cpp | 13 ++++++++----- opentrack/keybinding-worker.cpp | 5 +++-- opentrack/keybinding-worker.hpp | 3 ++- opentrack/win32-joystick-shortcuts.hpp | 13 ++++++++++--- 5 files changed, 25 insertions(+), 13 deletions(-) (limited to 'opentrack') diff --git a/gui/keyboard.h b/gui/keyboard.h index aa4b4a24..b840bc78 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -22,7 +22,7 @@ public: { if(k.guid != "") { - joystick_button_pressed(k.guid, k.keycode); + joystick_button_pressed(k.guid, k.keycode, k.held); } else { @@ -54,5 +54,5 @@ public: #endif signals: void key_pressed(QKeySequence k); - void joystick_button_pressed(QString guid, int idx); + void joystick_button_pressed(QString guid, int idx, bool held); }; diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index c8bf668d..4cff6e77 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -90,11 +90,14 @@ void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) kopts.button = -1; d.close(); }); - connect(k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx) -> void { - kopts.guid = guid; - kopts.keycode = ""; - kopts.button = idx; - d.close(); + connect(k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx, bool held) -> void { + if (!held) + { + kopts.guid = guid; + kopts.keycode = ""; + kopts.button = idx; + d.close(); + } }); d.exec(); label->setText(kopts_to_string(kopts)); diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index e6c023ef..e9255801 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -73,12 +73,13 @@ void KeybindingWorker::run() { while (!should_quit) { { - using joy_fn = std::function; + using joy_fn = std::function; - joy_fn f = [&](const QString& guid, int idx) -> void { + joy_fn f = [&](const QString& guid, int idx, bool held) -> void { Key k; k.keycode = idx; k.guid = guid; + k.held = held; receiver(k); }; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 8cf59d65..cb3e5f9f 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -32,9 +32,10 @@ struct Key { bool shift; bool ctrl; bool alt; + bool held; Timer timer; public: - Key() : keycode(0), shift(false), ctrl(false), alt(false) + Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) { } diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 67465bce..3c839197 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -16,7 +16,7 @@ struct win32_joy_ctx { - using fn = std::function; + using fn = std::function; void poll(fn f) { @@ -32,10 +32,13 @@ struct win32_joy_ctx { LPDIRECTINPUTDEVICE8 joy_handle; QString guid; + bool pressed[128]; joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid) { qDebug() << "got joy" << guid; + for (int i = 0; i < 128; i++) + pressed[i] = false; } ~joy() @@ -88,8 +91,12 @@ struct win32_joy_ctx } for (int i = 0; i < 128; i++) - if (js.rgbButtons[i] & 0x80) - f(guid, i); + { + const bool state = !!(js.rgbButtons[i] & 0x80); + if (state != pressed[i]) + f(guid, i, state); + pressed[i] = state; + } return true; } -- cgit v1.2.3 From dce46278e8ccb63a1f6dd60733671fdcaad59873 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 13:45:10 +0100 Subject: shortcuts: register joysticks every 250 ms, not 2 seconds Issue: #118 --- opentrack/win32-joystick-shortcuts.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 3c839197..23228835 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -267,5 +267,5 @@ end: return DIENUM_CONTINUE; LPDIRECTINPUT8 dinput_handle; std::vector> joys; Timer timer_joylist; - enum { joylist_refresh_ms = 2000 }; + enum { joylist_refresh_ms = 250 }; }; \ No newline at end of file -- cgit v1.2.3 From 4c2529611677e204b7ecf40508723f355cfd423b Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 14:13:46 +0100 Subject: joy: refresh immediately once on startup --- opentrack/win32-joystick-shortcuts.hpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 23228835..5a2fc6c8 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -20,7 +20,7 @@ struct win32_joy_ctx void poll(fn f) { - refresh(); + refresh(false); for (int i = joys.size() - 1; i >= 0; i--) { if (!joys[i]->poll(f)) @@ -126,6 +126,8 @@ struct win32_joy_ctx nullptr))) goto fail; + refresh(true); + return; fail: qDebug() << "dinput8 failed for shortcuts" << hr; @@ -148,15 +150,17 @@ fail: } } - void refresh() + void refresh(bool first) { if (!dinput_handle) return; - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - - timer_joylist.start(); + if (!first) + { + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + timer_joylist.start(); + } enum_state st(dinput_handle, joys); } -- cgit v1.2.3 From 605d267622b8d2e69bc761f4f49442566164d843 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 14:35:13 +0100 Subject: joy: pass shortcut only if pressed, not depressed Issue: #118 Reported-by: @Len62 --- opentrack/shortcuts.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'opentrack') diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 0d7f79b9..108b6b3b 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -68,6 +68,8 @@ void Shortcuts::receiver(Key &k) continue; if (k.keycode != k_->keycode) continue; + if (!k.held) + continue; if (!k_->should_process()) continue; if (k_->alt && !k.alt) continue; -- cgit v1.2.3 From 9f8cbd79fc1040e855fe9325447983bd8d13f1b9 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 14:35:26 +0100 Subject: joy: memset won't hurt --- opentrack/win32-joystick-shortcuts.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 5a2fc6c8..ee26215e 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -83,6 +83,7 @@ struct win32_joy_ctx } DIJOYSTATE2 js; + memset(&js, 0, sizeof(js)); if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) { -- cgit v1.2.3 From ef897ea95734917c3679dc9e2cad89e8d55c3099 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 14:35:34 +0100 Subject: joy: add cheap debug info --- opentrack/win32-joystick-shortcuts.hpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index ee26215e..bde690c5 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -95,7 +95,10 @@ struct win32_joy_ctx { const bool state = !!(js.rgbButtons[i] & 0x80); if (state != pressed[i]) + { f(guid, i, state); + qDebug() << "btn" << guid << i << state; + } pressed[i] = state; } -- cgit v1.2.3 From e79ab73d99d3cc19e0db82cce8884589e0e93396 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 14:35:46 +0100 Subject: joy: slurp keys on startup --- opentrack/win32-joystick-shortcuts.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index bde690c5..530545dc 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -39,6 +39,7 @@ struct win32_joy_ctx qDebug() << "got joy" << guid; for (int i = 0; i < 128; i++) pressed[i] = false; + poll([&](const QString&, int idx, bool held) -> void { pressed[idx] = held; }); } ~joy() -- cgit v1.2.3 From c8805112acca1ba3bd0056fcf0b9332c4ba10f03 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 15:28:50 +0100 Subject: shortcuts: alloy kbd mods for joystick buttons --- gui/keyboard.h | 6 +++++- opentrack/keybinding-worker.cpp | 21 ++++++++++++++------- opentrack/shortcuts.cpp | 5 ++++- 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'opentrack') diff --git a/gui/keyboard.h b/gui/keyboard.h index b840bc78..75226aa3 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -22,7 +22,11 @@ public: { if(k.guid != "") { - joystick_button_pressed(k.guid, k.keycode, k.held); + int mods = 0; + if (k.alt) mods |= Qt::AltModifier; + if (k.shift) mods |= Qt::ShiftModifier; + if (k.ctrl) mods |= Qt::ControlModifier; + joystick_button_pressed(k.guid, k.keycode | mods, k.held); } else { diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index e9255801..fd777211 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -68,16 +68,29 @@ KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : } void KeybindingWorker::run() { - BYTE keystate[256]; + BYTE keystate[256] = {0}; while (!should_quit) { + { + 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; receiver(k); @@ -85,12 +98,6 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } - - if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - Sleep(25); - continue; - } QMutexLocker l(&mtx); diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 108b6b3b..6eab6071 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -38,7 +38,10 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) if (k.guid != "") { key.guid = k.guid; - key.keycode = k.button; + 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 { -- cgit v1.2.3 From 390e9f1ad63a4ac90ffa4fab8094999cfe794c64 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 15:52:50 +0100 Subject: joy: guard _WIN32. retab. --- opentrack/win32-joystick-shortcuts.hpp | 86 ++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 41 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 530545dc..3e384da5 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef _WIN32 + #include #include #include @@ -17,7 +19,7 @@ struct win32_joy_ctx { using fn = std::function; - + void poll(fn f) { refresh(false); @@ -27,13 +29,13 @@ struct win32_joy_ctx joys.erase(joys.begin() + i); } } - + struct joy { LPDIRECTINPUTDEVICE8 joy_handle; QString guid; bool pressed[128]; - + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid) { qDebug() << "got joy" << guid; @@ -41,13 +43,13 @@ struct win32_joy_ctx pressed[i] = false; poll([&](const QString&, int idx, bool held) -> void { pressed[idx] = held; }); } - + ~joy() { qDebug() << "nix joy" << guid; release(); } - + void release() { if (joy_handle) @@ -57,12 +59,12 @@ struct win32_joy_ctx joy_handle = nullptr; } } - + bool poll(fn f) { HRESULT hr; bool ok = false; - + for (int i = 0; i < 5; i++) { if (!FAILED(joy_handle->Poll())) @@ -76,22 +78,22 @@ struct win32_joy_ctx ok = true; break; } - + if (!ok) { qDebug() << "joy acquire failed" << guid << hr; 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); @@ -102,49 +104,49 @@ struct win32_joy_ctx } pressed[i] = state; } - + return true; } }; - + static QString 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); } - + win32_joy_ctx() : dinput_handle(nullptr) { (void) CoInitialize(nullptr); - + HRESULT hr; - + if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**) &dinput_handle, nullptr))) goto fail; - + refresh(true); - + return; fail: qDebug() << "dinput8 failed for shortcuts" << hr; - + release(); } - + ~win32_joy_ctx() { release(); } - + void release() { joys = std::vector>(); @@ -154,32 +156,32 @@ fail: dinput_handle = nullptr; } } - + void refresh(bool first) { if (!dinput_handle) return; - + if (!first) { if (timer_joylist.elapsed_ms() < joylist_refresh_ms) return; timer_joylist.start(); } - + enum_state st(dinput_handle, joys); } - + struct enum_state { std::vector>& joys; std::vector all; LPDIRECTINPUT8 dinput_handle; - + enum_state(LPDIRECTINPUT8 di, std::vector>& joys) : joys(joys), dinput_handle(di) { HRESULT hr; - + if(FAILED(hr = dinput_handle->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, @@ -188,7 +190,7 @@ fail: qDebug() << "failed enum joysticks" << hr; return; } - + for (int i = joys.size() - 1; i >= 0; i--) { const auto& guid = joys[i]->guid; @@ -196,7 +198,7 @@ fail: joys.erase(joys.begin() + i); } } - + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) { enum_state& state = *reinterpret_cast(pContext); @@ -207,13 +209,13 @@ fail: const int cnt_names = std::count_if(state.joys.begin(), state.joys.end(), [&](const joy& j) -> bool { return j.name == name; }); // this is potentially bad since replugged sticks can change guids (?) #endif - + const bool exists = std::find_if(state.joys.cbegin(), state.joys.cend(), [&](const std::shared_ptr& j) -> bool { return j->guid == guid; }) != state.joys.cend(); - + state.all.push_back(guid); - + if (!exists) { HRESULT hr; @@ -229,7 +231,7 @@ fail: h->Release(); goto end; } - + if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) { qDebug() << "coop"; @@ -246,10 +248,10 @@ fail: #endif state.joys.push_back(std::make_shared(h, guid)); } - + end: return DIENUM_CONTINUE; } - + #if 0 static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx) { @@ -263,18 +265,20 @@ end: return DIENUM_CONTINUE; diprg.diph.dwObj = pdidoi->dwType; diprg.lMax = 32; diprg.lMin = -32; - + if (FAILED(reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) return DIENUM_STOP; } - + return DIENUM_CONTINUE; } #endif }; - + LPDIRECTINPUT8 dinput_handle; std::vector> joys; Timer timer_joylist; enum { joylist_refresh_ms = 250 }; -}; \ No newline at end of file +}; + +#endif -- cgit v1.2.3 From afc6da0a17eec9e1da31a79c610a8f090507b39e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 12 Nov 2015 08:28:41 +0100 Subject: joy: for newly plugged sticks, only emit events after 3 seconds My X65 emits modeswitch events only a while after getting plugged in. This only affects newly hotplugged joysticks. Ones plugged in before listening start start processing events immediately. Issue: #118 --- opentrack/win32-joystick-shortcuts.hpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 3e384da5..f3bca827 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -35,13 +35,16 @@ struct win32_joy_ctx LPDIRECTINPUTDEVICE8 joy_handle; QString guid; bool pressed[128]; + Timer first_timer; + bool first; + + enum { first_event_delay_ms = 3000 }; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid) + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, bool first) : joy_handle(handle), guid(guid), first(first) { qDebug() << "got joy" << guid; for (int i = 0; i < 128; i++) pressed[i] = false; - poll([&](const QString&, int idx, bool held) -> void { pressed[idx] = held; }); } ~joy() @@ -64,6 +67,9 @@ struct win32_joy_ctx { HRESULT hr; bool ok = false; + + if (first_timer.elapsed_ms() > first_event_delay_ms) + first = true; for (int i = 0; i < 5; i++) { @@ -97,7 +103,7 @@ struct win32_joy_ctx for (int i = 0; i < 128; i++) { const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i]) + if (state != pressed[i] && first) { f(guid, i, state); qDebug() << "btn" << guid << i << state; @@ -169,7 +175,7 @@ fail: timer_joylist.start(); } - enum_state st(dinput_handle, joys); + enum_state st(dinput_handle, joys, first); } struct enum_state @@ -177,8 +183,9 @@ fail: std::vector>& joys; std::vector all; LPDIRECTINPUT8 dinput_handle; + bool first; - enum_state(LPDIRECTINPUT8 di, std::vector>& joys) : joys(joys), dinput_handle(di) + enum_state(LPDIRECTINPUT8 di, std::vector>& joys, bool first) : joys(joys), dinput_handle(di), first(first) { HRESULT hr; @@ -246,7 +253,7 @@ fail: goto end; } #endif - state.joys.push_back(std::make_shared(h, guid)); + state.joys.push_back(std::make_shared(h, guid, state.first)); } end: return DIENUM_CONTINUE; -- cgit v1.2.3 From 798f6e9076855bf7769aba8abde4d570960d0755 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 12 Nov 2015 08:48:51 +0100 Subject: joy: remove branching --- opentrack/win32-joystick-shortcuts.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index f3bca827..e54596bd 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -67,9 +67,6 @@ struct win32_joy_ctx { HRESULT hr; bool ok = false; - - if (first_timer.elapsed_ms() > first_event_delay_ms) - first = true; for (int i = 0; i < 5; i++) { @@ -99,6 +96,8 @@ struct win32_joy_ctx qDebug() << "joy get state failed" << guid << hr; return false; } + + first |= first_timer.elapsed_ms() > first_event_delay_ms; for (int i = 0; i < 128; i++) { -- cgit v1.2.3 From 42217bbb858ddb158ad13777e2aace942aaf9525 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 19 Nov 2015 01:41:49 +0100 Subject: shortcuts: nix single-use mutex It also slept with lock held. Good riddance. --- opentrack/keybinding-worker.cpp | 2 -- opentrack/keybinding-worker.hpp | 1 - opentrack/shortcuts.cpp | 1 - 3 files changed, 4 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index fd777211..31eb9e80 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -99,8 +99,6 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } - QMutexLocker l(&mtx); - for (int i = 0; i < 256; i++) { Key k; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index cb3e5f9f..b5d63fac 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -58,7 +58,6 @@ struct OPENTRACK_EXPORT KeybindingWorker : public QThread { private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; - QMutex mtx; win32_joy_ctx joy_ctx; public: volatile bool should_quit; diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 6eab6071..059febdb 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -8,7 +8,6 @@ #include "shortcuts.h" #include "win32-shortcuts.h" -#include void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) { -- cgit v1.2.3 From a9860e951757bf454b83b13ce7eff865f0b6644e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:06:30 +0100 Subject: api/keyboard: implement a central worker DirectInput dies when two LPDIRECTINPUT8 handles are obtained. Implement a singleton worker providing keypress events. --- opentrack/keybinding-worker.cpp | 153 ++++++++++++++++++++++++++-------------- opentrack/keybinding-worker.hpp | 48 ++++++++++--- 2 files changed, 137 insertions(+), 64 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 31eb9e80..d876d5a1 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -9,11 +9,14 @@ #include "keybinding-worker.hpp" #if defined(_WIN32) -# include -# include -# include + +#include +#include +#include +#include KeybindingWorker::~KeybindingWorker() { + qDebug() << "keybinding worker stop"; should_quit = true; wait(); if (dinkeyboard) { @@ -24,11 +27,8 @@ KeybindingWorker::~KeybindingWorker() { din->Release(); } -KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : - should_quit(true), receiver(receiver) +KeybindingWorker::KeybindingWorker() : should_quit(true) { - HWND handle = reinterpret_cast(h); - if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); return; @@ -47,7 +47,7 @@ KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : din = 0; return; } - if (dinkeyboard->SetCooperativeLevel((HWND) handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + if (dinkeyboard->SetCooperativeLevel(GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { dinkeyboard->Release(); din->Release(); din = 0; @@ -65,6 +65,13 @@ KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : return; } should_quit = false; + start(); +} + +KeybindingWorker& KeybindingWorker::make() +{ + static KeybindingWorker k; + return k; } void KeybindingWorker::run() { @@ -73,59 +80,99 @@ void KeybindingWorker::run() { while (!should_quit) { { - 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; - receiver(k); - }; + QMutexLocker l(&mtx); - joy_ctx.poll(f); - } - - for (int i = 0; i < 256; i++) - { - Key k; - if (keystate[i] & 0x80) + if (receivers.size()) { - 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; - receiver(k); - break; + 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(k); + }; + + joy_ctx.poll(f); + } + + for (int i = 0; i < 256; i++) + { + Key k; + if (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; + + for (auto& r : receivers) + r(k); + break; + } + } } } } - + // keypresses get dropped with high values Sleep(4); } } + +KeybindingWorker::fun* KeybindingWorker::_add_receiver(KeybindingWorker::fun receiver) +{ + QMutexLocker l(&mtx); + receivers.push_back(receiver); + qDebug() << "add receiver" << (long) &receivers[receivers.size()-1]; + return &receivers[receivers.size()-1]; +} + +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] == pos) + { + ok = true; + qDebug() << "remove receiver" << (long) pos; + receivers.erase(receivers.begin() + i); + } + } + if (!ok) + { + qDebug() << "bad remove receiver" << (long) pos; + } +} + #endif \ No newline at end of file diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index b5d63fac..5a73b1b1 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef _WIN32 # undef DIRECTINPUT_VERSION @@ -53,21 +54,46 @@ typedef unsigned char BYTE; struct Key { int foo; }; #endif -struct OPENTRACK_EXPORT KeybindingWorker : public QThread { -#ifdef _WIN32 +struct OPENTRACK_EXPORT KeybindingWorker : private QThread +{ private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; win32_joy_ctx joy_ctx; -public: volatile bool should_quit; - std::function receiver; + using fun = std::function; + std::vector receivers; + QMutex mtx; + + 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(); - KeybindingWorker(std::function receiver, WId h); - void run(); -#else public: - KeybindingWorker(Key, Key, Key, WId) {} - void run() {} -#endif -}; \ No newline at end of file + class Token + { + friend class KeybindingWorker; + fun* pos; + //Token(const Token&) = delete; + Token& operator=(Token&) = delete; + public: + Token(fun receiver) + { + pos = make()._add_receiver(receiver); + } + ~Token() + { + make().remove_receiver(pos); + } + }; + friend class Token; + static Token add_receiver(fun receiver) + { + return Token(receiver); + } +}; -- cgit v1.2.3 From bf5931532f91107747cc45befffb5cc189777c89 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:07:23 +0100 Subject: work: use the centralized keypress worker --- gui/keyboard.h | 10 +++------- opentrack/shortcuts.cpp | 10 +--------- opentrack/shortcuts.h | 11 ++++++----- opentrack/work.hpp | 3 ++- 4 files changed, 12 insertions(+), 22 deletions(-) (limited to 'opentrack') diff --git a/gui/keyboard.h b/gui/keyboard.h index 75226aa3..696df605 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -13,13 +13,12 @@ class KeyboardListener : public QLabel Q_OBJECT Ui_keyboard_listener ui; #ifdef _WIN32 - KeybindingWorker w; + KeybindingWorker::Token token; #endif public: KeyboardListener(QWidget* parent = nullptr) : QLabel(parent) #ifdef _WIN32 - , w([&](Key& k) - { + , token([&](const Key& k) { if(k.guid != "") { int mods = 0; @@ -35,14 +34,11 @@ public: if (win_key::to_qt(k, k_, m)) key_pressed(static_cast(k_).toInt() | m); } - }, this->winId()) + }) #endif { ui.setupUi(this); setFocusPolicy(Qt::StrongFocus); -#ifdef _WIN32 - w.start(); -#endif } #ifndef _WIN32 void keyPressEvent(QKeyEvent* event) override diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 059febdb..b961294f 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -61,7 +61,7 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) #endif #ifdef _WIN32 -void Shortcuts::receiver(Key &k) +void Shortcuts::receiver(const Key& k) { std::vector ks { &keyCenter, &keyToggle, &keyZero }; for (K* k_ : ks) @@ -92,12 +92,4 @@ void Shortcuts::reload() { bind_keyboard_shortcut(keyCenter, s.center); bind_keyboard_shortcut(keyToggle, s.toggle); bind_keyboard_shortcut(keyZero, s.zero); -#ifdef _WIN32 - bool is_new = keybindingWorker == nullptr; - if (is_new) - { - keybindingWorker = std::make_shared([&](Key& k) { receiver(k); }, handle); - keybindingWorker->start(); - } -#endif } diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 1643485e..930952e8 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -40,10 +40,8 @@ public: K keyCenter; K keyToggle; K keyZero; - - WId handle; #ifdef _WIN32 - mem keybindingWorker; + KeybindingWorker::Token key_token; #endif struct key_opts { @@ -68,13 +66,16 @@ public: {} } s; - Shortcuts(WId handle) : handle(handle) { reload(); } + Shortcuts() : key_token(KeybindingWorker::add_receiver([&](const Key& k) { receiver(k); })) + { + reload(); + } void reload(); private: void bind_keyboard_shortcut(K &key, key_opts& k); #ifdef _WIN32 - void receiver(Key& k); + void receiver(const Key& k); #endif signals: void center(); diff --git a/opentrack/work.hpp b/opentrack/work.hpp index 5d1f6b54..e338e9f4 100644 --- a/opentrack/work.hpp +++ b/opentrack/work.hpp @@ -28,7 +28,7 @@ struct Work Work(main_settings& s, Mappings& m, SelectedLibraries& libs, QObject* recv, WId handle) : s(s), libs(libs), tracker(std::make_shared(s, m, libs)), - sc(std::make_shared(handle)), + sc(std::make_shared()), handle(handle) { #ifndef _WIN32 @@ -50,6 +50,7 @@ struct Work ~Work() { + sc = nullptr; // order matters, otherwise use-after-free -sh tracker = nullptr; libs = SelectedLibraries(); -- cgit v1.2.3 From 38a7253d20f7e29760e536e7e172a43d413a9372 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:11:31 +0100 Subject: api/joy: implement a central joystick worker - Make the dinput handle a singleton also across module boundaries. - Provide axis values per connected stick. - Robustify in case of sudden unplug. --- opentrack/win32-joystick-shortcuts.cpp | 24 ++++ opentrack/win32-joystick-shortcuts.hpp | 216 +++++++++++++++++++++------------ 2 files changed, 162 insertions(+), 78 deletions(-) create mode 100644 opentrack/win32-joystick-shortcuts.cpp (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.cpp b/opentrack/win32-joystick-shortcuts.cpp new file mode 100644 index 00000000..44659b7e --- /dev/null +++ b/opentrack/win32-joystick-shortcuts.cpp @@ -0,0 +1,24 @@ +#include "win32-joystick-shortcuts.hpp" + +LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() +{ + (void) CoInitialize(nullptr); + + static LPDIRECTINPUT8 dinput_handle_ = nullptr; + + if (dinput_handle_ == nullptr) + (void) DirectInput8Create(GetModuleHandle(nullptr), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (void**) &dinput_handle_, + nullptr); + + return dinput_handle_; +} + +std::unordered_map>& win32_joy_ctx::joys() +{ + static std::unordered_map> js; + + return js; +} diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index e54596bd..081dc0ce 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #ifndef DIRECTINPUT_VERSION # define DIRECTINPUT_VERSION 0x800 #endif @@ -15,32 +16,109 @@ #include "opentrack-compat/timer.hpp" #include #include +#include +#include -struct win32_joy_ctx +namespace std { +template<> +struct hash +{ + 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; void poll(fn f) { + QMutexLocker l(&mtx); + refresh(false); - for (int i = joys.size() - 1; i >= 0; i--) + for (auto& j : joys()) { - if (!joys[i]->poll(f)) - joys.erase(joys.begin() + i); + j.second->poll(f); } } + + bool poll_axis(const QString& guid, int axes[8]) + { + QMutexLocker l(&mtx); + + auto iter = joys().find(guid); + + if (iter == joys().end() || iter->second->joy_handle == nullptr) + return false; + + refresh(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]; + + (void) joy_handle->Unacquire(); + + return true; + } struct joy { LPDIRECTINPUTDEVICE8 joy_handle; - QString guid; + QString guid, name; bool pressed[128]; Timer first_timer; bool first; enum { first_event_delay_ms = 3000 }; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, bool first) : joy_handle(handle), guid(guid), first(first) + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) : joy_handle(handle), guid(guid), name(name), first(first) { qDebug() << "got joy" << guid; for (int i = 0; i < 128; i++) @@ -67,24 +145,19 @@ struct win32_joy_ctx { HRESULT hr; bool ok = false; - - for (int i = 0; i < 5; i++) - { - if (!FAILED(joy_handle->Poll())) - { - ok = true; - break; - } - if ((hr = joy_handle->Acquire()) != DI_OK) - continue; - else - ok = true; - break; - } + + if (joy_handle == nullptr) + return false; + + (void) joy_handle->Acquire(); + + if (!FAILED(joy_handle->Poll())) + ok = true; if (!ok) { qDebug() << "joy acquire failed" << guid << hr; + (void) joy_handle->Unacquire(); return false; } @@ -97,6 +170,8 @@ struct win32_joy_ctx return false; } + (void) joy_handle->Unacquire(); + first |= first_timer.elapsed_ms() > first_event_delay_ms; for (int i = 0; i < 128; i++) @@ -125,26 +200,10 @@ struct win32_joy_ctx return QString(buf); } - win32_joy_ctx() : dinput_handle(nullptr) + win32_joy_ctx() { - (void) CoInitialize(nullptr); - - HRESULT hr; - - if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), - DIRECTINPUT_VERSION, - IID_IDirectInput8, - (void**) &dinput_handle, - nullptr))) - goto fail; - refresh(true); - return; -fail: - qDebug() << "dinput8 failed for shortcuts" << hr; - - release(); } ~win32_joy_ctx() @@ -154,19 +213,17 @@ fail: void release() { - joys = std::vector>(); - if (dinput_handle) + qDebug() << "release dinput handle"; + joys() = std::unordered_map>(); { - dinput_handle->Release(); - dinput_handle = nullptr; + auto& di = dinput_handle(); + di->Release(); + di = nullptr; } } void refresh(bool first) { - if (!dinput_handle) - return; - if (!first) { if (timer_joylist.elapsed_ms() < joylist_refresh_ms) @@ -174,34 +231,37 @@ fail: timer_joylist.start(); } - enum_state st(dinput_handle, joys, first); + enum_state st(joys(), first); } + + enum { joy_axis_size = 65535 }; struct enum_state { - std::vector>& joys; + std::unordered_map>& joys; std::vector all; - LPDIRECTINPUT8 dinput_handle; bool first; - enum_state(LPDIRECTINPUT8 di, std::vector>& joys, bool first) : joys(joys), dinput_handle(di), first(first) + enum_state(std::unordered_map>& joys, bool first) : joys(joys), first(first) { HRESULT hr; + LPDIRECTINPUT8 di = dinput_handle(); - if(FAILED(hr = dinput_handle->EnumDevices(DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) { qDebug() << "failed enum joysticks" << hr; return; } - - for (int i = joys.size() - 1; i >= 0; i--) + + for (auto it = joys.begin(); it != joys.end(); ) { - const auto& guid = joys[i]->guid; - if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return guid == guid2; }) == all.cend()) - joys.erase(joys.begin() + i); + 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++; } } @@ -209,16 +269,10 @@ fail: { enum_state& state = *reinterpret_cast(pContext); const QString guid = guid_to_string(pdidInstance->guidInstance); -#if 0 const QString name = QString(pdidInstance->tszInstanceName); - // the logic here is that iff multiple joysticks of same name exist, then take guids into account at all - const int cnt_names = std::count_if(state.joys.begin(), state.joys.end(), [&](const joy& j) -> bool { return j.name == name; }); - // this is potentially bad since replugged sticks can change guids (?) -#endif - - const bool exists = std::find_if(state.joys.cbegin(), - state.joys.cend(), - [&](const std::shared_ptr& j) -> bool { return j->guid == guid; }) != state.joys.cend(); + + auto it = state.joys.find(guid); + const bool exists = it != state.joys.end() && it->second->joy_handle != nullptr; state.all.push_back(guid); @@ -226,9 +280,10 @@ fail: { HRESULT hr; LPDIRECTINPUTDEVICE8 h; - if (FAILED(hr = state.dinput_handle->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + LPDIRECTINPUT8 di = dinput_handle(); + if (FAILED(hr = di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) { - qDebug() << "create joystick breakage" << guid << hr; + qDebug() << "createdevice" << guid << hr; goto end; } if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) @@ -244,21 +299,20 @@ fail: h->Release(); goto end; } -#if 0 if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) { qDebug() << "enum-objects"; h->Release(); goto end; } -#endif - state.joys.push_back(std::make_shared(h, guid, state.first)); + + qDebug() << "add joy" << guid; + state.joys[guid] = std::make_shared(h, guid, name, state.first); } end: return DIENUM_CONTINUE; } -#if 0 static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx) { if (pdidoi->dwType & DIDFT_AXIS) @@ -269,20 +323,26 @@ end: return DIENUM_CONTINUE; diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); diprg.diph.dwHow = DIPH_BYID; diprg.diph.dwObj = pdidoi->dwType; - diprg.lMax = 32; - diprg.lMin = -32; + diprg.lMax = joy_axis_size; + diprg.lMin = -joy_axis_size; + + HRESULT hr; - if (FAILED(reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) + if (FAILED(hr = reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) + { + qDebug() << "DIPROP_RANGE" << hr; return DIENUM_STOP; + } } return DIENUM_CONTINUE; } -#endif }; - LPDIRECTINPUT8 dinput_handle; - std::vector> joys; + static LPDIRECTINPUT8& dinput_handle(); + static std::unordered_map>& joys(); + + QMutex mtx; Timer timer_joylist; enum { joylist_refresh_ms = 250 }; }; -- cgit v1.2.3 From 86f1df90b405b56b46d698b4059ed2c6b10df8b3 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:49:52 +0100 Subject: api/joy: protect dinput with mutex in all cases Also practice object-oriented information hiding to avoid accesses without the mutex. Also provide basic joy information (guid, name) without exposing dinput handles and so on. --- opentrack/win32-joystick-shortcuts.cpp | 6 ++ opentrack/win32-joystick-shortcuts.hpp | 132 +++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 56 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick-shortcuts.cpp b/opentrack/win32-joystick-shortcuts.cpp index 44659b7e..61a2a74a 100644 --- a/opentrack/win32-joystick-shortcuts.cpp +++ b/opentrack/win32-joystick-shortcuts.cpp @@ -22,3 +22,9 @@ std::unordered_map>& win32_joy_ctx: return js; } + +win32_joy_ctx& win32_joy_ctx::make() +{ + static win32_joy_ctx ret; + return ret; +} diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 081dc0ce..ed0b4412 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -55,13 +55,13 @@ struct OPENTRACK_EXPORT win32_joy_ctx { QMutexLocker l(&mtx); + refresh(false); + auto iter = joys().find(guid); if (iter == joys().end() || iter->second->joy_handle == nullptr) return false; - refresh(false); - auto& j = iter->second; auto& joy_handle = j->joy_handle; @@ -107,7 +107,79 @@ struct OPENTRACK_EXPORT win32_joy_ctx return true; } + + ~win32_joy_ctx() + { + release(); + } + + enum { joy_axis_size = 65535 }; + + struct joy_info + { + QString name, guid; + }; + + std::vector 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; + } + + static win32_joy_ctx& make(); + + win32_joy_ctx(const win32_joy_ctx&) = delete; + win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; +private: + static QString 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); + } + + static LPDIRECTINPUT8& dinput_handle(); + + win32_joy_ctx() + { + refresh(true); + } + void release() + { + qDebug() << "release joystick dinput handle"; + joys() = std::unordered_map>(); + { + auto& di = dinput_handle(); + di->Release(); + di = nullptr; + } + } + void refresh(bool first) + { + if (!first) + { + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + timer_joylist.start(); + } + + enum_state st(joys(), first); + } + QMutex mtx; + Timer timer_joylist; + enum { joylist_refresh_ms = 250 }; + struct joy { LPDIRECTINPUTDEVICE8 joy_handle; @@ -140,7 +212,7 @@ struct OPENTRACK_EXPORT win32_joy_ctx joy_handle = nullptr; } } - + bool poll(fn f) { HRESULT hr; @@ -189,53 +261,6 @@ struct OPENTRACK_EXPORT win32_joy_ctx } }; - static QString 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); - } - - win32_joy_ctx() - { - refresh(true); - return; - } - - ~win32_joy_ctx() - { - release(); - } - - void release() - { - qDebug() << "release dinput handle"; - joys() = std::unordered_map>(); - { - auto& di = dinput_handle(); - di->Release(); - di = nullptr; - } - } - - void refresh(bool first) - { - if (!first) - { - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } - - enum_state st(joys(), first); - } - - enum { joy_axis_size = 65535 }; - struct enum_state { std::unordered_map>& joys; @@ -338,13 +363,8 @@ end: return DIENUM_CONTINUE; return DIENUM_CONTINUE; } }; - - static LPDIRECTINPUT8& dinput_handle(); + static std::unordered_map>& joys(); - - QMutex mtx; - Timer timer_joylist; - enum { joylist_refresh_ms = 250 }; }; #endif -- cgit v1.2.3 From 119671e4e7f4dc07c1fb20eb999a0a7fcfbbdba8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:50:46 +0100 Subject: api/shortcuts, tracker/joy: adapt to synchronized joy api --- opentrack/keybinding-worker.cpp | 2 +- opentrack/keybinding-worker.hpp | 2 +- tracker-joystick/ftnoir_tracker_joystick.cpp | 11 ++++++++++- tracker-joystick/ftnoir_tracker_joystick.h | 2 +- tracker-joystick/ftnoir_tracker_joystick_dialog.cpp | 9 +++++---- 5 files changed, 18 insertions(+), 8 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index d876d5a1..5f42f44e 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -27,7 +27,7 @@ KeybindingWorker::~KeybindingWorker() { din->Release(); } -KeybindingWorker::KeybindingWorker() : should_quit(true) +KeybindingWorker::KeybindingWorker() : joy_ctx(win32_joy_ctx::make()), should_quit(true) { if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 5a73b1b1..551be144 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -59,7 +59,7 @@ struct OPENTRACK_EXPORT KeybindingWorker : private QThread private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; - win32_joy_ctx joy_ctx; + win32_joy_ctx& joy_ctx; volatile bool should_quit; using fun = std::function; std::vector receivers; diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp index 4c180eaa..112f20ca 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -8,8 +8,17 @@ #include "opentrack/plugin-api.hpp" #include -FTNoIR_Tracker::FTNoIR_Tracker() +FTNoIR_Tracker::FTNoIR_Tracker() : joy_ctx(win32_joy_ctx::make()) { + if (static_cast(s.guid) == "") + { + std::vector info = joy_ctx.get_joy_info(); + if (info.size()) + { + s.guid = info[0].guid; + s.b->save(); + } + } } FTNoIR_Tracker::~FTNoIR_Tracker() diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 18ac349e..e94e2ee7 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -47,7 +47,7 @@ public: settings s; QString guid; static constexpr int AXIS_MAX = win32_joy_ctx::joy_axis_size - 1; - win32_joy_ctx joy_ctx; + win32_joy_ctx& joy_ctx; }; class TrackerControls: public ITrackerDialog diff --git a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp index 28846809..1ca1441c 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -10,20 +10,21 @@ TrackerControls::TrackerControls() : tracker(nullptr) connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); { - win32_joy_ctx joy_ctx; + win32_joy_ctx& joy_ctx(win32_joy_ctx::make()); _joys = QList(); - for (auto& j : joy_ctx.joys()) - _joys.push_back(joys { j.second->name, j.first }); + for (auto j : joy_ctx.get_joy_info()) + _joys.push_back(joys { j.name, j.guid }); } { + const QString guid = s.guid; int idx = 0; for (int i = 0; i < _joys.size(); i++) { const joys& j = _joys[i]; - if (j.guid == s.guid && j.name == s.joyid) + if (j.guid == guid) idx = i; ui.joylist->addItem(j.name + " " + j.guid); } -- cgit v1.2.3 From b7541ef9c3fe8e52fd6d27fe6e65d48a68acff96 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:57:51 +0100 Subject: api/shortcuts: add missing win32 delete key definition --- opentrack/win32-shortcuts.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'opentrack') diff --git a/opentrack/win32-shortcuts.cpp b/opentrack/win32-shortcuts.cpp index a0ed51b3..fb84e709 100644 --- a/opentrack/win32-shortcuts.cpp +++ b/opentrack/win32-shortcuts.cpp @@ -116,6 +116,7 @@ QList windows_key_sequences = 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), -- cgit v1.2.3 From aac65283a2b254f0338a6ad1609e5d916ba9dcfc Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 17:44:19 +0100 Subject: opentrack/joystick: rename header to clarify usage --- opentrack/keybinding-worker.hpp | 2 +- opentrack/win32-joystick-shortcuts.cpp | 30 --- opentrack/win32-joystick-shortcuts.hpp | 370 ----------------------------- opentrack/win32-joystick.cpp | 30 +++ opentrack/win32-joystick.hpp | 370 +++++++++++++++++++++++++++++ tracker-joystick/ftnoir_tracker_joystick.h | 2 +- 6 files changed, 402 insertions(+), 402 deletions(-) delete mode 100644 opentrack/win32-joystick-shortcuts.cpp delete mode 100644 opentrack/win32-joystick-shortcuts.hpp create mode 100644 opentrack/win32-joystick.cpp create mode 100644 opentrack/win32-joystick.hpp (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 551be144..8474ae1e 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -15,7 +15,7 @@ #endif #include "opentrack-compat/timer.hpp" -#include "opentrack/win32-joystick-shortcuts.hpp" +#include "opentrack/win32-joystick.hpp" #include #include #include diff --git a/opentrack/win32-joystick-shortcuts.cpp b/opentrack/win32-joystick-shortcuts.cpp deleted file mode 100644 index 61a2a74a..00000000 --- a/opentrack/win32-joystick-shortcuts.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "win32-joystick-shortcuts.hpp" - -LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() -{ - (void) CoInitialize(nullptr); - - static LPDIRECTINPUT8 dinput_handle_ = nullptr; - - if (dinput_handle_ == nullptr) - (void) DirectInput8Create(GetModuleHandle(nullptr), - DIRECTINPUT_VERSION, - IID_IDirectInput8, - (void**) &dinput_handle_, - nullptr); - - return dinput_handle_; -} - -std::unordered_map>& win32_joy_ctx::joys() -{ - static std::unordered_map> js; - - return js; -} - -win32_joy_ctx& win32_joy_ctx::make() -{ - static win32_joy_ctx ret; - return ret; -} diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp deleted file mode 100644 index ed0b4412..00000000 --- a/opentrack/win32-joystick-shortcuts.hpp +++ /dev/null @@ -1,370 +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 - -namespace std { -template<> -struct hash -{ - 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; - - void poll(fn f) - { - QMutexLocker l(&mtx); - - refresh(false); - for (auto& j : joys()) - { - j.second->poll(f); - } - } - - bool poll_axis(const QString& guid, int axes[8]) - { - QMutexLocker l(&mtx); - - refresh(false); - - auto iter = joys().find(guid); - - if (iter == joys().end() || iter->second->joy_handle == nullptr) - 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]; - - (void) joy_handle->Unacquire(); - - return true; - } - - ~win32_joy_ctx() - { - release(); - } - - enum { joy_axis_size = 65535 }; - - struct joy_info - { - QString name, guid; - }; - - std::vector 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; - } - - static win32_joy_ctx& make(); - - win32_joy_ctx(const win32_joy_ctx&) = delete; - win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; -private: - static QString 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); - } - - static LPDIRECTINPUT8& dinput_handle(); - - win32_joy_ctx() - { - refresh(true); - } - void release() - { - qDebug() << "release joystick dinput handle"; - joys() = std::unordered_map>(); - { - auto& di = dinput_handle(); - di->Release(); - di = nullptr; - } - } - - void refresh(bool first) - { - if (!first) - { - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } - - enum_state st(joys(), first); - } - QMutex mtx; - Timer timer_joylist; - enum { joylist_refresh_ms = 250 }; - - struct joy - { - LPDIRECTINPUTDEVICE8 joy_handle; - QString guid, name; - bool pressed[128]; - Timer first_timer; - bool first; - - enum { first_event_delay_ms = 3000 }; - - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) : joy_handle(handle), guid(guid), name(name), first(first) - { - qDebug() << "got joy" << guid; - for (int i = 0; i < 128; i++) - pressed[i] = false; - } - - ~joy() - { - qDebug() << "nix joy" << guid; - release(); - } - - void release() - { - if (joy_handle) - { - (void) joy_handle->Unacquire(); - joy_handle->Release(); - joy_handle = nullptr; - } - } - - bool poll(fn f) - { - HRESULT hr; - bool ok = false; - - if (joy_handle == nullptr) - return false; - - (void) joy_handle->Acquire(); - - if (!FAILED(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; - } - - (void) joy_handle->Unacquire(); - - first |= first_timer.elapsed_ms() > first_event_delay_ms; - - for (int i = 0; i < 128; i++) - { - const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i] && first) - { - f(guid, i, state); - qDebug() << "btn" << guid << i << state; - } - pressed[i] = state; - } - - return true; - } - }; - - struct enum_state - { - std::unordered_map>& joys; - std::vector all; - bool first; - - enum_state(std::unordered_map>& joys, bool first) : joys(joys), first(first) - { - HRESULT hr; - LPDIRECTINPUT8 di = dinput_handle(); - - 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++; - } - } - - static BOOL CALLBACK 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() && it->second->joy_handle != nullptr; - - state.all.push_back(guid); - - if (!exists) - { - HRESULT hr; - LPDIRECTINPUTDEVICE8 h; - LPDIRECTINPUT8 di = dinput_handle(); - if (FAILED(hr = 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) GetDesktopWindow(), 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, state.first); - } - -end: return DIENUM_CONTINUE; - } - - static BOOL CALLBACK 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; - } - }; - - static std::unordered_map>& joys(); -}; - -#endif diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp new file mode 100644 index 00000000..b4a1f9cd --- /dev/null +++ b/opentrack/win32-joystick.cpp @@ -0,0 +1,30 @@ +#include "win32-joystick.hpp" + +LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() +{ + (void) CoInitialize(nullptr); + + static LPDIRECTINPUT8 dinput_handle_ = nullptr; + + if (dinput_handle_ == nullptr) + (void) DirectInput8Create(GetModuleHandle(nullptr), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (void**) &dinput_handle_, + nullptr); + + return dinput_handle_; +} + +std::unordered_map>& win32_joy_ctx::joys() +{ + static std::unordered_map> js; + + return js; +} + +win32_joy_ctx& win32_joy_ctx::make() +{ + static win32_joy_ctx ret; + return ret; +} diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp new file mode 100644 index 00000000..ed0b4412 --- /dev/null +++ b/opentrack/win32-joystick.hpp @@ -0,0 +1,370 @@ +#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 + +namespace std { +template<> +struct hash +{ + 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; + + void poll(fn f) + { + QMutexLocker l(&mtx); + + refresh(false); + for (auto& j : joys()) + { + j.second->poll(f); + } + } + + bool poll_axis(const QString& guid, int axes[8]) + { + QMutexLocker l(&mtx); + + refresh(false); + + auto iter = joys().find(guid); + + if (iter == joys().end() || iter->second->joy_handle == nullptr) + 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]; + + (void) joy_handle->Unacquire(); + + return true; + } + + ~win32_joy_ctx() + { + release(); + } + + enum { joy_axis_size = 65535 }; + + struct joy_info + { + QString name, guid; + }; + + std::vector 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; + } + + static win32_joy_ctx& make(); + + win32_joy_ctx(const win32_joy_ctx&) = delete; + win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; +private: + static QString 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); + } + + static LPDIRECTINPUT8& dinput_handle(); + + win32_joy_ctx() + { + refresh(true); + } + void release() + { + qDebug() << "release joystick dinput handle"; + joys() = std::unordered_map>(); + { + auto& di = dinput_handle(); + di->Release(); + di = nullptr; + } + } + + void refresh(bool first) + { + if (!first) + { + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + timer_joylist.start(); + } + + enum_state st(joys(), first); + } + QMutex mtx; + Timer timer_joylist; + enum { joylist_refresh_ms = 250 }; + + struct joy + { + LPDIRECTINPUTDEVICE8 joy_handle; + QString guid, name; + bool pressed[128]; + Timer first_timer; + bool first; + + enum { first_event_delay_ms = 3000 }; + + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) : joy_handle(handle), guid(guid), name(name), first(first) + { + qDebug() << "got joy" << guid; + for (int i = 0; i < 128; i++) + pressed[i] = false; + } + + ~joy() + { + qDebug() << "nix joy" << guid; + release(); + } + + void release() + { + if (joy_handle) + { + (void) joy_handle->Unacquire(); + joy_handle->Release(); + joy_handle = nullptr; + } + } + + bool poll(fn f) + { + HRESULT hr; + bool ok = false; + + if (joy_handle == nullptr) + return false; + + (void) joy_handle->Acquire(); + + if (!FAILED(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; + } + + (void) joy_handle->Unacquire(); + + first |= first_timer.elapsed_ms() > first_event_delay_ms; + + for (int i = 0; i < 128; i++) + { + const bool state = !!(js.rgbButtons[i] & 0x80); + if (state != pressed[i] && first) + { + f(guid, i, state); + qDebug() << "btn" << guid << i << state; + } + pressed[i] = state; + } + + return true; + } + }; + + struct enum_state + { + std::unordered_map>& joys; + std::vector all; + bool first; + + enum_state(std::unordered_map>& joys, bool first) : joys(joys), first(first) + { + HRESULT hr; + LPDIRECTINPUT8 di = dinput_handle(); + + 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++; + } + } + + static BOOL CALLBACK 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() && it->second->joy_handle != nullptr; + + state.all.push_back(guid); + + if (!exists) + { + HRESULT hr; + LPDIRECTINPUTDEVICE8 h; + LPDIRECTINPUT8 di = dinput_handle(); + if (FAILED(hr = 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) GetDesktopWindow(), 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, state.first); + } + +end: return DIENUM_CONTINUE; + } + + static BOOL CALLBACK 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; + } + }; + + static std::unordered_map>& joys(); +}; + +#endif diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 67061585..9923dd1c 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-shortcuts.hpp" +#include "opentrack/win32-joystick.hpp" #include "opentrack-compat/options.hpp" using namespace options; -- cgit v1.2.3 From 0c3a306b8588ae1cbe190ee18db2336bcd0eb527 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 17:46:46 +0100 Subject: api/shortcuts: hopefully guard joystick _WIN32 --- opentrack/keybinding-worker.cpp | 8 +++++++- opentrack/keybinding-worker.hpp | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 5f42f44e..3659a768 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -27,7 +27,11 @@ KeybindingWorker::~KeybindingWorker() { din->Release(); } -KeybindingWorker::KeybindingWorker() : joy_ctx(win32_joy_ctx::make()), should_quit(true) +KeybindingWorker::KeybindingWorker() : +#ifdef _WIN32 + joy_ctx(win32_joy_ctx::make()), +#endif + should_quit(true) { if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); @@ -94,6 +98,7 @@ void KeybindingWorker::run() { } } +#ifdef _WIN32 { using joy_fn = std::function; @@ -112,6 +117,7 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } +#endif for (int i = 0; i < 256; i++) { diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 8474ae1e..c4a39ec6 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -15,7 +15,9 @@ #endif #include "opentrack-compat/timer.hpp" -#include "opentrack/win32-joystick.hpp" +#ifdef _WIN32 +# include "opentrack/win32-joystick.hpp" +#endif #include #include #include @@ -59,7 +61,9 @@ struct OPENTRACK_EXPORT KeybindingWorker : private QThread private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; +#ifdef _WIN32 win32_joy_ctx& joy_ctx; +#endif volatile bool should_quit; using fun = std::function; std::vector receivers; -- cgit v1.2.3 From 5d4a9c78fbbbd59d366e91bfe4c4263d12833abe Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 18:01:06 +0100 Subject: api/joy: guard _WIN32 properly --- opentrack/keybinding-worker.hpp | 10 ++++++---- opentrack/shortcuts.h | 5 ++++- opentrack/win32-joystick.cpp | 4 ++++ 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index c4a39ec6..83ffadf1 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -59,19 +59,18 @@ struct Key { int foo; }; struct OPENTRACK_EXPORT KeybindingWorker : private QThread { private: +#ifdef _WIN32 LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; -#ifdef _WIN32 win32_joy_ctx& joy_ctx; -#endif volatile bool should_quit; using fun = std::function; std::vector receivers; QMutex mtx; - + void run() override; KeybindingWorker(); - + KeybindingWorker(const KeybindingWorker&) = delete; KeybindingWorker& operator=(KeybindingWorker&) = delete; static KeybindingWorker& make(); @@ -100,4 +99,7 @@ public: { return Token(receiver); } +#else + void run() override {} +#endif }; diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 930952e8..8acc5ba5 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -66,7 +66,10 @@ public: {} } s; - Shortcuts() : key_token(KeybindingWorker::add_receiver([&](const Key& k) { receiver(k); })) + Shortcuts() +#ifdef _WIN32 + : key_token(KeybindingWorker::add_receiver([&](const Key& k) { receiver(k); })) +#endif { reload(); } diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index b4a1f9cd..56a1b070 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -1,5 +1,7 @@ #include "win32-joystick.hpp" +#ifdef _WIN32 + LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() { (void) CoInitialize(nullptr); @@ -28,3 +30,5 @@ win32_joy_ctx& win32_joy_ctx::make() static win32_joy_ctx ret; return ret; } + +#endif -- cgit v1.2.3 From e2ea45a81d5f30fdbd42e0b03a192afa81e877dc Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 18:05:04 +0100 Subject: api/shortcuts: don't provide guard/stubs for non-win32 The worker class is win32-only. Don't guard there, consumers are expected only to include it on _WIN32. For the same reason don't provide a stub for the keybinding worker. --- opentrack/keybinding-worker.cpp | 29 ++++++++++++++--------------- opentrack/keybinding-worker.hpp | 20 +++++--------------- 2 files changed, 19 insertions(+), 30 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 3659a768..dcf5c1b6 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -6,10 +6,9 @@ * notice appear in all copies. */ -#include "keybinding-worker.hpp" - -#if defined(_WIN32) +#ifdef _WIN32 +#include "keybinding-worker.hpp" #include #include #include @@ -29,7 +28,7 @@ KeybindingWorker::~KeybindingWorker() { KeybindingWorker::KeybindingWorker() : #ifdef _WIN32 - joy_ctx(win32_joy_ctx::make()), + joy_ctx(win32_joy_ctx::make()), #endif should_quit(true) { @@ -85,23 +84,23 @@ void KeybindingWorker::run() { { { 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; } } - + #ifdef _WIN32 { using joy_fn = std::function; - + joy_fn f = [&](const QString& guid, int idx, bool held) -> void { Key k; k.keycode = idx; @@ -110,15 +109,15 @@ void KeybindingWorker::run() { k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); k.guid = guid; k.held = held; - + for (auto& r : receivers) r(k); }; - + joy_ctx.poll(f); } #endif - + for (int i = 0; i < 256; i++) { Key k; @@ -138,7 +137,7 @@ void KeybindingWorker::run() { k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); k.keycode = i; - + for (auto& r : receivers) r(k); break; @@ -147,7 +146,7 @@ void KeybindingWorker::run() { } } } - + // keypresses get dropped with high values Sleep(4); } @@ -165,7 +164,7 @@ 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] == pos) @@ -181,4 +180,4 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) } } -#endif \ No newline at end of file +#endif diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 83ffadf1..e3967682 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -15,20 +15,17 @@ #endif #include "opentrack-compat/timer.hpp" -#ifdef _WIN32 -# include "opentrack/win32-joystick.hpp" -#endif +#include "opentrack/win32-joystick.hpp" #include #include #include #include #include -#ifdef _WIN32 -# undef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x0800 -# include -# include +#undef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION 0x0800 +#include +#include struct Key { BYTE keycode; QString guid; @@ -51,15 +48,10 @@ public: return ret; } }; -#else -typedef unsigned char BYTE; -struct Key { int foo; }; -#endif struct OPENTRACK_EXPORT KeybindingWorker : private QThread { private: -#ifdef _WIN32 LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; win32_joy_ctx& joy_ctx; @@ -99,7 +91,5 @@ public: { return Token(receiver); } -#else void run() override {} -#endif }; -- cgit v1.2.3 From c72948a8fcec675f5ddb059d6ad5e5d6c10f0691 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 18:46:34 +0100 Subject: api/shortcuts: fix copy-paste error --- opentrack/keybinding-worker.hpp | 1 - 1 file changed, 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index e3967682..7661f88d 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -91,5 +91,4 @@ public: { return Token(receiver); } - void run() override {} }; -- cgit v1.2.3 From f09ff290addc66f2256534641f1dc91318da47c3 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Tue, 24 Nov 2015 01:03:55 +0100 Subject: api/shortcuts: don't unacquire joy handle pointlessly --- opentrack/win32-joystick.hpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index ed0b4412..b08da6c8 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -103,8 +103,6 @@ struct OPENTRACK_EXPORT win32_joy_ctx for (int i = 0; i < 8; i++) axes[i] = values[i]; - (void) joy_handle->Unacquire(); - return true; } @@ -242,8 +240,6 @@ private: return false; } - (void) joy_handle->Unacquire(); - first |= first_timer.elapsed_ms() > first_event_delay_ms; for (int i = 0; i < 128; i++) -- cgit v1.2.3 From 3566dc23946b798b396946297cbf70f2d46fd242 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 26 Nov 2015 09:04:29 +0100 Subject: api/shortcuts: move to separate definition There's no need to have definitions in header for non-template classes --- opentrack/keybinding-worker.cpp | 10 ++ opentrack/keybinding-worker.hpp | 13 +- opentrack/win32-joystick.cpp | 275 +++++++++++++++++++++++++++++++++++ opentrack/win32-joystick.hpp | 308 ++++------------------------------------ 4 files changed, 315 insertions(+), 291 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index dcf5c1b6..59bc4afd 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -14,6 +14,15 @@ #include #include +bool Key::should_process() +{ + if (keycode == 0 && guid == "") + return false; + bool ret = timer.elapsed_ms() > 100; + timer.start(); + return ret; +} + KeybindingWorker::~KeybindingWorker() { qDebug() << "keybinding worker stop"; should_quit = true; @@ -172,6 +181,7 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) ok = true; qDebug() << "remove receiver" << (long) pos; receivers.erase(receivers.begin() + i); + break; } } if (!ok) diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 7661f88d..054182e7 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -35,18 +35,9 @@ struct Key { bool held; Timer timer; public: - Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) - { - } + Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) {} - bool should_process() - { - if (keycode == 0 && guid == "") - return false; - bool ret = timer.elapsed_ms() > 100; - timer.start(); - return ret; - } + bool should_process(); }; struct OPENTRACK_EXPORT KeybindingWorker : private QThread diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 56a1b070..29a51a43 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -31,4 +31,279 @@ win32_joy_ctx& win32_joy_ctx::make() return ret; } +void win32_joy_ctx::poll(fn f) +{ + QMutexLocker l(&mtx); + + refresh(false); + for (auto& j : joys()) + { + j.second->poll(f); + } +} + +bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) +{ + QMutexLocker l(&mtx); + + refresh(false); + + auto iter = joys().find(guid); + + if (iter == joys().end() || iter->second->joy_handle == nullptr) + 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() +{ + refresh(true); +} + +void win32_joy_ctx::release() +{ + qDebug() << "release joystick dinput handle"; + joys() = std::unordered_map>(); + { + auto& di = dinput_handle(); + di->Release(); + di = nullptr; + } +} + +void win32_joy_ctx::refresh(bool first) +{ + if (!first) + { + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + timer_joylist.start(); + } + + enum_state st(joys(), first); +} + +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; + + if (joy_handle == nullptr) + return false; + + (void) joy_handle->Acquire(); + + if (!FAILED(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; + } + + first |= first_timer.elapsed_ms() > first_event_delay_ms; + + for (int i = 0; i < 128; i++) + { + const bool state = !!(js.rgbButtons[i] & 0x80); + if (state != pressed[i] && first) + { + f(guid, i, state); + qDebug() << "btn" << guid << i << state; + } + pressed[i] = state; + } + + return true; +} + +win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first) : joys(joys), first(first) +{ + HRESULT hr; + LPDIRECTINPUT8 di = dinput_handle(); + + 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++; + } +} + +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() && it->second->joy_handle != nullptr; + + state.all.push_back(guid); + + if (!exists) + { + HRESULT hr; + LPDIRECTINPUTDEVICE8 h; + LPDIRECTINPUT8 di = dinput_handle(); + if (FAILED(hr = 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) GetDesktopWindow(), 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, state.first); + } +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; +} + #endif diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index b08da6c8..334b617a 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -39,77 +39,6 @@ struct hash struct OPENTRACK_EXPORT win32_joy_ctx { using fn = std::function; - - void poll(fn f) - { - QMutexLocker l(&mtx); - - refresh(false); - for (auto& j : joys()) - { - j.second->poll(f); - } - } - - bool poll_axis(const QString& guid, int axes[8]) - { - QMutexLocker l(&mtx); - - refresh(false); - - auto iter = joys().find(guid); - - if (iter == joys().end() || iter->second->joy_handle == nullptr) - 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() - { - release(); - } enum { joy_axis_size = 65535 }; @@ -117,78 +46,42 @@ struct OPENTRACK_EXPORT win32_joy_ctx { QString name, guid; }; - - std::vector 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; - } + void poll(fn f); + bool poll_axis(const QString& guid, int axes[8]); + ~win32_joy_ctx(); + std::vector get_joy_info(); static win32_joy_ctx& make(); - win32_joy_ctx(const win32_joy_ctx&) = delete; win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; -private: - static QString 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); - } - static LPDIRECTINPUT8& dinput_handle(); +private: + enum { joylist_refresh_ms = 250 }; - win32_joy_ctx() - { - refresh(true); - } - void release() - { - qDebug() << "release joystick dinput handle"; - joys() = std::unordered_map>(); - { - auto& di = dinput_handle(); - di->Release(); - di = nullptr; - } - } - - void refresh(bool first) - { - if (!first) - { - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } - - enum_state st(joys(), first); - } QMutex mtx; Timer timer_joylist; - enum { joylist_refresh_ms = 250 }; + + static QString guid_to_string(const GUID guid); + static LPDIRECTINPUT8& dinput_handle(); + win32_joy_ctx(); + void release(); + void refresh(bool first); + + struct joy; + static std::unordered_map>& joys(); struct joy { + enum { first_event_delay_ms = 3000 }; + LPDIRECTINPUTDEVICE8 joy_handle; QString guid, name; bool pressed[128]; Timer first_timer; bool first; - - enum { first_event_delay_ms = 3000 }; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) : joy_handle(handle), guid(guid), name(name), first(first) + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) + : joy_handle(handle), guid(guid), name(name), first(first) { qDebug() << "got joy" << guid; for (int i = 0; i < 128; i++) @@ -201,166 +94,21 @@ private: release(); } - void release() - { - if (joy_handle) - { - (void) joy_handle->Unacquire(); - joy_handle->Release(); - joy_handle = nullptr; - } - } - - bool poll(fn f) - { - HRESULT hr; - bool ok = false; - - if (joy_handle == nullptr) - return false; - - (void) joy_handle->Acquire(); - - if (!FAILED(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; - } - - first |= first_timer.elapsed_ms() > first_event_delay_ms; - - for (int i = 0; i < 128; i++) - { - const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i] && first) - { - f(guid, i, state); - qDebug() << "btn" << guid << i << state; - } - pressed[i] = state; - } - - return true; - } + void release(); + bool poll(fn f); }; - struct enum_state + class enum_state { std::unordered_map>& joys; - std::vector all; bool first; - - enum_state(std::unordered_map>& joys, bool first) : joys(joys), first(first) - { - HRESULT hr; - LPDIRECTINPUT8 di = dinput_handle(); - - 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++; - } - } - - static BOOL CALLBACK 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() && it->second->joy_handle != nullptr; - - state.all.push_back(guid); - - if (!exists) - { - HRESULT hr; - LPDIRECTINPUTDEVICE8 h; - LPDIRECTINPUT8 di = dinput_handle(); - if (FAILED(hr = 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) GetDesktopWindow(), 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, state.first); - } - -end: return DIENUM_CONTINUE; - } - - static BOOL CALLBACK 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; - } + + 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, bool first); }; - - static std::unordered_map>& joys(); }; #endif -- cgit v1.2.3 From bb605f416f9dd5e89150e8937d17c6647fcfe346 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 26 Nov 2015 09:09:43 +0100 Subject: api/shortcuts: remove pointless "friend" declarations --- opentrack/keybinding-worker.hpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 054182e7..5b669331 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -63,7 +63,6 @@ private: public: class Token { - friend class KeybindingWorker; fun* pos; //Token(const Token&) = delete; Token& operator=(Token&) = delete; @@ -77,7 +76,6 @@ public: make().remove_receiver(pos); } }; - friend class Token; static Token add_receiver(fun receiver) { return Token(receiver); -- cgit v1.2.3 From edb0e01947f67142c00c3f75a62df7af708cdf11 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 11:58:20 +0100 Subject: api/joystick: reduce mutex contention Don't look for changes in hotplug joysticks by freezing up polling for joysticks' axis and button. Issue: #267 --- opentrack/win32-joystick.cpp | 21 ++++++++++++++++----- opentrack/win32-joystick.hpp | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 29a51a43..0bd6bfda 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -33,9 +33,10 @@ win32_joy_ctx& win32_joy_ctx::make() void win32_joy_ctx::poll(fn f) { + refresh(false); + QMutexLocker l(&mtx); - refresh(false); for (auto& j : joys()) { j.second->poll(f); @@ -44,10 +45,10 @@ void win32_joy_ctx::poll(fn f) bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) { - QMutexLocker l(&mtx); - refresh(false); + QMutexLocker l(&mtx); + auto iter = joys().find(guid); if (iter == joys().end() || iter->second->joy_handle == nullptr) @@ -134,12 +135,14 @@ void win32_joy_ctx::refresh(bool first) { if (!first) { + QMutexLocker l(&mtx); + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) return; timer_joylist.start(); } - enum_state st(joys(), first); + enum_state st(joys(), first, mtx); } QString win32_joy_ctx::guid_to_string(const GUID guid) @@ -210,11 +213,16 @@ bool win32_joy_ctx::joy::poll(fn f) return true; } -win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first) : joys(joys), first(first) +win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first, QMutex& mtx) : first(first) { HRESULT hr; LPDIRECTINPUT8 di = dinput_handle(); + { + QMutexLocker l(&mtx); + this->joys = joys; + } + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, @@ -231,6 +239,9 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys; } win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 334b617a..3f47d170 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -100,14 +100,14 @@ private: class enum_state { - std::unordered_map>& joys; + std::unordered_map> joys; bool first; 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, bool first); + enum_state(std::unordered_map>& joys, bool first, QMutex &mtx); }; }; -- cgit v1.2.3 From c03c6f2bdb6a4f236c22a916753d4aa9728085fa Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 12:34:05 +0100 Subject: api/joystick: oops, access the right 'joys' variable --- opentrack/win32-joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 0bd6bfda..a705adbc 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -232,7 +232,7 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys.begin(); it != this->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); -- cgit v1.2.3 From a07eed2a0de09224adb1381d7744a2f98857836e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 12:34:19 +0100 Subject: api/joystick: drop locking, add comment --- opentrack/win32-joystick.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index a705adbc..6e64355c 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -135,8 +135,8 @@ void win32_joy_ctx::refresh(bool first) { if (!first) { - QMutexLocker l(&mtx); - + // accessing struct Timer without a lock. worst can happen is seconds + // and nanoseconds getting out of sync. no big deal. if (timer_joylist.elapsed_ms() < joylist_refresh_ms) return; timer_joylist.start(); -- cgit v1.2.3 From dd67c2971d4f41267d4d08ebd8c5aefdb675c6e5 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:27:01 +0100 Subject: api/joy: fix race erase from iterator referenced the wrong 'joys' variable --- opentrack/win32-joystick.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 6e64355c..0f8a08f8 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -222,7 +222,7 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys = joys; } - + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, @@ -232,10 +232,12 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys.begin(); it != this->joys.end(); ) + auto& js = this->joys; + + for (auto it = js.begin(); it != js.end(); ) { if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) - it = joys.erase(it); + it = js.erase(it); else it++; } -- cgit v1.2.3 From 22d4c7cc0cadf212052ef72c3bf8ddda6f73a647 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:31:57 +0100 Subject: api, compat: clean up verbose fprintf logspam --- opentrack-compat/shm.cpp | 1 - opentrack/keybinding-worker.cpp | 1 - opentrack/win32-joystick.cpp | 1 - 3 files changed, 3 deletions(-) (limited to 'opentrack') diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index fffb3709..a306d581 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -92,7 +92,6 @@ struct secattr attrs.lpSecurityDescriptor = pSD; attrs.nLength = sizeof(SECURITY_ATTRIBUTES); - fprintf(stderr, "security descriptor ok\n"); fflush(stderr); return; diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 59bc4afd..3c801cf2 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -24,7 +24,6 @@ bool Key::should_process() } KeybindingWorker::~KeybindingWorker() { - qDebug() << "keybinding worker stop"; should_quit = true; wait(); if (dinkeyboard) { diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 0f8a08f8..cd3502b4 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -122,7 +122,6 @@ win32_joy_ctx::win32_joy_ctx() void win32_joy_ctx::release() { - qDebug() << "release joystick dinput handle"; joys() = std::unordered_map>(); { auto& di = dinput_handle(); -- cgit v1.2.3 From fc9d0a76f47e97f2bdd35edc24695c95654a2a67 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:32:44 +0100 Subject: api/joy: there's no joy_handle == nullptr case, don't check for it --- opentrack/win32-joystick.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index cd3502b4..1c658c75 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -51,7 +51,7 @@ bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) auto iter = joys().find(guid); - if (iter == joys().end() || iter->second->joy_handle == nullptr) + if (iter == joys().end()) return false; auto& j = iter->second; @@ -172,9 +172,6 @@ bool win32_joy_ctx::joy::poll(fn f) HRESULT hr; bool ok = false; - if (joy_handle == nullptr) - return false; - (void) joy_handle->Acquire(); if (!FAILED(joy_handle->Poll())) @@ -252,7 +249,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns const QString name = QString(pdidInstance->tszInstanceName); auto it = state.joys.find(guid); - const bool exists = it != state.joys.end() && it->second->joy_handle != nullptr; + const bool exists = it != state.joys.end(); state.all.push_back(guid); -- cgit v1.2.3 From 3ac3eb2b4874782bac4aeac14cc39e63c1188acd Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:45:02 +0100 Subject: api/joystick: refresh more often, it's cheap enough cpu-wise --- opentrack/win32-joystick.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 3f47d170..421774a9 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -56,7 +56,7 @@ struct OPENTRACK_EXPORT win32_joy_ctx win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; private: - enum { joylist_refresh_ms = 250 }; + enum { joylist_refresh_ms = 100 }; QMutex mtx; Timer timer_joylist; -- cgit v1.2.3 From 578749c5b7f245aac08c4e514d2767dba059c4db Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 5 Dec 2015 23:30:43 +0100 Subject: api/keys: fix multiple shortcut receivers We can't depend on std::vector's address of array subscript to remain constant, duh. --- opentrack/keybinding-worker.cpp | 15 ++++++++------- opentrack/keybinding-worker.hpp | 20 ++++++++------------ 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 3c801cf2..9ff825a0 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -119,7 +119,7 @@ void KeybindingWorker::run() { k.held = held; for (auto& r : receivers) - r(k); + r->operator()(k); }; joy_ctx.poll(f); @@ -147,7 +147,7 @@ void KeybindingWorker::run() { k.keycode = i; for (auto& r : receivers) - r(k); + r->operator()(k); break; } } @@ -160,12 +160,13 @@ void KeybindingWorker::run() { } } -KeybindingWorker::fun* KeybindingWorker::_add_receiver(KeybindingWorker::fun receiver) +KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) { QMutexLocker l(&mtx); - receivers.push_back(receiver); - qDebug() << "add receiver" << (long) &receivers[receivers.size()-1]; - return &receivers[receivers.size()-1]; + receivers.push_back(std::unique_ptr(new fun(receiver))); + fun* f = receivers[receivers.size() - 1].get(); + qDebug() << "add receiver" << (long) f; + return f; } void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) @@ -175,7 +176,7 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) for (int i = receivers.size() - 1; i >= 0; i--) { - if (&receivers[i] == pos) + if (receivers[i].get() == pos) { ok = true; qDebug() << "remove receiver" << (long) pos; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 5b669331..c8d8e009 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -47,8 +47,8 @@ private: LPDIRECTINPUTDEVICE8 dinkeyboard; win32_joy_ctx& joy_ctx; volatile bool should_quit; - using fun = std::function; - std::vector receivers; + using fun = std::function; + std::vector> receivers; QMutex mtx; void run() override; @@ -57,27 +57,23 @@ private: KeybindingWorker(const KeybindingWorker&) = delete; KeybindingWorker& operator=(KeybindingWorker&) = delete; static KeybindingWorker& make(); - fun* _add_receiver(fun receiver); + fun* _add_receiver(fun &receiver); void remove_receiver(fun* pos); ~KeybindingWorker(); public: class Token { fun* pos; - //Token(const Token&) = delete; + Token(const Token&) = delete; Token& operator=(Token&) = delete; public: - Token(fun receiver) - { - pos = make()._add_receiver(receiver); - } ~Token() { make().remove_receiver(pos); } + Token(fun receiver) + { + pos = make()._add_receiver(receiver); + } }; - static Token add_receiver(fun receiver) - { - return Token(receiver); - } }; -- cgit v1.2.3 From 86708a2311c1a3efd975798ff42d934eea0078ed Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 5 Dec 2015 23:32:43 +0100 Subject: api/shortcuts: no longer keep shortcuts hardcoded --- gui/options-dialog.cpp | 3 +++ gui/ui.cpp | 23 +---------------------- gui/ui.h | 4 ---- opentrack/shortcuts.cpp | 48 +++++++++++++++++++++++++++++------------------- opentrack/shortcuts.h | 34 +++++++++++++++++----------------- opentrack/tracker.h | 6 +++--- opentrack/work.hpp | 32 ++++++++++++++++++-------------- 7 files changed, 71 insertions(+), 79 deletions(-) (limited to 'opentrack') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 9631d41e..70d5be62 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -73,6 +73,9 @@ OptionsDialog::OptionsDialog() connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center, ui.center_text); }); connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero, ui.zero_text); }); connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle, ui.toggle_text); }); + connect(ui.bind_start, &QPushButton::pressed, [&]() -> void { bind_key(s.start_tracking, ui.start_tracking_text); }); + connect(ui.bind_stop, &QPushButton::pressed, [&]() -> void { bind_key(s.stop_tracking, ui.stop_tracking_text); }); + connect(ui.bind_toggle_tracking, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle_tracking, ui.toggle_tracking_text); }); ui.center_text->setText(kopts_to_string(s.center)); ui.toggle_text->setText(kopts_to_string(s.toggle)); diff --git a/gui/ui.cpp b/gui/ui.cpp index fc6d4754..c3e47912 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -281,7 +281,7 @@ void MainWindow::startTracker() { return; } - work = std::make_shared(s, pose, libs, this, winId()); + work = std::make_shared(s, pose, libs, winId()); reload_options(); @@ -489,27 +489,6 @@ void MainWindow::profileSelected(QString name) } } -void MainWindow::shortcutRecentered() -{ - qDebug() << "Center"; - if (work) - work->tracker->center(); -} - -void MainWindow::shortcutToggled() -{ - qDebug() << "Toggle"; - if (work) - work->tracker->toggle_enabled(); -} - -void MainWindow::shortcutZeroed() -{ - qDebug() << "Zero"; - if (work) - work->tracker->zero(); -} - void MainWindow::ensure_tray() { if (tray) diff --git a/gui/ui.h b/gui/ui.h index 44bcde0c..b4bab271 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -100,10 +100,6 @@ private slots: void startTracker(); void stopTracker(); void reload_options(); -public slots: - void shortcutRecentered(); - void shortcutToggled(); - void shortcutZeroed(); public: MainWindow(); ~MainWindow(); diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index b961294f..560a31ab 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -9,7 +9,7 @@ #include "shortcuts.h" #include "win32-shortcuts.h" -void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) +void Shortcuts::bind_keyboard_shortcut(K &key, const key_opts& k) { #if !defined(_WIN32) using sh = QxtGlobalShortcut; @@ -63,33 +63,43 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) #ifdef _WIN32 void Shortcuts::receiver(const Key& k) { - std::vector ks { &keyCenter, &keyToggle, &keyZero }; - for (K* k_ : ks) + const int sz = keys.size(); + for (int i = 0; i < sz; i++) { - if (k.guid != k_->guid) + 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) + if (k.keycode != k_.keycode) continue; if (!k.held) continue; - if (!k_->should_process()) + if (!k_.should_process()) continue; - if (k_->alt && !k.alt) continue; - if (k_->ctrl && !k.ctrl) continue; - if (k_->shift && !k.shift) continue; + if (k_.alt && !k.alt) continue; + if (k_.ctrl && !k.ctrl) continue; + if (k_.shift && !k.shift) continue; - if (k_ == &keyCenter) - emit center(); - else if (k_ == &keyToggle) - emit toggle(); - else if (k_ == &keyZero) - emit zero(); + fun(); } } #endif -void Shortcuts::reload() { - bind_keyboard_shortcut(keyCenter, s.center); - bind_keyboard_shortcut(keyToggle, s.toggle); - bind_keyboard_shortcut(keyZero, s.zero); +void Shortcuts::reload(const std::vector > &keys_) +{ + const int sz = keys_.size(); + keys = std::vector(); + + for (int i = 0; i < sz; i++) + { + const auto& kk = keys_[i]; + const key_opts& opts = std::get<0>(kk); + auto& fun = std::get<1>(kk); + K k; + bind_keyboard_shortcut(k, opts); + keys.push_back(std::tuple(k, fun)); +#ifndef _WIN32 + connect(k.get(), &QGlobalShortcut::activated, fun); +#endif + } } diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 8acc5ba5..4dec7c2c 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -8,6 +8,9 @@ #pragma once #include +#include +#include +#include #ifdef BUILD_api # include "opentrack-compat/export.hpp" @@ -36,10 +39,10 @@ public: Key #endif ; - - K keyCenter; - K keyToggle; - K keyZero; + + using fun = std::function; + using tt = std::tuple; + std::vector keys; #ifdef _WIN32 KeybindingWorker::Token key_token; #endif @@ -56,32 +59,29 @@ public: }; struct settings : opts { - key_opts center, toggle, zero; + key_opts center, toggle, zero, start_tracking, stop_tracking, toggle_tracking; main_settings s_main; settings() : opts("keyboard-shortcuts"), center(b, "center"), toggle(b, "toggle"), - zero(b, "zero") + zero(b, "zero"), + start_tracking(b, "start-tracking"), + stop_tracking(b, "stop-tracking"), + toggle_tracking(b, "toggle-tracking") {} } s; - Shortcuts() + Shortcuts() : #ifdef _WIN32 - : key_token(KeybindingWorker::add_receiver([&](const Key& k) { receiver(k); })) + key_token([&](const Key& k) { receiver(k); }) #endif - { - reload(); - } + {} - void reload(); + void reload(const std::vector > &keys); private: - void bind_keyboard_shortcut(K &key, key_opts& k); + void bind_keyboard_shortcut(K &key, const key_opts& k); #ifdef _WIN32 void receiver(const Key& k); #endif -signals: - void center(); - void toggle(); - void zero(); }; diff --git a/opentrack/tracker.h b/opentrack/tracker.h index e26c3f7a..36b5cad4 100644 --- a/opentrack/tracker.h +++ b/opentrack/tracker.h @@ -80,7 +80,7 @@ public: void get_raw_and_mapped_poses(double* mapped, double* raw) const; void start() { QThread::start(); } - void toggle_enabled() { enabledp = !enabledp; } - void center() { centerp = !centerp; } - void zero() { zero_ = !zero_; } + void toggle_enabled() { qDebug() << "toggle enabled"; enabledp = !enabledp; } + void center() { qDebug() << "toggle center"; centerp = !centerp; } + void zero() { qDebug() << "toggle zero"; zero_ = !zero_; } }; diff --git a/opentrack/work.hpp b/opentrack/work.hpp index e338e9f4..a3c0e014 100644 --- a/opentrack/work.hpp +++ b/opentrack/work.hpp @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include struct Work { @@ -24,28 +27,29 @@ struct Work mem tracker; mem sc; WId handle; - - Work(main_settings& s, Mappings& m, SelectedLibraries& libs, QObject* recv, WId handle) : + using fn = std::function; + using key_opts = Shortcuts::key_opts; + 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) + handle(handle), + keys { + tt(sc->s.center, [&]() -> void { tracker->center(); }), + tt(sc->s.toggle, [&]() -> void { tracker->toggle_enabled(); }), + tt(sc->s.zero, [&]() -> void { tracker->zero(); }), + } { -#ifndef _WIN32 - QObject::connect(sc->keyCenter.get(), SIGNAL(activated()), recv, SLOT(shortcutRecentered())); - QObject::connect(sc->keyToggle.get(), SIGNAL(activated()), recv, SLOT(shortcutToggled())); - QObject::connect(sc->keyZero.get(), SIGNAL(activated()), recv, SLOT(shortcutZeroed())); -#else - QObject::connect(sc.get(), SIGNAL(center()), recv, SLOT(shortcutRecentered())); - QObject::connect(sc.get(), SIGNAL(toggle()), recv, SLOT(shortcutToggled())); - QObject::connect(sc.get(), SIGNAL(zero()), recv, SLOT(shortcutZeroed())); -#endif - tracker->start(); + reload_shortcuts(); + tracker->start(); } void reload_shortcuts() { - sc->reload(); + sc->reload(keys); } ~Work() -- cgit v1.2.3 From 52b75a02aeeaf2c23f5af32fededf4e5fb24bade Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 00:43:58 +0100 Subject: api, main: implement global shortcuts for controlling tracking Issue: #252 That involves moving stuff around to get rid of circular dependencies. You need to bind keys to shortcuts again this once. --- gui/options-dialog.cpp | 100 +++++++++++++++++++++++--------------------- gui/options-dialog.hpp | 12 +++--- gui/ui.cpp | 50 +++++++++++++++++++--- gui/ui.h | 10 +++++ opentrack/main-settings.hpp | 26 ++++++++++-- opentrack/shortcuts.h | 27 +----------- opentrack/work.hpp | 7 ++-- 7 files changed, 140 insertions(+), 92 deletions(-) (limited to 'opentrack') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 70d5be62..1edf069d 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -12,7 +12,7 @@ #include #include -static QString kopts_to_string(const Shortcuts::key_opts& kopts) +static QString kopts_to_string(const key_opts& kopts) { if (static_cast(kopts.guid) != "") { @@ -29,60 +29,65 @@ static QString kopts_to_string(const Shortcuts::key_opts& kopts) return kopts.keycode; } -OptionsDialog::OptionsDialog() +OptionsDialog::OptionsDialog(main_settings& main, std::function register_global_keys) + : main(main), register_global_keys(register_global_keys) { ui.setupUi(this); connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - tie_setting(s.s_main.tray_enabled, ui.trayp); + tie_setting(main.tray_enabled, ui.trayp); - tie_setting(s.s_main.center_at_startup, ui.center_at_startup); + tie_setting(main.center_at_startup, ui.center_at_startup); - tie_setting(s.s_main.tcomp_p, ui.tcomp_enable); - tie_setting(s.s_main.tcomp_tz, ui.tcomp_rz); - - tie_setting(s.s_main.a_x.zero, ui.pos_tx); - tie_setting(s.s_main.a_y.zero, ui.pos_ty); - tie_setting(s.s_main.a_z.zero, ui.pos_tz); - tie_setting(s.s_main.a_yaw.zero, ui.pos_rx); - tie_setting(s.s_main.a_pitch.zero, ui.pos_ry); - tie_setting(s.s_main.a_roll.zero, ui.pos_rz); - - tie_setting(s.s_main.a_yaw.invert, ui.invert_yaw); - tie_setting(s.s_main.a_pitch.invert, ui.invert_pitch); - tie_setting(s.s_main.a_roll.invert, ui.invert_roll); - tie_setting(s.s_main.a_x.invert, ui.invert_x); - tie_setting(s.s_main.a_y.invert, ui.invert_y); - tie_setting(s.s_main.a_z.invert, ui.invert_z); - - tie_setting(s.s_main.a_yaw.src, ui.src_yaw); - tie_setting(s.s_main.a_pitch.src, ui.src_pitch); - tie_setting(s.s_main.a_roll.src, ui.src_roll); - tie_setting(s.s_main.a_x.src, ui.src_x); - tie_setting(s.s_main.a_y.src, ui.src_y); - tie_setting(s.s_main.a_z.src, ui.src_z); + tie_setting(main.tcomp_p, ui.tcomp_enable); + tie_setting(main.tcomp_tz, ui.tcomp_rz); + + tie_setting(main.a_x.zero, ui.pos_tx); + tie_setting(main.a_y.zero, ui.pos_ty); + tie_setting(main.a_z.zero, ui.pos_tz); + tie_setting(main.a_yaw.zero, ui.pos_rx); + tie_setting(main.a_pitch.zero, ui.pos_ry); + tie_setting(main.a_roll.zero, ui.pos_rz); + + tie_setting(main.a_yaw.invert, ui.invert_yaw); + tie_setting(main.a_pitch.invert, ui.invert_pitch); + tie_setting(main.a_roll.invert, ui.invert_roll); + tie_setting(main.a_x.invert, ui.invert_x); + tie_setting(main.a_y.invert, ui.invert_y); + tie_setting(main.a_z.invert, ui.invert_z); + + tie_setting(main.a_yaw.src, ui.src_yaw); + tie_setting(main.a_pitch.src, ui.src_pitch); + tie_setting(main.a_roll.src, ui.src_roll); + tie_setting(main.a_x.src, ui.src_x); + tie_setting(main.a_y.src, ui.src_y); + tie_setting(main.a_z.src, ui.src_z); - tie_setting(s.s_main.camera_yaw, ui.camera_yaw); - tie_setting(s.s_main.camera_pitch, ui.camera_pitch); - tie_setting(s.s_main.camera_roll, ui.camera_roll); - - tie_setting(s.s_main.center_method, ui.center_method); - - connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center, ui.center_text); }); - connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero, ui.zero_text); }); - connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle, ui.toggle_text); }); - connect(ui.bind_start, &QPushButton::pressed, [&]() -> void { bind_key(s.start_tracking, ui.start_tracking_text); }); - connect(ui.bind_stop, &QPushButton::pressed, [&]() -> void { bind_key(s.stop_tracking, ui.stop_tracking_text); }); - connect(ui.bind_toggle_tracking, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle_tracking, ui.toggle_tracking_text); }); - - ui.center_text->setText(kopts_to_string(s.center)); - ui.toggle_text->setText(kopts_to_string(s.toggle)); - ui.zero_text->setText(kopts_to_string(s.zero)); + tie_setting(main.camera_yaw, ui.camera_yaw); + tie_setting(main.camera_pitch, ui.camera_pitch); + tie_setting(main.camera_roll, ui.camera_roll); + + tie_setting(main.center_method, ui.center_method); + + connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(main.key_center, ui.center_text); }); + connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(main.key_zero, ui.zero_text); }); + connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(main.key_toggle, ui.toggle_text); }); + connect(ui.bind_start, &QPushButton::pressed, [&]() -> void { bind_key(main.key_start_tracking, ui.start_tracking_text); }); + connect(ui.bind_stop, &QPushButton::pressed, [&]() -> void { bind_key(main.key_stop_tracking, ui.stop_tracking_text); }); + connect(ui.bind_toggle_tracking, &QPushButton::pressed, [&]() -> void { bind_key(main.key_toggle_tracking, ui.toggle_tracking_text); }); + + ui.center_text->setText(kopts_to_string(main.key_center)); + ui.toggle_text->setText(kopts_to_string(main.key_toggle)); + ui.zero_text->setText(kopts_to_string(main.key_zero)); + + ui.start_tracking_text->setText(kopts_to_string(main.key_start_tracking)); + ui.stop_tracking_text->setText(kopts_to_string(main.key_stop_tracking)); + ui.toggle_tracking_text->setText(kopts_to_string(main.key_toggle_tracking)); } -void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) +void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) { kopts.button = -1; kopts.guid = ""; @@ -111,22 +116,21 @@ void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) } }); d.exec(); + register_global_keys(); label->setText(kopts_to_string(kopts)); delete k; delete l; } void OptionsDialog::doOK() { - s.b->save(); - s.s_main.b->save(); + main.b->save(); ui.game_detector->save(); this->close(); emit reload(); } void OptionsDialog::doCancel() { - s.b->reload(); - s.s_main.b->reload(); + main.b->reload(); ui.game_detector->revert(); close(); } diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 308b5b0f..72ae3c30 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -1,9 +1,10 @@ #pragma once -#include -#include #include "ui_settings.h" #include "opentrack/shortcuts.h" +#include +#include +#include class OptionsDialog: public QWidget { @@ -11,13 +12,14 @@ class OptionsDialog: public QWidget signals: void reload(); public: - OptionsDialog(); + OptionsDialog(main_settings& main, std::function register_global_keys); private: + main_settings& main; + std::function register_global_keys; Ui::UI_Settings ui; - Shortcuts::settings s; void closeEvent(QCloseEvent *) override { doCancel(); } private slots: void doOK(); void doCancel(); - void bind_key(Shortcuts::key_opts &kopts, QLabel* label); + void bind_key(key_opts &kopts, QLabel* label); }; diff --git a/gui/ui.cpp b/gui/ui.cpp index c3e47912..26fcd9ed 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -108,10 +108,40 @@ MainWindow::MainWindow() : "Configuration not saved.", "Can't create configuration directory! Expect major malfunction.", QMessageBox::Ok, QMessageBox::NoButton); - + + connect(this, &MainWindow::emit_start_tracker, + this, [&]() -> void { qDebug() << "start tracker"; startTracker(); }, + Qt::QueuedConnection); + + connect(this, &MainWindow::emit_stop_tracker, + this, [&]() -> void { qDebug() << "stop tracker"; stopTracker(); }, + Qt::QueuedConnection); + + connect(this, &MainWindow::emit_toggle_tracker, + this, [&]() -> void { qDebug() << "toggle tracker"; if (work) stopTracker(); else startTracker(); }, + Qt::QueuedConnection); + + register_shortcuts(); + ui.btnStartTracker->setFocus(); } +void MainWindow::register_shortcuts() +{ + using t_shortcut = std::tuple; + + std::vector keys { + t_shortcut(s.key_start_tracking, [&]() -> void { emit_start_tracker(); }), + t_shortcut(s.key_stop_tracking, [&]() -> void { emit_stop_tracker(); }), + t_shortcut(s.key_toggle_tracking, [&]() -> void { emit_toggle_tracker(); }), + }; + + global_shortcuts.reload(keys); + + if (work) + work->reload_shortcuts(); +} + bool MainWindow::get_new_config_name_from_dialog(QString& ret) { new_file_dialog dlg; @@ -261,6 +291,9 @@ void MainWindow::reload_options() } void MainWindow::startTracker() { + if (work) + return; + // tracker dtor needs run first work = nullptr; @@ -306,7 +339,10 @@ void MainWindow::startTracker() { ui.btnStopTracker->setFocus(); } -void MainWindow::stopTracker( ) { +void MainWindow::stopTracker() { + if (!work) + return; + //ui.game_name->setText("Not connected"); pose_update_timer.stop(); @@ -436,7 +472,7 @@ void MainWindow::showFilterSettings() { } template -bool mk_window(mem* place, Args... params) +bool mk_window(mem* place, Args&&... params) { if (*place && (*place)->isVisible()) { @@ -446,7 +482,7 @@ bool mk_window(mem* place, Args... params) } else { - *place = std::make_shared(params...); + *place = std::make_shared(std::forward(params)...); (*place)->setWindowFlags(Qt::Dialog); (*place)->show(); (*place)->raise(); @@ -455,12 +491,14 @@ bool mk_window(mem* place, Args... params) } void MainWindow::show_options_dialog() { - if (mk_window(&options_widget)) + if (mk_window(&options_widget, + s, + [&]() -> void { register_shortcuts(); })) connect(options_widget.get(), SIGNAL(reload()), this, SLOT(reload_options())); } void MainWindow::showCurveConfiguration() { - mk_window(&mapping_widget, pose, s); + mk_window(&mapping_widget, pose, s); } void MainWindow::exit() { diff --git a/gui/ui.h b/gui/ui.h index b4bab271..12ef1f24 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -17,6 +17,9 @@ #include #include +#include +#include + #include "ui_main.h" #include "opentrack-compat/options.hpp" @@ -35,6 +38,8 @@ using namespace options; class MainWindow : public QMainWindow, private State { Q_OBJECT + + Shortcuts global_shortcuts; Ui::OpentrackUI ui; mem tray; @@ -76,6 +81,7 @@ class MainWindow : public QMainWindow, private State static bool get_new_config_name_from_dialog(QString &ret); void set_profile(const QString& profile); void maybe_save(); + void register_shortcuts(); private slots: void _save(); void save(); @@ -100,6 +106,10 @@ private slots: void startTracker(); void stopTracker(); void reload_options(); +signals: + void emit_start_tracker(); + void emit_stop_tracker(); + void emit_toggle_tracker(); public: MainWindow(); ~MainWindow(); diff --git a/opentrack/main-settings.hpp b/opentrack/main-settings.hpp index b7b086ad..793c52f7 100644 --- a/opentrack/main-settings.hpp +++ b/opentrack/main-settings.hpp @@ -32,7 +32,18 @@ private: } }; -struct main_settings : opts { +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; @@ -40,6 +51,8 @@ struct main_settings : opts { 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_opts key_center, key_toggle, key_zero; main_settings() : opts("opentrack-ui"), tracker_dll(b, "tracker-dll", ""), @@ -58,6 +71,13 @@ struct main_settings : opts { 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) - {} + 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_center(b, "center"), + key_toggle(b, "toggle"), + key_zero(b, "zero") + { + } }; diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 4dec7c2c..f8343ad8 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -46,31 +46,6 @@ public: #ifdef _WIN32 KeybindingWorker::Token key_token; #endif - - 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 settings : opts { - key_opts center, toggle, zero, start_tracking, stop_tracking, toggle_tracking; - main_settings s_main; - settings() : - opts("keyboard-shortcuts"), - center(b, "center"), - toggle(b, "toggle"), - zero(b, "zero"), - start_tracking(b, "start-tracking"), - stop_tracking(b, "stop-tracking"), - toggle_tracking(b, "toggle-tracking") - {} - } s; Shortcuts() : #ifdef _WIN32 @@ -78,7 +53,7 @@ public: #endif {} - void reload(const std::vector > &keys); + void reload(const std::vector > &keys); private: void bind_keyboard_shortcut(K &key, const key_opts& k); #ifdef _WIN32 diff --git a/opentrack/work.hpp b/opentrack/work.hpp index a3c0e014..4188b937 100644 --- a/opentrack/work.hpp +++ b/opentrack/work.hpp @@ -28,7 +28,6 @@ struct Work mem sc; WId handle; using fn = std::function; - using key_opts = Shortcuts::key_opts; using tt = std::tuple; std::vector> keys; @@ -38,9 +37,9 @@ struct Work sc(std::make_shared()), handle(handle), keys { - tt(sc->s.center, [&]() -> void { tracker->center(); }), - tt(sc->s.toggle, [&]() -> void { tracker->toggle_enabled(); }), - tt(sc->s.zero, [&]() -> void { tracker->zero(); }), + tt(s.key_center, [&]() -> void { tracker->center(); }), + tt(s.key_toggle, [&]() -> void { tracker->toggle_enabled(); }), + tt(s.key_zero, [&]() -> void { tracker->zero(); }), } { reload_shortcuts(); -- cgit v1.2.3 From ae1faae5d963b75a0b04bf69e77fc0ee12d2232d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 00:53:44 +0100 Subject: api/keys: fix build --- opentrack/shortcuts.cpp | 2 +- opentrack/shortcuts.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'opentrack') diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 560a31ab..bab1283a 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -99,7 +99,7 @@ void Shortcuts::reload(const std::vector > &keys_) bind_keyboard_shortcut(k, opts); keys.push_back(std::tuple(k, fun)); #ifndef _WIN32 - connect(k.get(), &QGlobalShortcut::activated, fun); + connect(k.get(), &QxtGlobalShortcut::activated, fun); #endif } } diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index f8343ad8..38037923 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -47,9 +47,9 @@ public: KeybindingWorker::Token key_token; #endif - Shortcuts() : + Shortcuts() #ifdef _WIN32 - key_token([&](const Key& k) { receiver(k); }) + : key_token([&](const Key& k) { receiver(k); }) #endif {} -- cgit v1.2.3 From 0be7e0a4e6ec65800a12bff1e7384995592c226f Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 02:02:55 +0100 Subject: api/keys: initialize hresult --- opentrack/win32-joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 1c658c75..e3147929 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -174,7 +174,7 @@ bool win32_joy_ctx::joy::poll(fn f) (void) joy_handle->Acquire(); - if (!FAILED(joy_handle->Poll())) + if (!FAILED(hr = joy_handle->Poll())) ok = true; if (!ok) -- cgit v1.2.3 From dbc4722f14aa6d4b3322405c9251c5cee2e165d8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 02:14:23 +0100 Subject: api/camera: move from header There's no need to have a copy in each module. --- opentrack/camera-names.cpp | 113 +++++++++++++++++++++++++++++++++++++++++++++ opentrack/camera-names.hpp | 113 +-------------------------------------------- 2 files changed, 115 insertions(+), 111 deletions(-) create mode 100644 opentrack/camera-names.cpp (limited to 'opentrack') diff --git a/opentrack/camera-names.cpp b/opentrack/camera-names.cpp new file mode 100644 index 00000000..74e998ca --- /dev/null +++ b/opentrack/camera-names.cpp @@ -0,0 +1,113 @@ +#include "camera-names.hpp" + +#if defined(OPENTRACK_API) && defined(_WIN32) +# define NO_DSHOW_STRSAFE +# include +# include +#endif + +#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) +# include +#endif + +#ifdef __linux +#include +#include +#include +#include +#endif + +#include + +int camera_name_to_index(const QString &name) +{ + auto list = get_camera_names(); + int ret = list.indexOf(name); + if (ret < 0) + ret = 0; + return ret; +} + +QList get_camera_names() { + QList ret; +#if defined(_WIN32) + // Create the System Device Enumerator. + HRESULT hr; + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (FAILED(hr)) + qDebug() << "failed CoInitializeEx" << hr; + ICreateDevEnum *pSysDevEnum = NULL; + hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); + if (FAILED(hr)) + { + qDebug() << "failed CLSID_SystemDeviceEnum" << hr; + return ret; + } + // Obtain a class enumerator for the video compressor category. + IEnumMoniker *pEnumCat = NULL; + hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); + + if (hr == S_OK) { + // Enumerate the monikers. + IMoniker *pMoniker = NULL; + ULONG cFetched; + while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (SUCCEEDED(hr)) { + // To retrieve the filter's friendly name, do the following: + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) + { + // Display the name in your UI somehow. + QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); + ret.append(str); + } + VariantClear(&varName); + + ////// To create an instance of the filter, do the following: + ////IBaseFilter *pFilter; + ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, + //// (void**)&pFilter); + // Now add the filter to the graph. + //Remember to release pFilter later. + pPropBag->Release(); + } + pMoniker->Release(); + } + pEnumCat->Release(); + } + else + qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; + + pSysDevEnum->Release(); +#endif +#ifdef __linux + for (int i = 0; i < 16; i++) { + char buf[128]; + sprintf(buf, "/dev/video%d", i); + if (access(buf, F_OK) == 0) + ret.append(buf); + else + continue; + + if (access(buf, R_OK | W_OK) == 0) { + int fd = open(buf, O_RDONLY); + if (fd == -1) + continue; + struct v4l2_capability video_cap; + if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) + { + qDebug() << "VIDIOC_QUERYCAP" << errno; + close(fd); + continue; + } + ret[ret.size()-1] = reinterpret_cast(video_cap.card); + close(fd); + } + } +#endif + return ret; +} \ No newline at end of file diff --git a/opentrack/camera-names.hpp b/opentrack/camera-names.hpp index f6ab736e..ef914458 100644 --- a/opentrack/camera-names.hpp +++ b/opentrack/camera-names.hpp @@ -10,116 +10,7 @@ #include #include -#include -#if defined(OPENTRACK_API) && defined(_WIN32) -# define NO_DSHOW_STRSAFE -# include -# include -#endif +QList get_camera_names(); +int camera_name_to_index(const QString &name); -#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) -# include -#endif - -#ifdef __linux -#include -#include -#include -#include -#endif - -template -QList get_camera_names() { - QList ret; -#if defined(_WIN32) - // Create the System Device Enumerator. - HRESULT hr; - hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - if (FAILED(hr)) - qDebug() << "failed CoInitializeEx" << hr; - ICreateDevEnum *pSysDevEnum = NULL; - hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); - if (FAILED(hr)) - { - qDebug() << "failed CLSID_SystemDeviceEnum" << hr; - return ret; - } - // Obtain a class enumerator for the video compressor category. - IEnumMoniker *pEnumCat = NULL; - hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); - - if (hr == S_OK) { - // Enumerate the monikers. - IMoniker *pMoniker = NULL; - ULONG cFetched; - while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); - if (SUCCEEDED(hr)) { - // To retrieve the filter's friendly name, do the following: - VARIANT varName; - VariantInit(&varName); - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if (SUCCEEDED(hr)) - { - // Display the name in your UI somehow. - QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); - ret.append(str); - } - VariantClear(&varName); - - ////// To create an instance of the filter, do the following: - ////IBaseFilter *pFilter; - ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, - //// (void**)&pFilter); - // Now add the filter to the graph. - //Remember to release pFilter later. - pPropBag->Release(); - } - pMoniker->Release(); - } - pEnumCat->Release(); - } - else - qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; - - pSysDevEnum->Release(); -#endif -#ifdef __linux - for (int i = 0; i < 16; i++) { - char buf[128]; - sprintf(buf, "/dev/video%d", i); - if (access(buf, F_OK) == 0) - ret.append(buf); - else - continue; - - if (access(buf, R_OK | W_OK) == 0) { - int fd = open(buf, O_RDONLY); - if (fd == -1) - continue; - struct v4l2_capability video_cap; - if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) - { - qDebug() << "VIDIOC_QUERYCAP" << errno; - close(fd); - continue; - } - ret[ret.size()-1] = reinterpret_cast(video_cap.card); - close(fd); - } - } -#endif - return ret; -} - -template -int camera_name_to_index(const QString &name) -{ - auto list = get_camera_names(); - int ret = list.indexOf(name); - if (ret < 0) - ret = 0; - return ret; -} -- cgit v1.2.3 From 211a17996e3ffc0d84c985c43c612da32923b42d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 02:24:44 +0100 Subject: api/camera-names: move to compat/ --- opentrack-compat/CMakeLists.txt | 1 + opentrack-compat/camera-names.cpp | 113 ++++++++++++++++++++++++++++++++ opentrack-compat/camera-names.hpp | 22 +++++++ opentrack/CMakeLists.txt | 1 - opentrack/camera-names.cpp | 113 -------------------------------- opentrack/camera-names.hpp | 16 ----- opentrack/opencv-camera-dialog.hpp | 2 +- tracker-aruco/ftnoir_tracker_aruco.cpp | 2 +- tracker-pt/ftnoir_tracker_pt.cpp | 2 +- tracker-pt/ftnoir_tracker_pt_dialog.cpp | 2 +- 10 files changed, 140 insertions(+), 134 deletions(-) create mode 100644 opentrack-compat/camera-names.cpp create mode 100644 opentrack-compat/camera-names.hpp delete mode 100644 opentrack/camera-names.cpp delete mode 100644 opentrack/camera-names.hpp (limited to 'opentrack') diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt index 37d53e6c..8dba67e2 100644 --- a/opentrack-compat/CMakeLists.txt +++ b/opentrack-compat/CMakeLists.txt @@ -2,3 +2,4 @@ opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT LINKAGE) if(NOT WIN32 AND NOT APPLE) target_link_libraries(opentrack-compat rt) endif() +link_with_dinput8(opentrack-compat) diff --git a/opentrack-compat/camera-names.cpp b/opentrack-compat/camera-names.cpp new file mode 100644 index 00000000..72bcf41a --- /dev/null +++ b/opentrack-compat/camera-names.cpp @@ -0,0 +1,113 @@ +#include "camera-names.hpp" + +#if defined(OPENTRACK_API) && defined(_WIN32) +# define NO_DSHOW_STRSAFE +# include +# include +#endif + +#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) +# include +#endif + +#ifdef __linux +#include +#include +#include +#include +#endif + +#include + +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name) +{ + auto list = get_camera_names(); + int ret = list.indexOf(name); + if (ret < 0) + ret = 0; + return ret; +} + +OPENTRACK_COMPAT_EXPORT QList get_camera_names() { + QList ret; +#if defined(_WIN32) + // Create the System Device Enumerator. + HRESULT hr; + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (FAILED(hr)) + qDebug() << "failed CoInitializeEx" << hr; + ICreateDevEnum *pSysDevEnum = NULL; + hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); + if (FAILED(hr)) + { + qDebug() << "failed CLSID_SystemDeviceEnum" << hr; + return ret; + } + // Obtain a class enumerator for the video compressor category. + IEnumMoniker *pEnumCat = NULL; + hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); + + if (hr == S_OK) { + // Enumerate the monikers. + IMoniker *pMoniker = NULL; + ULONG cFetched; + while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (SUCCEEDED(hr)) { + // To retrieve the filter's friendly name, do the following: + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) + { + // Display the name in your UI somehow. + QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); + ret.append(str); + } + VariantClear(&varName); + + ////// To create an instance of the filter, do the following: + ////IBaseFilter *pFilter; + ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, + //// (void**)&pFilter); + // Now add the filter to the graph. + //Remember to release pFilter later. + pPropBag->Release(); + } + pMoniker->Release(); + } + pEnumCat->Release(); + } + else + qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; + + pSysDevEnum->Release(); +#endif +#ifdef __linux + for (int i = 0; i < 16; i++) { + char buf[128]; + sprintf(buf, "/dev/video%d", i); + if (access(buf, F_OK) == 0) + ret.append(buf); + else + continue; + + if (access(buf, R_OK | W_OK) == 0) { + int fd = open(buf, O_RDONLY); + if (fd == -1) + continue; + struct v4l2_capability video_cap; + if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) + { + qDebug() << "VIDIOC_QUERYCAP" << errno; + close(fd); + continue; + } + ret[ret.size()-1] = reinterpret_cast(video_cap.card); + close(fd); + } + } +#endif + return ret; +} \ No newline at end of file diff --git a/opentrack-compat/camera-names.hpp b/opentrack-compat/camera-names.hpp new file mode 100644 index 00000000..c2879000 --- /dev/null +++ b/opentrack-compat/camera-names.hpp @@ -0,0 +1,22 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik + + * 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 + +#ifdef BUILD_compat +# include "compat-export.hpp" +#else +# include "compat-import.hpp" +#endif + +OPENTRACK_COMPAT_EXPORT QList get_camera_names(); +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name); + diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt index de5975e2..08003a5c 100644 --- a/opentrack/CMakeLists.txt +++ b/opentrack/CMakeLists.txt @@ -4,5 +4,4 @@ if(NOT WIN32) else() target_link_libraries(opentrack-api winmm) endif() -link_with_dinput8(opentrack-api) target_link_libraries(opentrack-api opentrack-spline-widget) diff --git a/opentrack/camera-names.cpp b/opentrack/camera-names.cpp deleted file mode 100644 index 74e998ca..00000000 --- a/opentrack/camera-names.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "camera-names.hpp" - -#if defined(OPENTRACK_API) && defined(_WIN32) -# define NO_DSHOW_STRSAFE -# include -# include -#endif - -#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) -# include -#endif - -#ifdef __linux -#include -#include -#include -#include -#endif - -#include - -int camera_name_to_index(const QString &name) -{ - auto list = get_camera_names(); - int ret = list.indexOf(name); - if (ret < 0) - ret = 0; - return ret; -} - -QList get_camera_names() { - QList ret; -#if defined(_WIN32) - // Create the System Device Enumerator. - HRESULT hr; - hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - if (FAILED(hr)) - qDebug() << "failed CoInitializeEx" << hr; - ICreateDevEnum *pSysDevEnum = NULL; - hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); - if (FAILED(hr)) - { - qDebug() << "failed CLSID_SystemDeviceEnum" << hr; - return ret; - } - // Obtain a class enumerator for the video compressor category. - IEnumMoniker *pEnumCat = NULL; - hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); - - if (hr == S_OK) { - // Enumerate the monikers. - IMoniker *pMoniker = NULL; - ULONG cFetched; - while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); - if (SUCCEEDED(hr)) { - // To retrieve the filter's friendly name, do the following: - VARIANT varName; - VariantInit(&varName); - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if (SUCCEEDED(hr)) - { - // Display the name in your UI somehow. - QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); - ret.append(str); - } - VariantClear(&varName); - - ////// To create an instance of the filter, do the following: - ////IBaseFilter *pFilter; - ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, - //// (void**)&pFilter); - // Now add the filter to the graph. - //Remember to release pFilter later. - pPropBag->Release(); - } - pMoniker->Release(); - } - pEnumCat->Release(); - } - else - qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; - - pSysDevEnum->Release(); -#endif -#ifdef __linux - for (int i = 0; i < 16; i++) { - char buf[128]; - sprintf(buf, "/dev/video%d", i); - if (access(buf, F_OK) == 0) - ret.append(buf); - else - continue; - - if (access(buf, R_OK | W_OK) == 0) { - int fd = open(buf, O_RDONLY); - if (fd == -1) - continue; - struct v4l2_capability video_cap; - if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) - { - qDebug() << "VIDIOC_QUERYCAP" << errno; - close(fd); - continue; - } - ret[ret.size()-1] = reinterpret_cast(video_cap.card); - close(fd); - } - } -#endif - return ret; -} \ No newline at end of file diff --git a/opentrack/camera-names.hpp b/opentrack/camera-names.hpp deleted file mode 100644 index ef914458..00000000 --- a/opentrack/camera-names.hpp +++ /dev/null @@ -1,16 +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 - -QList get_camera_names(); -int camera_name_to_index(const QString &name); - diff --git a/opentrack/opencv-camera-dialog.hpp b/opentrack/opencv-camera-dialog.hpp index 0d4a51af..96c7a643 100644 --- a/opentrack/opencv-camera-dialog.hpp +++ b/opentrack/opencv-camera-dialog.hpp @@ -12,7 +12,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #ifdef __linux #include diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 1da5b8df..316c7e13 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -16,7 +16,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #include "opentrack-compat/sleep.hpp" typedef struct { diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 2dbf9068..3dd91a45 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -12,7 +12,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #include "opentrack-compat/sleep.hpp" //#define PT_PERF_LOG //log performance diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp index b1ae2238..551910f7 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -12,7 +12,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #include //----------------------------------------------------------------------------- -- cgit v1.2.3 From 0bd32bf56d5b31e7d7e8288b33f536158903e95e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 03:35:33 +0100 Subject: api/keys: nix tautological #ifdef --- opentrack/keybinding-worker.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 9ff825a0..461f8416 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -105,7 +105,6 @@ void KeybindingWorker::run() { } } -#ifdef _WIN32 { using joy_fn = std::function; @@ -124,7 +123,6 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } -#endif for (int i = 0; i < 256; i++) { -- cgit v1.2.3 From 1aa7bceaed59770adeb389d6c4c8f5561d0e7402 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:15:07 +0100 Subject: api/keys: use a fake window for DirectInput handle --- opentrack/keybinding-worker.cpp | 6 ++---- opentrack/keybinding-worker.hpp | 4 +++- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 461f8416..2ac814af 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -35,9 +35,6 @@ KeybindingWorker::~KeybindingWorker() { } KeybindingWorker::KeybindingWorker() : -#ifdef _WIN32 - joy_ctx(win32_joy_ctx::make()), -#endif should_quit(true) { if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { @@ -58,7 +55,8 @@ KeybindingWorker::KeybindingWorker() : din = 0; return; } - if (dinkeyboard->SetCooperativeLevel(GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + + if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { dinkeyboard->Release(); din->Release(); din = 0; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index c8d8e009..fa50a974 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -45,11 +46,12 @@ struct OPENTRACK_EXPORT KeybindingWorker : private QThread private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; - win32_joy_ctx& joy_ctx; + 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(); -- cgit v1.2.3 From acef508f0b6f16a7be987eeebbb3402455f9aef8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:16:39 +0100 Subject: joystick: no longer singleton, use fake window handle We can create arbitrary amount of dinput handles, given they're passed unique window handles. --- opentrack/win32-joystick.cpp | 60 ++++++++++++++++---------------------------- opentrack/win32-joystick.hpp | 23 +++++++++-------- 2 files changed, 33 insertions(+), 50 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index e3147929..89092403 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -1,23 +1,9 @@ +#undef NDEBUG +#include #include "win32-joystick.hpp" #ifdef _WIN32 -LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() -{ - (void) CoInitialize(nullptr); - - static LPDIRECTINPUT8 dinput_handle_ = nullptr; - - if (dinput_handle_ == nullptr) - (void) DirectInput8Create(GetModuleHandle(nullptr), - DIRECTINPUT_VERSION, - IID_IDirectInput8, - (void**) &dinput_handle_, - nullptr); - - return dinput_handle_; -} - std::unordered_map>& win32_joy_ctx::joys() { static std::unordered_map> js; @@ -25,12 +11,6 @@ std::unordered_map>& win32_joy_ctx: return js; } -win32_joy_ctx& win32_joy_ctx::make() -{ - static win32_joy_ctx ret; - return ret; -} - void win32_joy_ctx::poll(fn f) { refresh(false); @@ -117,17 +97,18 @@ std::vector win32_joy_ctx::get_joy_info() 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(true); } void win32_joy_ctx::release() { joys() = std::unordered_map>(); - { - auto& di = dinput_handle(); - di->Release(); - di = nullptr; - } + di->Release(); + di = nullptr; } void win32_joy_ctx::refresh(bool first) @@ -141,7 +122,7 @@ void win32_joy_ctx::refresh(bool first) timer_joylist.start(); } - enum_state st(joys(), first, mtx); + enum_state st(joys(), mtx, fake_main_window, di); } QString win32_joy_ctx::guid_to_string(const GUID guid) @@ -193,12 +174,10 @@ bool win32_joy_ctx::joy::poll(fn f) return false; } - first |= first_timer.elapsed_ms() > first_event_delay_ms; - for (int i = 0; i < 128; i++) { const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i] && first) + if (state != pressed[i]) { f(guid, i, state); qDebug() << "btn" << guid << i << state; @@ -209,15 +188,19 @@ bool win32_joy_ctx::joy::poll(fn f) return true; } -win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first, QMutex& mtx) : first(first) +win32_joy_ctx::enum_state::enum_state(std::unordered_map> &joys, + QMutex& mtx, + QMainWindow &fake_main_window, + LPDIRECTINPUT8 di) : + fake_main_window(fake_main_window), + di(di) { - HRESULT hr; - LPDIRECTINPUT8 di = dinput_handle(); - { QMutexLocker l(&mtx); this->joys = joys; } + + HRESULT hr; if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, @@ -257,8 +240,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns { HRESULT hr; LPDIRECTINPUTDEVICE8 h; - LPDIRECTINPUT8 di = dinput_handle(); - if (FAILED(hr = di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + if (FAILED(hr = state.di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) { qDebug() << "createdevice" << guid << hr; goto end; @@ -270,7 +252,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns goto end; } - if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + if (FAILED(h->SetCooperativeLevel((HWND) state.fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) { qDebug() << "coop"; h->Release(); @@ -284,7 +266,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns } qDebug() << "add joy" << guid; - state.joys[guid] = std::make_shared(h, guid, name, state.first); + state.joys[guid] = std::make_shared(h, guid, name); } end: return DIENUM_CONTINUE; diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 421774a9..f7629c3d 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace std { template<> @@ -49,21 +50,23 @@ struct OPENTRACK_EXPORT win32_joy_ctx void poll(fn f); bool poll_axis(const QString& guid, int axes[8]); - ~win32_joy_ctx(); std::vector get_joy_info(); - static win32_joy_ctx& make(); + win32_joy_ctx(const win32_joy_ctx&) = delete; win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; + win32_joy_ctx(); + ~win32_joy_ctx(); + private: enum { joylist_refresh_ms = 100 }; QMutex mtx; Timer timer_joylist; + QMainWindow fake_main_window; + LPDIRECTINPUT8 di; static QString guid_to_string(const GUID guid); - static LPDIRECTINPUT8& dinput_handle(); - win32_joy_ctx(); void release(); void refresh(bool first); @@ -72,16 +75,13 @@ private: struct joy { - enum { first_event_delay_ms = 3000 }; - LPDIRECTINPUTDEVICE8 joy_handle; QString guid, name; bool pressed[128]; Timer first_timer; - bool first; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) - : joy_handle(handle), guid(guid), name(name), first(first) + 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++) @@ -101,13 +101,14 @@ private: class enum_state { std::unordered_map> joys; - bool first; + 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, bool first, QMutex &mtx); + enum_state(std::unordered_map>& joys, QMutex &mtx, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); }; }; -- cgit v1.2.3 From 5076d0c35eacb2e7b246e7bd5e6637086ea74a15 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:23:04 +0100 Subject: api/joy: nix static, now that we're not a singleton --- opentrack/win32-joystick.cpp | 19 ++++++------------- opentrack/win32-joystick.hpp | 5 ++--- 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 89092403..78720c79 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -4,20 +4,13 @@ #ifdef _WIN32 -std::unordered_map>& win32_joy_ctx::joys() -{ - static std::unordered_map> js; - - return js; -} - void win32_joy_ctx::poll(fn f) { refresh(false); QMutexLocker l(&mtx); - for (auto& j : joys()) + for (auto& j : joys) { j.second->poll(f); } @@ -29,9 +22,9 @@ bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) QMutexLocker l(&mtx); - auto iter = joys().find(guid); + auto iter = joys.find(guid); - if (iter == joys().end()) + if (iter == joys.end()) return false; auto& j = iter->second; @@ -89,7 +82,7 @@ std::vector win32_joy_ctx::get_joy_info() std::vector ret; - for (auto& j : joys()) + for (auto& j : joys) ret.push_back(joy_info { j.second->name, j.first }); return ret; @@ -106,7 +99,7 @@ win32_joy_ctx::win32_joy_ctx() void win32_joy_ctx::release() { - joys() = std::unordered_map>(); + joys = std::unordered_map>(); di->Release(); di = nullptr; } @@ -122,7 +115,7 @@ void win32_joy_ctx::refresh(bool first) timer_joylist.start(); } - enum_state st(joys(), mtx, fake_main_window, di); + enum_state st(joys, mtx, fake_main_window, di); } QString win32_joy_ctx::guid_to_string(const GUID guid) diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index f7629c3d..e68ea2c6 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -70,9 +70,6 @@ private: void release(); void refresh(bool first); - struct joy; - static std::unordered_map>& joys(); - struct joy { LPDIRECTINPUTDEVICE8 joy_handle; @@ -97,6 +94,8 @@ private: void release(); bool poll(fn f); }; + + std::unordered_map> joys; class enum_state { -- cgit v1.2.3 From b31e4997de81efc3941072cc48b5f09064e62e81 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:59:36 +0100 Subject: api/joy: speed up poll_axis path We don't really need to poll for joysticks in tracker/joy. --- opentrack/win32-joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 78720c79..f4bfba76 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -18,7 +18,7 @@ void win32_joy_ctx::poll(fn f) bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) { - refresh(false); + //refresh(false); QMutexLocker l(&mtx); -- cgit v1.2.3 From 75b4a6e3a32b4345941e15953d55572384eb210e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 20:13:42 +0100 Subject: api/joy: prevent idempotent keypressed passed to receiver --- opentrack/win32-joystick.cpp | 4 +++- opentrack/win32-joystick.hpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index f4bfba76..73e27f80 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -169,7 +169,7 @@ bool win32_joy_ctx::joy::poll(fn f) for (int i = 0; i < 128; i++) { - const bool state = !!(js.rgbButtons[i] & 0x80); + const bool state = !!(js.rgbButtons[i] & 0x80) && js.rgbButtons[i] != js_old.rgbButtons[i]; if (state != pressed[i]) { f(guid, i, state); @@ -178,6 +178,8 @@ bool win32_joy_ctx::joy::poll(fn f) pressed[i] = state; } + js_old = js; + return true; } diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index e68ea2c6..df00aee7 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -76,6 +76,7 @@ private: QString guid, name; bool pressed[128]; Timer first_timer; + DIJOYSTATE2 js_old; joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name) : joy_handle(handle), guid(guid), name(name) -- cgit v1.2.3 From 4864dfaa4b455905fece5cd93502b80890d1b2d2 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 20:13:56 +0100 Subject: api/joy: move from header --- opentrack/win32-joystick.cpp | 15 +++++++++++++++ opentrack/win32-joystick.hpp | 17 +++-------------- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'opentrack') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 73e27f80..728e2f68 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -292,4 +292,19 @@ win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdi 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 index df00aee7..6d5e1074 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -24,7 +24,7 @@ namespace std { template<> struct hash { - std::size_t operator()(const QString& value) const + inline std::size_t operator()(const QString& value) const { return qHash(value); } @@ -78,19 +78,8 @@ private: Timer first_timer; DIJOYSTATE2 js_old; - 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; - } - - ~joy() - { - qDebug() << "nix joy" << guid; - release(); - } + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name); + ~joy(); void release(); bool poll(fn f); -- cgit v1.2.3 From d6eb142710e6ac307b4c5c0e0a54166852d71cbc Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 20:14:09 +0100 Subject: api/keys: prevent idempotent keys --- opentrack/keybinding-worker.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 2ac814af..b0cef22d 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -85,6 +85,7 @@ KeybindingWorker& KeybindingWorker::make() void KeybindingWorker::run() { BYTE keystate[256] = {0}; + BYTE old_keystate[256] = {0}; while (!should_quit) { @@ -125,7 +126,7 @@ void KeybindingWorker::run() { for (int i = 0; i < 256; i++) { Key k; - if (keystate[i] & 0x80) + if (old_keystate[i] != keystate[i] && keystate[i] & 0x80) { switch (i) { @@ -147,6 +148,7 @@ void KeybindingWorker::run() { break; } } + old_keystate[i] = keystate[i]; } } } -- cgit v1.2.3 From 4821c0337a64ada6db44a6ccbb84f6067d898d4b Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 17 Dec 2015 10:25:55 +0100 Subject: cmake/api: link with strmiids.lib on win32 It worked by accident since cmake/compat already links to it. --- opentrack/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'opentrack') diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt index 08003a5c..6baa05db 100644 --- a/opentrack/CMakeLists.txt +++ b/opentrack/CMakeLists.txt @@ -5,3 +5,4 @@ else() target_link_libraries(opentrack-api winmm) endif() target_link_libraries(opentrack-api opentrack-spline-widget) +link_with_dinput8(opentrack-api) -- cgit v1.2.3 From 3e543b11f57aa6c010045fb9614eb2638ac6ae81 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 17 Dec 2015 22:52:54 +0100 Subject: api/joy: refresh only manually on certain events Refresh joylist when new listener arrives, and when the joy singleton just gets created. Enumerating joys all the time causes high CPU usage for some of the users. Issue: #279 Backtrace-by: @exulant Reported-by: @aka2k --- opentrack/keybinding-worker.cpp | 1 + opentrack/win32-joystick.cpp | 25 +++++++------------------ opentrack/win32-joystick.hpp | 8 ++------ 3 files changed, 10 insertions(+), 24 deletions(-) (limited to 'opentrack') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index b0cef22d..39693a7c 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -164,6 +164,7 @@ KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) 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; } diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 728e2f68..5e6f2011 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -6,7 +6,7 @@ void win32_joy_ctx::poll(fn f) { - refresh(false); + //refresh(false); QMutexLocker l(&mtx); @@ -94,7 +94,7 @@ win32_joy_ctx::win32_joy_ctx() qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); assert(!"direct input handle can't be created"); } - refresh(true); + refresh(); } void win32_joy_ctx::release() @@ -104,18 +104,12 @@ void win32_joy_ctx::release() di = nullptr; } -void win32_joy_ctx::refresh(bool first) +void win32_joy_ctx::refresh() { - if (!first) - { - // accessing struct Timer without a lock. worst can happen is seconds - // and nanoseconds getting out of sync. no big deal. - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } + QMutexLocker l(&mtx); - enum_state st(joys, mtx, fake_main_window, di); + qDebug() << "joy list refresh"; + enum_state st(joys, fake_main_window, di); } QString win32_joy_ctx::guid_to_string(const GUID guid) @@ -184,16 +178,12 @@ bool win32_joy_ctx::joy::poll(fn f) } win32_joy_ctx::enum_state::enum_state(std::unordered_map> &joys, - QMutex& mtx, QMainWindow &fake_main_window, LPDIRECTINPUT8 di) : fake_main_window(fake_main_window), di(di) { - { - QMutexLocker l(&mtx); - this->joys = joys; - } + this->joys = joys; HRESULT hr; @@ -216,7 +206,6 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys; } diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 6d5e1074..9c888326 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -57,18 +57,14 @@ struct OPENTRACK_EXPORT win32_joy_ctx win32_joy_ctx(); ~win32_joy_ctx(); - + void refresh(); private: - enum { joylist_refresh_ms = 100 }; - QMutex mtx; - Timer timer_joylist; QMainWindow fake_main_window; LPDIRECTINPUT8 di; static QString guid_to_string(const GUID guid); void release(); - void refresh(bool first); struct joy { @@ -97,7 +93,7 @@ private: 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, QMutex &mtx, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); + enum_state(std::unordered_map>& joys, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); }; }; -- cgit v1.2.3 From f53f0c3ebb3553543dcd0814d6d1fe54faef030e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 00:54:45 +0100 Subject: api/mat: fix typos/breakage --- opentrack/simple-mat.hpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'opentrack') diff --git a/opentrack/simple-mat.hpp b/opentrack/simple-mat.hpp index 59afbbf0..4f885f4f 100644 --- a/opentrack/simple-mat.hpp +++ b/opentrack/simple-mat.hpp @@ -157,7 +157,7 @@ public: return ret; } - Mat operator*(const num& other) const + Mat operator*(const num other) const { Mat ret; for (int j = 0; j < h_; j++) @@ -167,20 +167,16 @@ public: } template - Mat operator*(const Mat& other) const + Mat operator*(const Mat& other) const { - Mat ret; - for (int j = 0; j < w_; j++) + Mat ret; + for (int k = 0; k < h_; k++) for (int i = 0; i < p; i++) { - num sum = num(0); - - for (int k = 0; k < h_; k++) - sum += data[j][k]*other(k, i); - - ret(j, i) = sum; + ret(k, i) = 0; + for (int j = 0; j < w_; j++) + ret(k, i) += data[k][j] * other(j, i); } - return ret; } @@ -189,7 +185,7 @@ public: template::value>::type> - Mat(ts const&... xs) + Mat(const ts... xs) { const std::initializer_list init = { static_cast(xs)... }; auto iter = init.begin(); @@ -236,7 +232,7 @@ public: for (int j = 0; j < h_; j++) for (int i = 0; i < w_; i++) - ret.data[i][j] = data[j][i]; + ret(i, j) = data[j][i]; return ret; } -- cgit v1.2.3