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 ++ spline-widget/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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) diff --git a/spline-widget/CMakeLists.txt b/spline-widget/CMakeLists.txt index 03706d91..93958f50 100644 --- a/spline-widget/CMakeLists.txt +++ b/spline-widget/CMakeLists.txt @@ -1 +1 @@ -opentrack_boilerplate(opentrack-spline-widget NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-spline-widget NO-LINKER-SCRIPT NO-COMPAT) -- cgit v1.2.3 From 0497f57268e8be7af69d37e24fa356e441c0d5f6 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 09:09:25 +0100 Subject: cmake: less linkage boilerplate --- cmake/opentrack-macros.cmake | 3 ++- csv/csv.h | 2 +- opentrack-compat/shm.h | 2 +- pose-widget/glwidget.h | 2 +- qxt-mini/qxtglobal.h | 2 +- spline-widget/functionconfig.h | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmake/opentrack-macros.cmake b/cmake/opentrack-macros.cmake index e43dc3b5..46cf3c61 100644 --- a/cmake/opentrack-macros.cmake +++ b/cmake/opentrack-macros.cmake @@ -66,7 +66,8 @@ macro(opentrack_library n dir) set_target_properties(${n} PROPERTIES LINK_FLAGS "${link-flags} ${opentrack-foolib_LINK}" COMPILE_FLAGS "${opentrack-foolib_COMPILE}") set(link-flags) endif() - string(REPLACE "-" "_" n_ ${n}) + string(REGEX REPLACE "^opentrack-" "" n_ ${n}) + string(REPLACE "-" "_" n_ ${n_}) target_compile_definitions(${n} PRIVATE "BUILD_${n_}") if(NOT opentrack-foolib_STATIC) install(TARGETS ${n} RUNTIME DESTINATION . LIBRARY DESTINATION .) diff --git a/csv/csv.h b/csv/csv.h index 7ae1ad5c..e5a37793 100644 --- a/csv/csv.h +++ b/csv/csv.h @@ -7,7 +7,7 @@ #include #include -#ifdef BUILD_opentrack_csv +#ifdef BUILD_csv # define CSV_EXPORT Q_DECL_EXPORT #else # define CSV_EXPORT Q_DECL_IMPORT diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h index c74534e7..28bda986 100644 --- a/opentrack-compat/shm.h +++ b/opentrack-compat/shm.h @@ -28,7 +28,7 @@ # define COMPAT_GNUC_VISIBILITY #endif -#ifdef BUILD_opentrack_compat +#ifdef BUILD_compat # ifdef _WIN32 # define COMPAT_WIN32_EXPORT __declspec(dllexport) # else diff --git a/pose-widget/glwidget.h b/pose-widget/glwidget.h index fca3502d..8896a3cf 100644 --- a/pose-widget/glwidget.h +++ b/pose-widget/glwidget.h @@ -13,7 +13,7 @@ #include "opentrack/plugin-api.hpp" #include "opentrack/simple-mat.hpp" -#ifdef BUILD_opentrack_pose_widget +#ifdef BUILD_pose_widget # define POSE_WIDGET_EXPORT Q_DECL_EXPORT #else # define POSE_WIDGET_EXPORT Q_DECL_IMPORT diff --git a/qxt-mini/qxtglobal.h b/qxt-mini/qxtglobal.h index 64fd35dc..913da556 100644 --- a/qxt-mini/qxtglobal.h +++ b/qxt-mini/qxtglobal.h @@ -51,7 +51,7 @@ #define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE -#ifdef BUILD_opentrack_qxt_mini +#ifdef BUILD_qxt_mini # define QXT_BUILD # define BUILD_QXT_GUI # define BUILD_QXT diff --git a/spline-widget/functionconfig.h b/spline-widget/functionconfig.h index 3d2fc23c..97a80cac 100644 --- a/spline-widget/functionconfig.h +++ b/spline-widget/functionconfig.h @@ -18,7 +18,7 @@ #include #include "opentrack-compat/qcopyable-mutex.hpp" -#ifdef BUILD_opentrack_spline_widget +#ifdef BUILD_spline_widget # define SPLINE_WIDGET_EXPORT Q_DECL_EXPORT #else # define SPLINE_WIDGET_EXPORT Q_DECL_IMPORT -- cgit v1.2.3 From 5a2ddaf39cf5ad86cf43d8a01f51989b5e3afa49 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 09:20:17 +0100 Subject: cmake: export only needed symbols --- cmake/opentrack-macros.cmake | 22 +++++++++++++++------- csv/CMakeLists.txt | 2 +- opentrack-compat/CMakeLists.txt | 2 +- pose-widget/CMakeLists.txt | 2 +- qxt-mini/CMakeLists.txt | 2 +- spline-widget/CMakeLists.txt | 2 +- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/cmake/opentrack-macros.cmake b/cmake/opentrack-macros.cmake index 46cf3c61..9be09397 100644 --- a/cmake/opentrack-macros.cmake +++ b/cmake/opentrack-macros.cmake @@ -32,7 +32,7 @@ endfunction() macro(opentrack_library n dir) cmake_parse_arguments(opentrack-foolib - "NO-LIBRARY;STATIC;NO-COMPAT;NO-LINKER-SCRIPT" + "NO-LIBRARY;STATIC;NO-COMPAT;NO-LINKER-SCRIPT;LINKAGE" "LINK;COMPILE;GNU-LINK;GNU-COMPILE" "" ${ARGN} @@ -54,17 +54,25 @@ macro(opentrack_library n dir) endif() target_link_libraries(${n} ${MY_QT_LIBS}) if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE AND NOT opentrack-foolib_NO-LINKER-SCRIPT) - SET_TARGET_PROPERTIES(${n} PROPERTIES + set_target_properties(${n} PROPERTIES LINK_FLAGS "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} -Wl,--as-needed -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack-compat/${version-script}-version-script.txt\"" COMPILE_FLAGS "${opentrack-foolib_COMPILE} ${opentrack-foolib_GNU-COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden" ) else() - set(link-flags) - if(MSVC) - set(link-flags "${msvc-subsystem} /DEBUG /OPT:ICF") + set(c-props) + set(l-props) + if(opentrack-foolib_LINKAGE AND CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) + set(c-props "${opentrack-foolib_COMPILE} ${opentrack-foolib_GNU-COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden") + set(l-props "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} -Wl,--as-needed") + else() + if(MSVC) + set(l-props "${msvc-subsystem} /DEBUG /OPT:ICF") + endif() endif() - set_target_properties(${n} PROPERTIES LINK_FLAGS "${link-flags} ${opentrack-foolib_LINK}" COMPILE_FLAGS "${opentrack-foolib_COMPILE}") - set(link-flags) + set_target_properties(${n} PROPERTIES + LINK_FLAGS "${l-props} ${opentrack-foolib_LINK}" + COMPILE_FLAGS "${c-props} ${opentrack-foolib_COMPILE}" + ) endif() string(REGEX REPLACE "^opentrack-" "" n_ ${n}) string(REPLACE "-" "_" n_ ${n_}) diff --git a/csv/CMakeLists.txt b/csv/CMakeLists.txt index 7e80317c..7bafc7ff 100644 --- a/csv/CMakeLists.txt +++ b/csv/CMakeLists.txt @@ -1 +1 @@ -opentrack_boilerplate(opentrack-csv NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-csv NO-LINKER-SCRIPT LINKAGE) diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt index a92f4f31..37d53e6c 100644 --- a/opentrack-compat/CMakeLists.txt +++ b/opentrack-compat/CMakeLists.txt @@ -1,4 +1,4 @@ -opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT LINKAGE) if(NOT WIN32 AND NOT APPLE) target_link_libraries(opentrack-compat rt) endif() diff --git a/pose-widget/CMakeLists.txt b/pose-widget/CMakeLists.txt index 66cafef7..e48660d7 100644 --- a/pose-widget/CMakeLists.txt +++ b/pose-widget/CMakeLists.txt @@ -1 +1 @@ -opentrack_boilerplate(opentrack-pose-widget NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-pose-widget NO-LINKER-SCRIPT LINKAGE) diff --git a/qxt-mini/CMakeLists.txt b/qxt-mini/CMakeLists.txt index 5de29cd1..a8b8fb1d 100644 --- a/qxt-mini/CMakeLists.txt +++ b/qxt-mini/CMakeLists.txt @@ -1,5 +1,5 @@ if(UNIX OR APPLE) - opentrack_boilerplate(opentrack-qxt-mini NO-LINKER-SCRIPT NO-COMPAT) + opentrack_boilerplate(opentrack-qxt-mini NO-LINKER-SCRIPT NO-COMPAT LINKAGE) if(NOT APPLE) target_link_libraries(opentrack-qxt-mini X11) else() diff --git a/spline-widget/CMakeLists.txt b/spline-widget/CMakeLists.txt index 93958f50..4d951f92 100644 --- a/spline-widget/CMakeLists.txt +++ b/spline-widget/CMakeLists.txt @@ -1 +1 @@ -opentrack_boilerplate(opentrack-spline-widget NO-LINKER-SCRIPT NO-COMPAT) +opentrack_boilerplate(opentrack-spline-widget NO-LINKER-SCRIPT NO-COMPAT LINKAGE) -- 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 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 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 014e021d36e1096f17d999f42e64e89d3ffd3f01 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:29:34 +0100 Subject: ovr: pass -Wall -Wextra -pedantic --- tracker-rift-080/ftnoir_tracker_rift_080.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.cpp b/tracker-rift-080/ftnoir_tracker_rift_080.cpp index 889ac8c3..ea77b6d1 100644 --- a/tracker-rift-080/ftnoir_tracker_rift_080.cpp +++ b/tracker-rift-080/ftnoir_tracker_rift_080.cpp @@ -21,11 +21,8 @@ Rift_Tracker::~Rift_Tracker() void Rift_Tracker::start_tracker(QFrame*) { - { - ovrInitParams args = {0}; - if (!OVR_SUCCESS(ovr_Initialize(&args))) - goto error; - } + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) + goto error; { ovrGraphicsLuid luid = {0}; ovrResult res = ovr_Create(&hmd, &luid); -- 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(-) 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 1e9579290745f1d375c4ab8b42f710cb1249bcec Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:44:10 +0100 Subject: options-dialog: add missing include --- gui/options-dialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index fef2b0ca..2778be0f 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -10,6 +10,7 @@ #include "keyboard.h" #include #include +#include OptionsDialog::OptionsDialog() { -- 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 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 e82679127004934f44d86aba3854811223abe477 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:44:55 +0100 Subject: qxt: guard against _WIN32 --- qxt-mini/QxtGlobalShortcut | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qxt-mini/QxtGlobalShortcut b/qxt-mini/QxtGlobalShortcut index d673035b..c2827bc2 100644 --- a/qxt-mini/QxtGlobalShortcut +++ b/qxt-mini/QxtGlobalShortcut @@ -1,2 +1,4 @@ -#include "qxtglobalshortcut.h" +#ifndef _WIN32 +# include "qxtglobalshortcut.h" +#endif -- cgit v1.2.3 From b58b72a31083968793dcefa6f38c02a910a7da8a Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:47:05 +0100 Subject: keyboard-chooser: use only keyboard worker, not full shortcuts --- gui/keyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/keyboard.h b/gui/keyboard.h index 62a9ce20..03edacc7 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -2,7 +2,7 @@ #include "ui_keyboard_listener.h" #ifdef _WIN32 #include "opentrack/win32-shortcuts.h" -#include "opentrack/shortcuts.h" +#include "opentrack/keybinding-worker.hpp" #endif #include #include -- cgit v1.2.3 From a1ebe07fb572781ab7a9a7da07f6f6c93a6b7833 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 12:52:54 +0100 Subject: options: whitespace --- opentrack-compat/options.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp index be8c688c..9b03c18f 100644 --- a/opentrack-compat/options.hpp +++ b/opentrack-compat/options.hpp @@ -51,8 +51,7 @@ template using mem = std::shared_ptr; #define OPENTRACK_ORG "opentrack-2.3" namespace options { - template - using map = std::map; + template using map = std::map; using std::string; template @@ -405,7 +404,7 @@ namespace options { b->reload(); } }; - + template inline void tie_setting(value&, q*); -- cgit v1.2.3 From 53fc047667e6e7cf71be13504e003a074b6a83bf Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 13:20:35 +0100 Subject: gui: hidden symbol visibility by default --- gui/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 158804c2..7fec9a15 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -39,4 +39,16 @@ if(LINUX) target_link_libraries(opentrack procps) endif() +set(c-props) +set(l-props) +if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) + set(c-props "-fvisibility=hidden -fvisibility-inlines-hidden") + set(l-props "-Wl,--as-needed") +endif() + +set_target_properties(opentrack PROPERTIES + LINK_FLAGS "${l-props}" + COMPILE_FLAGS "${c-props}" +) + install(TARGETS opentrack DESTINATION .) -- cgit v1.2.3 From 075d7eee2c5c218451246d0407617ea2bf099274 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 14:06:10 +0100 Subject: shm: allow everyone to use the mapping on win32 Issue: #261 --- opentrack-compat/shm.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index 029a4c95..9eb1b90e 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -6,15 +6,115 @@ */ #include +#include #include "shm.h" #if defined(_WIN32) + +#include +#include + +struct secattr +{ + bool success; + SECURITY_DESCRIPTOR* pSD; + SECURITY_ATTRIBUTES attrs; + PSID pEveryoneSID; + PACL pACL; + + void cleanup() + { + if (pEveryoneSID) + FreeSid(pEveryoneSID); + if (pACL) + LocalFree(pACL); + if (pSD) + LocalFree(pSD); + success = false; + pSD = nullptr; + pEveryoneSID = nullptr; + pACL = nullptr; + } + + secattr() : success(true), pSD(nullptr), pEveryoneSID(nullptr), pACL(nullptr) + { + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + EXPLICIT_ACCESS ea; + + if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &pEveryoneSID)) + { + fprintf(stderr, "AllocateAndInitializeSid: %d\n", (int) GetLastError()); + goto cleanup; + } + + memset(&ea, 0, sizeof(ea)); + + ea.grfAccessPermissions = KEY_READ; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; + + if (SetEntriesInAcl(1, &ea, NULL, &pACL) != ERROR_SUCCESS) + { + fprintf(stderr, "SetEntriesInAcl: %d\n", (int) GetLastError()); + goto cleanup; + } + + pSD = (SECURITY_DESCRIPTOR*) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD == nullptr) + { + fprintf(stderr, "LocalAlloc: %d\n", (int) GetLastError()); + goto cleanup; + } + + if (!InitializeSecurityDescriptor(pSD, + SECURITY_DESCRIPTOR_REVISION)) + { + fprintf(stderr, "InitializeSecurityDescriptor: %d\n", (int) GetLastError()); + goto cleanup; + } + + if (!SetSecurityDescriptorDacl(pSD, + TRUE, + pACL, + FALSE)) + { + fprintf(stderr, "SetSecurityDescriptorDacl: %d\n", (int) GetLastError()); + goto cleanup; + } + + attrs.bInheritHandle = false; + attrs.lpSecurityDescriptor = pSD; + attrs.nLength = sizeof(SECURITY_ATTRIBUTES); + + fprintf(stderr, "security descriptor ok\n"); + fflush(stderr); + + return; +cleanup: + fflush(stderr); + cleanup(); + } + + ~secattr() + { + cleanup(); + } +}; + PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize) { - hMutex = CreateMutexA(NULL, false, mutexName); + secattr sa; + + hMutex = CreateMutexA(sa.success ? &sa.attrs : nullptr, false, mutexName); hMapFile = CreateFileMappingA( INVALID_HANDLE_VALUE, - NULL, + sa.success ? &sa.attrs : nullptr, PAGE_READWRITE, 0, mapSize, -- cgit v1.2.3 From fd54d69ff9b1667e22bd3964de2bd06a2ac90cb3 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 17:00:33 +0100 Subject: shm: fix winegcc on osx targetting 10.8 see: [ 74%] Generating opentrack-wrapper-wine.exe.so In file included from /Users/sthalik/dev/opentrack/proto-wine/opentrack-wrapper-wine-windows.cxx:7: In file included from /Users/sthalik/dev/opentrack/opentrack-compat/shm.cpp:9: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdio:108:10: fatal error: 'support/win32/support.h' file not found ^ 1 error generated. winegcc: clang++ failed --- opentrack-compat/shm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index 9eb1b90e..a26b808b 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -6,7 +6,7 @@ */ #include -#include +#include #include "shm.h" #if defined(_WIN32) -- cgit v1.2.3 From 1929fe27e90da135eaa2ffa3654b955d231352ff Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 17:01:13 +0100 Subject: hatire: fix clang warning --- tracker-hatire/ftnoir_tracker_hat_dialog.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracker-hatire/ftnoir_tracker_hat_dialog.h b/tracker-hatire/ftnoir_tracker_hat_dialog.h index ebaffc6d..bd225b3e 100644 --- a/tracker-hatire/ftnoir_tracker_hat_dialog.h +++ b/tracker-hatire/ftnoir_tracker_hat_dialog.h @@ -29,8 +29,8 @@ public: ~TrackerControls() override; #ifdef OPENTRACK_API void Initialize(QWidget *parent) ; // unused - void register_tracker(ITracker *tracker); - void unregister_tracker(); + void register_tracker(ITracker *tracker) override; + void unregister_tracker() override; #else void Initialize(QWidget *parent) ; void registerTracker(ITracker *tracker) ; -- 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(-) 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 2cf3acb8fad9276e9fda412fd011d6c41d6195e6 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 2 Nov 2015 09:04:09 +0100 Subject: shm: guard pragma against non-GNUC --- opentrack-compat/shm.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h index c62976bd..3edb0080 100644 --- a/opentrack-compat/shm.h +++ b/opentrack-compat/shm.h @@ -19,8 +19,10 @@ #include #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wattributes" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wattributes" +#endif #ifdef BUILD_compat # include "compat-export.hpp" @@ -45,4 +47,6 @@ private: #endif }; -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif -- cgit v1.2.3 From 94ce93cf0ba816d5748244ae4ef740396956350d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 2 Nov 2015 12:11:45 +0100 Subject: ht: disconnect the face tracker from build It performs awfully, also needs run in subprocess since flandmark is GPL3. --- tracker-ht/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tracker-ht/CMakeLists.txt b/tracker-ht/CMakeLists.txt index 248a113e..cbbda108 100644 --- a/tracker-ht/CMakeLists.txt +++ b/tracker-ht/CMakeLists.txt @@ -1,3 +1,4 @@ +if(FALSE) set(SDK_HT "" CACHE FILEPATH "Path to headtracker library") set(SDK_HT_FLANDMARK "" CACHE FILEPATH "Path to flandmark library for headtracker") find_package(OpenCV 3.0 QUIET) @@ -9,3 +10,4 @@ if(OpenCV_FOUND) target_include_directories(opentrack-tracker-ht SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) endif() endif() +endif() -- cgit v1.2.3 From 8563a6cc6bd11dcca87e77eb922252b7ddf532e0 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 2 Nov 2015 12:49:31 +0100 Subject: freetrack: new game support --- settings/facetracknoir supported games.csv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/settings/facetracknoir supported games.csv b/settings/facetracknoir supported games.csv index cf43d7f6..a08d4171 100644 --- a/settings/facetracknoir supported games.csv +++ b/settings/facetracknoir supported games.csv @@ -286,8 +286,8 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 225;ManuVAR;FreeTrack20;V160;;;20455;00E153FE1E901CB0448800 226;MaqSIM4;FreeTrack20;V160;;;20026;00E28F54A207D29B611700 227;Mech Tactical Sim;FreeTrack20;V160;;;9501;00E3F3E85B1A8E34A53300 -228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200 516;MechWarrior Online;FreeTrack20;V170;;;3026;0BD2E0DCBC723836CD2400 +228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200 229;Medical Image Visualization;FreeTrack20;V160;;;20295;00E59343488532A5359B00 230;Meggitt Defense Systems;FreeTrack20;V160;;;20045;00E6926ED9122AB22AF300 231;MetaVR;FreeTrack20;V160;;;20545;00E7C5BEE48120A8308800 @@ -474,6 +474,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 381;Tenstar Simulator;FreeTrack20;V160;;;20605;017D318F88A2EA62DBA200 382;Test Drive Unlimited;FreeTrack20;V160;;;13201;017E6F2699559730A84000 509;Tetrahedral;FreeTrack20;V160;;;3525;01FDCFF1C56D6F757E8200 +576;The Battle of Sol;FreeTrack20;V160;;;4575;02408ED99EB5DF5D79A800 501;The Crew;FreeTrack20;V170;;;1009;03F1F534E94F4834D9B100 488;The Gallery;FreeTrack20;V160;;;3350;01E8CE152EDE5FFD267700 383;The Sky Gods;FreeTrack20;V170;;;1525;017FDFF782DCCEEA27C200 -- cgit v1.2.3 From 9da1484e6c1bbd130a6b618f72efb0acf222e548 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Tue, 3 Nov 2015 09:58:13 +0100 Subject: cmake: can use default hidden visibility on apple --- cmake/opentrack-macros.cmake | 8 ++++++-- gui/CMakeLists.txt | 6 ++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cmake/opentrack-macros.cmake b/cmake/opentrack-macros.cmake index 9be09397..d84f9175 100644 --- a/cmake/opentrack-macros.cmake +++ b/cmake/opentrack-macros.cmake @@ -53,9 +53,13 @@ macro(opentrack_library n dir) target_link_libraries(${n} opentrack-api opentrack-compat) endif() target_link_libraries(${n} ${MY_QT_LIBS}) - if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE AND NOT opentrack-foolib_NO-LINKER-SCRIPT) + if(CMAKE_COMPILER_IS_GNUCXX AND NOT opentrack-foolib_NO-LINKER-SCRIPT) + set(l-flags) + if(NOT APPLE) + set(l-flags "-Wl,--as-needed -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack-compat/${version-script}-version-script.txt\"") + endif() set_target_properties(${n} PROPERTIES - LINK_FLAGS "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} -Wl,--as-needed -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack-compat/${version-script}-version-script.txt\"" + LINK_FLAGS "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} ${l-flags}" COMPILE_FLAGS "${opentrack-foolib_COMPILE} ${opentrack-foolib_GNU-COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden" ) else() diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 7fec9a15..d34ea981 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -41,9 +41,11 @@ endif() set(c-props) set(l-props) -if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) +if(CMAKE_COMPILER_IS_GNUCXX) set(c-props "-fvisibility=hidden -fvisibility-inlines-hidden") - set(l-props "-Wl,--as-needed") + if(NOT APPLE) + set(l-props "-Wl,--as-needed") + endif() endif() set_target_properties(opentrack PROPERTIES -- cgit v1.2.3 From ae71a80a7b84899fd9d8c64265a7509e71f2c380 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 5 Nov 2015 06:02:54 +0100 Subject: shm: set right permissions for the mapping Fix a copy-paste error. --- opentrack-compat/shm.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index a26b808b..fffb3709 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -36,7 +36,7 @@ struct secattr pACL = nullptr; } - secattr() : success(true), pSD(nullptr), pEveryoneSID(nullptr), pACL(nullptr) + secattr(DWORD perms) : success(true), pSD(nullptr), pEveryoneSID(nullptr), pACL(nullptr) { SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; EXPLICIT_ACCESS ea; @@ -52,7 +52,7 @@ struct secattr memset(&ea, 0, sizeof(ea)); - ea.grfAccessPermissions = KEY_READ; + ea.grfAccessPermissions = perms; ea.grfAccessMode = SET_ACCESS; ea.grfInheritance = NO_INHERITANCE; ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; @@ -109,9 +109,14 @@ cleanup: PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize) { - secattr sa; + secattr sa(GENERIC_ALL|SYNCHRONIZE); hMutex = CreateMutexA(sa.success ? &sa.attrs : nullptr, false, mutexName); + if (!hMutex) + { + fprintf(stderr, "CreateMutexA: %d\n", (int) GetLastError()); + fflush(stderr); + } hMapFile = CreateFileMappingA( INVALID_HANDLE_VALUE, sa.success ? &sa.attrs : nullptr, @@ -119,11 +124,21 @@ PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, 0, mapSize, shmName); + if (!hMapFile) + { + fprintf(stderr, "CreateFileMappingA: %d\n", (int) GetLastError()); + fflush(stderr); + } mem = MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, mapSize); + if (!mem) + { + fprintf(stderr, "MapViewOfFile: %d\n", (int) GetLastError()); + fflush(stderr); + } } PortableLockedShm::~PortableLockedShm() -- cgit v1.2.3 From 0fb267c19925a949a8b1f8c62d9fbe52ba821d3d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 6 Nov 2015 00:44:35 +0100 Subject: qfc: always ensure at least one point exists Previously, insertion of the lone point was postponed until opening the mapping window. --- spline-widget/functionconfig.cpp | 6 +++++- spline-widget/functionconfig.h | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/spline-widget/functionconfig.cpp b/spline-widget/functionconfig.cpp index dcc9ca65..33100e07 100644 --- a/spline-widget/functionconfig.cpp +++ b/spline-widget/functionconfig.cpp @@ -219,7 +219,11 @@ void Map::loadSettings(QSettings& settings, const QString& title) { void Map::saveSettings(QSettings& settings, const QString& title) { QMutexLocker foo(&_mutex); settings.beginGroup(QString("Curves-%1").arg(title)); - int max = cur.input.size(); + + if (cur.input.size() == 0) + cur.input.push_back(QPointF(max_x, max_y)); + + const int max = cur.input.size(); settings.setValue("point-count", max); for (int i = 0; i < max; i++) { diff --git a/spline-widget/functionconfig.h b/spline-widget/functionconfig.h index 97a80cac..145ee14e 100644 --- a/spline-widget/functionconfig.h +++ b/spline-widget/functionconfig.h @@ -30,7 +30,7 @@ private: struct State { QList input; - std::vector data; + std::vector data; }; int precision() const; @@ -52,6 +52,8 @@ public: { setMaxInput(maxx); setMaxOutput(maxy); + if (cur.input.size() == 0) + cur.input.push_back(QPointF(maxx, maxy)); reload(); } -- cgit v1.2.3 From 2521a7918783758928a58f6032ca6fad53a89c01 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 6 Nov 2015 21:18:13 +0100 Subject: spline: snap x, y coordinates to grid --- gui/curve-config.cpp | 6 ++++++ spline-widget/qfunctionconfigurator.cpp | 13 ++++++++++--- spline-widget/qfunctionconfigurator.h | 3 +++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/gui/curve-config.cpp b/gui/curve-config.cpp index 2e9065b4..7cd78580 100644 --- a/gui/curve-config.cpp +++ b/gui/curve-config.cpp @@ -54,6 +54,12 @@ MapWidget::MapWidget(Mappings& m, main_settings& s) : qfc.setEnabled(qfcs[i].checkbox->isChecked()); qfc.force_redraw(); } + + if (qfcs[i].axis >= 3) + qfcs[i].qfc->set_snap(2, 5); + else + qfcs[i].qfc->set_snap(1, 5); + qfcs[i].qfc->setConfig(conf, name); } } diff --git a/spline-widget/qfunctionconfigurator.cpp b/spline-widget/qfunctionconfigurator.cpp index 5d910826..112b5457 100644 --- a/spline-widget/qfunctionconfigurator.cpp +++ b/spline-widget/qfunctionconfigurator.cpp @@ -21,7 +21,9 @@ QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) : QWidget(parent), _config(nullptr), moving_control_point_idx(-1), - _draw_function(true) + _draw_function(true), + snap_x(0), + snap_y(0) { update_range(); setMouseTracking(true); @@ -412,8 +414,13 @@ QPointF QFunctionConfigurator::pixel_coord_to_point(const QPointF& point) if (!_config) return QPointF(-1, -1); - double x = (point.x() - pixel_bounds.x()) / c.x(); - double y = (pixel_bounds.height() - point.y() + pixel_bounds.y()) / c.y(); + int x = (point.x() - pixel_bounds.x()) / c.x(); + int y = (pixel_bounds.height() - point.y() + pixel_bounds.y()) / c.y(); + + if (snap_x > 0) + x -= x % snap_x; + if (snap_y > 0) + y -= y % snap_y; if (x < 0) x = 0; diff --git a/spline-widget/qfunctionconfigurator.h b/spline-widget/qfunctionconfigurator.h index 4a9cb5f1..d4ba904a 100644 --- a/spline-widget/qfunctionconfigurator.h +++ b/spline-widget/qfunctionconfigurator.h @@ -39,6 +39,8 @@ public: _background = QPixmap(); update(); } + void set_snap(int x, int y) { snap_x = x; snap_y = y; } + void get_snap(int& x, int& y) const { x = snap_x; y = snap_y; } protected slots: void paintEvent(QPaintEvent *e) override; void mousePressEvent(QMouseEvent *e) override; @@ -72,4 +74,5 @@ private: QPixmap _background; QPixmap _function; bool _draw_function; + int snap_x, snap_y; }; -- 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 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 c4c3e746f030e6c5e5a1f8b88762fae95d1b9225 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 06:14:13 +0100 Subject: options: konst korrektness --- opentrack-compat/options.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp index 9b03c18f..3e4fb20e 100644 --- a/opentrack-compat/options.hpp +++ b/opentrack-compat/options.hpp @@ -382,7 +382,7 @@ namespace options { 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() + operator t() const { return b->contains(self_name) ? b->get(self_name) : def; } -- 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(-) 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(-) 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(-) 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(+) 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(+) 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(+) 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(+) 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(-) 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 e8edf8b4498ff79ae62751cadb9b61ac6569e25d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 15:29:07 +0100 Subject: options: stringify keyboard mods for joy buttons --- gui/options-dialog.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 4cff6e77..9631d41e 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -15,7 +15,15 @@ static QString kopts_to_string(const Shortcuts::key_opts& kopts) { if (static_cast(kopts.guid) != "") - return "Joystick button " + QString::number(kopts.button); + { + const int btn = kopts.button & ~Qt::KeyboardModifierMask; + const int mods = kopts.button & Qt::KeyboardModifierMask; + QString mm; + if (mods & Qt::ControlModifier) mm += "Control+"; + if (mods & Qt::AltModifier) mm += "Alt+"; + if (mods & Qt::ShiftModifier) mm += "Shift+"; + return mm + "Joy button " + QString::number(btn); + } if (static_cast(kopts.keycode) == "") return "None"; return kopts.keycode; -- 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(-) 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 c960436a9f6bdecce8f7cfa0d022569c9fda229d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 16:10:07 +0100 Subject: installer: fix path to icon only --- installer/opentrack-installer.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/opentrack-installer.iss b/installer/opentrack-installer.iss index 65a1ff93..c29bc4a3 100755 --- a/installer/opentrack-installer.iss +++ b/installer/opentrack-installer.iss @@ -24,7 +24,7 @@ DefaultDirName={pf}\{#MyAppName} DefaultGroupName={#MyAppName} AllowNoIcons=yes OutputBaseFilename={#MyAppVersion}-win32-setup -SetupIconFile=..\facetracknoir\facetracknoir.ico +SetupIconFile=..\gui\facetracknoir.ico Compression=lzma2/ultra64 SolidCompression=yes DisableWelcomePage=True -- 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(-) 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(-) 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 73c62db8a98e676328a17569b821a0fb3c397a39 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 16 Nov 2015 09:45:19 +0100 Subject: tracker/win32-joy: forgot to save stick index Issue: #267 --- .../ftnoir_tracker_joystick_dialog.cpp | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp index 0463933f..26436c7a 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -9,8 +9,6 @@ static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance TrackerControls::joys cur { name, guid }; self->_joys.append(cur); - self->ui.joylist->addItem(name + " " + guid); - return DIENUM_CONTINUE; } @@ -40,6 +38,27 @@ fin: if (g_pDI) g_pDI->Release(); } + + std::sort(_joys.begin(), + _joys.end(), + [&](const joys& j1, const joys& j2) -> bool + { + if (j1.name == j2.name) + return j1.guid < j2.guid; + return j1.name < j2.name; + }); + + { + 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) + idx = i; + ui.joylist->addItem(j.name + " " + j.guid); + } + ui.joylist->setCurrentIndex(idx); + } tie_setting(s.joy_1, ui.joy_1); tie_setting(s.joy_2, ui.joy_2); -- 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(-) 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 411d85cf66d89696ba51f5bc44d92322613e2e9f Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 19 Nov 2015 01:42:40 +0100 Subject: tracker/joystick: avoid recursive acquire of non-recursive mutex --- tracker-joystick/ftnoir_tracker_joystick.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp index 77fd7241..742ce972 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -19,17 +19,20 @@ FTNoIR_Tracker::FTNoIR_Tracker() : void FTNoIR_Tracker::reload() { s.b->reload(); - QMutexLocker foo(&mtx); - if (g_pJoystick) { - g_pJoystick->Unacquire(); - g_pJoystick->Release(); + QMutexLocker foo(&mtx); + + if (g_pJoystick) + { + g_pJoystick->Unacquire(); + g_pJoystick->Release(); + } + if (g_pDI) + g_pDI->Release(); + + g_pJoystick = nullptr; + g_pDI = nullptr; } - if (g_pDI) - g_pDI->Release(); - - g_pJoystick = nullptr; - g_pDI = nullptr; start_tracker(frame); } -- cgit v1.2.3 From 763da906a83b80eadb736008dbb558b809552505 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Thu, 19 Nov 2015 14:34:26 +0100 Subject: tracker-rs: updated RealSense SDK version to R5 --- tracker-rs/CMakeLists.txt | 2 +- tracker-rs/ftnoir_tracker_rs.cpp | 6 +++--- tracker-rs/ftnoir_tracker_rs_controls.cpp | 2 +- .../intel_rs_sdk_runtime_websetup_6.0.21.6598.exe | Bin 780456 -> 0 bytes .../intel_rs_sdk_runtime_websetup_7.0.23.6161.exe | Bin 0 -> 1203240 bytes .../rs_impl/bin/opentrack-tracker-rs-impl.exe | Bin 83968 -> 93696 bytes tracker-rs/rs_impl/build.bat | 6 +++++- 7 files changed, 10 insertions(+), 6 deletions(-) delete mode 100644 tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe create mode 100644 tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe diff --git a/tracker-rs/CMakeLists.txt b/tracker-rs/CMakeLists.txt index f4f6d4b9..24dd5c74 100644 --- a/tracker-rs/CMakeLists.txt +++ b/tracker-rs/CMakeLists.txt @@ -1,5 +1,5 @@ if(WIN32) opentrack_boilerplate(opentrack-tracker-rs) install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe" DESTINATION . ${opentrack-perms}) - install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe" DESTINATION ./contrib/ ${opentrack-perms}) + install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe" DESTINATION ./contrib/ ${opentrack-perms}) endif() diff --git a/tracker-rs/ftnoir_tracker_rs.cpp b/tracker-rs/ftnoir_tracker_rs.cpp index 3e9b23c8..42224428 100644 --- a/tracker-rs/ftnoir_tracker_rs.cpp +++ b/tracker-rs/ftnoir_tracker_rs.cpp @@ -71,17 +71,17 @@ void RSTracker::rsImplProcessFinished(int exitCode){ msgBox.setIcon(QMessageBox::Critical); msgBox.setText("RealSense Tracking Error"); if(exitCode==-101){ //The implementation got an invalid handle from the RealSense SDK session/modules - msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please install SDK Runtime R4."); + msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please install SDK Runtime R5."); } else { - msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime R4 to be installed."); + msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime R5 to be installed."); } QPushButton* triggerSdkInstallation = msgBox.addButton("Install Runtime", QMessageBox::ActionRole); msgBox.addButton(QMessageBox::Ok); msgBox.exec(); if(msgBox.clickedButton() == triggerSdkInstallation){ - bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); + bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.6161.exe --finstall=core,face3d --fnone=all"); if(!pStarted){ QMessageBox::warning(0, "Intel® RealSense™ Runtime Installation", "Installation process failed to start.", QMessageBox::Ok); } diff --git a/tracker-rs/ftnoir_tracker_rs_controls.cpp b/tracker-rs/ftnoir_tracker_rs_controls.cpp index 6c71d58f..b97ab9d0 100644 --- a/tracker-rs/ftnoir_tracker_rs_controls.cpp +++ b/tracker-rs/ftnoir_tracker_rs_controls.cpp @@ -20,7 +20,7 @@ RSTrackerControls::RSTrackerControls() void RSTrackerControls::doInstallRSRuntime() { - bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); + bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.6161.exe --finstall=core,face3d --fnone=all"); if(processStarted){ this->close(); } diff --git a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe deleted file mode 100644 index 34ecc9df..00000000 Binary files a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe and /dev/null differ diff --git a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe new file mode 100644 index 00000000..2c16bd93 Binary files /dev/null and b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe differ diff --git a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe index 1e2a57f1..f7023255 100644 Binary files a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe and b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe differ diff --git a/tracker-rs/rs_impl/build.bat b/tracker-rs/rs_impl/build.bat index 15206431..3a44fed5 100644 --- a/tracker-rs/rs_impl/build.bat +++ b/tracker-rs/rs_impl/build.bat @@ -1,2 +1,6 @@ -cd "%VS120COMNTOOLS%\..\..\VC" +IF DEFINED %VS120COMNTOOLS%] ( + cd "%VS120COMNTOOLS%\..\..\VC" + ) ELSE ( + cd "%VS140COMNTOOLS%\..\..\VC" + ) vcvarsall x64 && cd %~dp0 && CL /nologo /Ox /DUNICODE /D_UNICODE /MT /I"%RSSDK_DIR%\opensource\include" ftnoir_tracker_rs_impl.cpp udp_sender.cpp "%RSSDK_DIR%\opensource\src\libpxc\libpxc.cpp" /link ADVAPI32.LIB Ws2_32.lib /SUBSYSTEM:CONSOLE /OUT:bin\opentrack-tracker-rs-impl.exe \ No newline at end of file -- 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(-) 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(-) 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 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 7075c9a3612f39edf4f068705f7a1ebc4ad0614e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:12:55 +0100 Subject: tracker/joy: use the centralized joystick state worker Most of the code can be removed. --- tracker-joystick/ftnoir_tracker_joystick.cpp | 230 ++------------------- tracker-joystick/ftnoir_tracker_joystick.h | 37 +--- .../ftnoir_tracker_joystick_dialog.cpp | 46 +---- 3 files changed, 28 insertions(+), 285 deletions(-) diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp index 742ce972..4c180eaa 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -8,223 +8,20 @@ #include "opentrack/plugin-api.hpp" #include -FTNoIR_Tracker::FTNoIR_Tracker() : - g_pDI(nullptr), - g_pJoystick(nullptr), - mtx(QMutex::Recursive), - iter(-1) +FTNoIR_Tracker::FTNoIR_Tracker() { } -void FTNoIR_Tracker::reload() -{ - s.b->reload(); - { - QMutexLocker foo(&mtx); - - if (g_pJoystick) - { - g_pJoystick->Unacquire(); - g_pJoystick->Release(); - } - if (g_pDI) - g_pDI->Release(); - - g_pJoystick = nullptr; - g_pDI = nullptr; - } - - start_tracker(frame); -} - FTNoIR_Tracker::~FTNoIR_Tracker() { - if (g_pJoystick) - { - g_pJoystick->Unacquire(); - g_pJoystick->Release(); - } - if (g_pDI) - { - g_pDI->Release(); - } -} - -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, - VOID* pContext ) -{ - auto self = (FTNoIR_Tracker*) pContext; - - if( pdidoi->dwType & DIDFT_AXIS ) - { - DIPROPRANGE diprg = {0}; - diprg.diph.dwSize = sizeof( DIPROPRANGE ); - diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); - diprg.diph.dwHow = DIPH_BYID; - diprg.diph.dwObj = pdidoi->dwType; - diprg.lMax = FTNoIR_Tracker::AXIS_MAX; - diprg.lMin = -FTNoIR_Tracker::AXIS_MAX; - - if( FAILED( self->g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) - return DIENUM_STOP; - - self->iter++; - } - - return self->iter == 8 ? DIENUM_STOP : DIENUM_CONTINUE; -} - -static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) -{ - auto self = reinterpret_cast(pContext); - bool stop = QString(pdidInstance->tszInstanceName) == self->s.joyid; - - if (stop) - { - if (self->guid_to_check.size()) - { - QString guid = guid_to_string(pdidInstance->guidInstance); - if (guid != self->guid_to_check) - { - return DIENUM_CONTINUE; - } - else - qDebug() << "guid ok" << self->guid_to_check; - } - - (void) self->g_pDI->CreateDevice( pdidInstance->guidInstance, &self->g_pJoystick, NULL); - qDebug() << "device" << static_cast(self->s.joyid); - } - - return stop ? DIENUM_STOP : DIENUM_CONTINUE; } -void FTNoIR_Tracker::start_tracker(QFrame* frame) +void FTNoIR_Tracker::start_tracker(QFrame*) { - QMutexLocker foo(&mtx); - this->frame = frame; - iter = 0; - auto hr = CoInitialize( nullptr ); - - if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, - IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) - { - qDebug() << "create"; - goto fail; - } - - guid_to_check = s.guid; - - if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) - { - qDebug() << "enum1"; - goto fail; - } - - if (!g_pJoystick && guid_to_check.size()) - { - guid_to_check = ""; - - if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) - { - qDebug() << "enum2"; - goto fail; - } - } - - if (!g_pJoystick) - { - qDebug() << "ENODEV"; - goto fail; - } - - if (FAILED(g_pJoystick->SetDataFormat(&c_dfDIJoystick))) - { - qDebug() << "format"; - goto fail; - } - - if (FAILED(g_pJoystick->SetCooperativeLevel((HWND) frame->window()->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) - { - qDebug() << "coop"; - goto fail; - } - - iter = 0; - - if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback, - ( VOID* )this, DIDFT_ALL ))) - { - qDebug() << "enum axes"; - goto fail; - } - - return; - -fail: - if (g_pJoystick) - g_pJoystick->Release(); - if (g_pDI) - g_pDI->Release(); - g_pJoystick = nullptr; - g_pDI = nullptr; - - qDebug() << "joy init failure"; } void FTNoIR_Tracker::data(double *data) { - QMutexLocker foo(&mtx); - DIJOYSTATE js = {0}; - - if( !g_pDI || !g_pJoystick) - return; - - bool ok = false; - - for (int i = 0; i < 100; i++) - { - if (!FAILED(g_pJoystick->Poll())) - { - ok = true; - break; - } - if (g_pJoystick->Acquire() != DI_OK) - continue; - else - ok = true; - break; - } - - if (!ok) - return; - - HRESULT hr = 0; - - if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof( js ), &js ) ) ) - return; - - const LONG values[] = { - js.lX, - js.lY, - js.lZ, - js.lRx, - js.lRy, - js.lRz, - js.rglSlider[0], - js.rglSlider[1] - }; - int map[6] = { s.joy_1 - 1, s.joy_2 - 1, @@ -242,14 +39,21 @@ void FTNoIR_Tracker::data(double *data) 180, 180 }; - - for (int i = 0; i < 6; i++) - { - int k = map[i] - 1; - if (k < 0 || k >= 8) - data[i] = 0; - else - data[i] = values[k] * limits[i] / AXIS_MAX; + + const QString guid = s.guid; + int axes[8]; + const bool ret = joy_ctx.poll_axis(guid, axes); + + if (ret) + { + for (int i = 0; i < 6; i++) + { + int k = map[i] - 1; + if (k < 0 || k >= 8) + data[i] = 0; + else + data[i] = axes[k] * limits[i] / AXIS_MAX; + } } } diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 29e65af1..18ac349e 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -12,21 +12,12 @@ #include #include #include -#include #include #include #include #include "opentrack/plugin-api.hpp" -#ifndef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x800 -#endif -#include -#include -#include -#include -#include -#include +#include "opentrack/win32-joystick-shortcuts.hpp" #include "opentrack-compat/options.hpp" using namespace options; @@ -46,35 +37,17 @@ struct settings : opts { {} }; -template -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); -} - class FTNoIR_Tracker : public ITracker { public: FTNoIR_Tracker(); ~FTNoIR_Tracker(); - void start_tracker(QFrame *frame); + void start_tracker(QFrame *); void data(double *data); - void reload(); - LPDIRECTINPUT8 g_pDI; - LPDIRECTINPUTDEVICE8 g_pJoystick; - QMutex mtx; - QFrame* frame; - DIDEVICEINSTANCE def; - int iter; // XXX bad style settings s; - QString guid_to_check; - static constexpr int AXIS_MAX = 65535; + QString guid; + static constexpr int AXIS_MAX = win32_joy_ctx::joy_axis_size - 1; + 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 26436c7a..28846809 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -1,17 +1,6 @@ #include "ftnoir_tracker_joystick.h" #include "opentrack/plugin-api.hpp" -static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) -{ - auto self = ( TrackerControls* )pContext; - auto name = QString(pdidInstance->tszInstanceName); - auto guid = guid_to_string(pdidInstance->guidInstance); - TrackerControls::joys cur { name, guid }; - self->_joys.append(cur); - - return DIENUM_CONTINUE; -} - TrackerControls::TrackerControls() : tracker(nullptr) { ui.setupUi( this ); @@ -21,33 +10,14 @@ TrackerControls::TrackerControls() : tracker(nullptr) connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); { - auto hr = CoInitialize( nullptr ); - LPDIRECTINPUT8 g_pDI = nullptr; - - if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, - IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) - goto fin; - - if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY ))) - goto fin; - -fin: - if (g_pDI) - g_pDI->Release(); + win32_joy_ctx joy_ctx; + + _joys = QList(); + + for (auto& j : joy_ctx.joys()) + _joys.push_back(joys { j.second->name, j.first }); } - std::sort(_joys.begin(), - _joys.end(), - [&](const joys& j1, const joys& j2) -> bool - { - if (j1.name == j2.name) - return j1.guid < j2.guid; - return j1.name < j2.name; - }); - { int idx = 0; for (int i = 0; i < _joys.size(); i++) @@ -75,8 +45,6 @@ void TrackerControls::doOK() { s.guid = val.guid; s.joyid = val.name; s.b->save(); - if (tracker) - tracker->reload(); this->close(); } @@ -84,5 +52,3 @@ void TrackerControls::doCancel() { s.b->reload(); this->close(); } - - -- cgit v1.2.3 From e44b2853196565ebd22eb1e27109e5e54e77ed15 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:13:47 +0100 Subject: compat/options: no need to heap-alloc here --- opentrack-compat/options.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp index 91cd3664..48cc514b 100644 --- a/opentrack-compat/options.cpp +++ b/opentrack-compat/options.cpp @@ -7,8 +7,8 @@ namespace detail { OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() { - static auto ret = std::make_shared(); - return *ret; + static opt_singleton ret; + return ret; } } -- 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(-) 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(-) 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 34483211fc182df6b85cb344759819d80ed9d142 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:51:11 +0100 Subject: tracker/joy: don't save joy friendly name We don't need it for joy selection --- tracker-joystick/ftnoir_tracker_joystick.h | 3 +-- tracker-joystick/ftnoir_tracker_joystick_dialog.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index e94e2ee7..67061585 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -22,11 +22,10 @@ using namespace options; struct settings : opts { - value joyid, guid; + value guid; value joy_1, joy_2, joy_3, joy_4, joy_5, joy_6; settings() : opts("tracker-joystick"), - joyid(b, "joy-id", ""), guid(b, "joy-guid", ""), joy_1(b, "axis-map-1", 1), joy_2(b, "axis-map-2", 2), diff --git a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp index 1ca1441c..0a630c1e 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -44,7 +44,6 @@ void TrackerControls::doOK() { joys def { "", "" }; auto val = _joys.value(idx, def); s.guid = val.guid; - s.joyid = val.name; s.b->save(); this->close(); } -- 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(+) 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 1dd600c77c4b38c8b0531a02f061915d8234e30d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 16:02:41 +0100 Subject: cmake: default to tarball build at -j4 --- make-tar.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make-tar.sh b/make-tar.sh index 3e119d12..08114127 100644 --- a/make-tar.sh +++ b/make-tar.sh @@ -4,7 +4,7 @@ prefix="$1" filename="$2" bin="$3" -cmake --build "$bin" --target install || exit 1 +cmake --build "$bin" --target install -- -j4 || exit 1 if : && cd $(dirname -- "${prefix}") && -- 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 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(-) 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(-) 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(-) 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 60772640a27d316fe7301117fc74af78859da8db Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 18:08:11 +0100 Subject: cmake: build osx .app only after install By accident tarball was build prior to install qxt-mini. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16ee3be3..fef1baed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ file(GLOB opentrack-subprojects "csv/${C}" "pose-widget/${C}" "spline-widget/${C}" - "macosx/${C}" "qxt-mini/${C}" + "macosx/${C}" ) foreach(i ${opentrack-subprojects}) get_filename_component(i ${i} DIRECTORY) -- 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(-) 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(-) 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 e8c5d0cde6676c7924c92cd43ac36588a401c8e4 Mon Sep 17 00:00:00 2001 From: Stanisław Halik Date: Tue, 24 Nov 2015 17:16:52 +0100 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 82327af9..f837b847 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Not to be confused with railway planning software <> # Tracking sources - PointTracker by Patrick Ruoff, freetrack-like light sources -- Oculus Rift DK2 +- Oculus Rift DK1, DK2 and legacy versions - Paper marker support via the ArUco library <> - Human face tracker <> - Razer Hydra -- 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(-) 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(-) 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 62f67b76a17b201abd140892c3bd66a95b4489cf Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Thu, 26 Nov 2015 16:55:48 +0100 Subject: tracker/rs: updated RealSense SDK to R5-HF1 --- tracker-rs/CMakeLists.txt | 2 +- tracker-rs/ftnoir_tracker_rs.cpp | 2 +- tracker-rs/ftnoir_tracker_rs_controls.cpp | 2 +- .../intel_rs_sdk_runtime_websetup_7.0.23.6161.exe | Bin 1203240 -> 0 bytes .../intel_rs_sdk_runtime_websetup_7.0.23.8048.exe | Bin 0 -> 1203240 bytes .../rs_impl/bin/opentrack-tracker-rs-impl.exe | Bin 93696 -> 93696 bytes 6 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe create mode 100644 tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe diff --git a/tracker-rs/CMakeLists.txt b/tracker-rs/CMakeLists.txt index 24dd5c74..901d68bb 100644 --- a/tracker-rs/CMakeLists.txt +++ b/tracker-rs/CMakeLists.txt @@ -1,5 +1,5 @@ if(WIN32) opentrack_boilerplate(opentrack-tracker-rs) install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe" DESTINATION . ${opentrack-perms}) - install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe" DESTINATION ./contrib/ ${opentrack-perms}) + install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe" DESTINATION ./contrib/ ${opentrack-perms}) endif() diff --git a/tracker-rs/ftnoir_tracker_rs.cpp b/tracker-rs/ftnoir_tracker_rs.cpp index 42224428..e073fa3f 100644 --- a/tracker-rs/ftnoir_tracker_rs.cpp +++ b/tracker-rs/ftnoir_tracker_rs.cpp @@ -81,7 +81,7 @@ void RSTracker::rsImplProcessFinished(int exitCode){ msgBox.exec(); if(msgBox.clickedButton() == triggerSdkInstallation){ - bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.6161.exe --finstall=core,face3d --fnone=all"); + bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.8048.exe --finstall=core,face3d --fnone=all"); if(!pStarted){ QMessageBox::warning(0, "Intel® RealSense™ Runtime Installation", "Installation process failed to start.", QMessageBox::Ok); } diff --git a/tracker-rs/ftnoir_tracker_rs_controls.cpp b/tracker-rs/ftnoir_tracker_rs_controls.cpp index b97ab9d0..be18b3f8 100644 --- a/tracker-rs/ftnoir_tracker_rs_controls.cpp +++ b/tracker-rs/ftnoir_tracker_rs_controls.cpp @@ -20,7 +20,7 @@ RSTrackerControls::RSTrackerControls() void RSTrackerControls::doInstallRSRuntime() { - bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.6161.exe --finstall=core,face3d --fnone=all"); + bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.8048.exe --finstall=core,face3d --fnone=all"); if(processStarted){ this->close(); } diff --git a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe deleted file mode 100644 index 2c16bd93..00000000 Binary files a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.6161.exe and /dev/null differ diff --git a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe new file mode 100644 index 00000000..2e2b365c Binary files /dev/null and b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe differ diff --git a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe index f7023255..e00ed69c 100644 Binary files a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe and b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe differ -- cgit v1.2.3 From 946330846e7a33fc5357a91f4d2a7ef9bea6af02 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Thu, 26 Nov 2015 17:12:40 +0100 Subject: tracker/rs adjusted UI to reflect SDK update --- tracker-rs/ftnoir_tracker_rs_controls.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracker-rs/ftnoir_tracker_rs_controls.ui b/tracker-rs/ftnoir_tracker_rs_controls.ui index 834803d1..023e14d3 100644 --- a/tracker-rs/ftnoir_tracker_rs_controls.ui +++ b/tracker-rs/ftnoir_tracker_rs_controls.ui @@ -37,14 +37,14 @@ Intel® RealSense™ SDK. By design, the application has no direct access to any camera images. In order to use this tracker, you need a PC equipped with -an Intel® RealSense™ R200 camera and the RealSense™ SDK R4 runtime. +an Intel® RealSense™ R200 camera and the RealSense™ SDK R5 runtime. - Install SDK Runtime R4 + Install SDK Runtime R5 -- cgit v1.2.3 From fdf6585e61e7e76abee0ddf5bd02db79885d42ec Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 26 Nov 2015 09:26:58 +0100 Subject: qfc: use euclidean distance to point Don't use rectangle bounding box for circles --- spline-widget/qfunctionconfigurator.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spline-widget/qfunctionconfigurator.cpp b/spline-widget/qfunctionconfigurator.cpp index 112b5457..3df9fc9c 100644 --- a/spline-widget/qfunctionconfigurator.cpp +++ b/spline-widget/qfunctionconfigurator.cpp @@ -404,9 +404,8 @@ void QFunctionConfigurator::update_range() bool QFunctionConfigurator::point_within_pixel(const QPointF &pt, const QPointF &pixel) { - QPointF pixel2 = point_to_pixel(pt); - return pixel2.x() >= pixel.x() - pointSize && pixel2.x() < pixel.x() + pointSize && - pixel2.y() >= pixel.y() - pointSize && pixel2.y() < pixel.y() + pointSize; + QPointF tmp = pixel - point_to_pixel(pt); + return sqrt(QPointF::dotProduct(tmp, tmp)) < pointSize; } QPointF QFunctionConfigurator::pixel_coord_to_point(const QPointF& point) -- cgit v1.2.3 From c1ec8841f10bc647f9d27adb19f81c67f2b805fb Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 26 Nov 2015 09:27:47 +0100 Subject: fixup! qfc: use euclidean distance to point Don't use rectangle bounding box for circles --- spline-widget/qfunctionconfigurator.cpp | 2 -- spline-widget/qfunctionconfigurator.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/spline-widget/qfunctionconfigurator.cpp b/spline-widget/qfunctionconfigurator.cpp index 3df9fc9c..8a5bda4d 100644 --- a/spline-widget/qfunctionconfigurator.cpp +++ b/spline-widget/qfunctionconfigurator.cpp @@ -15,8 +15,6 @@ using namespace options; #include #include -static const int pointSize = 5; - QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) : QWidget(parent), _config(nullptr), diff --git a/spline-widget/qfunctionconfigurator.h b/spline-widget/qfunctionconfigurator.h index d4ba904a..ce8208a8 100644 --- a/spline-widget/qfunctionconfigurator.h +++ b/spline-widget/qfunctionconfigurator.h @@ -19,6 +19,7 @@ class SPLINE_WIDGET_EXPORT QFunctionConfigurator : public QWidget { Q_OBJECT Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier) + enum { pointSize = 5 }; public: QFunctionConfigurator(QWidget *parent = 0); -- cgit v1.2.3 From 044b799a15ec8b47094d6086b13ec77f991b6054 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 26 Nov 2015 09:28:06 +0100 Subject: qfc: use cross cursor when hovering over a point --- spline-widget/qfunctionconfigurator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spline-widget/qfunctionconfigurator.cpp b/spline-widget/qfunctionconfigurator.cpp index 8a5bda4d..256bf45e 100644 --- a/spline-widget/qfunctionconfigurator.cpp +++ b/spline-widget/qfunctionconfigurator.cpp @@ -358,7 +358,7 @@ void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e) } if (is_on_point) { - setCursor(Qt::OpenHandCursor); + setCursor(Qt::CrossCursor); } else { setCursor(Qt::ArrowCursor); -- 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(-) 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(-) 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(-) 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 e1ae4a738c011fbbe44e5203cc304dacb6489768 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 18:42:28 +0100 Subject: aruco: rework timeout logic - cycle otsu twice before selecting new box size don't cycle otsu each frame. - slower backoff from timeout value before new box size on occasional detections need at least 5 successes for each failure to not exceed. - select more sensible timeout per box size of .35 seconds. this is enough also with 30 Hz webcams, but too little for 15 Hz modes. --- tracker-aruco/ftnoir_tracker_aruco.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 570c2e0d..2d364a86 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -124,13 +124,14 @@ void Tracker::run() cv::Rect last_roi(65535, 65535, 0, 0); + // XXX change to timer.hpp auto freq = cv::getTickFrequency(); auto last_time = cv::getTickCount(); double cur_fps = 0; std::vector box_sizes { 5, 7, 9, 11 }; int box_idx = 0; - double failed = 0; - const double max_failed = 1.25; + double failed_otsu = 0; + const double max_failed_otsu = .35; cv::Vec3d rvec, tvec; cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); @@ -188,7 +189,7 @@ void Tracker::run() if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), markers.size() == 1 && markers[0].size() == 4) { - failed = std::max(0., failed - dt); + failed_otsu = std::max(0., failed_otsu - dt*.2); auto& m = markers.at(0); for (int i = 0; i < 4; i++) { @@ -202,15 +203,19 @@ void Tracker::run() if (!roi_valid) { - otsu = !otsu; detector._thresMethod = otsu ? aruco::MarkerDetector::FIXED_THRES : aruco::MarkerDetector::ADPT_THRES; - failed += dt; - if (failed > max_failed) + failed_otsu += dt; + if (failed_otsu > max_failed_otsu) { - box_idx++; - box_idx %= box_sizes.size(); - qDebug() << "aruco: box size now" << box_sizes[box_idx]; - failed = 0; + if (otsu == true) + { + box_idx++; + box_idx %= box_sizes.size(); + qDebug() << "aruco: box size now" << box_sizes[box_idx]; + } + qDebug() << "aruco: otsu now" << !otsu; + failed_otsu = 0; + otsu = !otsu; } detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(size_min, size_max); -- cgit v1.2.3 From 3883936fb476ef6e13ee808374c64c226f4fdf8c Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:17:44 +0100 Subject: accela: don't clamp max speed to just few degrees --- filter-accela/ftnoir_filter_accela.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/filter-accela/ftnoir_filter_accela.cpp b/filter-accela/ftnoir_filter_accela.cpp index 62d1598d..0bc03097 100644 --- a/filter-accela/ftnoir_filter_accela.cpp +++ b/filter-accela/ftnoir_filter_accela.cpp @@ -12,11 +12,13 @@ #include "opentrack/plugin-api.hpp" static constexpr double rot_gains[][2] = { + { 4.0, 350 }, + //{ 3.33, 200 }, { 2.66, 110 }, - { 2.33, 80 }, - { 2, 50 }, + //{ 2.33, 85 }, + //{ 2, 45 }, { 1.66, 30 }, - { 1.33, 15 }, + //{ 1.33, 15 }, { 1, 5 }, { .66, 1.4 }, { .33, .4 }, -- 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(-) 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(-) 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 35e959cf6836522d1d0e4506a9756470c9e904ee Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:32:15 +0100 Subject: compat/shm: move header inclusion after guard --- opentrack-compat/shm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index a306d581..19199bd9 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -5,12 +5,12 @@ * copyright notice and this permission notice appear in all copies. */ +#if defined(_WIN32) + #include #include #include "shm.h" -#if defined(_WIN32) - #include #include -- 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(-) 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(-) 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 e98880adc20988fadacc72f2a520bf0a674f135e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:58:58 +0100 Subject: aruco: use only Otsu thresholding, never adaptive Detection rate stays as good, likely better as before. @mursey reports in #274 that non-Otsu case eats way more CPU. --- tracker-aruco/ftnoir_tracker_aruco.cpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 2d364a86..32c81694 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -121,6 +121,7 @@ void Tracker::run() aruco::MarkerDetector detector; detector.setDesiredSpeed(3); + detector._thresMethod = aruco::MarkerDetector::FIXED_THRES; cv::Rect last_roi(65535, 65535, 0, 0); @@ -128,14 +129,13 @@ void Tracker::run() auto freq = cv::getTickFrequency(); auto last_time = cv::getTickCount(); double cur_fps = 0; - std::vector box_sizes { 5, 7, 9, 11 }; + std::vector box_sizes { 5, 9, 13 }; int box_idx = 0; - double failed_otsu = 0; - const double max_failed_otsu = .35; + double failed = 0; + const double max_failed = .8; cv::Vec3d rvec, tvec; cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); - bool otsu = false; while (!stop) { @@ -181,7 +181,6 @@ void Tracker::run() if (last_roi.width > 0 && last_roi.height) { - detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width), std::min(1.0, size_max * grayscale.cols / last_roi.width)); @@ -189,7 +188,7 @@ void Tracker::run() if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), markers.size() == 1 && markers[0].size() == 4) { - failed_otsu = std::max(0., failed_otsu - dt*.2); + failed = std::max(0., failed - dt*.25); auto& m = markers.at(0); for (int i = 0; i < 4; i++) { @@ -203,19 +202,13 @@ void Tracker::run() if (!roi_valid) { - detector._thresMethod = otsu ? aruco::MarkerDetector::FIXED_THRES : aruco::MarkerDetector::ADPT_THRES; - failed_otsu += dt; - if (failed_otsu > max_failed_otsu) + failed += dt; + if (failed > max_failed) { - if (otsu == true) - { - box_idx++; - box_idx %= box_sizes.size(); - qDebug() << "aruco: box size now" << box_sizes[box_idx]; - } - qDebug() << "aruco: otsu now" << !otsu; - failed_otsu = 0; - otsu = !otsu; + box_idx++; + box_idx %= box_sizes.size(); + qDebug() << "aruco: box size now" << box_sizes[box_idx]; + failed = 0; } detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(size_min, size_max); -- cgit v1.2.3 From e6b5a7a710890520ab56691e41f080cf97010e5c Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 23:48:43 +0100 Subject: aruco: use a single standard box size Higher box sizes use more CPU due to the need to convolve a lot. It looks fine with both high and low exposure on both Logitech C525 and PS3 Eye webcams. Issue: #273 --- tracker-aruco/ftnoir_tracker_aruco.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 32c81694..2b38bb2f 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -129,10 +129,6 @@ void Tracker::run() auto freq = cv::getTickFrequency(); auto last_time = cv::getTickCount(); double cur_fps = 0; - std::vector box_sizes { 5, 9, 13 }; - int box_idx = 0; - double failed = 0; - const double max_failed = .8; cv::Vec3d rvec, tvec; cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); @@ -146,12 +142,12 @@ void Tracker::run() if (!camera.read(color)) continue; } - static constexpr int thres_param2 = 5; cv::Mat grayscale; cv::cvtColor(color, grayscale, cv::COLOR_RGB2GRAY); const int scale = grayscale.cols > 480 ? 2 : 1; - detector.setThresholdParams(box_sizes[box_idx], thres_param2); + // param 2 ignored for Otsu thresholding. it's required to use our fork of Aruco. + detector.setThresholdParams(5, -1); static constexpr double pi = 3.1415926f; const int w = grayscale.cols, h = grayscale.rows; @@ -188,7 +184,6 @@ void Tracker::run() if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), markers.size() == 1 && markers[0].size() == 4) { - failed = std::max(0., failed - dt*.25); auto& m = markers.at(0); for (int i = 0; i < 4; i++) { @@ -202,15 +197,6 @@ void Tracker::run() if (!roi_valid) { - failed += dt; - if (failed > max_failed) - { - box_idx++; - box_idx %= box_sizes.size(); - qDebug() << "aruco: box size now" << box_sizes[box_idx]; - failed = 0; - } - detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(size_min, size_max); detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false); } -- cgit v1.2.3 From f9a6946d26dca681a14a5aacf523414dbc6bdfb3 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 4 Dec 2015 23:50:20 +0100 Subject: aruco: smaller search window Suitable for 30 Hz camera modes and higher. Requested-by: @frost555 Issue: #273 --- tracker-aruco/ftnoir_tracker_aruco.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracker-aruco/ftnoir_tracker_aruco.h b/tracker-aruco/ftnoir_tracker_aruco.h index 018f69ea..b9503c6e 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.h +++ b/tracker-aruco/ftnoir_tracker_aruco.h @@ -48,7 +48,7 @@ class Tracker : protected QThread, public ITracker { Q_OBJECT friend class TrackerControls; - static constexpr double c_search_window = 2.65; + static constexpr double c_search_window = 1.3; public: Tracker(); ~Tracker() override; -- 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(-) 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(-) 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 14550c0f9070bc108c865736364349b3e8d1f995 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 5 Dec 2015 23:33:12 +0100 Subject: gui: add shortcuts for starting/toggling tracking --- gui/settings.ui | 104 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 16 deletions(-) diff --git a/gui/settings.ui b/gui/settings.ui index e277b5d8..03566c2e 100644 --- a/gui/settings.ui +++ b/gui/settings.ui @@ -6,8 +6,8 @@ 0 0 - 348 - 548 + 381 + 603 @@ -62,6 +62,33 @@ QGroupBox { border: 0; } + + + + Bind + + + + + + + Start tracking + + + false + + + + + + + Stop tracking + + + false + + + @@ -79,42 +106,49 @@ - - + + - - + + - - + + - Toggle + Zero false - - + + - Zero + Bind + + + + + + + Toggle false - - + + Bind @@ -127,13 +161,51 @@ - - + + + + Bind + + + + + + + Toggle tracking + + + false + + + + + Bind + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 0f577dbe8adb8f7e210241c6bee0be73349f8d45 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 00:41:59 +0100 Subject: tracker/aruco, tracker/pt: sleep before releasing camera Really fast toggling tracking crashed with my PS3 Eye. --- tracker-aruco/ftnoir_tracker_aruco.cpp | 2 ++ tracker-pt/ftnoir_tracker_pt.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 2b38bb2f..1da5b8df 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -43,6 +43,8 @@ Tracker::~Tracker() delete videoWidget; if(layout) delete layout; + // fast start/stop causes breakage + portable::sleep(1000); camera.release(); } diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 15a60962..2dbf9068 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -13,6 +13,7 @@ #include #include #include "opentrack/camera-names.hpp" +#include "opentrack-compat/sleep.hpp" //#define PT_PERF_LOG //log performance @@ -34,6 +35,8 @@ Tracker_PT::~Tracker_PT() delete video_widget; video_widget = NULL; if (video_frame->layout()) delete video_frame->layout(); + // fast start/stop causes breakage + portable::sleep(1000); camera.stop(); } -- 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(-) 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 179870eb019f5b2d2327292e8beef63c01a33e4a Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 00:51:40 +0100 Subject: compat/shm: fix build --- opentrack-compat/shm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index 19199bd9..55aa7a41 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -5,11 +5,12 @@ * copyright notice and this permission notice appear in all copies. */ +#include "shm.h" + #if defined(_WIN32) #include #include -#include "shm.h" #include #include -- 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(-) 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(-) 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 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 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 6d04283583b1318b2295de0683c3f769b496719d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 02:35:57 +0100 Subject: contrib/aruco: use @frost555's marker image --- contrib/aruco/test3.jpg | Bin 2145 -> 53101 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/contrib/aruco/test3.jpg b/contrib/aruco/test3.jpg index 2ff6dbd0..81f2d201 100644 Binary files a/contrib/aruco/test3.jpg and b/contrib/aruco/test3.jpg differ -- cgit v1.2.3 From 3a779b32ca9443b252382a7e2a5d7a53af783bb6 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 02:38:43 +0100 Subject: contrib/aruco: oops, right extension --- contrib/aruco/test3.jpg | Bin 53101 -> 0 bytes contrib/aruco/test3.png | Bin 0 -> 53101 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contrib/aruco/test3.jpg create mode 100644 contrib/aruco/test3.png diff --git a/contrib/aruco/test3.jpg b/contrib/aruco/test3.jpg deleted file mode 100644 index 81f2d201..00000000 Binary files a/contrib/aruco/test3.jpg and /dev/null differ diff --git a/contrib/aruco/test3.png b/contrib/aruco/test3.png new file mode 100644 index 00000000..81f2d201 Binary files /dev/null and b/contrib/aruco/test3.png differ -- 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(-) 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 4e74d6edef94e4f2f7caae76088f91e9ee993fba Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:14:07 +0100 Subject: gui/keys: allow for pausing global keystrokes for options dialog Toggling tracking while prompting for toggle tracking key causes a deadlock somewhere. --- gui/options-dialog.cpp | 10 ++++++++-- gui/options-dialog.hpp | 3 ++- gui/ui.cpp | 12 +++++++----- gui/ui.h | 1 + 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 1edf069d..65407184 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -29,8 +29,12 @@ static QString kopts_to_string(const key_opts& kopts) return kopts.keycode; } -OptionsDialog::OptionsDialog(main_settings& main, std::function register_global_keys) - : main(main), register_global_keys(register_global_keys) +OptionsDialog::OptionsDialog(main_settings& main, + std::function register_global_keys, + std::function pause_keybindings) : + main(main), + register_global_keys(register_global_keys), + pause_keybindings(pause_keybindings) { ui.setupUi(this); @@ -115,7 +119,9 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) d.close(); } }); + pause_keybindings(true); d.exec(); + pause_keybindings(false); register_global_keys(); label->setText(kopts_to_string(kopts)); delete k; diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 72ae3c30..7700162b 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -12,10 +12,11 @@ class OptionsDialog: public QWidget signals: void reload(); public: - OptionsDialog(main_settings& main, std::function register_global_keys); + OptionsDialog(main_settings& main, std::function register_global_keys, std::function pause_keybindings); private: main_settings& main; std::function register_global_keys; + std::function pause_keybindings; Ui::UI_Settings ui; void closeEvent(QCloseEvent *) override { doCancel(); } private slots: diff --git a/gui/ui.cpp b/gui/ui.cpp index 26fcd9ed..e59b1c23 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -23,7 +23,8 @@ MainWindow::MainWindow() : pose_update_timer(this), kbd_quit(QKeySequence("Ctrl+Q"), this), no_feed_pixmap(":/images/no-feed.png"), - is_refreshing_profiles(false) + is_refreshing_profiles(false), + keys_paused(false) { ui.setupUi(this); @@ -110,15 +111,15 @@ MainWindow::MainWindow() : QMessageBox::Ok, QMessageBox::NoButton); connect(this, &MainWindow::emit_start_tracker, - this, [&]() -> void { qDebug() << "start tracker"; startTracker(); }, + this, [&]() -> void { if (keys_paused) return; qDebug() << "start tracker"; startTracker(); }, Qt::QueuedConnection); connect(this, &MainWindow::emit_stop_tracker, - this, [&]() -> void { qDebug() << "stop tracker"; stopTracker(); }, + this, [&]() -> void { if (keys_paused) return; qDebug() << "stop tracker"; stopTracker(); }, Qt::QueuedConnection); connect(this, &MainWindow::emit_toggle_tracker, - this, [&]() -> void { qDebug() << "toggle tracker"; if (work) stopTracker(); else startTracker(); }, + this, [&]() -> void { if (keys_paused) return; qDebug() << "toggle tracker"; if (work) stopTracker(); else startTracker(); }, Qt::QueuedConnection); register_shortcuts(); @@ -493,7 +494,8 @@ bool mk_window(mem* place, Args&&... params) void MainWindow::show_options_dialog() { if (mk_window(&options_widget, s, - [&]() -> void { register_shortcuts(); })) + [&]() -> void { register_shortcuts(); }, + [&](bool flag) -> void { keys_paused = flag; })) connect(options_widget.get(), SIGNAL(reload()), this, SLOT(reload_options())); } diff --git a/gui/ui.h b/gui/ui.h index 12ef1f24..ee0a3ce7 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -56,6 +56,7 @@ class MainWindow : public QMainWindow, private State process_detector_worker det; QMenu profile_menu; bool is_refreshing_profiles; + volatile bool keys_paused; QTimer save_timer; mem current_tracker() -- 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(-) 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(-) 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 4bdcd48852a459fbd5bc6eb4452c95a3ad8b85e3 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:16:56 +0100 Subject: tracker/joy: adapt to non-singleton joy worker --- tracker-joystick/ftnoir_tracker_joystick.cpp | 2 +- tracker-joystick/ftnoir_tracker_joystick.h | 2 +- tracker-joystick/ftnoir_tracker_joystick_dialog.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp index 112f20ca..d10b15ca 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -8,7 +8,7 @@ #include "opentrack/plugin-api.hpp" #include -FTNoIR_Tracker::FTNoIR_Tracker() : joy_ctx(win32_joy_ctx::make()) +FTNoIR_Tracker::FTNoIR_Tracker() { if (static_cast(s.guid) == "") { diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 9923dd1c..1f940b63 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -46,7 +46,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 0a630c1e..a6fa6605 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -10,7 +10,7 @@ TrackerControls::TrackerControls() : tracker(nullptr) connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); { - win32_joy_ctx& joy_ctx(win32_joy_ctx::make()); + win32_joy_ctx joy_ctx; _joys = QList(); -- 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(-) 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(-) 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 aa593e0840783d1b38b0c812fd2f8120491ee296 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 06:14:57 +0100 Subject: gui/main: don't raise a new window, it's enough to set visible --- gui/ui.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/gui/ui.cpp b/gui/ui.cpp index e59b1c23..2bd8e72a 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -446,7 +446,6 @@ bool mk_dialog(mem lib, mem& orig) orig = dialog; dialog->show(); - dialog->raise(); QObject::connect(dialog.get(), &plugin_api::detail::BaseDialog::closing, [&]() -> void { orig = nullptr; }); @@ -486,7 +485,6 @@ bool mk_window(mem* place, Args&&... params) *place = std::make_shared(std::forward(params)...); (*place)->setWindowFlags(Qt::Dialog); (*place)->show(); - (*place)->raise(); return true; } } -- cgit v1.2.3 From 2de0b6427d8d768771cf22686c1c3b65f15e2f40 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 06:15:19 +0100 Subject: gui/settings: don't forget to show a modal dialog before executing --- gui/options-dialog.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 65407184..a7efdb75 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -99,18 +99,18 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) QDialog d; auto l = new QHBoxLayout; l->setMargin(0); - auto k = new KeyboardListener; - l->addWidget(k); + KeyboardListener k; + l->addWidget(&k); d.setLayout(l); d.setFixedSize(QSize(500, 300)); d.setWindowFlags(Qt::Dialog); - connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { + 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, bool held) -> void { + connect(&k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx, bool held) -> void { if (!held) { kopts.guid = guid; @@ -120,11 +120,11 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) } }); pause_keybindings(true); + d.show(); d.exec(); pause_keybindings(false); register_global_keys(); label->setText(kopts_to_string(kopts)); - delete k; delete l; } -- cgit v1.2.3 From da8ec5c60841a926874c9ef2c4fed0078d47ebc8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 06:20:56 +0100 Subject: gui/settings: set parent, otherwise not modal --- gui/options-dialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index a7efdb75..e1324ccc 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -96,7 +96,7 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) kopts.button = -1; kopts.guid = ""; kopts.keycode = ""; - QDialog d; + QDialog d(this); auto l = new QHBoxLayout; l->setMargin(0); KeyboardListener k; @@ -104,6 +104,7 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) d.setLayout(l); d.setFixedSize(QSize(500, 300)); d.setWindowFlags(Qt::Dialog); + d.setWindowModality(Qt::ApplicationModal); connect(&k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { kopts.keycode = s.toString(QKeySequence::PortableText); kopts.guid = ""; -- cgit v1.2.3 From 69a188510e14130e2aded0c9398a67d4e3ff4dcd Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 19:53:06 +0100 Subject: compat/options: move from header --- opentrack-compat/options.cpp | 190 +++++++++++++++++++++++++++++++++++++++ opentrack-compat/options.hpp | 206 ++++++------------------------------------- 2 files changed, 218 insertions(+), 178 deletions(-) diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp index 48cc514b..7938b075 100644 --- a/opentrack-compat/options.cpp +++ b/opentrack-compat/options.cpp @@ -13,4 +13,194 @@ OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() } +group::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 group::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(); +} + +void group::put(const std::string &s, const QVariant &d) +{ + kvs[s] = d; +} + +bool group::contains(const std::string &s) +{ + return kvs.count(s) != 0; +} + +QString group::ini_directory() +{ + const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + if (dirs.size() == 0) + return ""; + if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) + return dirs[0] + "/" OPENTRACK_ORG; + return ""; +} + +QString group::ini_filename() +{ + QSettings settings(OPENTRACK_ORG); + return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +QString group::ini_pathname() +{ + const auto dir = ini_directory(); + if (dir == "") + return ""; + QSettings settings(OPENTRACK_ORG); + return dir + "/" + settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +const QStringList group::ini_list() +{ + const auto dirname = ini_directory(); + if (dirname == "") + return QStringList(); + QDir settings_dir(dirname); + return settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); +} + +const mem group::ini_file() +{ + const auto pathname = ini_pathname(); + if (pathname != "") + return std::make_shared(ini_pathname(), QSettings::IniFormat); + return std::make_shared(); +} + +impl_bundle::impl_bundle(const std::string &group_name) + : + mtx(QMutex::Recursive), + group_name(group_name), + saved(group_name), + transient(saved), + modified(false) +{} + +void impl_bundle::reload() +{ + { + QMutexLocker l(&mtx); + saved = group(group_name); + transient = saved; + modified = false; + } + emit reloading(); +} + +void impl_bundle::store_kv(const std::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 impl_bundle::contains(const std::string &name) +{ + QMutexLocker l(&mtx); + return transient.contains(name); +} + +void impl_bundle::save() +{ + { + QMutexLocker l(&mtx); + modified = false; + saved = transient; + transient.save(); + } + emit saving(); +} + +bool impl_bundle::modifiedp() +{ + QMutexLocker l(&mtx); + return modified; +} + +namespace detail +{ + +pbundle opt_singleton::bundle(const opt_singleton::k &key) +{ + QMutexLocker l(&implsgl_mtx); + + if (implsgl_data.count(key) != 0) + { + auto shared = std::get<1>(implsgl_data[key]).lock(); + if (shared != nullptr) + return shared; + } + + qDebug() << "bundle +" << QString::fromStdString(key); + + auto shr = std::make_shared(key); + implsgl_data[key] = tt(cnt(1), shr); + return shr; +} + +void opt_singleton::bundle_decf(const opt_singleton::k &key) +{ + QMutexLocker l(&implsgl_mtx); + + if (--std::get<0>(implsgl_data[key]) == 0) + implsgl_data.erase(key); +} + +opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) {} + +} + +opt_bundle::opt_bundle(const std::string &group_name) + : impl_bundle(group_name) +{ +} + +opt_bundle::~opt_bundle() +{ + qDebug() << "bundle -" << QString::fromStdString(group_name); + detail::singleton().bundle_decf(group_name); +} + +base_value::base_value(pbundle b, const std::string &name) : b(b), self_name(name) {} + +opts::~opts() +{ + b->reload(); +} + +opts::opts(const std::string &name) : b(bundle(name)) {} + + + } diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp index 3e4fb20e..81a53067 100644 --- a/opentrack-compat/options.hpp +++ b/opentrack-compat/options.hpp @@ -90,96 +90,26 @@ namespace options { } // snapshot of qsettings group at given time - class group { + class OPENTRACK_COMPAT_EXPORT 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(); - } + group(const string& name); + void save(); + void put(const string& s, const QVariant& d); + bool contains(const string& s); + static QString ini_directory(); + static QString ini_filename(); + static QString ini_pathname(); + static const QStringList ini_list(); + static const mem ini_file(); 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 { @@ -196,64 +126,20 @@ namespace options { 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) - { - } - + impl_bundle(const string& group_name); 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); - } + void reload(); + void store_kv(const string& name, const QVariant& datum); + bool contains(const string& name); + void save(); + bool modifiedp(); + 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; @@ -272,33 +158,9 @@ namespace options { 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); - } + opt_singleton(); + pbundle bundle(const k& key); + void bundle_decf(const k& key); }; OPENTRACK_COMPAT_EXPORT opt_singleton& singleton(); @@ -308,19 +170,12 @@ namespace options { static inline pbundle bundle(const string name) { return detail::singleton().bundle(name); } - class opt_bundle : public impl_bundle + class OPENTRACK_COMPAT_EXPORT 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); - } + opt_bundle(const string& group_name); + ~opt_bundle(); }; class OPENTRACK_COMPAT_EXPORT base_value : public QObject @@ -330,7 +185,7 @@ namespace options { #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) {} + base_value(pbundle b, const string& name); signals: DEFINE_SIGNAL(double); DEFINE_SIGNAL(int); @@ -355,7 +210,7 @@ namespace options { virtual void reload() = 0; }; - static inline string string_from_qstring(const QString& datum) + static inline std::string string_from_qstring(const QString &datum) { auto tmp = datum.toUtf8(); return string(tmp.constData()); @@ -393,16 +248,11 @@ namespace options { t def; }; - struct opts + struct OPENTRACK_COMPAT_EXPORT opts { pbundle b; - - opts(const std::string& name) : b(bundle(name)) {} - - ~opts() - { - b->reload(); - } + opts(const std::string& name); + ~opts(); }; template -- cgit v1.2.3 From dcd4df5e49e6207273c961069d14ce42ad83d147 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 20:02:18 +0100 Subject: compat/options: get rid of std::string usage It's pointless to use it here. --- opentrack-compat/options.cpp | 37 +++++++++++++------------------- opentrack-compat/options.hpp | 51 ++++++++++++++++++-------------------------- 2 files changed, 36 insertions(+), 52 deletions(-) diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp index 7938b075..550fec24 100644 --- a/opentrack-compat/options.cpp +++ b/opentrack-compat/options.cpp @@ -13,15 +13,14 @@ OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() } -group::group(const string& name) : name(name) +group::group(const QString& name) : name(name) { auto conf = ini_file(); - auto q_name = QString::fromStdString(name); - conf->beginGroup(q_name); + conf->beginGroup(name); for (auto& k_ : conf->childKeys()) { auto tmp = k_.toUtf8(); - string k(tmp); + QString k(tmp); kvs[k] = conf->value(k_); } conf->endGroup(); @@ -30,23 +29,19 @@ group::group(const string& name) : name(name) void group::save() { auto s = ini_file(); - auto q_name = QString::fromStdString(name); - s->beginGroup(q_name); + s->beginGroup(name); for (auto& i : kvs) - { - auto k = QString::fromStdString(i.first); - s->setValue(k, i.second); - } + s->setValue(i.first, i.second); s->endGroup(); s->sync(); } -void group::put(const std::string &s, const QVariant &d) +void group::put(const QString &s, const QVariant &d) { kvs[s] = d; } -bool group::contains(const std::string &s) +bool group::contains(const QString &s) { return kvs.count(s) != 0; } @@ -93,7 +88,7 @@ const mem group::ini_file() return std::make_shared(); } -impl_bundle::impl_bundle(const std::string &group_name) +impl_bundle::impl_bundle(const QString &group_name) : mtx(QMutex::Recursive), group_name(group_name), @@ -113,7 +108,7 @@ void impl_bundle::reload() emit reloading(); } -void impl_bundle::store_kv(const std::string &name, const QVariant &datum) +void impl_bundle::store_kv(const QString &name, const QVariant &datum) { QMutexLocker l(&mtx); @@ -125,7 +120,7 @@ void impl_bundle::store_kv(const std::string &name, const QVariant &datum) } } -bool impl_bundle::contains(const std::string &name) +bool impl_bundle::contains(const QString &name) { QMutexLocker l(&mtx); return transient.contains(name); @@ -162,7 +157,7 @@ pbundle opt_singleton::bundle(const opt_singleton::k &key) return shared; } - qDebug() << "bundle +" << QString::fromStdString(key); + qDebug() << "bundle +" << key; auto shr = std::make_shared(key); implsgl_data[key] = tt(cnt(1), shr); @@ -181,26 +176,24 @@ opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) {} } -opt_bundle::opt_bundle(const std::string &group_name) +opt_bundle::opt_bundle(const QString &group_name) : impl_bundle(group_name) { } opt_bundle::~opt_bundle() { - qDebug() << "bundle -" << QString::fromStdString(group_name); + qDebug() << "bundle -" << group_name; detail::singleton().bundle_decf(group_name); } -base_value::base_value(pbundle b, const std::string &name) : b(b), self_name(name) {} +base_value::base_value(pbundle b, const QString &name) : b(b), self_name(name) {} opts::~opts() { b->reload(); } -opts::opts(const std::string &name) : b(bundle(name)) {} - - +opts::opts(const QString &name) : b(bundle(name)) {} } diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp index 81a53067..d41c5cd1 100644 --- a/opentrack-compat/options.hpp +++ b/opentrack-compat/options.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -52,7 +51,6 @@ template using mem = std::shared_ptr; namespace options { template using map = std::map; - using std::string; template // don't elide usages of the function, qvariant default implicit @@ -92,13 +90,13 @@ namespace options { // snapshot of qsettings group at given time class OPENTRACK_COMPAT_EXPORT group { private: - map kvs; - string name; + map kvs; + QString name; public: - group(const string& name); + group(const QString& name); void save(); - void put(const string& s, const QVariant& d); - bool contains(const string& s); + void put(const QString& s, const QVariant& d); + bool contains(const QString& s); static QString ini_directory(); static QString ini_filename(); static QString ini_pathname(); @@ -106,7 +104,7 @@ namespace options { static const mem ini_file(); template - t get(const string& k) + t get(const QString& k) { return qcruft_to_t(kvs[k]); } @@ -116,7 +114,7 @@ namespace options { Q_OBJECT protected: QMutex mtx; - const string group_name; + const QString group_name; group saved; group transient; bool modified; @@ -126,16 +124,16 @@ namespace options { void reloading(); void saving(); public: - impl_bundle(const string& group_name); - string name() { return group_name; } + impl_bundle(const QString& group_name); + QString name() { return group_name; } void reload(); - void store_kv(const string& name, const QVariant& datum); - bool contains(const string& name); + void store_kv(const QString& name, const QVariant& datum); + bool contains(const QString& name); void save(); bool modifiedp(); template - t get(const string& name) + t get(const QString& name) { QMutexLocker l(&mtx); return transient.get(name); @@ -149,7 +147,7 @@ namespace options { struct OPENTRACK_COMPAT_EXPORT opt_singleton { public: - using k = std::string; + using k = QString; using v = opt_bundle; using cnt = int; using pbundle = std::shared_ptr; @@ -168,13 +166,13 @@ namespace options { using pbundle = std::shared_ptr; - static inline pbundle bundle(const string name) { return detail::singleton().bundle(name); } + static inline pbundle bundle(const QString name) { return detail::singleton().bundle(name); } class OPENTRACK_COMPAT_EXPORT opt_bundle : public impl_bundle { public: opt_bundle() : impl_bundle("i-have-no-name") {} - opt_bundle(const string& group_name); + opt_bundle(const QString& group_name); ~opt_bundle(); }; @@ -184,8 +182,8 @@ namespace options { #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); + QString name() { return self_name; } + base_value(pbundle b, const QString& name); signals: DEFINE_SIGNAL(double); DEFINE_SIGNAL(int); @@ -193,7 +191,7 @@ namespace options { DEFINE_SIGNAL(QString); protected: pbundle b; - string self_name; + QString self_name; template void store(const t& datum) @@ -210,12 +208,6 @@ namespace options { virtual void reload() = 0; }; - static inline std::string string_from_qstring(const QString &datum) - { - auto tmp = datum.toUtf8(); - return string(tmp.constData()); - } - template class value : public base_value { public: @@ -226,7 +218,7 @@ namespace options { } 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) + value(pbundle b, const QString& name, t def) : base_value(b, name), def(def) { QObject::connect(b.get(), SIGNAL(reloading()), this, SLOT(reload()), @@ -234,8 +226,7 @@ namespace options { 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) {} + value(pbundle b, const char* name, t def) : value(b, QString(name), def) {} operator t() const { @@ -251,7 +242,7 @@ namespace options { struct OPENTRACK_COMPAT_EXPORT opts { pbundle b; - opts(const std::string& name); + opts(const QString& name); ~opts(); }; -- 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(-) 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(-) 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(-) 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 143ffce5486739368a9b35c10f2e8a7ad22a2236 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Tue, 8 Dec 2015 02:34:46 +0100 Subject: tracker/pt: reduce auto thresholding histogram bucket size Previously it was too slow to 640x480@75. --- tracker-pt/point_extractor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index ec37dd00..e1d55b8d 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -67,12 +67,13 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) else { cv::Mat hist; + constexpr int hist_c = 6; cv::calcHist(std::vector { frame_gray }, std::vector { 0 }, cv::Mat(), hist, - std::vector { 256 }, - std::vector { 0, 256 }, + std::vector { 256/hist_c }, + std::vector { 0, 256/hist_c }, false); const int sz = hist.rows*hist.cols; int val = 0; @@ -88,6 +89,7 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) break; } } + val *= hist_c; val *= 240./256.; //qDebug() << "val" << val; -- 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(+) 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 f38541f1956133be9b093d5439128d3481b7e5fa Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 17 Dec 2015 10:26:47 +0100 Subject: pt: histogram more granular 6 -> 8 256 is divisible by 8, also less cpu usage --- tracker-pt/point_extractor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index e1d55b8d..c90310bb 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -67,7 +67,7 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) else { cv::Mat hist; - constexpr int hist_c = 6; + constexpr int hist_c = 8; cv::calcHist(std::vector { frame_gray }, std::vector { 0 }, cv::Mat(), -- 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(-) 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(-) 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 From ca25abbf871fb92518910c3beb51d59182df8fe6 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 00:55:29 +0100 Subject: glwidget: use transparent octopus background --- pose-widget/glwidget.cpp | 23 ++++++++++++++--------- pose-widget/images/side1.png | Bin 26449 -> 27564 bytes pose-widget/images/side6.png | Bin 26493 -> 28651 bytes 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/pose-widget/glwidget.cpp b/pose-widget/glwidget.cpp index 3ee480a1..9b350010 100644 --- a/pose-widget/glwidget.cpp +++ b/pose-widget/glwidget.cpp @@ -98,16 +98,18 @@ inline GLWidget::vec3 GLWidget::normal(const vec3& p1, const vec3& p2, const vec void GLWidget::project_quad_texture() { const int sx = width(), sy = height(); - vec2 pt[4]; + const int ow = front.width(), oh = front.height(); const vec3 corners[] = { - vec3(0., 0, 0), - vec3(sx-1, 0, 0), - vec3(0, sy-1, 0), - vec3(sx-1, sy-1, 0.) + vec3(-ow/2., -oh/2, 0), + vec3(ow/2, -oh/2, 0), + vec3(-ow/2, oh/2, 0), + vec3(ow/2, oh/2, 0.) }; + vec2 pt[4]; + vec2 sz((sx-ow)/2, (sy-oh)/2); for (int i = 0; i < 4; i++) - pt[i] = project(vec3(corners[i].x() - sx/2, corners[i].y() - sy/2, 0)) + vec2(sx/2, sy/2); + pt[i] = project(corners[i]) + vec2(sx/2, sy/2); vec3 normal1(0, 0, 1); vec3 normal2; @@ -122,9 +124,7 @@ void GLWidget::project_quad_texture() { QImage& tex = dir < 0 ? back : front; - int ow = tex.width(), oh = tex.height(); - - QImage texture(QSize(sx, sy), QImage::Format_RGB888); + QImage texture(QSize(sx, sy), QImage::Format_RGBA8888); QColor bgColor = palette().color(QPalette::Current, QPalette::Window); texture.fill(bgColor); @@ -199,6 +199,10 @@ void GLWidget::project_quad_texture() { const unsigned char r___ = orig[orig_pos___ + 2]; const unsigned char g___ = orig[orig_pos___ + 1]; const unsigned char b___ = orig[orig_pos___ + 0]; + + const unsigned char a1 = orig[orig_pos + 3]; + const unsigned char a2 = orig[orig_pos_ + 3]; + const unsigned char a3 = orig[orig_pos__ + 3]; const int pos = y * dest_pitch + x * dest_depth; @@ -207,6 +211,7 @@ void GLWidget::project_quad_texture() { dest[pos + 0] = (r * ax + r__ * ax_) * ay + (r___ * ax + r_ * ax_) * ay_; dest[pos + 1] = (g * ax + g__ * ax_) * ay + (g___ * ax + g_ * ax_) * ay_; dest[pos + 2] = (b * ax + b__ * ax_) * ay + (b___ * ax + b_ * ax_) * ay_; + dest[pos + 3] = (a1 + a2 + a3)/3; break; } diff --git a/pose-widget/images/side1.png b/pose-widget/images/side1.png index d7467943..5fb72d64 100644 Binary files a/pose-widget/images/side1.png and b/pose-widget/images/side1.png differ diff --git a/pose-widget/images/side6.png b/pose-widget/images/side6.png index eaa80d7e..3b3bda10 100644 Binary files a/pose-widget/images/side6.png and b/pose-widget/images/side6.png differ -- cgit v1.2.3 From bd17446dbb598ca46e308d9295178882b8d81e8f Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 00:55:46 +0100 Subject: ui: make more compact --- gui/main.ui | 1632 +++++++++++++++++++++++++++++------------------------------ gui/ui.cpp | 2 - gui/ui.h | 1 - 3 files changed, 803 insertions(+), 832 deletions(-) diff --git a/gui/main.ui b/gui/main.ui index 5b276dbb..a3d1896b 100644 --- a/gui/main.ui +++ b/gui/main.ui @@ -7,8 +7,8 @@ 0 0 - 716 - 537 + 654 + 485 @@ -31,16 +31,16 @@ 0 - 0 + 6 0 - 0 + 6 - 0 + 6 @@ -53,7 +53,10 @@ 0 - + + + 0 + 0 @@ -66,10 +69,7 @@ 0 - - 0 - - + QFrame::NoFrame @@ -93,21 +93,15 @@ - + 0 0 - 480 - 360 - - - - - 480 - 360 + 320 + 240 @@ -115,12 +109,12 @@ 0 0 - 480 - 360 + 320 + 240 - + 0 0 @@ -130,8 +124,8 @@ 0 0 - 480 - 360 + 320 + 240 @@ -142,921 +136,718 @@ - 480 - 360 + 320 + 240 - 480 - 360 + 320 + 240 + + :/images/no-feed.png + + + true + - - - QFrame::NoFrame + + + + 0 + 0 + - - 0 + + + 320 + 240 + - - - 12 - + + + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 4 + + + + + + 0 + 0 + + + + Raw tracker data + + - 6 + 0 - 12 + 0 - 8 + 0 - 4 + 0 - - + + 0 + + + + + true + - + 0 0 - - - 80 - 90 - + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline - - + + + + true + - + 0 0 - - Raw tracker data + + false + + + QFrame::Raised + + + TZ - - - 0 - - - 0 - - - 0 - - - 0 - - - 3 - - - 2 - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - yaw - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - roll - - - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TZ - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - pitch - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - TX - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TY - - - - - - + + - + 0 0 - - Game data + + QFrame::Raised + + + pitch + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + true + + + + 0 + 0 + + + + false + + + QFrame::Raised + + + TY + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + TX + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + roll + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + yaw + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline - - - 0 - - - 0 - - - 0 - - - 0 - - - 3 - - - 2 - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TY - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - pitch - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - yaw - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - roll - - - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TZ - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - TX - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - - - - - - 0 - 0 - - - - - 4 - - - 8 - - - 10 - - - 0 - - - 4 - - - 0 - - - + + - - 4 + + 0 0 - Settings - - - true + Game data - - - 3 - + - 4 + 0 - 2 + 0 0 - 6 + 0 - - + + 0 + + + + + true + - + 0 - 2 + 0 - - - 0 - - - 0 - - - 2 - - - 2 - - - - - true - - - - 0 - 0 - - - - Profile - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextBesideIcon - - - true - - - Qt::DownArrow - - - - - - - - 0 - 0 - - - - 20 - - - - + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + - - + + + + true + - + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + 0 - 3 + 0 + + QFrame::Raised + - Mapping + TX - - - :/images/curves.png:/images/curves.png + + + + + + true + + + + 0 + 0 + + + + false + + + QFrame::Raised + + + TY + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + pitch + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + roll + + + + + + + + 0 + 0 + + + + QFrame::Raised - - - 80 - 24 - + + yaw - - + + + + true + - + 0 - 3 + 0 - - Options + + false - - - :/images/tools.png:/images/tools.png + + QFrame::Raised - - - 80 - 24 - + + TZ - - - - - - - - 3 - 0 - - - - Controls - - - true - - - - 8 - - - 0 - - - 8 - - - 0 - - - 9 - - - + + + + true + - + 0 0 - - Start + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat - - + + - false + true - + 0 0 - - Stop + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat - + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + @@ -1218,6 +1009,188 @@ + + + + + 4 + 0 + + + + 0 + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + Profile + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + Qt::DownArrow + + + + + + + 20 + + + + + + + + + + Options + + + + :/images/tools.png:/images/tools.png + + + + 80 + 24 + + + + + + + + Mapping + + + + :/images/curves.png:/images/curves.png + + + + 80 + 24 + + + + + + + + + 3 + 0 + + + + Controls + + + true + + + + 8 + + + 0 + + + 8 + + + 0 + + + 9 + + + + + + 0 + 0 + + + + Start + + + + + + + false + + + + 0 + 0 + + + + Stop + + + + + + + + + @@ -1235,7 +1208,6 @@ - btnStartTracker btnStopTracker iconcomboTrackerSource btnShowEngineControls @@ -1245,8 +1217,10 @@ btnShowFilterControls profile_button iconcomboProfile - btnEditCurves btnShortcuts + btnEditCurves + profile_button + iconcomboProfile diff --git a/gui/ui.cpp b/gui/ui.cpp index 2bd8e72a..c19e4840 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -22,7 +22,6 @@ MainWindow::MainWindow() : pose_update_timer(this), kbd_quit(QKeySequence("Ctrl+Q"), this), - no_feed_pixmap(":/images/no-feed.png"), is_refreshing_profiles(false), keys_paused(false) { @@ -31,7 +30,6 @@ MainWindow::MainWindow() : setFixedSize(size()); updateButtonState(false, false); - ui.video_frame_label->setPixmap(no_feed_pixmap); connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration())); connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(show_options_dialog())); diff --git a/gui/ui.h b/gui/ui.h index ee0a3ce7..deeb116d 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -49,7 +49,6 @@ class MainWindow : public QMainWindow, private State mem options_widget; mem mapping_widget; QShortcut kbd_quit; - QPixmap no_feed_pixmap; mem pFilterDialog; mem pProtocolDialog; mem pTrackerDialog; -- cgit v1.2.3 From f795b06001ac9281f42d2565add85d0c3ea1cf15 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 01:06:54 +0100 Subject: ui: adjust margin --- gui/main.ui | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gui/main.ui b/gui/main.ui index a3d1896b..7ef4abcb 100644 --- a/gui/main.ui +++ b/gui/main.ui @@ -7,8 +7,8 @@ 0 0 - 654 - 485 + 664 + 497 @@ -88,7 +88,7 @@ 0 - 0 + 4 @@ -194,7 +194,7 @@ - 0 + 6 0 @@ -206,7 +206,7 @@ 0 - 4 + 6 @@ -845,7 +845,7 @@ 0 - 0 + 6 -- cgit v1.2.3 From f502b3823222c204110484bc2d27c40775ff4b36 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 03:55:37 +0100 Subject: pose-widget: also bilinear interpolation of alpha value --- pose-widget/glwidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pose-widget/glwidget.cpp b/pose-widget/glwidget.cpp index 9b350010..1b30e585 100644 --- a/pose-widget/glwidget.cpp +++ b/pose-widget/glwidget.cpp @@ -203,6 +203,7 @@ void GLWidget::project_quad_texture() { const unsigned char a1 = orig[orig_pos + 3]; const unsigned char a2 = orig[orig_pos_ + 3]; const unsigned char a3 = orig[orig_pos__ + 3]; + const unsigned char a4 = orig[orig_pos___ + 3]; const int pos = y * dest_pitch + x * dest_depth; @@ -211,7 +212,7 @@ void GLWidget::project_quad_texture() { dest[pos + 0] = (r * ax + r__ * ax_) * ay + (r___ * ax + r_ * ax_) * ay_; dest[pos + 1] = (g * ax + g__ * ax_) * ay + (g___ * ax + g_ * ax_) * ay_; dest[pos + 2] = (b * ax + b__ * ax_) * ay + (b___ * ax + b_ * ax_) * ay_; - dest[pos + 3] = (a1 + a2 + a3)/3; + dest[pos + 3] = (a1 * ax + a3 * ax_) * ay + (a4 * ax + a2 * ax_) * ay_; break; } -- cgit v1.2.3 From 2ef49b8f192b7856e7e6b54064e5981a7a334d44 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 03:56:56 +0100 Subject: tracker/pt: don't fill mask on frame Saves few % of cpu load --- tracker-pt/point_extractor.cpp | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index c90310bb..bd33ffdd 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -51,7 +51,6 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) }; // mask for everything that passes the threshold (or: the upper threshold of the hysteresis) - cv::Mat frame_bin = cv::Mat::zeros(H, W, CV_8U); std::vector blobs; std::vector> contours; @@ -59,10 +58,9 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) const int thres = s.threshold; if (!s.auto_threshold) { - cv::Mat frame_bin_; - cv::threshold(frame_gray, frame_bin_, thres, 255, cv::THRESH_BINARY); - frame_bin.setTo(170, frame_bin_); - cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + cv::Mat frame_bin; + cv::threshold(frame_gray, frame_bin, thres, 255, cv::THRESH_BINARY); + cv::findContours(frame_bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); } else { @@ -93,10 +91,9 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) val *= 240./256.; //qDebug() << "val" << val; - cv::Mat frame_bin_; - cv::threshold(frame_gray, frame_bin_, val, 255, CV_THRESH_BINARY); - frame_bin.setTo(170, frame_bin_); - cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + cv::Mat frame_bin; + cv::threshold(frame_gray, frame_bin, val, 255, CV_THRESH_BINARY); + cv::findContours(frame_bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); } int cnt = 0; @@ -166,17 +163,5 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) points.push_back(p); } - // draw output image - std::vector channels_; - cv::split(frame, channels_); - std::vector channels; - { - cv::Mat frame_bin__ = frame_bin * .5; - channels.push_back(channels_[0] + frame_bin__); - channels.push_back(channels_[1] - frame_bin__); - channels.push_back(channels_[2] - frame_bin__); - cv::merge(channels, frame); - } - return points; } -- cgit v1.2.3 From 02fe02c3e09ff28ce235a90bdd7f70eba1da95c8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 19:45:09 +0100 Subject: tracker/pt: nix unused --- tracker-pt/point_tracker.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tracker-pt/point_tracker.h b/tracker-pt/point_tracker.h index fd002948..cdcf2998 100644 --- a/tracker-pt/point_tracker.h +++ b/tracker-pt/point_tracker.h @@ -118,10 +118,6 @@ public: void track(const std::vector& projected_points, const PointModel& model, float f, bool dynamic_pose, int init_phase_timeout); Affine pose() const { return X_CM; } cv::Vec2f project(const cv::Vec3f& v_M, float f); - void reset(const Affine& pose) - { - X_CM = pose; - } private: // the points in model order struct PointOrder -- cgit v1.2.3 From fd99faebde3361e5acf1dfc4ebebfe4727a47124 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 19:45:29 +0100 Subject: tracker/pt: move ctor out of the loop --- tracker-pt/camera.cpp | 3 +++ tracker-pt/ftnoir_tracker_pt.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tracker-pt/camera.cpp b/tracker-pt/camera.cpp index 63b401a8..ff721557 100644 --- a/tracker-pt/camera.cpp +++ b/tracker-pt/camera.cpp @@ -117,6 +117,9 @@ bool CVCamera::_get_frame(cv::Mat* frame) if (img.empty()) return false; + if (frame->rows != img.rows || frame->cols != img.cols) + *frame = cv::Mat(); + *frame = img; cam_info.res_x = img.cols; cam_info.res_y = img.rows; diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 3dd91a45..877b58fd 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -79,12 +79,12 @@ void Tracker_PT::run() #endif apply_settings(); + cv::Mat frame; while((commands & ABORT) == 0) { const double dt = time.elapsed() * 1e-9; time.start(); - cv::Mat frame; bool new_frame; { -- cgit v1.2.3 From f34dca33bc07680d89591ca5a8ac1e5801bf2950 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 19:46:05 +0100 Subject: tracker/pt: remove krap --- tracker-pt/point_extractor.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index bd33ffdd..dd36c57f 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -13,13 +13,9 @@ # include "opentrack-compat/timer.hpp" #endif -PointExtractor::PointExtractor(){ - //if (!AllocConsole()){} - //else SetConsoleTitle("debug"); - //freopen("CON", "w", stdout); - //freopen("CON", "w", stderr); +PointExtractor::PointExtractor() +{ } -// ---------------------------------------------------------------------------- std::vector PointExtractor::extract_points(cv::Mat& frame) { const int W = frame.cols; -- cgit v1.2.3 From 84fb0aab5633a98fd2aef7d9e642628e826e2a9d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 19:50:22 +0100 Subject: gui: fix left margin --- gui/main.ui | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/gui/main.ui b/gui/main.ui index 7ef4abcb..689c4c23 100644 --- a/gui/main.ui +++ b/gui/main.ui @@ -7,8 +7,8 @@ 0 0 - 664 - 497 + 646 + 492 @@ -31,7 +31,7 @@ 0 - 6 + 0 0 @@ -71,6 +71,12 @@ + + + 0 + 0 + + QFrame::NoFrame @@ -197,7 +203,7 @@ 6 - 0 + 5 0 @@ -833,7 +839,7 @@ - 0 + 6 0 -- cgit v1.2.3 From 8a60f1c9613d396b50aa6adec4b1f5ffdb9e9806 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 19:57:42 +0100 Subject: tracker/pt: reduce mutex contention --- tracker-pt/ftnoir_tracker_pt.cpp | 12 ++++-------- tracker-pt/ftnoir_tracker_pt.h | 5 ++--- tracker-pt/point_extractor.cpp | 7 ++++--- tracker-pt/point_extractor.h | 7 ++++--- tracker-pt/point_tracker.cpp | 1 + tracker-pt/point_tracker.h | 6 +++--- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 877b58fd..80227a39 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -19,8 +19,7 @@ //----------------------------------------------------------------------------- Tracker_PT::Tracker_PT() - : mutex(QMutex::Recursive), - commands(0), + : commands(0), video_widget(NULL), video_frame(NULL), ever_success(false) @@ -94,29 +93,26 @@ void Tracker_PT::run() if (new_frame && !frame.empty()) { - QMutexLocker lock(&mutex); - std::vector points = point_extractor.extract_points(frame); // blobs are sorted in order of circularity if (points.size() > PointModel::N_POINTS) points.resize(PointModel::N_POINTS); - bool success = points.size() == PointModel::N_POINTS; - float fx; if (!get_focal_length(fx)) continue; + + const bool success = points.size() == PointModel::N_POINTS; if (success) { point_tracker.track(points, PointModel(s), fx, s.dynamic_pose, s.init_phase_timeout); + ever_success = true; } Affine X_CM = pose(); - ever_success |= success; - { Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); // just copy pasted these lines from below Affine X_GH = X_CM * X_MH; diff --git a/tracker-pt/ftnoir_tracker_pt.h b/tracker-pt/ftnoir_tracker_pt.h index f73d106b..5ec7ea91 100644 --- a/tracker-pt/ftnoir_tracker_pt.h +++ b/tracker-pt/ftnoir_tracker_pt.h @@ -40,15 +40,14 @@ public: void start_tracker(QFrame* parent_window) override; void data(double* data) override; - Affine pose() { QMutexLocker lock(&mutex); return point_tracker.pose(); } - int get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); } + Affine pose() { return point_tracker.pose(); } + int get_n_points() { return point_extractor.get_points().size(); } bool get_cam_info(CamInfo* info) { QMutexLocker lock(&camera_mtx); return camera.get_info(*info); } public slots: void apply_settings(); protected: void run() override; private: - QMutex mutex; // thread commands enum Command { ABORT = 1<<0 diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index dd36c57f..6eb255a5 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -147,12 +147,13 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) blobs.push_back(blob(radius, pos, confid, area)); } - // clear old points - points.clear(); - using b = const blob; std::sort(blobs.begin(), blobs.end(), [](b& b1, b& b2) {return b1.confid > b2.confid;}); + QMutexLocker l(&mtx); + + points.clear(); + for (auto& b : blobs) { cv::Vec2f p((b.pos[0] - W/2)/W, -(b.pos[1] - H/2)/W); diff --git a/tracker-pt/point_extractor.h b/tracker-pt/point_extractor.h index b9368ab6..80c1897d 100644 --- a/tracker-pt/point_extractor.h +++ b/tracker-pt/point_extractor.h @@ -13,8 +13,8 @@ #include "ftnoir_tracker_pt_settings.h" -// ---------------------------------------------------------------------------- -// Extracts points from an opencv image +#include + class PointExtractor { public: @@ -22,12 +22,13 @@ public: // dt: time since last call in seconds // WARNING: returned reference is valid as long as object std::vector extract_points(cv::Mat &frame); - const std::vector& get_points() { return points; } + const std::vector& get_points() { QMutexLocker l(&mtx); return points; } PointExtractor(); settings_pt s; private: std::vector points; + QMutex mtx; }; #endif //POINTEXTRACTOR_H diff --git a/tracker-pt/point_tracker.cpp b/tracker-pt/point_tracker.cpp index 924b75de..aa6feb5b 100644 --- a/tracker-pt/point_tracker.cpp +++ b/tracker-pt/point_tracker.cpp @@ -249,6 +249,7 @@ int PointTracker::POSIT(const PointModel& model, const PointOrder& order_, float old_epsilon_2 = epsilon_2; } + QMutexLocker l(&mtx); // apply results X_CM.R = *R_current; X_CM.t[0] = order[0][0] * Z0/focal_length; diff --git a/tracker-pt/point_tracker.h b/tracker-pt/point_tracker.h index cdcf2998..2757f22c 100644 --- a/tracker-pt/point_tracker.h +++ b/tracker-pt/point_tracker.h @@ -15,9 +15,8 @@ #include "ftnoir_tracker_pt_settings.h" #include +#include -// ---------------------------------------------------------------------------- -// Affine frame trafo class Affine { public: @@ -116,7 +115,7 @@ public: // f : (focal length)/(sensor width) // dt : time since last call void track(const std::vector& projected_points, const PointModel& model, float f, bool dynamic_pose, int init_phase_timeout); - Affine pose() const { return X_CM; } + Affine pose() { QMutexLocker l(&mtx); return X_CM; } cv::Vec2f project(const cv::Vec3f& v_M, float f); private: // the points in model order @@ -138,6 +137,7 @@ private: Timer t; bool init_phase; + QMutex mtx; }; #endif //POINTTRACKER_H -- cgit v1.2.3 From eb9e4840dd3734ebe28e665657e499493b4173fc Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 19:57:53 +0100 Subject: cmake/mingw-w64: update --- cmake/mingw-w64.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/mingw-w64.cmake b/cmake/mingw-w64.cmake index 02ab66cb..679f67de 100644 --- a/cmake/mingw-w64.cmake +++ b/cmake/mingw-w64.cmake @@ -27,7 +27,7 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # oldest CPU supported here is Northwood-based Pentium 4. -sh 20150811 set(fpu "-ffast-math -fno-finite-math-only -mfpmath=both") -set(cpu "-O3 -march=pentium4 -mtune=corei7-avx ${fpu} -msse -msse2 -mno-sse3") +set(cpu "-O3 -march=pentium4 -mtune=corei7-avx ${fpu} -msse -msse2 -mno-sse3 -frename-registers") set(CFLAGS-OVERRIDE "" CACHE STRING "") -- cgit v1.2.3 From 29b43593962137f27abac7ca4d7f86a3e6d81dd2 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 20:08:50 +0100 Subject: tracker/pt: update video widget at 40 -> 50 ms --- tracker-pt/pt_video_widget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracker-pt/pt_video_widget.h b/tracker-pt/pt_video_widget.h index af1d60fd..1235c0d5 100644 --- a/tracker-pt/pt_video_widget.h +++ b/tracker-pt/pt_video_widget.h @@ -28,7 +28,7 @@ public: freshp(false) { connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); - timer.start(40); + timer.start(50); } void update_image(const cv::Mat &frame); protected slots: -- cgit v1.2.3 From 377202f037aeff97481252bdc7856cfacf939b66 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 20:41:49 +0100 Subject: tracker/pt: optimize widget --- tracker-pt/pt_video_widget.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/tracker-pt/pt_video_widget.cpp b/tracker-pt/pt_video_widget.cpp index cbb7c268..860d0a77 100644 --- a/tracker-pt/pt_video_widget.cpp +++ b/tracker-pt/pt_video_widget.cpp @@ -23,33 +23,29 @@ void PTVideoWidget::update_image(const cv::Mat& frame) void PTVideoWidget::update_and_repaint() { - QImage qframe; { QMutexLocker foo(&mtx); if (_frame.empty() || !freshp) return; - qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); + texture = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); freshp = false; - uchar* data = qframe.bits(); - const int pitch = qframe.bytesPerLine(); - unsigned char *input = (unsigned char*) _frame.data; + uchar* data = texture.bits(); const int chans = _frame.channels(); + const int pitch = texture.bytesPerLine(); for (int y = 0; y < _frame.rows; y++) { - const int step = y * _frame.step; - const int pitch_ = y * pitch; + unsigned char* dest = data + pitch * y; + const unsigned char* ln = _frame.ptr(y); for (int x = 0; x < _frame.cols; x++) { - data[pitch_ + x * 3 + 0] = input[step + x * chans + 2]; - data[pitch_ + x * 3 + 1] = input[step + x * chans + 1]; - data[pitch_ + x * 3 + 2] = input[step + x * chans + 0]; + const int idx = x * chans; + const int x_ = x * 3; + dest[x_ + 0] = ln[idx + 2]; + dest[x_ + 1] = ln[idx + 1]; + dest[x_ + 2] = ln[idx + 0]; } } } - qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); - { - QMutexLocker foo(&mtx); - texture = qframe; - } + texture = texture.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); update(); } -- cgit v1.2.3 From 487ee12372d054ec8d6cfaf534ca8c6639d0b96f Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 18 Dec 2015 21:28:30 +0100 Subject: tracker/pt: avoid widget malloc when able --- tracker-pt/pt_video_widget.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tracker-pt/pt_video_widget.cpp b/tracker-pt/pt_video_widget.cpp index 860d0a77..8c18e678 100644 --- a/tracker-pt/pt_video_widget.cpp +++ b/tracker-pt/pt_video_widget.cpp @@ -16,7 +16,13 @@ void PTVideoWidget::update_image(const cv::Mat& frame) if (!freshp) { - _frame = frame.clone(); + if (_frame.cols != frame.cols || + _frame.rows != frame.rows || + _frame.channels() != frame.channels()) + { + _frame = cv::Mat(); + } + frame.copyTo(_frame); freshp = true; } } -- cgit v1.2.3 From a2ceed01e32fd941e20e1362b6c44af8db05b5b2 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 19 Dec 2015 19:48:55 +0100 Subject: tracker/pt: cv::Mat::at is slow, use cv::Mat::ptr --- tracker-pt/point_extractor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index 6eb255a5..6118f3d2 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -74,9 +74,10 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) int cnt = 0; constexpr int min_pixels = 250; const auto pixels_to_include = std::max(0, min_pixels * s.threshold/100.); + auto ptr = reinterpret_cast(hist.ptr(0)); for (int i = sz-1; i >= 0; i--) { - cnt += hist.at(i); + cnt += ptr[i]; if (cnt >= pixels_to_include) { val = i; -- cgit v1.2.3 From 90138a999b4c95afeb9a49d355b0234b6145e221 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 19 Dec 2015 20:43:24 +0100 Subject: tracker/pt: don't allocate temporary frame --- tracker-pt/camera.cpp | 13 ++++--------- tracker-pt/ftnoir_tracker_pt.cpp | 14 +++++++------- tracker-pt/ftnoir_tracker_pt.h | 1 + 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/tracker-pt/camera.cpp b/tracker-pt/camera.cpp index ff721557..600ab26a 100644 --- a/tracker-pt/camera.cpp +++ b/tracker-pt/camera.cpp @@ -110,19 +110,14 @@ bool CVCamera::_get_frame(cv::Mat* frame) { if (cap && cap->isOpened()) { - cv::Mat img; - for (int i = 0; i < 100 && !cap->read(img); i++) + for (int i = 0; i < 100 && !cap->read(*frame); i++) ;; - if (img.empty()) + if (frame->empty()) return false; - if (frame->rows != img.rows || frame->cols != img.cols) - *frame = cv::Mat(); - - *frame = img; - cam_info.res_x = img.cols; - cam_info.res_y = img.rows; + cam_info.res_x = frame->cols; + cam_info.res_y = frame->rows; return true; } return false; diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 80227a39..9a4fa037 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -14,6 +14,7 @@ #include #include "opentrack-compat/camera-names.hpp" #include "opentrack-compat/sleep.hpp" +#include //#define PT_PERF_LOG //log performance @@ -78,7 +79,7 @@ void Tracker_PT::run() #endif apply_settings(); - cv::Mat frame; + cv::Mat frame_; while((commands & ABORT) == 0) { @@ -89,9 +90,12 @@ void Tracker_PT::run() { QMutexLocker l(&camera_mtx); new_frame = camera.get_frame(dt, &frame); + if (frame.rows != frame_.rows || frame.cols != frame_.cols) + frame_ = cv::Mat(frame.rows, frame.cols, CV_8UC3); + frame.copyTo(frame_); } - if (new_frame && !frame.empty()) + if (new_frame && !frame_.empty()) { std::vector points = point_extractor.extract_points(frame); @@ -142,11 +146,6 @@ void Tracker_PT::run() video_widget->update_image(frame); } -#ifdef PT_PERF_LOG - log_stream<<"dt: "< Date: Sat, 19 Dec 2015 20:44:41 +0100 Subject: tracker/pt: don't copy points array needlessly --- tracker-pt/ftnoir_tracker_pt.cpp | 47 +++++++++++++++++++--------------------- tracker-pt/point_extractor.cpp | 13 +++++++++-- tracker-pt/point_extractor.h | 2 +- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 9a4fa037..88356771 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -97,17 +97,13 @@ void Tracker_PT::run() if (new_frame && !frame_.empty()) { - std::vector points = point_extractor.extract_points(frame); - - // blobs are sorted in order of circularity - if (points.size() > PointModel::N_POINTS) - points.resize(PointModel::N_POINTS); + const auto& points = point_extractor.extract_points(frame_); float fx; if (!get_focal_length(fx)) continue; - const bool success = points.size() == PointModel::N_POINTS; + const bool success = points.size() >= PointModel::N_POINTS; if (success) { @@ -116,35 +112,36 @@ void Tracker_PT::run() } Affine X_CM = pose(); - - { - Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); // just copy pasted these lines from below - Affine X_GH = X_CM * X_MH; - cv::Vec3f p = X_GH.t; // head (center?) position in global space - cv::Vec2f p_(p[0] / p[2] * fx, p[1] / p[2] * fx); // projected to screen - points.push_back(p_); - } - - for (unsigned i = 0; i < points.size(); i++) + + std::function fun = [&](const cv::Vec2f& p, const cv::Scalar color) { - auto& p = points[i]; - auto p2 = cv::Point(p[0] * frame.cols + frame.cols/2, -p[1] * frame.cols + frame.rows/2); - cv::Scalar color(0, 255, 0); - if (i == points.size()-1) - color = cv::Scalar(0, 0, 255); - cv::line(frame, + auto p2 = cv::Point(p[0] * frame_.cols + frame_.cols/2, -p[1] * frame_.cols + frame_.rows/2); + cv::line(frame_, cv::Point(p2.x - 20, p2.y), cv::Point(p2.x + 20, p2.y), color, 4); - cv::line(frame, + cv::line(frame_, cv::Point(p2.x, p2.y - 20), cv::Point(p2.x, p2.y + 20), color, - 4); + 4); + }; + + for (unsigned i = 0; i < points.size(); i++) + { + fun(points[i], cv::Scalar(0, 255, 0)); + } + + { + Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); // just copy pasted these lines from below + Affine X_GH = X_CM * X_MH; + cv::Vec3f p = X_GH.t; // head (center?) position in global space + cv::Vec2f p_(p[0] / p[2] * fx, p[1] / p[2] * fx); // projected to screen + fun(p_, cv::Scalar(0, 0, 255)); } - video_widget->update_image(frame); + video_widget->update_image(frame_); } } qDebug()<<"Tracker:: Thread stopping"; diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index 6118f3d2..3808c408 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -16,10 +16,17 @@ PointExtractor::PointExtractor() { } -std::vector PointExtractor::extract_points(cv::Mat& frame) + +const std::vector& PointExtractor::extract_points(cv::Mat& frame) { const int W = frame.cols; const int H = frame.rows; + + if (frame_gray.rows != frame.rows || frame_gray.cols != frame.cols) + { + frame_gray = cv::Mat(frame.rows, frame.cols, CV_8U); + frame_bin = cv::Mat(frame.rows, frame.cols, CV_8U);; + } // convert to grayscale cv::Mat frame_gray; @@ -151,9 +158,11 @@ std::vector PointExtractor::extract_points(cv::Mat& frame) using b = const blob; std::sort(blobs.begin(), blobs.end(), [](b& b1, b& b2) {return b1.confid > b2.confid;}); + points.reserve(blobs.size()); + QMutexLocker l(&mtx); - points.clear(); + points.clear(); for (auto& b : blobs) { diff --git a/tracker-pt/point_extractor.h b/tracker-pt/point_extractor.h index 80c1897d..979cc8b6 100644 --- a/tracker-pt/point_extractor.h +++ b/tracker-pt/point_extractor.h @@ -21,7 +21,7 @@ public: // extracts points from frame and draws some processing info into frame, if draw_output is set // dt: time since last call in seconds // WARNING: returned reference is valid as long as object - std::vector extract_points(cv::Mat &frame); + const std::vector &extract_points(cv::Mat &frame); const std::vector& get_points() { QMutexLocker l(&mtx); return points; } PointExtractor(); -- cgit v1.2.3 From f4647a9960f531829f1add40554442a7c84d82a6 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 19 Dec 2015 20:46:10 +0100 Subject: tracker/pt: don't allocate temporary dynamic size arrays --- tracker-pt/point_extractor.cpp | 7 +------ tracker-pt/point_extractor.h | 4 ++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index 3808c408..655e1412 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -29,7 +29,6 @@ const std::vector& PointExtractor::extract_points(cv::Mat& frame) } // convert to grayscale - cv::Mat frame_gray; cv::cvtColor(frame, frame_gray, cv::COLOR_RGB2GRAY); const double region_size_min = s.min_point_size; @@ -61,14 +60,11 @@ const std::vector& PointExtractor::extract_points(cv::Mat& frame) const int thres = s.threshold; if (!s.auto_threshold) { - cv::Mat frame_bin; cv::threshold(frame_gray, frame_bin, thres, 255, cv::THRESH_BINARY); cv::findContours(frame_bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); } else { - cv::Mat hist; - constexpr int hist_c = 8; cv::calcHist(std::vector { frame_gray }, std::vector { 0 }, cv::Mat(), @@ -76,7 +72,7 @@ const std::vector& PointExtractor::extract_points(cv::Mat& frame) std::vector { 256/hist_c }, std::vector { 0, 256/hist_c }, false); - const int sz = hist.rows*hist.cols; + const int sz = hist.cols * hist.rows; int val = 0; int cnt = 0; constexpr int min_pixels = 250; @@ -95,7 +91,6 @@ const std::vector& PointExtractor::extract_points(cv::Mat& frame) val *= 240./256.; //qDebug() << "val" << val; - cv::Mat frame_bin; cv::threshold(frame_gray, frame_bin, val, 255, CV_THRESH_BINARY); cv::findContours(frame_bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); } diff --git a/tracker-pt/point_extractor.h b/tracker-pt/point_extractor.h index 979cc8b6..ad8955fc 100644 --- a/tracker-pt/point_extractor.h +++ b/tracker-pt/point_extractor.h @@ -27,8 +27,12 @@ public: settings_pt s; private: + enum { hist_c = 8 }; std::vector points; QMutex mtx; + cv::Mat frame_gray; + cv::Mat frame_bin; + cv::Mat hist; }; #endif //POINTEXTRACTOR_H -- cgit v1.2.3 From 29b7e7c2cd3f7d2b72f15168ecfa167beee0ded5 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 19 Dec 2015 20:56:44 +0100 Subject: spline-widget: oops, pass by reference --- spline-widget/functionconfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spline-widget/functionconfig.cpp b/spline-widget/functionconfig.cpp index 33100e07..777b4f6f 100644 --- a/spline-widget/functionconfig.cpp +++ b/spline-widget/functionconfig.cpp @@ -62,7 +62,7 @@ float Map::getValueInternal(int x) { return ret * sign; } -static QPointF ensureInBounds(QList points, int i) { +static QPointF ensureInBounds(const QList& points, int i) { int siz = points.size(); if (siz == 0 || i < 0) return QPointF(0, 0); -- cgit v1.2.3 From f6c32359f0697b3c8caea669d4a766b684b06a9b Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 19 Dec 2015 21:57:01 +0100 Subject: tracker/pt: avoid widget temp QImage allocation --- tracker-pt/pt_video_widget.cpp | 44 +++++++++++++++--------------------------- tracker-pt/pt_video_widget.h | 2 +- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/tracker-pt/pt_video_widget.cpp b/tracker-pt/pt_video_widget.cpp index 8c18e678..095c325f 100644 --- a/tracker-pt/pt_video_widget.cpp +++ b/tracker-pt/pt_video_widget.cpp @@ -9,6 +9,7 @@ */ #include "pt_video_widget.h" +#include void PTVideoWidget::update_image(const cv::Mat& frame) { @@ -16,11 +17,10 @@ void PTVideoWidget::update_image(const cv::Mat& frame) if (!freshp) { - if (_frame.cols != frame.cols || - _frame.rows != frame.rows || - _frame.channels() != frame.channels()) + if (_frame.cols != frame.cols || _frame.rows != frame.rows) { - _frame = cv::Mat(); + _frame = cv::Mat(frame.rows, frame.cols, CV_8U); + _frame2 = cv::Mat(frame.rows, frame.cols, CV_8U); } frame.copyTo(_frame); freshp = true; @@ -29,29 +29,17 @@ void PTVideoWidget::update_image(const cv::Mat& frame) void PTVideoWidget::update_and_repaint() { - { - QMutexLocker foo(&mtx); - if (_frame.empty() || !freshp) - return; - texture = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); - freshp = false; - uchar* data = texture.bits(); - const int chans = _frame.channels(); - const int pitch = texture.bytesPerLine(); - for (int y = 0; y < _frame.rows; y++) - { - unsigned char* dest = data + pitch * y; - const unsigned char* ln = _frame.ptr(y); - for (int x = 0; x < _frame.cols; x++) - { - const int idx = x * chans; - const int x_ = x * 3; - dest[x_ + 0] = ln[idx + 2]; - dest[x_ + 1] = ln[idx + 1]; - dest[x_ + 2] = ln[idx + 0]; - } - } - } - texture = texture.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); + QMutexLocker foo(&mtx); + if (_frame.empty() || !freshp) + return; + cv::cvtColor(_frame, _frame2, cv::COLOR_RGB2BGR); + + if (_frame3.cols != width() || _frame3.rows != height()) + _frame3 = cv::Mat(height(), width(), CV_8U); + + cv::resize(_frame2, _frame3, cv::Size(width(), height()), 0, 0, cv::INTER_NEAREST); + + texture = QImage((const unsigned char*) _frame2.data, _frame2.cols, _frame2.rows, QImage::Format_RGB888); + freshp = false; update(); } diff --git a/tracker-pt/pt_video_widget.h b/tracker-pt/pt_video_widget.h index 1235c0d5..073b2e93 100644 --- a/tracker-pt/pt_video_widget.h +++ b/tracker-pt/pt_video_widget.h @@ -42,6 +42,6 @@ private: QMutex mtx; QImage texture; QTimer timer; - cv::Mat _frame; + cv::Mat _frame, _frame2, _frame3; bool freshp; }; -- cgit v1.2.3 From 023e2254db1d2e66986fa1a6bd4d032f21236c11 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 19 Dec 2015 22:13:49 +0100 Subject: contrib/make-csv: perl sort isn't stable, don't ignore case --- contrib/very-important-source-code/make-csv.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/very-important-source-code/make-csv.pl b/contrib/very-important-source-code/make-csv.pl index ee60364e..fcac9369 100644 --- a/contrib/very-important-source-code/make-csv.pl +++ b/contrib/very-important-source-code/make-csv.pl @@ -58,7 +58,7 @@ sub merge { } } print "No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID\n"; - for (sort { lc($a->{name}) cmp lc($b->{name}) } values %game_hash) { + for (sort { $a->{name} cmp $b->{name} } values %game_hash) { my $g = {%$_}; if (!defined $g->{key}) { $g->{key} = (sprintf "%04X", $g->{no}) . (join"", map { sprintf "%02X", int rand 256 } 0 .. 7) . '00'; -- cgit v1.2.3 From 2f679349aea7f4602175a500340c3a7fb8800d75 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 19 Dec 2015 22:14:04 +0100 Subject: freetrack/games: regen --- settings/facetracknoir supported games.csv | 239 +++++++++++++++-------------- 1 file changed, 120 insertions(+), 119 deletions(-) diff --git a/settings/facetracknoir supported games.csv b/settings/facetracknoir supported games.csv index a08d4171..55b38a47 100644 --- a/settings/facetracknoir supported games.csv +++ b/settings/facetracknoir supported games.csv @@ -5,13 +5,17 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 3;3D Instructor;FreeTrack20;V160;;;20490;00034B0FC367116611B100 4;3D Interactive;FreeTrack20;V160;;;20425;0004C6371D77135815A600 505;3D Interieur Visualisation;FreeTrack20;V160;;;20815;01F9EDEE75DAC2968D9A00 -5;3d Nav;FreeTrack20;V160;;;20235;000579EC0E26932651EA00 6;3D-Fahrschule Driving Simulator;FreeTrack20;V160;;;20020;000601075146E0E9625B00 +5;3d Nav;FreeTrack20;V160;;;20235;000579EC0E26932651EA00 7;3ds Max;FreeTrack20;V160;;;8601;00077A32A1A7523A4DE700 +11;ADS;FreeTrack20;V160;;;20690;000BB25377780C8A894400 +20;ANAG 3D;FreeTrack20;V160;;;20250;0014E2D1D7780A72166300 +498;ARI;FreeTrack20;V160;;;20795;01F23FB9A61044E206E200 +32;AV Core Technology;FreeTrack20;V160;;;20016;00204655E791166FEB5300 +33;AVRS;FreeTrack20;V160;;;20340;0021231517525830F41D00 8;Aaaaa!;FreeTrack20;V160;;;1775;00085485D831DA62CA7E00 9;Accessible Computer Games;FreeTrack20;V160;;;4301;000916BC07A2F9B35B6300 10;Aces High II;FreeTrack20;V160;V;bash1;2701;000A4B798B7221A72E5800 -11;ADS;FreeTrack20;V160;;;20690;000BB25377780C8A894400 12;Aerofly FS;FreeTrack20;V160;V;V4Friend;2025;000C3797169752CAB39A00 13;Affineon;FreeTrack20;V160;;;20405;000D662B0374339635A000 14;Air Battles: Sky Defender;FreeTrack20;V160;;;7003;000E7C822098630A2ED700 @@ -20,12 +24,10 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 17;AirBook;FreeTrack20;V160;;;15201;0011D615A9C8430A201A00 18;America's Army;FreeTrack20;V160;;;4101;00120BCF5753D98399E200 19;America's Army 3;FreeTrack20;V170;;;14203;00133F3206BCEA252BB700 -20;ANAG 3D;FreeTrack20;V160;;;20250;0014E2D1D7780A72166300 21;Apache: Air Assault;FreeTrack20;V160;V;paleta77;1875;001591D997A2D912AAA200 519;Apex Motorsports;FreeTrack20;V160;;;3675;02078F3159271BBE676800 22;Aprisoft Gartenplaner;FreeTrack20;V160;;;20014;0016F2F27A5762FA937A00 23;Aprisoft Traumhaus Designer;FreeTrack20;V160;;;20013;00174655E792BB825B9300 -498;ARI;FreeTrack20;V160;;;20795;01F23FB9A61044E206E200 24;ArmA;FreeTrack20;V160;V;EmBeES;10601;0018F2F27A57631A40F200 25;ArmA 2;FreeTrack20;V170;V;V4Friend Ronski;7502;0019EB3616B3A44F05B900 26;ArmA 2 Operation Arrowhead;FreeTrack20;V160;V;vn88holden;0;001ABC224B7783DAF0D500 @@ -36,22 +38,20 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 30;Arvoch Conflict;FreeTrack20;V160;;;14901;001E5C1FDE722DAE2BA900 31;Auditory Displays for the blind;FreeTrack20;V160;;;20035;001F0FC9FF862F9D34BA00 486;Autodesk;FreeTrack20;V160;;;20755;01E6953FA7F759AF33AC00 -32;AV Core Technology;FreeTrack20;V160;;;20016;00204655E791166FEB5300 -33;AVRS;FreeTrack20;V160;;;20340;0021231517525830F41D00 482;B.O.M.B.;FreeTrack20;V160;;;3325;01E248ECCB81191AD49F00 34;BAE Systems HILAS cockpit;FreeTrack20;V160;;;20019;00220D9C887FD88E98B300 +45;BF2 (Unsupported Demo);FreeTrack20;V160;;;9651;002DC6371D86156AEB6000 35;Battle of Britain (iENT);FreeTrack20;V170;;;1305;00230BA119195B701AED00 36;Battle of Britain II - Wings of Victory;FreeTrack20;V160;V;Normalguy;7001;002452135882CA6419E200 37;Battlecruiser;FreeTrack20;V160;;;6101;00257C822098728A442900 38;Battlefield 2;FreeTrack20;V170;;;9601;0026B1560A2A7327659200 39;Battlefield 2 Trauma Studios;FreeTrack20;V160;;;6501;002720C7529B733AE2EA00 40;Battlefield 2142;FreeTrack20;V170;;;9602;00281C739AD3817FD43300 -41;Battleground Europe : World War II Online;FreeTrack20;V160;;;3301;0029F07957792CAD3DAF00 42;Battleground Europe : WWII Online;FreeTrack20;V160;;;11201;002A985017330A844A1200 +41;Battleground Europe : World War II Online;FreeTrack20;V160;;;3301;0029F07957792CAD3DAF00 573;Beamng.drive;FreeTrack20;V160;;;4525;023D0291C9C05323AC9500 43;Beckman Institute UIUC;FreeTrack20;V160;;;20012;002BB59DEFA8322A926A00 44;Beyond The Red Line;FreeTrack20;V160;;;13301;002CE7A7FAA27424BA2A00 -45;BF2 (Unsupported Demo);FreeTrack20;V160;;;9651;002DC6371D86156AEB6000 46;Big Scale Racing;FreeTrack20;V160;;;8301;002E4655E7A24ADDB99200 47;Birds of Prey;FreeTrack20;V160;;;1601;002FBF8C4EAA57730B3200 48;Birds of Steel;FreeTrack20;V160;;;1878;0030D7690F607233A21E00 @@ -63,15 +63,17 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 82;C-Spine;FreeTrack20;V160;;;4901;00525FD692C188FB8B2D00 54;C.A.R.S.;FreeTrack20;V170;;;2825;003698EFE2EB6EE8E11300 55;C.U.B.;FreeTrack20;V160;;;20505;0037848174F986FD85F500 -56;CameraGripTools;FreeTrack20;V160;;;20150;003870A8B761FA524A4200 -57;Caterpillar Simulators;FreeTrack20;V160;;;23080;0039F52E4221742FA63100 58;CCG Metamedia;FreeTrack20;V160;;;20009;003A6FA8A8DD86FE8BDB00 547;CDF Ghostship;FreeTrack20;V160;;;4150;02230A04C45292CC5DA400 568;CDF Starfighter;FreeTrack20;V160;;;4153;0238E7D9A14B2A1AE98900 59;CEWIT Immersive Cabin;FreeTrack20;V160;;;20370;003B90B5780C90078DEE00 +62;CNKFsoft;FreeTrack20;V160;;;20495;003ED7690F6073187B0000 +555;COMPUTERGRAFIK;FreeTrack20;V160;;;20900;022B5BB1CE1DAA0B1DEB00 +571;CS GO MOD;FreeTrack20;V160;;;12504;023BCA154A55F9587FC500 +56;CameraGripTools;FreeTrack20;V160;;;20150;003870A8B761FA524A4200 +57;Caterpillar Simulators;FreeTrack20;V160;;;23080;0039F52E4221742FA63100 60;Chopper;FreeTrack20;V160;;;3150;003CC166C8632A32EA2300 61;Clearbox;FreeTrack20;V160;;;20565;003D5C1FDE74279D1DB800 -62;CNKFsoft;FreeTrack20;V160;;;20495;003ED7690F6073187B0000 558;Code 10;FreeTrack20;V160;;;2975;022E45423D22193FF81900 487;Cognitics;FreeTrack20;V160;;;20760;01E715A96D19515BFC1500 63;Colin McRae DiRT 2;FreeTrack20;V170;V;V4Friend;8107;003F7815C5379491C73300 @@ -82,7 +84,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 67;Combat Helo;FreeTrack20;V160;;;2001;004329DFA863FAE1EA7300 515;Combined Arms;FreeTrack20;V160;;;1309;0203387EDB1A5AFEADB600 68;Commandos Strike Force;FreeTrack20;V160;;;8801;0044C1BBF892DB037A7200 -555;COMPUTERGRAFIK;FreeTrack20;V160;;;20900;022B5BB1CE1DAA0B1DEB00 69;Concept RS;FreeTrack20;V160;;;10701;004537971697736A72DA00 70;Condor: The Competitive Soaring Simulator;FreeTrack20;V160;V;MicheleF;5901;004670A8B762DA623A1300 71;Conflict Taiwan;FreeTrack20;V160;;;1950;0047D7690F6073399E2000 @@ -97,16 +98,17 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 79;Crysis Mod;FreeTrack20;V160;;;1625;004F90B57839B231A24200 80;Crystal Growth Simulation;FreeTrack20;V160;;;20029;005026F79742FB241A6200 81;Crytek;FreeTrack20;V170;;;2775;0051D5F1EBBAD81C714600 -571;CS GO MOD;FreeTrack20;V160;;;12504;023BCA154A55F9587FC500 562;Cypher City;FreeTrack20;V160;;;4250;023259070AE238A9E78100 83;D2x-XL;FreeTrack20;V160;;;16001;00532E20237BEDABEB8A00 +87;DBS WalkAndFollow;FreeTrack20;V160;;;2525;005770A8B77008BDE89200 +88;DCS: Black Shark;FreeTrack20;V170;V;EmBeES;1006;0058F688FC9B0556868F00 +89;DCS: A-10C Warthog (32 and 64 bit);FreeTrack20;V170;V;fabri91 Shadow;1003;0059B6DCD15F5A572F6500 +101;DTS;FreeTrack20;V160;;;20625;006505B37C12868B3E8500 +103;DY Demo;FreeTrack20;V160;;;20345;006727D5047A15540F9D00 84;Dark Horizons Lore;FreeTrack20;V160;;;7901;005487801A852AA7385200 85;Dawn of Aces - Gold Edition;FreeTrack20;V170;;;1304;0055A9ED7700814190DE00 86;Dawn of Aces II;FreeTrack20;V160;;;1302;00566925967C2BB0285500 513;Dawn of Aces/Red Baron;FreeTrack20;V160;;;1307;0201916C14F32918D9B800 -87;DBS WalkAndFollow;FreeTrack20;V160;;;2525;005770A8B77008BDE89200 -88;DCS: Black Shark;FreeTrack20;V170;V;EmBeES;1006;0058F688FC9B0556868F00 -89;DCS: A-10C Warthog (32 and 64 bit);FreeTrack20;V170;V;fabri91 Shadow;1003;0059B6DCD15F5A572F6500 90;Dead Reckoning;FreeTrack20;V160;;;10401;005A4C2F6752F912D66200 91;Delivery;FreeTrack20;V160;;;15901;005BF3E85B1A8534AE3400 471;Demon Core;FreeTrack20;V160;;;3225;01D7D1DC6052A165A7AC00 @@ -117,40 +119,36 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 528;Dovetail Games;FreeTrack20;V160;;;3850;0210EE3E0DA9BC1B888100 534;Dovetail Train Simulator 2015;FreeTrack20;V160;;;3851;02160B238D555F3D389E00 95;Down In Flames;FreeTrack20;V160;;;1025;005F29DFA873FB82A66000 +98;DriveSim;FreeTrack20;V160;;;5001;0062DD7CC2B47830A14400 96;Driver Test;FreeTrack20;V160;;;20265;00609343487C3FAA429D00 97;Driver's Republic;FreeTrack20;V160;;;14001;0061D24C3F8A3F9C33AB00 -98;DriveSim;FreeTrack20;V160;;;5001;0062DD7CC2B47830A14400 99;Driving Simulator;FreeTrack20;V160;;;13001;00630AC67539AC3F9F3A00 -100;dSphere TBA;FreeTrack20;V160;;;2425;0064A2AE4981FB5389A300 -101;DTS;FreeTrack20;V160;;;20625;006505B37C12868B3E8500 102;Dungeons and Dragons Online;FreeTrack20;V170;;;1575;0066BD4D4DDC6BB6818800 -103;DY Demo;FreeTrack20;V160;;;20345;006727D5047A15540F9D00 104;EADS Testing;FreeTrack20;V160;;;20303;00680288709760D5512900 504;EAFIT;FreeTrack20;V160;;;20810;01F8D2675ABC163E99B000 +107;ECA-Sindel;FreeTrack20;V160;;;20590;006BC5BEE479FD75FB8500 +108;EMS Simulations;FreeTrack20;V160;;;20390;006CA59E687D1589DE8500 +112;EON Reality;FreeTrack20;V160;;;20410;0070B6C6142771F82EE900 +115;EVE Online;FreeTrack20;V160;;;11801;0073F47CC377C2388DC900 +550;EVE Valkyrie;FreeTrack20;V170;;;4175;104F28E121C07E6D84C200 +117;EVOC-101 Training;FreeTrack20;V160;;;20038;00756925967D2088FC6200 +122;EZCA;FreeTrack20;V160;V;dennison ;2475;007A6DBB52F7B147510601 +572;EZCamViews;FreeTrack20;V160;;;4475;023CF141A5E222B5ACE000 105;Eagle Lander 3D;FreeTrack20;V160;;;11901;00697686E5A7B209C27900 106;EasyVR;FreeTrack20;V160;;;20220;006A68292872FAC4588100 -107;ECA-Sindel;FreeTrack20;V160;;;20590;006BC5BEE479FD75FB8500 508;Elite: Dangerous;FreeTrack20;V170;;;3475;0D93A9485EECA12E18BE00 481;Embers of Caerus;FreeTrack20;V170;;;3275;0CCB4134258D7E10119E00 -108;EMS Simulations;FreeTrack20;V160;;;20390;006CA59E687D1589DE8500 109;Enemy Engaged 2;FreeTrack20;V160;;;2102;006D010873EA635AEDC800 110;Enemy Engaged: Commanche vs Hokum;FreeTrack20;V160;;;2101;006E157D789379636AED00 524;Enemy Starfighter;FreeTrack20;V160;;;3725;020C7EF3AC4F08C8787600 111;Envision TE;FreeTrack20;V160;;;20320;006FD13C2A863CAF26AB00 -112;EON Reality;FreeTrack20;V160;;;20410;0070B6C6142771F82EE900 -113;eSigma;FreeTrack20;V160;;;20700;0071950F9AA60DAD2E9F00 114;Euro Truck Simulator;FreeTrack20;V160;V;mamsa;13602;00721B4BFF8B3EA3296600 -115;EVE Online;FreeTrack20;V160;;;11801;0073F47CC377C2388DC900 -550;EVE Valkyrie;FreeTrack20;V170;;;4175;104F28E121C07E6D84C200 116;Eventology;FreeTrack20;V160;;;12201;0074849F8B469C2BAC3600 -117;EVOC-101 Training;FreeTrack20;V160;;;20038;00756925967D2088FC6200 118;Evochron Alliance 2.0;FreeTrack20;V160;;;14904;00767A32A1A8735A022900 557;Evochron Legacy;FreeTrack20;V160;;;14909;022D84A6946770E4EFD800 119;Evochron Legends;FreeTrack20;V160;;;14906;0077D6E585F8B41A12BA00 120;Evochron Mercenary;FreeTrack20;V160;V;Scavenger4711 ;14907;00783752FBC7B42B221A00 121;Evochron Renegades;FreeTrack20;V160;;;14905;0079621E7763FB421A1300 -122;EZCA;FreeTrack20;V160;V;dennison ;2475;007A6DBB52F7B147510601 -572;EZCamViews;FreeTrack20;V160;;;4475;023CF141A5E222B5ACE000 125;F-22 Total Air War;FreeTrack20;V160;;;1750;007D20C79F475F0621DB00 126;F-35 PTA;FreeTrack20;V160;;;20185;007E26F7977E96C0352100 148;F-Trainer;FreeTrack20;V160;;;20615;0094C6371D8AFB8C3E9900 @@ -158,11 +156,13 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 531;F1 2015;FreeTrack20;V170;;;8110;1FAE39C238A4D2D6541200 124;F1 Challenge 99-02;FreeTrack20;V160;;;4401;007CA15F278FB660C9D210 127;FAAC;FreeTrack20;V160;;;20500;007F0F00F489118300C000 +132;FIFA 09;FreeTrack20;V170;;;9002;0084288979C65B0DAA0D00 +552;FSX Steam Edition;FreeTrack20;V160;;;3852;02287F45F0FFBEF6102900 +147;FTAlpha;FreeTrack20;V160;;;20270;00936C69677F1D772AA900 128;Farmer Simulator 2009;FreeTrack20;V160;;;1725;0080926ED8A1EB628AB300 129;Faros Driving Simulator;FreeTrack20;V160;;;8001;0081B1C6647A1EA839A800 130;Faubert Lab Car Simulator;FreeTrack20;V160;;;20480;00822E542A7F2DB61F9700 131;Ferrari Virtual Academy;FreeTrack20;V160;V;sosna1983 ;0;0083C0AF8C24B62D974000 -132;FIFA 09;FreeTrack20;V170;;;9002;0084288979C65B0DAA0D00 133;Fighter Ace;FreeTrack20;V160;;;8401;0085E2D1D77D259837B700 134;Fighter Ops;FreeTrack20;V160;;;9301;00860FC9FF8B23A033BA00 135;Fighter Squadron: Screamin Demons Over Europe;FreeTrack20;V160;;;1675;00872E20237D259A27A600 @@ -183,10 +183,13 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 144;Free Falcon 4.0: Allied Force;FreeTrack20;V160;;;8901;0090656DD6793CA9325900 145;Free Falcon 5;FreeTrack20;V160;V;V4Friend;1902;00911038C3AAB32590E900 146;FreeSpace2;FreeTrack20;V160;;;13302;0092C8CDF8C2EA63496300 -552;FSX Steam Edition;FreeTrack20;V160;;;3852;02287F45F0FFBEF6102900 -147;FTAlpha;FreeTrack20;V160;;;20270;00936C69677F1D772AA900 149;Full Out;FreeTrack20;V160;;;1701;009527D5047C31A0375800 150;Future Pinball;FreeTrack20;V160;V;V4Friend;13101;00969343487E42B541AA00 +159;GRID;FreeTrack20;V160;V;LeapoEclipse ;8105;009FD8175F8D1D7C0D3800 +160;GSE Power Plant Simulation;FreeTrack20;V160;;;20044;00A0432C28C217BEF93300 +161;GT Legends;FreeTrack20;V160;V;TrickyDee ;3902;00A116BC08020581CA8200 +162;GTR;FreeTrack20;V160;;;3901;00A2FD6BFE39A881B85B00 +163;GTR2 EVO;FreeTrack20;V160;V;zild1221 ;0;00A34B0FC37B2198F96300 151;Game VR;FreeTrack20;V160;;;20325;009756BA018030B0355500 152;GameLab;FreeTrack20;V160;;;20555;00985485D891DB23092200 472;Games Farm;FreeTrack20;V160;;;3250;01D875C0981E627E5C7600 @@ -202,38 +205,34 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 156;Gothic 3;FreeTrack20;V160;;;14401;009C37971697B36AD32A00 157;Grand Prix Legends;FreeTrack20;V160;;;6701;009D521358D3D933B96E01 158;Grand Theft Auto: San Andreas;FreeTrack20;V160;;;7808;009E5F3D95777D3BA23700 -159;GRID;FreeTrack20;V160;V;LeapoEclipse ;8105;009FD8175F8D1D7C0D3800 -160;GSE Power Plant Simulation;FreeTrack20;V160;;;20044;00A0432C28C217BEF93300 -161;GT Legends;FreeTrack20;V160;V;TrickyDee ;3902;00A116BC08020581CA8200 -162;GTR;FreeTrack20;V160;;;3901;00A2FD6BFE39A881B85B00 -163;GTR2 EVO;FreeTrack20;V160;V;zild1221 ;0;00A34B0FC37B2198F96300 164;Gun Commander;FreeTrack20;V160;;;2675;00A4E2D1D77E319FEE8600 520;H1Z1;FreeTrack20;V170;;;6004;1774F090B1BA9E782D0800 +169;HAWX;FreeTrack20;V160;V;EmBeES ;0;00A9D615A9C8B088717000 +171;HOBI;FreeTrack20;V160;;;20335;00ABB253777F1779168900 +173;HPC;FreeTrack20;V160;;;20600;00AD0FC9FF8D0A7CEF9500 +174;HPG Tracking;FreeTrack20;V160;;;20255;00AE0288A1879D98930900 +175;HTW;FreeTrack20;V160;;;20630;00AF26F797911901C22C00 165;Half Life 2;FreeTrack20;V160;;;7806;00A556BA018130AF365500 166;Halo;FreeTrack20;V160;;;3801;00A656BA018130AF3F9C00 -502;hapTEL;FreeTrack20;V160;;;20805;01F63ADE510A20446B6A00 167;Hardware Control Simulator Railway Electronics;FreeTrack20;V160;;;20705;00A7F3E85B1A8930B42F00 168;Harrier Attack II;FreeTrack20;V160;;;1175;00A8F2F27A57D20A940900 499;Harry's Hard Choices Interactive;FreeTrack20;V160;;;20800;01F33A21BAE3DB6D48A000 -169;HAWX;FreeTrack20;V160;V;EmBeES ;0;00A9D615A9C8B088717000 170;Herissons (Paris France);FreeTrack20;V160;;;20001;00AAEA1CBED8C20B430B00 -523;hiCRANE2;FreeTrack20;V160;;;20835;020BA8FC8C7DFFA1381A00 -171;HOBI;FreeTrack20;V160;;;20335;00ABB253777F1779168900 172;HoverAssault;FreeTrack20;V160;;;5303;00AC521358E3AA832A4000 -173;HPC;FreeTrack20;V160;;;20600;00AD0FC9FF8D0A7CEF9500 -174;HPG Tracking;FreeTrack20;V160;;;20255;00AE0288A1879D98930900 -175;HTW;FreeTrack20;V160;;;20630;00AF26F797911901C22C00 176;Huawei Software;FreeTrack20;V160;;;20660;00B04655E8030A733AB300 177;HueSpace;FreeTrack20;V160;;;20510;00B1231517C44960FB6300 178;Hyper Vision;FreeTrack20;V160;;;15101;00B2DB242B657D43B32300 -179;iAmFootball;FreeTrack20;V160;;;1250;00B3B59DEFAAAFDB301A00 -180;id Research;FreeTrack20;V170;;;2950;00B4E723B873D7FC87D700 181;IESA;FreeTrack20;V160;;;20037;00B5157D78D0E840AD7100 182;IL-2 Cliffs of Dover;FreeTrack20;V160;V;V4Friend;0;00B6282282095F00521000 183;IL-2 Forgotten Battles ACE Pacific Fighters;FreeTrack20;V160;V;Glenn;1001;00B722FD79137100621100 484;IL-2 Sturmovik: Battle of Stalingrad;FreeTrack20;V170;;;1008;03F04D5368D1FD2DF2AE00 -184;Illumina;FreeTrack20;V160;;;1350;00B8054E8B39A33DB02400 185;ILP;FreeTrack20;V160;;;20310;00B9F07957801789C9A600 +193;IREQ Robotic Camera Control;FreeTrack20;V160;;;20027;00C10448E0E8618521EB00 +536;ISAMM;FreeTrack20;V160;;;20860;0218303730165E681DB000 +194;ISIC;FreeTrack20;V160;;;20680;00C2DEE3582F8F217E0B00 +506;ITCL;FreeTrack20;V160;;;20820;01FAD19412681DC9CC6100 +195;IVD Online;FreeTrack20;V160;;;20535;00C390B57E1D7DDD883D00 +184;Illumina;FreeTrack20;V160;;;1350;00B8054E8B39A33DB02400 186;Imagine 3D ATC Tower Simulation;FreeTrack20;V160;;;20032;00BAEF7A8F4B8812B95300 187;In Touch Technologies Inc.;FreeTrack20;V160;;;20006;00BB84817A3A5124B23D00 188;Inglobe;FreeTrack20;V160;;;20360;00BCE7A7FAA27B2DA82700 @@ -242,19 +241,13 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 575;Interstellar Rift;FreeTrack20;V160;;;4550;023FF83230A370CBC6AC00 191;Intific;FreeTrack20;V160;;;20655;00BF2BCA747F2AA8309D00 566;Into the Dungeon;FreeTrack20;V160;;;4375;0236B346990ACCFC047A00 -192;iRacing;FreeTrack20;V160;V;vn88holden ;14101;00C0103AF1AA730A236900 -193;IREQ Robotic Camera Control;FreeTrack20;V160;;;20027;00C10448E0E8618521EB00 -536;ISAMM;FreeTrack20;V160;;;20860;0218303730165E681DB000 -194;ISIC;FreeTrack20;V160;;;20680;00C2DEE3582F8F217E0B00 -506;ITCL;FreeTrack20;V160;;;20820;01FAD19412681DC9CC6100 -195;IVD Online;FreeTrack20;V160;;;20535;00C390B57E1D7DDD883D00 196;J.J. Keller and Associates;FreeTrack20;V160;;;20002;00C4E482F57FE77CF46300 +199;JC Demo;FreeTrack20;V160;;;20470;00C70AC67B0A630D9B3900 +202;JFIST;FreeTrack20;V160;;;20560;00CAC932727C0F8D208600 197;Janes F18;FreeTrack20;V160;;;9001;00C55F3D9577802AAF2E00 198;Javal Ent.;FreeTrack20;V160;;;2650;00C622FD7A28BA2FAEEA00 -199;JC Demo;FreeTrack20;V160;;;20470;00C70AC67B0A630D9B3900 200;Jet Thunder;FreeTrack20;V160;;;4501;00C82100801FA4EA9A3500 201;Jetfighter V;FreeTrack20;V160;;;2501;00C9F52E42217B33A63200 -202;JFIST;FreeTrack20;V160;;;20560;00CAC932727C0F8D208600 203;John Deere Vehicle Simulator;FreeTrack20;V160;;;20175;00CB29DFA8D3FA92A66000 204;Jump to Lightspeed;FreeTrack20;V160;;;6001;00CCC166C8D3FA12E52400 205;Jumpgate;FreeTrack20;V160;;;15001;00CD26F797B32A63E99200 @@ -263,28 +256,32 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 476;KAI FLight Simulator;FreeTrack20;V160;;;20725;01DCC522132A5C01EDE500 560;Keita Head Tracking;FreeTrack20;V160;;;20385;02307E33478667072B0800 208;Key Macro View;FreeTrack20;V160;;;12001;00D016BC08431B1EF90100 -209;kiwi.vg;FreeTrack20;V160;;;20395;00D1409A430AB33633E900 521;Kongsberg GlobalSim;FreeTrack20;V160;;;20825;0209B2C573D990BF764700 210;L-3;FreeTrack20;V160;;;20465;00D2F885EFA8DE67878B00 211;L-3 Communications;FreeTrack20;V160;;;20051;00D3D6E585F92F765E7800 522;LG Electronics;FreeTrack20;V160;;;20830;020A3678F5833D513DCA00 +577;Limb;FreeTrack20;V160;;;4650;0241D999E2E247B1DFDD00 212;Lionhead MGS Game Research;FreeTrack20;V160;;;15301;00D4C1BBF9227B238AE200 213;Live For Speed;FreeTrack20;V160;V;zild1221 ;7101;00D528228526A833521300 214;Live for Speed S2;FreeTrack20;V160;;;11601;00D63752FBC8235B923500 218;Lock-On: Modern Air Combat;FreeTrack20;V160;;;1002;00DAAC156D903C993B6200 +217;LockOn: Flaming Cliffs 2;FreeTrack20;V170;V;EmBeES ;1005;00D9AFB0D279F3A6F72200 215;Lockheed Martin Littoral Combat Ship simulator;FreeTrack20;V160;;;20025;00D771ED5E802A9827A000 216;Lockheed Martin Prepar3D;SimConnect;V130;V;elelbe ;0;00D8D615A9C8F36932AA00 -217;LockOn: Flaming Cliffs 2;FreeTrack20;V170;V;EmBeES ;1005;00D9AFB0D279F3A6F72200 219;London NHS;FreeTrack20;V160;;;20640;00DB2E2023832BA123A100 220;Lore (Dark Horizons);FreeTrack20;V160;;;5302;00DCF478D27833DB62D500 221;Love;FreeTrack20;V160;;;3125;00DD71ED5E802AAB214800 222;Lucid Engine;FreeTrack20;V160;;;10501;00DE71ED5E803098259C00 514;M4 Tank Brigade;FreeTrack20;V160;;;1308;02024ED5A3A26741604300 223;M4 Tank Platoon;FreeTrack20;V160;;;1306;00DFDCC441A8E036320900 -224;Mach 1;FreeTrack20;V160;;;2575;00E0231518130942466000 549;MAG WIP;FreeTrack20;V160;;;4152;02252A1C82FD29D9FFB900 +244;MKMapper Keymapper;FreeTrack20;V160;;;2201;00F487801A8E14822EA200 +250;MS World Tour Kart 2004;FreeTrack20;V160;;;6601;00FA9F819CA27F10591600 +251;MSN Virtual Earth;FreeTrack20;V160;;;2309;00FBF47CC37842091DC900 +224;Mach 1;FreeTrack20;V160;;;2575;00E0231518130942466000 225;ManuVAR;FreeTrack20;V160;;;20455;00E153FE1E901CB0448800 226;MaqSIM4;FreeTrack20;V160;;;20026;00E28F54A207D29B611700 +233;MeVEA;FreeTrack20;V160;;;2250;00E9D24C3F933289028700 227;Mech Tactical Sim;FreeTrack20;V160;;;9501;00E3F3E85B1A8E34A53300 516;MechWarrior Online;FreeTrack20;V170;;;3026;0BD2E0DCBC723836CD2400 228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200 @@ -292,41 +289,36 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 230;Meggitt Defense Systems;FreeTrack20;V160;;;20045;00E6926ED9122AB22AF300 231;MetaVR;FreeTrack20;V160;;;20545;00E7C5BEE48120A8308800 232;Meteoroid Maze;FreeTrack20;V160;;;13003;00E8F079578430AD2EB200 -233;MeVEA;FreeTrack20;V160;;;2250;00E9D24C3F933289028700 234;Micro Flight;FreeTrack20;V160;V;V4Friend;5101;00EABA89D078439932EA00 235;Microsoft ESP;FreeTrack20;V160;;;2306;00EB0AC67E30A63BA53F00 -236;Microsoft Flight;FreeTrack20;V170;V;V4Friend;2307;00ECAFBC54959539C51500 -237;Microsoft Flight Simulator 3;FreeTrack20;V160;V;V4Friend;0;00ED5909437D36963EA810 238;Microsoft FS2002/2004;FSUIPC;V130;V;V4Friend;0;00EE44958F34992CB43A00 239;Microsoft FSX;SimConnect;V130;V;V4Friend;0;00EFF478D278437A73AA00 +236;Microsoft Flight;FreeTrack20;V170;V;V4Friend;2307;00ECAFBC54959539C51500 +237;Microsoft Flight Simulator 3;FreeTrack20;V160;V;V4Friend;0;00ED5909437D36963EA810 240;Microsoft Train Simulator;FreeTrack20;V160;;;7805;00F00449225A439A13FB00 494;MiddleVR;FreeTrack20;V160;;;20785;01EE1227DF43CA90C26100 241;Mig Alley;FreeTrack20;V160;;;1501;00F17686E5A83289CDA700 242;Mimik Vehicle Simulator;FreeTrack20;V160;;;20585;00F2AB1D58A8E35A531A00 243;Miner Wars;FreeTrack20;V160;;;2550;00F3C5BEE48124A234A400 -244;MKMapper Keymapper;FreeTrack20;V160;;;2201;00F487801A8E14822EA200 245;ModelSim;FreeTrack20;V160;;;20540;00F544958F3A9A1FB11A00 246;Morgan State University;FreeTrack20;V160;;;20010;00F65909437D3CA5339A00 247;Motor Company;FreeTrack20;V160;;;11501;00F70288F37A629A7DD700 248;Motorsport Simulators;FreeTrack20;V160;;;4201;00F8F52E42217E3DA63B00 249;Mouse Emulation;FreeTrack20;V160;;;8501;00F9950F9A8E29B93A9700 -250;MS World Tour Kart 2004;FreeTrack20;V160;;;6601;00FA9F819CA27F10591600 -251;MSN Virtual Earth;FreeTrack20;V160;;;2309;00FBF47CC37842091DC900 -252;mTBI Balance;FreeTrack20;V160;;;20420;00FC72456F9E0E78145800 253;NASA Crew Exploration Vehicle;FreeTrack20;V160;;;20017;00FD028900985FA5501A00 254;NASCAR Heat;FreeTrack20;V160;;;2602;00FE311857E10880B84100 255;NASCAR Racing 2003 season;FreeTrack20;V160;;;7804;00FFDE661F6D920B87FC10 256;NASCAR SimRacing;FreeTrack20;V160;;;6201;01004098708870D761A500 +262;NVH Sound Simulator;FreeTrack20;V160;;;20695;010655A2AA93158DDE9500 535;Navi Trainer Professional;FreeTrack20;V160;;;20855;0217C0E0793305EE8D5200 257;NecroVisioN;FreeTrack20;V160;;;15601;0101621E77F2EA830A8100 258;NetKar Pro;FreeTrack20;V160;V;sosna1983 ;10901;01028C3958334A5169A300 259;Nitro Stunt Racing;FreeTrack20;V160;;;13901;0103C0AF9428B82DA5ED00 260;North Eastern University;FreeTrack20;V160;;;20003;0104A2AE4823BB7449DE00 261;Novint;FreeTrack20;V160;;;2725;01051C76F8137B823A4300 -262;NVH Sound Simulator;FreeTrack20;V160;;;20695;010655A2AA93158DDE9500 479;OHJCH;FreeTrack20;V160;;;20740;01DF992E6C0DA43A703600 -551;Omni-Directional Movement;FreeTrack20;V160;;;20870;0227088B794053785DBE00 263;OMSI Bus Simulator;FreeTrack20;V160;V;Thiago ;2225;0107F47CC37861A9606600 +551;Omni-Directional Movement;FreeTrack20;V160;;;20870;0227088B794053785DBE00 264;Onadime - Realtime Animation;FreeTrack20;V160;;;20049;010853FE1E9229A3339B00 265;Open Falcon 4.5;FreeTrack20;V160;V;muplex ;0;0109B1C664832D9B385500 266;Operation Air Assault 2;FreeTrack20;V160;;;5401;010ABB5BF72C9238973B00 @@ -340,6 +332,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 274;Oryx Vehicle Simulators;FreeTrack20;V160;;;20028;0112C8CDF952EBA4763100 275;Outer Conflict: Frontiers;FreeTrack20;V160;;;1900;01136C6967883EAA23AB00 276;Over Flanders Fields;FreeTrack20;V160;V;Summelar ;2325;0114A59E68873E9B315210 +545;PULSAR: Lost Colony;FreeTrack20;V160;;;4075;02214BC732C034C3620400 277;PanoPro;FreeTrack20;V160;;;20525;0115B6C61428231A23E900 278;Paraworld;FreeTrack20;V160;;;14501;0116656DD6832BB62EB000 279;Phoenix R/C;FreeTrack20;V160;;;3075;0117B6C61428238A334B00 @@ -355,7 +348,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 286;Project Torque (Invictus);FreeTrack20;V160;;;4802;011E612F28540B52797100 287;Project X;FreeTrack20;V160;;;20022;011FE9D85E4842DA439900 529;Puegeot PSA Simulator;FreeTrack20;V160;;;20840;021127A7344E7C044E9500 -545;PULSAR: Lost Colony;FreeTrack20;V160;;;4075;02214BC732C034C3620400 553;QSTP;FreeTrack20;V160;;;20875;0229A3C108BE55FFF2BC00 288;Quanser;FreeTrack20;V160;;;20435;0120950F9A922FA535A500 289;QuantaDyn;FreeTrack20;V160;;;20575;012199BB5C9433A739B600 @@ -366,30 +358,31 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 293;R.U.D.O. Tools;FreeTrack20;V160;;;20039;0125612F287FB9BEA76E00 294;RACE (the WTCC game);FreeTrack20;V160;;;3904;01263C2C1C94FA86146300 295;RACE 07 RACE GTR 2;FreeTrack20;V160;V;zild1221 TrickyDee ;3903;0127C0AF9800870056FD00 +574;RCPlugin;FreeTrack20;V160;;;23090;023E0448BCFD48E0149D00 +312;REFLEX XTR;FreeTrack20;V160;;;2150;0138054E94127D14881300 +492;RITS;FreeTrack20;V160;;;20775;01ECEE745B83DD3A0DBE00 +327;ROV Sim;FreeTrack20;V160;;;20530;0147FA04BD27891D9ADD00 +329;RSD Demo;FreeTrack20;V160;;;2050;0149BF8C4EAA5871A85D00 +330;RTMS Crane Sim;FreeTrack20;V160;;;20400;014AC93272841D91205200 +331;RTT DeltaGen Plugin;FreeTrack20;V160;;;20195;014B90B5871B8DDD7D3400 296;RaceOn;FreeTrack20;V160;V;zild1221 ;0;0128621E7832AA82388200 +490;RaceRoom Racing Experience;FreeTrack20;V160;;;3905;01EA9124F663AF03BBC500 297;Racer;FreeTrack20;V160;;;2401;01296D2D103862E932EA00 298;Racer S;FreeTrack20;V160;;;20030;012AEA1CBED961CA52CB00 -490;RaceRoom Racing Experience;FreeTrack20;V160;;;3905;01EA9124F663AF03BBC500 299;Rail Simulator 1;FreeTrack20;V160;;;1550;012BB253778929A0395900 -300;Railway Work Simulator;FreeTrack20;V160;;;20225;012C91D998B1E9933B9100 301;RailWorks 2;FreeTrack20;V160;;;2750;012D3919C4972D9D299000 507;RailWorks 5 (TS2014);FreeTrack20;V160;;;1551;01FB8B5232CB1502C95A00 +300;Railway Work Simulator;FreeTrack20;V160;;;20225;012C91D998B1E9933B9100 302;Raydon Driving Simulator;FreeTrack20;V160;;;3701;012E5485D941DBE2FB5300 -574;RCPlugin;FreeTrack20;V160;;;23090;023E0448BCFD48E0149D00 304;Real Time Visual;FreeTrack20;V160;;;9901;0130B1C664862297365500 305;RealFlight;FreeTrack20;V160;;;4001;0131AC6E87892E993A8B00 -306;Reality Manager;FreeTrack20;V160;;;20046;0132DB242B65872FA42A00 307;RealWorld;FreeTrack20;V160;;;20215;0133B59DEFA9322A727800 +306;Reality Manager;FreeTrack20;V160;;;20046;0132DB242B65872FA42A00 308;Red Baron 3D;FreeTrack20;V160;;;1125;0134C6371D96349CEB7A00 309;Red Orchestra: Heroes of Stalingrad;FreeTrack20;V170;;;12602;013521F9121056CD997300 310;Red Orchestra: Ostfront;FreeTrack20;V170;;;12601;01369A9A2BE97252BB9000 311;Redline Monitor;FreeTrack20;V160;;;20210;01373752FBC8831A72AA00 -312;REFLEX XTR;FreeTrack20;V160;;;2150;0138054E94127D14881300 313;Remote Presence;FreeTrack20;V160;;;20710;01399BC3BDA93229D2BB00 -314;rFactor;FreeTrack20;V160;V;V4Friend;7401;013AEF7A8F4B8AA0495200 -315;rFactor Pro;FreeTrack20;V170;;;7403;013B175198D74BE8E89600 -316;rFactor2;FreeTrack20;V170;;;7402;013CBFF3A86D34DA24C000 -533;rFPro;FreeTrack20;V170;;;7404;1CEC6BE26009B31DE7BC00 317;Richard Burns Rally;FreeTrack20;V160;V;zild1221;3401;013D42868B339A31A73C10 318;RidingStar;FreeTrack20;V160;;;1475;013E3919C497359826A700 544;Rift's Cave;FreeTrack20;V160;;;4050;02209C681EAD3B06D15A00 @@ -398,41 +391,40 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 321;Rise of Flight;FreeTrack20;V160;V;Seborgarsen ;11401;0141AA71218335A51F5100 322;Rise: The Vieneo Province;FreeTrack20;V160;;;6301;0142DEE3582F9837A82D00 323;Rising Conflicts;FreeTrack20;V160;;;12101;014384818335A439B12F00 -492;RITS;FreeTrack20;V160;;;20775;01ECEE745B83DD3A0DBE00 +530;RoRo Simulator;FreeTrack20;V160;;;20845;02123A5F2F98EF4D0F0700 324;Road Legends;FreeTrack20;V160;;;1876;0144379716986369A2E600 325;Rogue Space;FreeTrack20;V160;;;3050;014588F5872C9C30ABE900 326;Rogue Warrior;FreeTrack20;V160;;;14202;0146432C2973D9D45A8E00 -530;RoRo Simulator;FreeTrack20;V160;;;20845;02123A5F2F98EF4D0F0700 -327;ROV Sim;FreeTrack20;V160;;;20530;0147FA04BD27891D9ADD00 328;Rowan's Battle Of Britain;FreeTrack20;V160;;;1502;014821008829A72CB4F300 -329;RSD Demo;FreeTrack20;V160;;;2050;0149BF8C4EAA5871A85D00 -330;RTMS Crane Sim;FreeTrack20;V160;;;20400;014AC93272841D91205200 -331;RTT DeltaGen Plugin;FreeTrack20;V160;;;20195;014B90B5871B8DDD7D3400 540;Rust;FreeTrack20;V170;;;3950;0F6EF7CEF7DFA93405D700 +335;SCANeR Studio Plugin;FreeTrack20;V160;;;20445;014FA2AE4870F861E9A100 +336;SEGA Demo;FreeTrack20;V160;;;2075;015016BC08C117F1163000 +338;SFSPC;FreeTrack20;V160;;;2801;0152F885EFA9400981B700 +343;SIA Games;FreeTrack20;V160;;;20015;0157926ED970685DA8D200 +358;SRI;FreeTrack20;V160;;;20620;01663FD0FC9D8B218D8100 +495;STRAFT;FreeTrack20;V160;;;3375;01EF1329E014ADF98D6B00 +367;STS Driving Simulator;FreeTrack20;V160;;;20300;016FA59E688B1C89DE7600 +371;SWRI Demo;FreeTrack20;V160;;;20230;01730AC6841E9512561000 511;Sail;FreeTrack20;V160;;;3575;01FF2916D764159099F800 332;Sail Simulator 5;FreeTrack20;V160;;;1975;014CE2D1D78A1D9A3B6300 333;Sailors of the Sky;FreeTrack20;V160;;;10201;014D17BE02961FAF3AB100 334;Santa Cruz Watermill;FreeTrack20;V160;;;20290;014E88F5881EA32FA7E900 -335;SCANeR Studio Plugin;FreeTrack20;V160;;;20445;014FA2AE4870F861E9A100 -336;SEGA Demo;FreeTrack20;V160;;;2075;015016BC08C117F1163000 337;Seven-G;FreeTrack20;V160;;;2350;01510F00F49635B822A200 -338;SFSPC;FreeTrack20;V160;;;2801;0152F885EFA9400981B700 +554;ShiVa;FreeTrack20;V160;;;4225;022AA2A7DC2F7222696C00 339;Ship Simulator 2006;FreeTrack20;V160;;;5002;015329DFA9638AA2C66100 340;Ship Simulator 2008;FreeTrack20;V160;V;djj3ff ;5003;01545213599339B3D52100 341;Shiphandling Simulator;FreeTrack20;V160;;;20570;01553FD0FC9D8B37AD3700 -554;ShiVa;FreeTrack20;V160;;;4225;022AA2A7DC2F7222696C00 342;Shooting Simulator;FreeTrack20;V160;;;20047;0156F2F27A58827A63DA00 -343;SIA Games;FreeTrack20;V160;;;20015;0157926ED970685DA8D200 344;Silent Wings;FreeTrack20;V160;;;8701;0158D615A9C96309C24A00 345;SilverHat;FreeTrack20;V160;;;12401;0159D8175F99349F3F9600 -346;Simax Simulator;FreeTrack20;V160;;;20021;015AAC156D9736A331AD00 -347;Simball 4D;FreeTrack20;V160;;;20315;015BD6E585F99349F2AA00 -348;Simbionix;FreeTrack20;V160;;;20485;015CE7A7FAA28528AE1D00 518;SimCraft;FreeTrack20;V160;;;3650;02065BA013963203CB1900 349;SimCreator;FreeTrack20;V160;;;20520;015D3752FBC8935B001A00 -350;Simlog Personal Simulator;FreeTrack20;V160;;;20635;015E42868C33A435B53100 351;SimQuest immersion system;FreeTrack20;V160;;;20023;015F6C69678C32A30FAE00 352;SimSol;FreeTrack20;V160;;;20034;01602315187389E0FB5300 +346;Simax Simulator;FreeTrack20;V160;;;20021;015AAC156D9736A331AD00 +347;Simball 4D;FreeTrack20;V160;;;20315;015BD6E585F99349F2AA00 +348;Simbionix;FreeTrack20;V160;;;20485;015CE7A7FAA28528AE1D00 +350;Simlog Personal Simulator;FreeTrack20;V160;;;20635;015E42868C33A435B53100 491;Simumak;FreeTrack20;V160;;;20770;01EB119629980784DCE600 510;Sir You Are Being Hunted;FreeTrack20;V160;;;3550;01FEDAB345FA104ED4A100 353;Sirocco Racing;FreeTrack20;V160;;;5801;01612BCA748925A6369A00 @@ -442,7 +434,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 356;Source Engine (Half-Life 2);FreeTrack20;V160;;;12502;0164E482F58829A739A600 357;Space Shuttle Mission 2007;FreeTrack20;V160;V;purewhitewings ;1225;0165662B03863D912F9700 517;Spaze;FreeTrack20;V160;;;3625;020573F9D3ED8C43B8DC00 -358;SRI;FreeTrack20;V160;;;20620;01663FD0FC9D8B218D8100 359;Stanford University;FreeTrack20;V160;;;20004;0167CE35BAF9933A62AA00 500;Star Citizen;FreeTrack20;V170;;;3450;0D7AF4CE4E343EC6B4A200 360;Starshatter;FreeTrack20;V160;;;6401;0168F079578A3F9A3BB600 @@ -452,23 +443,23 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 565;Steel Beasts Professional;FreeTrack20;V160;;;4350;02356C64A9AFBB37E56E00 364;Stoked Rider;FreeTrack20;V160;;;14701;016CC166C963EA32997300 365;Storm of War: the Battle of Britain;FreeTrack20;V170;;;11001;016D8F54A68B71F25D0200 -495;STRAFT;FreeTrack20;V160;;;3375;01EF1329E014ADF98D6B00 366;Stride;FreeTrack20;V170;;;2310;016EC784B21E4B21984400 541;Strike Suit Zero;FreeTrack20;V170;;;3975;0F87E77F3BD3DB8821A200 -367;STS Driving Simulator;FreeTrack20;V160;;;20300;016FA59E688B1C89DE7600 368;Sunaerosys;FreeTrack20;V160;;;20475;01700449831AF28973EB00 -369;Superkarting;FreeTrack20;V160;;;14903;0171DE661F6D973FA41F00 370;SuperX Research;FreeTrack20;V160;;;15401;0172BA89D078A45A021A00 -371;SWRI Demo;FreeTrack20;V160;;;20230;01730AC6841E9512561000 +369;Superkarting;FreeTrack20;V160;;;14903;0171DE661F6D973FA41F00 372;Syncon Robot Control;FreeTrack20;V160;;;20415;0174C1BBF9937B12DB5200 373;Synergy Simulation;FreeTrack20;V160;;;20595;0175926ED9736B220B8200 374;T and TS Corp.;FreeTrack20;V160;;;20005;017617BE0297DDA73CA600 +379;TD Demo;FreeTrack20;V160;;;1925;017BC5BEE488FE54139700 +389;TIRF4;FreeTrack20;V160;;;2203;0185311858418870E77000 +390;TNO;FreeTrack20;V160;;;20285;01861AAF6870A853D64900 +399;TPL Testing;FreeTrack20;V160;;;20260;018F849F9A2083DC8C2C00 539;Tacview;FreeTrack20;V160;;;20865;021B1F0CFB651B91405C00 375;Take On Helicopters;FreeTrack20;V170;;;7504;0177513CB40C0623B96A00 376;Target: Korea;FreeTrack20;V160;;;1201;0178F52E4221852FA43300 377;Target: Rabaul;FreeTrack20;V160;;;1202;0179E9D85E4881CA736900 378;Targeting Demo;FreeTrack20;V160;;;13002;017AAB1D58A952DAA2F900 -379;TD Demo;FreeTrack20;V160;;;1925;017BC5BEE488FE54139700 489;TeachLive;FreeTrack20;V160;;;20765;01E905245B5AC5484FC100 380;Telepresence;FreeTrack20;V160;;;20450;017CF478D278B33B02DA00 381;Tenstar Simulator;FreeTrack20;V160;;;20605;017D318F88A2EA62DBA200 @@ -478,13 +469,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 501;The Crew;FreeTrack20;V170;;;1009;03F1F534E94F4834D9B100 488;The Gallery;FreeTrack20;V160;;;3350;01E8CE152EDE5FFD267700 383;The Sky Gods;FreeTrack20;V170;;;1525;017FDFF782DCCEEA27C200 -384;theHunter;FreeTrack20;V170;;;2375;0180BFF3A86D34DA24C000 -385;thriXXX HII 3D;FreeTrack20;V160;;;13403;0181FA04BD27AB36B62700 -386;thriXXX Jenna;FreeTrack20;V160;;;13401;01829F819CA2A625AB2800 387;ThriXXX Technology;FreeTrack20;V160;;;13402;0183F47CC378B35B526900 -388;tir2joy;FreeTrack20;V160;;;2202;018487801AB532A7FE9C00 -389;TIRF4;FreeTrack20;V160;;;2203;0185311858418870E77000 -390;TNO;FreeTrack20;V160;;;20285;01861AAF6870A853D64900 391;ToCA Race Driver 2;FreeTrack20;V160;;;8102;0187FFE9E886F286297910 392;Toca Race Driver 3;FreeTrack20;V160;;;8101;01884098D36972B551A900 393;Tom Clancy's H.A.W.X.;FreeTrack20;V170;V;EmBeES ;1004;0189AA4D48E85966FBAA00 @@ -493,8 +478,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 396;Total War;FreeTrack20;V160;;;1375;018C72456F8529AA2CA400 397;Tower Crane Simulator;FreeTrack20;V160;;;20670;018D03FB9929B034A7D900 398;Tower I;FreeTrack20;V160;;;1325;018E662B03873CA731A400 -399;TPL Testing;FreeTrack20;V160;;;20260;018F849F9A2083DC8C2C00 -400;trackd;FreeTrack20;V160;;;20580;019053FE1EB72DA3329D00 401;TrackMapper2;FreeTrack20;V160;;;2175;0191CE35BAF9A31A61FA00 402;TrainMaster;FreeTrack20;V160;;;20042;01925C1FDE852D9925B400 403;Trainz;FreeTrack20;V160;;;4701;0193D1C9F2862C9630A100 @@ -502,6 +485,8 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 405;Turismo Carretera;FreeTrack20;V160;;;15801;01956F2699559740A73500 406;UK Rally Champion;FreeTrack20;V160;;;5701;019679EC0E28B196522A00 407;ULAN;FreeTrack20;V160;;;20645;01974ADE68E16780D97A00 +422;UQO;FreeTrack20;V160;;;23085;01A67C822099A187FE3600 +423;UVEG Machinery Simulator;FreeTrack20;V160;;;20024;01A73118585257A0F63100 473;Underwater Navigation;FreeTrack20;V160;;;20715;01D9FE2B94FB03772DE200 408;Unity 3D Plugin;FreeTrack20;V160;;;20430;0198D24C3F9B3B9C31BF00 525;Unity 64-bit;FreeTrack20;V160;;;3750;020DC8AB18AF3539FA5200 @@ -519,17 +504,20 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 419;Untitled Simbin;FreeTrack20;V160;;;3902;01A36C69678E37AA27AD00 420;Untitled WorkShield;FreeTrack20;V160;;;4601;01A442868E38AB32BA3600 421;Untitled ZootFly;FreeTrack20;V160;;;12701;01A5348B1863AA527A6300 -422;UQO;FreeTrack20;V160;;;23085;01A67C822099A187FE3600 -423;UVEG Machinery Simulator;FreeTrack20;V160;;;20024;01A73118585257A0F63100 424;VAR;FreeTrack20;V160;;;20460;01A8950F9A97FA96FD2E00 425;VBS2;FreeTrack20;V160;;;7501;01A999BB5C990099FCBF00 485;VBS2 2.0;FreeTrack20;V170;;;7505;1D51EB3616B3A44F05B900 527;VCORP RBR2 MOD;FreeTrack20;V160;;;3825;020FEE9EA847F2ADB45800 +429;VIRTools Engine;FreeTrack20;V160;;;10801;01AD1AAF68905881EB5300 +564;VR Truck Simulator;FreeTrack20;V160;;;4325;02344CAEE1BC9E243D9F00 +477;VRPlayer;FreeTrack20;V160;;;20730;01DD6787E57245201D5000 +439;VT08;FreeTrack20;V160;;;1275;01B7B78B06EC9912750200 +440;VVVV Plugin;FreeTrack20;V160;;;20075;01B8B1C6648A138C205500 +441;VW Testing;FreeTrack20;V160;;;20275;01B9AC6E878D205822AA00 426;Vehicle Simulator (Quality Simulations);FreeTrack20;V160;;;5102;01AA0FC9FF9B1FA134A900 478;Vehicle Simulator Direction;FreeTrack20;V160;;;20735;01DEB88CF58E570F1CEF00 427;Vestibular Ocular Reflex;FreeTrack20;V160;;;20008;01AB3919C49B31A731A200 428;Viper Arena;FreeTrack20;V160;;;3501;01AC6F2699559934A53100 -429;VIRTools Engine;FreeTrack20;V160;;;10801;01AD1AAF68905881EB5300 430;Virtools Plugin;FreeTrack20;V160;;;20200;01AE03FB9B23AB43A42900 431;Virtual Driving;FreeTrack20;V160;;;20245;01AF99BB5C9927B83FB700 432;Virtual Heroes;FreeTrack20;V160;;;20375;01B0621E78732B732AE200 @@ -538,18 +526,14 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 435;Virtual Shopper;FreeTrack20;V160;;;20610;01B3B78B06EC9927B73E00 436;Virtual Supermarket;FreeTrack20;V160;;;20280;01B4849F9C39A931AD2800 496;VirtualiTeach;FreeTrack20;V160;;;20790;01F062AE1CAB33B52D0700 -480;Vizard;FreeTrack20;V160;;;20745;01E0C1F20A79D7C0561300 437;VizRD;FreeTrack20;V160;;;20031;01B55485D9825BF1D8AB00 +480;Vizard;FreeTrack20;V160;;;20745;01E0C1F20A79D7C0561300 438;Void War;FreeTrack20;V160;;;10001;01B65C1FDE872AA1206600 -564;VR Truck Simulator;FreeTrack20;V160;;;4325;02344CAEE1BC9E243D9F00 -477;VRPlayer;FreeTrack20;V160;;;20730;01DD6787E57245201D5000 -439;VT08;FreeTrack20;V160;;;1275;01B7B78B06EC9912750200 -440;VVVV Plugin;FreeTrack20;V160;;;20075;01B8B1C6648A138C205500 -441;VW Testing;FreeTrack20;V160;;;20275;01B9AC6E878D205822AA00 +445;WAVES;FreeTrack20;V160;;;20515;01BD05B38FFE89008B8B00 +453;WWII Battle Tanks: T-34 vs. Tiger;FreeTrack20;V160;;;11102;01C5432C29C257F1963100 442;Walkabout3d;FreeTrack20;V160;;;20125;01BA2822901E9E39932F00 443;Wallbusters;FreeTrack20;V160;;;1450;01BB88F58C1EA127A83F00 444;War Thunder;FreeTrack20;V160;;;0;01BC17BE029A1FB8ED9600 -445;WAVES;FreeTrack20;V160;;;20515;01BD05B38FFE89008B8B00 446;Welding Simulator;FreeTrack20;V160;;;2625;01BE348B188319D229B300 447;West Racing;FreeTrack20;V160;;;1801;01BF91D999022A33B62000 448;Whirlwind of Vietnam;FreeTrack20;V160;;;11101;01C0054E9935A03AAF3200 @@ -558,9 +542,8 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 451;Wings of War;FreeTrack20;V160;;;7807;01C34B0FC38B36B42FB610 512;Wings: Over Flanders Fields;FreeTrack20;V160;;;2326;02008AE39AAA4624B33C00 570;Wingsuit Simulator;FreeTrack20;V160;;;4450;023A472FA37FCD7427D900 -543;World of Diving;FreeTrack20;V160;;;4025;021F27B7B28D5012E1B300 452;World Racing 2;FreeTrack20;V160;;;7201;01C41AAF68A2BA836AAE00 -453;WWII Battle Tanks: T-34 vs. Tiger;FreeTrack20;V160;;;11102;01C5432C29C257F1963100 +543;World of Diving;FreeTrack20;V160;;;4025;021F27B7B28D5012E1B300 454;X Motor Racing;FreeTrack20;V160;;;1150;01C669259690E98629A900 526;X-Camera;FreeTrack20;V160;;;3775;020E1C4055DE39CBC03D00 458;X-Cockpit for X-Plane;FreeTrack20;V160;;;2901;01CA1C76F8BF4852999300 @@ -572,6 +555,24 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID 456;X2: The Threat;FreeTrack20;V160;;;5501;01C81039EF980EC8D30900 457;X3: Albion Prelude and Reunion;FreeTrack20;V170;V;V4Friend;5502;01C97E101A708F8524E300 463;Xyphoid;FreeTrack20;V160;;;14301;01CF656DD68B43B435A800 -464;zedasoft F-35 Demo;FreeTrack20;V160;;;20041;01D02100B01F942CB93C00 493;ZKT;FreeTrack20;V160;;;20780;01ED2BAA723F3C097EE800 465;Zombie AA Research;FreeTrack20;V160;;;14201;01D1AA71218B3B9F1C9A00 +100;dSphere TBA;FreeTrack20;V160;;;2425;0064A2AE4981FB5389A300 +113;eSigma;FreeTrack20;V160;;;20700;0071950F9AA60DAD2E9F00 +502;hapTEL;FreeTrack20;V160;;;20805;01F63ADE510A20446B6A00 +523;hiCRANE2;FreeTrack20;V160;;;20835;020BA8FC8C7DFFA1381A00 +179;iAmFootball;FreeTrack20;V160;;;1250;00B3B59DEFAAAFDB301A00 +192;iRacing;FreeTrack20;V160;V;vn88holden ;14101;00C0103AF1AA730A236900 +180;id Research;FreeTrack20;V170;;;2950;00B4E723B873D7FC87D700 +209;kiwi.vg;FreeTrack20;V160;;;20395;00D1409A430AB33633E900 +252;mTBI Balance;FreeTrack20;V160;;;20420;00FC72456F9E0E78145800 +533;rFPro;FreeTrack20;V170;;;7404;1CEC6BE26009B31DE7BC00 +314;rFactor;FreeTrack20;V160;V;V4Friend;7401;013AEF7A8F4B8AA0495200 +315;rFactor Pro;FreeTrack20;V170;;;7403;013B175198D74BE8E89600 +316;rFactor2;FreeTrack20;V170;;;7402;013CBFF3A86D34DA24C000 +384;theHunter;FreeTrack20;V170;;;2375;0180BFF3A86D34DA24C000 +385;thriXXX HII 3D;FreeTrack20;V160;;;13403;0181FA04BD27AB36B62700 +386;thriXXX Jenna;FreeTrack20;V160;;;13401;01829F819CA2A625AB2800 +388;tir2joy;FreeTrack20;V160;;;2202;018487801AB532A7FE9C00 +400;trackd;FreeTrack20;V160;;;20580;019053FE1EB72DA3329D00 +464;zedasoft F-35 Demo;FreeTrack20;V160;;;20041;01D02100B01F942CB93C00 -- cgit v1.2.3 From 778b82aee0b6f41bb4bafdaf6d079221306d942c Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 20 Dec 2015 17:43:58 +0100 Subject: tracker/pt: don't resize twice in widget Fix typo. --- tracker-pt/pt_video_widget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracker-pt/pt_video_widget.cpp b/tracker-pt/pt_video_widget.cpp index 095c325f..608f754a 100644 --- a/tracker-pt/pt_video_widget.cpp +++ b/tracker-pt/pt_video_widget.cpp @@ -39,7 +39,7 @@ void PTVideoWidget::update_and_repaint() cv::resize(_frame2, _frame3, cv::Size(width(), height()), 0, 0, cv::INTER_NEAREST); - texture = QImage((const unsigned char*) _frame2.data, _frame2.cols, _frame2.rows, QImage::Format_RGB888); freshp = false; update(); + texture = QImage((const unsigned char*) _frame3.data, _frame3.cols, _frame3.rows, QImage::Format_RGB888); } -- cgit v1.2.3 From c88d7897eec259ea7c649467e01590a08faa2dcb Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 20 Dec 2015 17:44:21 +0100 Subject: tracker/pt: only show widget if the frame is visible --- tracker-pt/pt_video_widget.cpp | 27 +++++++++++++++------------ tracker-pt/pt_video_widget.h | 1 + 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tracker-pt/pt_video_widget.cpp b/tracker-pt/pt_video_widget.cpp index 608f754a..99f86eb2 100644 --- a/tracker-pt/pt_video_widget.cpp +++ b/tracker-pt/pt_video_widget.cpp @@ -29,17 +29,20 @@ void PTVideoWidget::update_image(const cv::Mat& frame) void PTVideoWidget::update_and_repaint() { - QMutexLocker foo(&mtx); - if (_frame.empty() || !freshp) - return; - cv::cvtColor(_frame, _frame2, cv::COLOR_RGB2BGR); - - if (_frame3.cols != width() || _frame3.rows != height()) - _frame3 = cv::Mat(height(), width(), CV_8U); - - cv::resize(_frame2, _frame3, cv::Size(width(), height()), 0, 0, cv::INTER_NEAREST); - - freshp = false; - update(); + if (static_cast(parent())->isEnabled()) + { + QMutexLocker foo(&mtx); + if (_frame.empty() || !freshp) + return; + cv::cvtColor(_frame, _frame2, cv::COLOR_RGB2BGR); + + if (_frame3.cols != width() || _frame3.rows != height()) + _frame3 = cv::Mat(height(), width(), CV_8U); + + cv::resize(_frame2, _frame3, cv::Size(width(), height()), 0, 0, cv::INTER_NEAREST); + texture = QImage((const unsigned char*) _frame3.data, _frame3.cols, _frame3.rows, QImage::Format_RGB888); + freshp = false; + update(); + } } diff --git a/tracker-pt/pt_video_widget.h b/tracker-pt/pt_video_widget.h index 073b2e93..d9144ac0 100644 --- a/tracker-pt/pt_video_widget.h +++ b/tracker-pt/pt_video_widget.h @@ -17,6 +17,7 @@ #include #include #include +#include class PTVideoWidget : public QWidget { -- cgit v1.2.3 From 057fe1752477bdaafd2c9ec15f88b750083aff38 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 20 Dec 2015 18:04:33 +0100 Subject: gui: don't update main window if we're minimized Shaves off 12% runtime in minimized case. --- gui/ui.cpp | 26 ++++++++++++++++++++++---- gui/ui.h | 3 +++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/gui/ui.cpp b/gui/ui.cpp index c19e4840..31bce40b 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -122,6 +122,8 @@ MainWindow::MainWindow() : register_shortcuts(); + connect(this, &MainWindow::emit_minimized, this, &MainWindow::mark_minimized, Qt::QueuedConnection); + ui.btnStartTracker->setFocus(); } @@ -419,6 +421,9 @@ void MainWindow::set_title(const QString& game_title_) void MainWindow::showHeadPose() { + if (!ui.video_frame->isEnabled()) + return; + double mapped[6], raw[6]; work->tracker->get_raw_and_mapped_poses(mapped, raw); @@ -548,15 +553,28 @@ void MainWindow::restore_from_tray(QSystemTrayIcon::ActivationReason) void MainWindow::changeEvent(QEvent* e) { - if (s.tray_enabled && e->type() == QEvent::WindowStateChange && (windowState() & Qt::WindowMinimized)) + if (e->type() == QEvent::WindowStateChange) { - if (!tray) - ensure_tray(); - hide(); + const bool is_minimized = windowState() & Qt::WindowMinimized; + + if (s.tray_enabled && is_minimized) + { + if (!tray) + ensure_tray(); + hide(); + } + + emit_minimized(is_minimized); } + QMainWindow::changeEvent(e); } +void MainWindow::mark_minimized(bool is_minimized) +{ + ui.video_frame->setEnabled(!is_minimized); +} + void MainWindow::maybe_start_profile_from_executable() { if (!work) diff --git a/gui/ui.h b/gui/ui.h index deeb116d..6dbcf962 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -106,10 +106,13 @@ private slots: void startTracker(); void stopTracker(); void reload_options(); + void mark_minimized(bool is_minimized); signals: void emit_start_tracker(); void emit_stop_tracker(); void emit_toggle_tracker(); + + void emit_minimized(bool); public: MainWindow(); ~MainWindow(); -- cgit v1.2.3 From ccdf021f5d1a8daed729369cc078c5756a3a5bee Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 24 Dec 2015 19:24:59 +0100 Subject: tracker/pt: limit max amount of extracted blobs --- tracker-pt/point_extractor.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index 655e1412..0208b11d 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -148,6 +148,11 @@ const std::vector& PointExtractor::extract_points(cv::Mat& frame) } blobs.push_back(blob(radius, pos, confid, area)); + + enum { max_blobs = 16 }; + + if (blobs.size() == max_blobs) + break; } using b = const blob; -- cgit v1.2.3 From f02baa0868f219076a641634625f7c032d3a9eef Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 28 Dec 2015 07:02:42 +0100 Subject: tracker/pt: increase auto threshold bucket size again Slowdown was caused by something else. I can no longer reproduce it. --- tracker-pt/point_extractor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracker-pt/point_extractor.h b/tracker-pt/point_extractor.h index ad8955fc..030251ff 100644 --- a/tracker-pt/point_extractor.h +++ b/tracker-pt/point_extractor.h @@ -27,7 +27,7 @@ public: settings_pt s; private: - enum { hist_c = 8 }; + enum { hist_c = 2 }; std::vector points; QMutex mtx; cv::Mat frame_gray; -- cgit v1.2.3