summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-05-09 15:34:38 +0200
committerStanislaw Halik <sthalik@misaki.pl>2023-05-09 15:34:38 +0200
commit780aca2622d907320a1cf462390f192fb3ae4b31 (patch)
treec7843a5ebe0620d8f97ae7ba86ba6f5d06ffc167
parentc1de1499775d47a574bd52d07acbb269845fb75b (diff)
parent051fb2f94f6364b80219a3c671bb953d2e54a140 (diff)
Merge branch 'master' into trackhat-sensor-v2
-rw-r--r--.clang-tidy3
-rw-r--r--.github/workflows/cmake.yml2
-rw-r--r--CMakeLists.txt14
-rw-r--r--README.md4
-rw-r--r--api/plugin-api.cpp6
-rw-r--r--cmake/msvc.cmake49
-rw-r--r--cmake/opentrack-load-user-settings.cmake7
-rw-r--r--cmake/opentrack-platform.cmake2
-rw-r--r--cmake/opentrack-qt.cmake2
-rw-r--r--gui/options-dialog.cpp2
-rw-r--r--opentrack/main-window.cpp36
-rw-r--r--options/base-value.cpp2
-rw-r--r--options/tie.cpp8
-rw-r--r--options/value.hpp1
-rw-r--r--proto-osc/CMakeLists.txt15
-rw-r--r--proto-osc/dialog.cpp38
-rw-r--r--proto-osc/dialog.hpp29
-rw-r--r--proto-osc/dialog.ui131
-rw-r--r--proto-osc/images/osc-icon.pngbin0 -> 868 bytes
-rw-r--r--proto-osc/lang/nl_NL.ts45
-rw-r--r--proto-osc/lang/ru_RU.ts45
-rw-r--r--proto-osc/lang/stub.ts45
-rw-r--r--proto-osc/lang/zh_CN.ts45
-rw-r--r--proto-osc/metadata.cpp8
-rw-r--r--proto-osc/metadata.hpp10
-rw-r--r--proto-osc/osc-res.qrc5
-rw-r--r--proto-osc/proto.cpp54
-rw-r--r--proto-osc/proto.hpp29
-rw-r--r--proto-osc/settings.hpp14
-rw-r--r--proto-wine/CMakeLists.txt6
-rw-r--r--proto-wine/ftnoir_protocol_wine.cpp31
-rw-r--r--proto-wine/ftnoir_protocol_wine.h9
-rw-r--r--proto-wine/ftnoir_protocol_wine_dialog.cpp73
-rw-r--r--proto-wine/ftnoir_winecontrols.ui121
-rw-r--r--proto-wine/lang/nl_NL.ts43
-rw-r--r--proto-wine/lang/ru_RU.ts43
-rw-r--r--proto-wine/lang/stub.ts43
-rw-r--r--proto-wine/lang/zh_CN.ts43
-rw-r--r--sdk-paths-runner@GNU-Linux.cmake3
-rw-r--r--sdk-paths-sthalik@MSVC-windows.cmake36
-rw-r--r--tracker-eyeware-beam/CMakeLists.txt27
-rw-r--r--tracker-eyeware-beam/eyeware_beam.cpp116
-rw-r--r--tracker-eyeware-beam/eyeware_beam.h70
-rw-r--r--tracker-eyeware-beam/eyeware_beam.qrc5
-rw-r--r--tracker-eyeware-beam/eyeware_beam.ui90
-rw-r--r--tracker-eyeware-beam/eyeware_beam_logo.pngbin0 -> 2032 bytes
-rw-r--r--tracker-eyeware-beam/lang/nl_NL.ts20
-rw-r--r--tracker-eyeware-beam/lang/ru_RU.ts20
-rw-r--r--tracker-eyeware-beam/lang/stub.ts20
-rw-r--r--tracker-eyeware-beam/lang/zh_CN.ts20
-rw-r--r--tracker-neuralnet/CMakeLists.txt14
-rw-r--r--tracker-neuralnet/ftnoir_tracker_neuralnet.cpp71
-rw-r--r--tracker-neuralnet/lang/ru_RU.ts107
-rw-r--r--tracker-neuralnet/model_adapters.cpp41
-rw-r--r--tracker-neuralnet/model_adapters.h13
-rw-r--r--tracker-trackhat/lang/nl_NL.ts2
-rw-r--r--tracker-trackhat/lang/ru_RU.ts2
-rw-r--r--tracker-trackhat/lang/stub.ts2
-rw-r--r--tracker-trackhat/lang/zh_CN.ts2
-rw-r--r--video-ps3eye/shm-layout.hpp6
-rw-r--r--x-plane-plugin/plugin.c4
61 files changed, 1492 insertions, 262 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 28fe3584..a29d0ffd 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -19,6 +19,8 @@ clang-analyzer-core.CallAndMessage,
clang-analyzer-deadcode.DeadStores,
-clang-diagnostic-nonportable-include-path,
-cppcoreguidelines-avoid-c-arrays,
+-cppcoreguidelines-avoid-capture-default-when-capturing-this,
+-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-goto,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-c-copy-assignment-signature,
@@ -61,6 +63,7 @@ clang-analyzer-deadcode.DeadStores,
-hicpp-use-override,
-hicpp-vararg,
-misc-non-private-member-variables-in-classes,
+-misc-use-anonymous-namespace,
-modernize-avoid-c-arrays,
-modernize-loop-convert,
-modernize-pass-by-value,
diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml
index ce47a3db..c24e9c99 100644
--- a/.github/workflows/cmake.yml
+++ b/.github/workflows/cmake.yml
@@ -36,7 +36,7 @@ jobs:
- uses: seanmiddleditch/gha-setup-ninja@master
- name: Install Linux Dependencies
- run: sudo apt update && sudo apt install libprocps-dev libopencv-dev libopencv-dev
+ run: sudo apt update && sudo apt install libprocps-dev libopencv-dev libopencv-dev wine64-tools
if: matrix.os == 'ubuntu-latest'
- name: Cache Qt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8c6613bd..bb1cfff2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,24 +110,24 @@ otr_merge_translations()
include(opentrack-install)
string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE)
-message(STATUS "-- Compile flags:")
+message("Compile flags:")
#foreach(j C CXX)
foreach(j CXX)
foreach(i "" "_${CMAKE_BUILD_TYPE}")
- message(STATUS " ${j}${i}: ${CMAKE_${j}_FLAGS${i}}")
+ message(" ${j}${i}: ${CMAKE_${j}_FLAGS${i}}")
endforeach()
endforeach()
-message(STATUS "-- Link flags:")
+message("Link flags:")
foreach(j "" "_${CMAKE_BUILD_TYPE}")
#foreach(i EXE SHARED)
foreach(i SHARED)
- message(STATUS " LINK_${i}${j}: ${CMAKE_${i}_LINKER_FLAGS${j}}")
+ message(" LINK_${i}${j}: ${CMAKE_${i}_LINKER_FLAGS${j}}")
endforeach()
endforeach()
-message(STATUS "-- Static archive flags:")
+message("Static archive flags:")
foreach(k "" "_${CMAKE_BUILD_TYPE}")
- message(STATUS " STATIC${k}: ${CMAKE_STATIC_LINKER_FLAGS${k}}")
+ message(" STATIC${k}: ${CMAKE_STATIC_LINKER_FLAGS${k}}")
endforeach()
-message(STATUS "--")
+message("--")
diff --git a/README.md b/README.md
index 1e485459..0ed51166 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
## Intro
-[<img src="https://ci.appveyor.com/api/projects/status/n0j9h38jnif5qbe9/branch/unstable?svg=true"/>](https://ci.appveyor.com/project/sthalik/opentrack/branch/unstable)
+[<img src="https://github.com/opentrack/opentrack/actions/workflows/cmake.yml/badge.svg">](https://github.com/opentrack/opentrack/actions/workflows/cmake.yml)
opentrack project home is located at <<http://github.com/opentrack/opentrack>>.
@@ -40,6 +40,7 @@ Don't be afraid to submit an **issue/feature request** if you have any problems!
- BBC micro:bit, LEGO, sensortag support via Smalltalk<sup>[(1)](https://en.wikipedia.org/wiki/Smalltalk)[(2)](https://en.wikipedia.org/wiki/Alan_Kay)</sup>
[S2Bot](http://www.picaxe.com/Teaching/Other-Software/Scratch-Helper-Apps/)
- Wiimote (Windows)
+- Eyeware Beam<sup>[[1](https://beam.eyeware.tech/)]</sup>
## Output protocols
@@ -69,6 +70,7 @@ Don't be afraid to submit an **issue/feature request** if you have any problems!
- Wei Shuai (Wiimote tracker)
- Stéphane Lenclud (Kinect Face Tracker, Easy Tracker)
- GO63-samara (Hamilton Filter, Pose-widget improvement)
+- Davide Mameli (Eyeware Beam tracker)
## Thanks
diff --git a/api/plugin-api.cpp b/api/plugin-api.cpp
index 6a43b55d..4d8d90e9 100644
--- a/api/plugin-api.cpp
+++ b/api/plugin-api.cpp
@@ -21,7 +21,7 @@ void BaseDialog::done(int)
bool BaseDialog::embeddable() noexcept { return false; }
void BaseDialog::save() {}
void BaseDialog::reload() {}
-void BaseDialog::set_buttons_visible(bool x) {}
+void BaseDialog::set_buttons_visible(bool) {}
} // ns plugin_api::detail
@@ -36,13 +36,13 @@ IFilter::IFilter() = default;
IFilter::~IFilter() = default;
IFilterDialog::IFilterDialog() = default;
IFilterDialog::~IFilterDialog() = default;
-void IFilterDialog::register_filter(IFilter* filter) {}
+void IFilterDialog::register_filter(IFilter*) {}
void IFilterDialog::unregister_filter() {}
IProtocol::IProtocol() = default;
IProtocol::~IProtocol() = default;
IProtocolDialog::IProtocolDialog() = default;
IProtocolDialog::~IProtocolDialog() = default;
-void IProtocolDialog::register_protocol(IProtocol* protocol){}
+void IProtocolDialog::register_protocol(IProtocol*){}
void IProtocolDialog::unregister_protocol() {}
ITracker::ITracker() = default;
ITracker::~ITracker() = default;
diff --git a/cmake/msvc.cmake b/cmake/msvc.cmake
index 12470eef..cf3bb0cb 100644
--- a/cmake/msvc.cmake
+++ b/cmake/msvc.cmake
@@ -37,7 +37,7 @@ add_definitions(-D_HAS_EXCEPTIONS=0)
if(DEFINED CMAKE_TOOLCHAIN_FILE)
# ignore cmake warning: Manually-specified variable not used by the project
- set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}}")
+ set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/opentrack-policy.cmake" NO_POLICY_SCOPE)
@@ -106,29 +106,42 @@ if(CMAKE_PROJECT_NAME STREQUAL "OpenCV")
set(BUILD_opencv_gapi OFF)
endif()
+if(CMAKE_PROJECT_NAME STREQUAL "TestOscpack")
+ add_compile_definitions(OSC_HOST_LITTLE_ENDIAN)
+endif()
+
set(opentrack-simd "SSE2")
if(CMAKE_PROJECT_NAME STREQUAL "onnxruntime")
set(opentrack-simd "AVX")
+ if(opentrack-no-static-crt)
+ sets(BOOL
+ ONNX_USE_MSVC_STATIC_RUNTIME OFF
+ protobuf_MSVC_STATIC_RUNTIME OFF
+ )
+ else()
+ sets(BOOL
+ ONNX_USE_MSVC_STATIC_RUNTIME ON
+ protobuf_MSVC_STATIC_RUNTIME ON
+ )
+ endif()
sets(BOOL
- onnxruntime_USE_AVX ON
- onnxruntime_USE_AVX2 OFF
- onnxruntime_USE_AVX512 OFF
- ONNX_USE_MSVC_STATIC_RUNTIME ON
- protobuf_MSVC_STATIC_RUNTIME ON
- onnxruntime_BUILD_BENCHMARKS OFF
- onnxruntime_BUILD_FOR_NATIVE_MACHINE OFF
- onnxruntime_BUILD_SHARED_LIB ON
- onnxruntime_BUILD_UNIT_TESTS OFF
- protobuf_BUILD_EXAMPLES OFF
- protobuf_BUILD_SHARED_LIBS OFF
- ONNX_BUILD_BENCHMARKS OFF
- ONNX_BUILD_TESTS OFF
- ONNX_DISABLE_EXCEPTIONS OFF # important!
- ONNX_GEN_PB_TYPE_STUBS OFF
- onnxruntime_DISABLE_CONTRIB_OPS ON
- BUILD_TESTING OFF
+ onnxruntime_USE_AVX ON
+ onnxruntime_USE_AVX2 OFF
+ onnxruntime_USE_AVX512 OFF
+ onnxruntime_BUILD_BENCHMARKS OFF
+ onnxruntime_BUILD_FOR_NATIVE_MACHINE OFF
+ onnxruntime_BUILD_SHARED_LIB ON
+ onnxruntime_BUILD_UNIT_TESTS OFF
+ protobuf_BUILD_EXAMPLES OFF
+ protobuf_BUILD_SHARED_LIBS OFF
+ ONNX_BUILD_BENCHMARKS OFF
+ ONNX_BUILD_TESTS OFF
+ ONNX_DISABLE_EXCEPTIONS OFF # important!
+ ONNX_GEN_PB_TYPE_STUBS OFF
+ onnxruntime_DISABLE_CONTRIB_OPS ON
+ BUILD_TESTING OFF
)
elseif(opentrack-64bit)
set(opentrack-simd "AVX")
diff --git a/cmake/opentrack-load-user-settings.cmake b/cmake/opentrack-load-user-settings.cmake
index 1baf3702..fdb63936 100644
--- a/cmake/opentrack-load-user-settings.cmake
+++ b/cmake/opentrack-load-user-settings.cmake
@@ -26,12 +26,11 @@ else()
set(__sdk_host_os "")
endif()
-set(__sdk_paths_basename "sdk-paths-${__sdk_username}@${CMAKE_CXX_COMPILER_ID}-${__sdk_host_os}${__sdk_target_os}.cmake")
-set(__sdk_paths_filename "${CMAKE_SOURCE_DIR}/${__sdk_paths_basename}")
+set(__sdk_paths_filename "${CMAKE_CURRENT_SOURCE_DIR}/sdk-paths-${__sdk_username}@${CMAKE_CXX_COMPILER_ID}-${__sdk_host_os}${__sdk_target_os}.cmake")
if(EXISTS "${__sdk_paths_filename}")
- message(STATUS "Loading user settings '${__sdk_paths_basename}'")
+ message(STATUS "Loading user settings '${__sdk_paths_filename}'")
include("${__sdk_paths_filename}")
else()
- message(STATUS "User settings file '${__sdk_paths_basename}' doesn't exist")
+ message(STATUS "User settings file '${__sdk_paths_filename}' doesn't exist")
endif()
diff --git a/cmake/opentrack-platform.cmake b/cmake/opentrack-platform.cmake
index fd82c1b5..7aceb17a 100644
--- a/cmake/opentrack-platform.cmake
+++ b/cmake/opentrack-platform.cmake
@@ -34,8 +34,6 @@ set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "" FORCE)
include_directories("${CMAKE_SOURCE_DIR}")
-set(opentrack_maintainer-mode FALSE CACHE INTERNAL "Select if developing core code (not modules)")
-
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_CXX_STANDARD 20)
diff --git a/cmake/opentrack-qt.cmake b/cmake/opentrack-qt.cmake
index 800e9096..1735e836 100644
--- a/cmake/opentrack-qt.cmake
+++ b/cmake/opentrack-qt.cmake
@@ -51,7 +51,7 @@ function(otr_qt n)
endfunction()
function(otr_qt2 n)
- target_include_directories("${n}" PRIVATE SYSTEM
+ target_include_directories("${n}" SYSTEM PRIVATE
${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}
)
target_compile_definitions("${n}" PRIVATE
diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp
index ac4117bc..9cd416ee 100644
--- a/gui/options-dialog.cpp
+++ b/gui/options-dialog.cpp
@@ -172,7 +172,7 @@ options_dialog::options_dialog(std::unique_ptr<ITrackerDialog>& tracker_dialog_,
val.label,
[=](const QString&) { val.label->setText(kopts_to_string(val.opt)); });
{
- connect(val.button, &QPushButton::clicked, this, [=] { bind_key(val.opt, val.label); });
+ connect(val.button, &QPushButton::clicked, this, [=, this] { bind_key(val.opt, val.label); });
}
}
diff --git a/opentrack/main-window.cpp b/opentrack/main-window.cpp
index 754d7e7c..f449845b 100644
--- a/opentrack/main-window.cpp
+++ b/opentrack/main-window.cpp
@@ -18,7 +18,6 @@
#include "compat/math.hpp"
#include "compat/sysexits.hpp"
#include "opentrack/defs.hpp"
-#include "software-update-dialog.hpp"
#include <cstring>
#include <utility>
@@ -34,7 +33,6 @@
#include <QDateTime>
extern "C" const char* const opentrack_version;
-extern "C" OTR_GENERIC_IMPORT bool opentrack_using_dark_theme;
using namespace options::globals;
using namespace options;
@@ -60,8 +58,6 @@ main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH)
setVisible(!start_in_tray());
ensure_tray();
- ui.pose_display->set_grid_background(opentrack_using_dark_theme);
-
connect(&pose_update_timer, &QTimer::timeout,
this, &main_window::show_pose, Qt::DirectConnection);
connect(&det_timer, &QTimer::timeout,
@@ -74,13 +70,7 @@ main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH)
#ifdef UI_NO_VIDEO_FEED
fake_video_frame.resize(640, 480);
fake_video_frame_parent.setVisible(false);
-#elif defined UI_COMPACT_VIDEO_FEED
- connect(ui.preview_checkbox, &QCheckBox::toggled, this, &main_window::toggle_video_preview);
#endif
-
- updater = std::make_unique<update_query>(this);
- updater->maybe_show_dialog();
-
}
void main_window::init_shortcuts()
@@ -429,12 +419,7 @@ void main_window::update_button_state(bool running, bool inertialp)
ui.iconcomboTrackerSource->setEnabled(not_running);
#endif
ui.profile_button->setEnabled(not_running);
-#ifdef UI_COMPACT_VIDEO_FEED
- ui.preview_checkbox->setChecked(false);
- ui.preview_checkbox->raise();
- ui.preview_checkbox->setVisible(running && !inertialp);
- toggle_video_preview(false);
-#elif !defined UI_NO_VIDEO_FEED
+#ifndef UI_NO_VIDEO_FEED
ui.video_frame_label->setVisible(not_running || inertialp);
if(not_running)
{
@@ -446,22 +431,6 @@ void main_window::update_button_state(bool running, bool inertialp)
#endif
}
-#ifdef UI_COMPACT_VIDEO_FEED
-void main_window::toggle_video_preview(bool value)
-{
- value &= ui.video_frame->layout() != nullptr;
- ui.video_frame_parent->setVisible(value);
- ui.video_frame_parent->raise();
- ui.video_frame->raise();
- ui.pose_display->setVisible(!value);
- ui.preview_checkbox->raise();
- if (value)
- ui.preview_checkbox->setStyleSheet("QCheckBox { color: #32CD32 }");
- else
- ui.preview_checkbox->setStyleSheet("");
-}
-#endif
-
void main_window::start_tracker_()
{
if (work)
@@ -502,7 +471,7 @@ void main_window::start_tracker_()
options_widget->register_filter(&*work->libs.pFilter);
}
- pose_update_timer.start((int)(1000./30));
+ pose_update_timer.start(1000/30);
// NB check valid since SelectedLibraries ctor called
// trackers take care of layout state updates
@@ -714,7 +683,6 @@ static void show_module_settings(std::shared_ptr<Instance> instance,
void(Dialog::*register_fun)(Instance*),
void(options_dialog::*switch_tab_fun)())
{
- using BaseDialog = plugin_api::detail::BaseDialog;
if (!lib || !lib->Dialog)
return;
diff --git a/options/base-value.cpp b/options/base-value.cpp
index 9ccbbdf8..950629d0 100644
--- a/options/base-value.cpp
+++ b/options/base-value.cpp
@@ -29,5 +29,5 @@ value_::~value_()
void value_::maybe_trace(const char* str) const
{
if (TRACE_NOTIFY)
- qDebug().noquote() << str << QThread::currentThreadId() << b->name() << self_name;
+ qDebug().noquote() << str << QThread::currentThreadId() << b->name() << self_name << get_variant();
}
diff --git a/options/tie.cpp b/options/tie.cpp
index c2976217..adf26b53 100644
--- a/options/tie.cpp
+++ b/options/tie.cpp
@@ -28,8 +28,12 @@ void tie_setting(value<QString>& v, QComboBox* cb)
{
cb->setCurrentText(v);
v = cb->currentText();
- value_::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(const QString&)), v.DIRECT_CONNTYPE);
- value_::connect(&v, SIGNAL(valueChanged(const QString&)), cb, SLOT(setCurrentText(const QString&)), v.SAFE_CONNTYPE);
+ auto set_current_text = [cb, &v](const QString& str) {
+ cb->setCurrentText(str);
+ v = cb->currentText();
+ };
+ value_::connect(cb, &QComboBox::currentTextChanged, &v, v.value_changed<QString>(), v.DIRECT_CONNTYPE);
+ value_::connect(&v, v.value_changed<QString>(), cb, set_current_text, v.SAFE_CONNTYPE);
}
void tie_setting(value<QVariant>& v, QComboBox* cb)
diff --git a/options/value.hpp b/options/value.hpp
index dacd0ea9..9a7487b8 100644
--- a/options/value.hpp
+++ b/options/value.hpp
@@ -137,6 +137,7 @@ public:
return *this;
store_variant(traits::qvariant_from_value(traits::pass_value(datum)));
+ maybe_trace("set-value");
return *this;
}
diff --git a/proto-osc/CMakeLists.txt b/proto-osc/CMakeLists.txt
new file mode 100644
index 00000000..eeaf206c
--- /dev/null
+++ b/proto-osc/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(SDK_OSCPACK "" CACHE PATH "oscpack build directory")
+if(SDK_OSCPACK)
+ if(WIN32)
+ if(NOT EXISTS "${SDK_OSCPACK}/include/.")
+ message(FATAL_ERROR "SDK_OSCPACK should have 'include' subdirectory (or symlink) to src dir")
+ endif()
+ link_directories("${SDK_OSCPACK}")
+ include_directories("${SDK_OSCPACK}/include" "${SDK_OSCPACK}/include/oscpack")
+ else()
+ link_directories("${SDK_OSCPACK}/lib" "${SDK_OSCPACK}/lib32")
+ include_directories("${SDK_OSCPACK}/include/oscpack")
+ endif()
+ link_libraries(oscpack)
+ otr_module(proto-osc)
+endif()
diff --git a/proto-osc/dialog.cpp b/proto-osc/dialog.cpp
new file mode 100644
index 00000000..54bf6885
--- /dev/null
+++ b/proto-osc/dialog.cpp
@@ -0,0 +1,38 @@
+#include "dialog.hpp"
+#include <QHostAddress>
+#include <QPalette>
+
+void osc_dialog::host_address_edited(const QString& str)
+{
+ bool bad = QHostAddress{str}.isNull();
+ auto pal = pal_;
+ for (auto role : { QPalette::Highlight, QPalette::Window })
+ if (bad)
+ pal.setColor(role, Qt::red);
+ ui.address->setPalette(pal);
+}
+
+osc_dialog::osc_dialog() :
+ pal_{palette()}
+{
+ ui.setupUi( this );
+
+ tie_setting(s.address, ui.address);
+ tie_setting(s.port, ui.port);
+ connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &osc_dialog::doOK);
+ connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &osc_dialog::doCancel);
+ connect(ui.address, &QLineEdit::textChanged, this, &osc_dialog::host_address_edited);
+ host_address_edited(ui.address->text());
+}
+
+void osc_dialog::save() { s.b->save(); }
+void osc_dialog::reload() { s.b->reload(); }
+
+void osc_dialog::doOK() { s.b->save(); close(); }
+void osc_dialog::doCancel() { close(); }
+
+void osc_dialog::register_protocol(IProtocol*) {}
+void osc_dialog::unregister_protocol() {}
+
+bool osc_dialog::embeddable() noexcept { return true; }
+void osc_dialog::set_buttons_visible(bool x) noexcept { ui.buttonBox->setVisible(x); }
diff --git a/proto-osc/dialog.hpp b/proto-osc/dialog.hpp
new file mode 100644
index 00000000..29682843
--- /dev/null
+++ b/proto-osc/dialog.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "settings.hpp"
+#include "ui_dialog.h"
+#include "api/plugin-api.hpp"
+
+class osc_dialog: public IProtocolDialog
+{
+ Q_OBJECT
+
+public:
+ osc_dialog();
+ void register_protocol(IProtocol*) override;
+ void unregister_protocol() override;
+private:
+ void set_buttons_visible(bool x) noexcept override;
+ bool embeddable() noexcept override;
+ void save() override;
+ void reload() override;
+
+ Ui_OSC_Dialog ui;
+ osc_settings s;
+ const QPalette pal_;
+
+private slots:
+ void doOK();
+ void doCancel();
+ void host_address_edited(const QString& str);
+};
diff --git a/proto-osc/dialog.ui b/proto-osc/dialog.ui
new file mode 100644
index 00000000..5a078bbd
--- /dev/null
+++ b/proto-osc/dialog.ui
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OSC_Dialog</class>
+ <widget class="QWidget" name="OSC_Dialog">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>284</width>
+ <height>102</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>284</width>
+ <height>102</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>OSC protocol settings</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="osc-res.qrc">
+ <normaloff>:/images/osc-icon.png</normaloff>:/images/osc-icon.png</iconset>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Destination address</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="address">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="maxLength">
+ <number>256</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Port</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="port">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../gui/opentrack-res.qrc"/>
+ <include location="osc-res.qrc"/>
+ </resources>
+ <connections/>
+ <designerdata>
+ <property name="gridDeltaX">
+ <number>5</number>
+ </property>
+ <property name="gridDeltaY">
+ <number>5</number>
+ </property>
+ <property name="gridSnapX">
+ <bool>true</bool>
+ </property>
+ <property name="gridSnapY">
+ <bool>true</bool>
+ </property>
+ <property name="gridVisible">
+ <bool>false</bool>
+ </property>
+ </designerdata>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/proto-osc/images/osc-icon.png b/proto-osc/images/osc-icon.png
new file mode 100644
index 00000000..3ef546e9
--- /dev/null
+++ b/proto-osc/images/osc-icon.png
Binary files differ
diff --git a/proto-osc/lang/nl_NL.ts b/proto-osc/lang/nl_NL.ts
new file mode 100644
index 00000000..260b7adc
--- /dev/null
+++ b/proto-osc/lang/nl_NL.ts
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="nl_NL">
+<context>
+ <name>OSC_Dialog</name>
+ <message>
+ <source>OSC protocol settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Destination address</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_metadata</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_proto</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error binding socket to INADDR_ANY</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Invalid destination address &apos;%1&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/proto-osc/lang/ru_RU.ts b/proto-osc/lang/ru_RU.ts
new file mode 100644
index 00000000..498d68d6
--- /dev/null
+++ b/proto-osc/lang/ru_RU.ts
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+ <name>OSC_Dialog</name>
+ <message>
+ <source>OSC protocol settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Destination address</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_metadata</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_proto</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error binding socket to INADDR_ANY</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Invalid destination address &apos;%1&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/proto-osc/lang/stub.ts b/proto-osc/lang/stub.ts
new file mode 100644
index 00000000..20828cbd
--- /dev/null
+++ b/proto-osc/lang/stub.ts
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+ <name>OSC_Dialog</name>
+ <message>
+ <source>OSC protocol settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Destination address</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_metadata</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_proto</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error binding socket to INADDR_ANY</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Invalid destination address &apos;%1&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/proto-osc/lang/zh_CN.ts b/proto-osc/lang/zh_CN.ts
new file mode 100644
index 00000000..e0d49844
--- /dev/null
+++ b/proto-osc/lang/zh_CN.ts
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="zh_CN">
+<context>
+ <name>OSC_Dialog</name>
+ <message>
+ <source>OSC protocol settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Destination address</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_metadata</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>osc_proto</name>
+ <message>
+ <source>Open Sound Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error binding socket to INADDR_ANY</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Invalid destination address &apos;%1&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/proto-osc/metadata.cpp b/proto-osc/metadata.cpp
new file mode 100644
index 00000000..9d69347d
--- /dev/null
+++ b/proto-osc/metadata.cpp
@@ -0,0 +1,8 @@
+#include "metadata.hpp"
+#include "proto.hpp"
+#include "dialog.hpp"
+
+QString osc_metadata::name() { return tr("Open Sound Control"); }
+QIcon osc_metadata::icon() { return QIcon(":/images/osc-icon.png"); }
+
+OPENTRACK_DECLARE_PROTOCOL(osc_proto, osc_dialog, osc_metadata)
diff --git a/proto-osc/metadata.hpp b/proto-osc/metadata.hpp
new file mode 100644
index 00000000..c0a947aa
--- /dev/null
+++ b/proto-osc/metadata.hpp
@@ -0,0 +1,10 @@
+#pragma once
+#include "api/plugin-api.hpp"
+
+class osc_metadata : public Metadata
+{
+ Q_OBJECT
+
+ QString name() override;
+ QIcon icon() override;
+};
diff --git a/proto-osc/osc-res.qrc b/proto-osc/osc-res.qrc
new file mode 100644
index 00000000..ade4c629
--- /dev/null
+++ b/proto-osc/osc-res.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/osc-icon.png</file>
+ </qresource>
+</RCC>
diff --git a/proto-osc/proto.cpp b/proto-osc/proto.cpp
new file mode 100644
index 00000000..2f90957c
--- /dev/null
+++ b/proto-osc/proto.cpp
@@ -0,0 +1,54 @@
+#include "proto.hpp"
+#include "ui_dialog.h"
+#include "api/plugin-api.hpp"
+#include <QQuaternion>
+#include <QHostAddress>
+#include "osc/OscOutboundPacketStream.h"
+
+osc_proto::osc_proto()
+{
+ auto reload_fn = [this] {
+ dest = QHostAddress{s.address };
+ port = (unsigned short)s.port;
+ };
+ connect(&*s.b, &bundle_::changed, this, reload_fn);
+ connect(&*s.b, &bundle_::reloading, this, reload_fn);
+}
+
+void osc_proto::pose(const double* data, const double*)
+{
+ if (dest.isNull())
+ return;
+
+ static constexpr unsigned buffer_size = 1024;
+ char buffer[buffer_size] = {};
+ osc::OutboundPacketStream p{buffer, buffer_size};
+ auto q = QQuaternion::fromEulerAngles((float)data[Pitch], (float)data[Yaw], (float)-data[Roll]).normalized();
+ p << osc::BeginMessage("/bridge/quat") << q.scalar() << q.x() << q.y() << q.z() << osc::EndMessage;
+ sock.writeDatagram(p.Data(), (int)p.Size(), dest, port);
+}
+
+module_status osc_proto::initialize()
+{
+ QString error;
+
+ dest = QHostAddress{s.address };
+ port = (unsigned short)s.port;
+
+ if (dest.isNull())
+ {
+ error = tr("Invalid destination address '%1'").arg(s.address);
+ goto fail;
+ }
+
+ if (!sock.bind())
+ {
+ error = tr("Error binding socket to INADDR_ANY");
+ goto fail;
+ }
+
+ return status_ok();
+
+fail:
+ return { tr("%1: %2").arg(error, sock.errorString()) };
+}
diff --git a/proto-osc/proto.hpp b/proto-osc/proto.hpp
new file mode 100644
index 00000000..53a5dee4
--- /dev/null
+++ b/proto-osc/proto.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+/* Copyright (c) 2023 Stanislaw Halik <sthalik@misaki.pl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "settings.hpp"
+#include "api/plugin-api.hpp"
+#include <QUdpSocket>
+#include <QHostAddress>
+
+class osc_proto : public QObject, public IProtocol
+{
+ Q_OBJECT
+
+ osc_settings s;
+ QUdpSocket sock;
+ QHostAddress dest;
+ unsigned short port = 0;
+
+public:
+ osc_proto();
+ module_status initialize() override;
+ void pose(const double *headpose, const double*) override;
+ QString game_name() override { return tr("Open Sound Control"); }
+};
diff --git a/proto-osc/settings.hpp b/proto-osc/settings.hpp
new file mode 100644
index 00000000..edeb45c6
--- /dev/null
+++ b/proto-osc/settings.hpp
@@ -0,0 +1,14 @@
+#pragma once
+#include <QString>
+#include "options/options.hpp"
+
+using namespace options;
+
+struct osc_settings : opts
+{
+ value<QString> address;
+ value<int> port;
+ osc_settings() : opts("proto-osc"), address{b, "address", "127.0.0.1"},
+ port(b, "port", 53101)
+ {}
+};
diff --git a/proto-wine/CMakeLists.txt b/proto-wine/CMakeLists.txt
index 0beb50e1..ff4932cc 100644
--- a/proto-wine/CMakeLists.txt
+++ b/proto-wine/CMakeLists.txt
@@ -17,10 +17,14 @@ if(NOT WIN32)
endif()
file(GLOB wine-deps "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx")
#install(FILES ${wine-deps} DESTINATION "${opentrack-src}/proto-wine")
+ set(winegxx-multilib "-m32")
+ if (NOT OPENTRACK_WINE_ARCH STREQUAL "")
+ set(winegxx-multilib "${OPENTRACK_WINE_ARCH}")
+ endif()
add_custom_command(
OUTPUT opentrack-wrapper-wine.exe.so
DEPENDS ${wine-deps}
- COMMAND wineg++ -mconsole -g -DNOMINMAX -O2 -m32 -std=c++17 -fPIC -o
+ COMMAND wineg++ -mconsole -g -DNOMINMAX -O2 ${winegxx-multilib} -std=c++17 -fPIC -o
opentrack-wrapper-wine.exe -I "${CMAKE_SOURCE_DIR}" -I "${CMAKE_BINARY_DIR}"
${wine-deps} -Wall -Wextra -Wpedantic
${my-rt})
diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp
index af53ff1f..75526c54 100644
--- a/proto-wine/ftnoir_protocol_wine.cpp
+++ b/proto-wine/ftnoir_protocol_wine.cpp
@@ -44,6 +44,7 @@ void wine::pose(const double *headpose, const double*)
#ifndef OTR_WINE_NO_WRAPPER
if (shm->gameid != gameid)
{
+ //qDebug() << "proto/wine: looking up gameData";
QString gamename;
QMutexLocker foo(&game_name_mutex);
/* only EZCA for FSX requires dummy process, and FSX doesn't work on Linux */
@@ -63,6 +64,22 @@ module_status wine::initialize()
static const QString library_path(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH);
QString wine_path = "wine";
+ if (s.wine_select_path().toString() != "WINE") {
+ // if we are not supposed to use system wine then:
+ if (s.wine_select_path().toString() != "CUSTOM") {
+ // if we don't have a custom path then change the wine_path to the path corresponding to the selected version
+ wine_path = s.wine_select_path().toString();
+ }
+ else if (!s.wine_custom_path->isEmpty()) {
+ // if we do have a custom path and it is not empty then
+ wine_path = s.wine_custom_path;
+ }
+ }
+ if (wine_path[0] == '~')
+ wine_path = qgetenv("HOME") + wine_path.mid(1);
+
+ qDebug() << "proto/wine: wine_path:" << wine_path;
+
auto env = QProcessEnvironment::systemEnvironment();
if (s.variant_proton)
@@ -91,6 +108,8 @@ module_status wine::initialize()
if (wineprefix[0] != '/')
return error(tr("Wine prefix must be an absolute path (given '%1')").arg(wineprefix));
+ qDebug() << "proto/wine: wineprefix:" << wineprefix;
+
env.insert("WINEPREFIX", wineprefix);
}
@@ -104,12 +123,24 @@ module_status wine::initialize()
wrapper.setProcessEnvironment(env);
wrapper.setWorkingDirectory(OPENTRACK_BASE_PATH);
wrapper.start(wine_path, { library_path + "opentrack-wrapper-wine.exe.so" });
+ wrapper.waitForStarted();
+ if (wrapper.state() == QProcess::ProcessState::NotRunning) {
+ return error(tr("Failed to start Wine! Make sure the binary is set correctly."));
+ }
#endif
if (lck_shm.success())
{
shm = (WineSHM*) lck_shm.ptr();
memset(shm, 0, sizeof(*shm));
+
+ qDebug() << "proto/wine: shm success";
+
+ // display "waiting for game message" (overwritten once a game is detected)
+ connected_game = "waiting for game...";
+ }
+ else {
+ qDebug() << "proto/wine: shm no success";
}
if (lck_shm.success())
diff --git a/proto-wine/ftnoir_protocol_wine.h b/proto-wine/ftnoir_protocol_wine.h
index f7346be9..f79f65dc 100644
--- a/proto-wine/ftnoir_protocol_wine.h
+++ b/proto-wine/ftnoir_protocol_wine.h
@@ -26,7 +26,9 @@ struct settings : opts
value<int> proton_appid{b, "proton-appid", 0};
value<QVariant> proton_path{b, "proton-version", {} };
- value<QString> wineprefix{b, "wineprefix", "~/.wine"};
+ value<QVariant> wine_select_path{b, "wine-select-version", {"WINE"}};
+ value<QString> wine_custom_path{b, "wine-custom-version", ""};
+ value<QString> wineprefix{b, "wineprefix", "~/.wine/"};
value<int> protocol{b, "protocol", 2};
};
@@ -77,6 +79,11 @@ private:
settings s;
private slots:
+ void onWinePathComboUpdated(QString selection);
+
+ void doBrowseWine();
+ void doBrowsePrefix();
+
void doOK();
void doCancel();
};
diff --git a/proto-wine/ftnoir_protocol_wine_dialog.cpp b/proto-wine/ftnoir_protocol_wine_dialog.cpp
index a954a752..07dc1469 100644
--- a/proto-wine/ftnoir_protocol_wine_dialog.cpp
+++ b/proto-wine/ftnoir_protocol_wine_dialog.cpp
@@ -1,9 +1,20 @@
#include "ftnoir_protocol_wine.h"
#include <QDebug>
+#include <QFileDialog>
#include <QDir>
#include "api/plugin-api.hpp"
+/*
+ * 0: path to the directory with wine versions
+ * 1: path from a wine version to the exectuable
+ * 2: name of the application using the wine versions
+ */
+static const char* wine_paths[][3] = {
+ {"/.local/share/lutris/runners/wine/", "/bin/wine", "Lutris"},
+ {"/.var/app/net.lutris.Lutris/data/lutris/runners/wine/", "/bin/wine", "Flatpak Lutris"}
+};
+
static const char* proton_paths[] = {
"/.steam/steam/steamapps/common",
"/.steam/root/compatibilitytools.d",
@@ -14,6 +25,23 @@ FTControls::FTControls()
{
ui.setupUi(this);
+ //populate wine select
+ ui.wine_path_combo->addItem("System Wine", QVariant{"WINE"});
+ for (const char** path : wine_paths) {
+ QDir dir(QDir::homePath() + path[0]);
+ dir.setFilter(QDir::Dirs);
+ QFileInfoList list = dir.entryInfoList();
+ for (int i = 0; i < list.size(); ++i) {
+ QFileInfo fileInfo = list.at(i);
+ if (fileInfo.fileName() == "." || fileInfo.fileName() == "..") continue;
+
+ QString name = fileInfo.fileName() + " (" + path[2] + ")";
+ ui.wine_path_combo->addItem(name, QVariant{fileInfo.filePath() + path[1]});
+ }
+ }
+ ui.wine_path_combo->addItem("Custom path to Wine executable", QVariant{"CUSTOM"});
+
+ //populate proton select
for (const char* path : proton_paths) {
QDir dir(QDir::homePath() + path);
dir.setFilter(QDir::Dirs);
@@ -24,17 +52,62 @@ FTControls::FTControls()
ui.proton_version->addItem(fileInfo.fileName(), QVariant{fileInfo.filePath()});
}
}
+
tie_setting(s.proton_path, ui.proton_version);
tie_setting(s.variant_wine, ui.variant_wine);
tie_setting(s.variant_proton, ui.variant_proton);
tie_setting(s.esync, ui.esync);
tie_setting(s.fsync, ui.fsync);
tie_setting(s.proton_appid, ui.proton_appid);
+ tie_setting(s.wine_select_path, ui.wine_path_combo);
+ tie_setting(s.wine_custom_path, ui.wine_path);
tie_setting(s.wineprefix, ui.wineprefix);
tie_setting(s.protocol, ui.protocol_selection);
+ connect(ui.wine_path_combo, &QComboBox::currentTextChanged, this, &FTControls::onWinePathComboUpdated);
+ connect(ui.browse_wine_path_button, &QPushButton::clicked, this, &FTControls::doBrowseWine);
+ connect(ui.browse_wine_prefix_button, &QPushButton::clicked, this, &FTControls::doBrowsePrefix);
connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &FTControls::doOK);
connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &FTControls::doCancel);
+
+ // update state of the combo box and associated ui elements
+ onWinePathComboUpdated(ui.wine_path_combo->currentText());
+}
+
+void FTControls::onWinePathComboUpdated(QString selection) {
+ // enable the custom text field if required
+ if (selection == "Custom path to Wine executable") {
+ ui.wine_path->setEnabled(true);
+ ui.browse_wine_path_button->setEnabled(true);
+ }
+ else {
+ ui.wine_path->setEnabled(false);
+ ui.browse_wine_path_button->setEnabled(false);
+ }
+}
+
+void FTControls::doBrowseWine() {
+ QFileDialog d(this);
+ d.setFileMode(QFileDialog::FileMode::ExistingFile);
+ d.setWindowTitle(tr("Select path to Wine Binary"));
+ if (s.wine_custom_path->startsWith("~/.local/share/lutris/runners")) {
+ d.selectFile(s.wine_custom_path);
+ }
+ if (d.exec()) {
+ s.wine_custom_path = d.selectedFiles()[0];
+ }
+}
+void FTControls::doBrowsePrefix() {
+ QFileDialog d(this);
+ d.setFileMode(QFileDialog::FileMode::Directory);
+ d.setOption(QFileDialog::Option::ShowDirsOnly, true);
+ d.setWindowTitle(tr("Select Wine Prefix"));
+ if (s.wineprefix->startsWith("/") || s.wineprefix->startsWith("~")) {
+ d.selectFile(s.wineprefix);
+ }
+ if (d.exec()) {
+ s.wineprefix = d.selectedFiles()[0];
+ }
}
void FTControls::doOK()
diff --git a/proto-wine/ftnoir_winecontrols.ui b/proto-wine/ftnoir_winecontrols.ui
index e9541447..365922ca 100644
--- a/proto-wine/ftnoir_winecontrols.ui
+++ b/proto-wine/ftnoir_winecontrols.ui
@@ -9,7 +9,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>528</width>
+ <width>951</width>
<height>424</height>
</rect>
</property>
@@ -33,8 +33,8 @@
<string>Wine variant</string>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QRadioButton" name="variant_wine">
+ <item row="10" column="0">
+ <widget class="QRadioButton" name="variant_proton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -42,55 +42,120 @@
</sizepolicy>
</property>
<property name="text">
- <string>Wine (system)</string>
+ <string>Proton (Steam Play)</string>
</property>
</widget>
</item>
- <item row="2" column="1" alignment="Qt::AlignRight">
- <widget class="QComboBox" name="proton_version">
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="variant_wine">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="minimumSize">
- <size>
- <width>120</width>
- <height>0</height>
- </size>
+ <property name="text">
+ <string>Wine (select path and prefix)</string>
</property>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="wineprefix">
+ <item row="10" column="1">
+ <widget class="QComboBox" name="proton_version">
<property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>286</width>
+ <width>120</width>
<height>0</height>
</size>
</property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QRadioButton" name="variant_proton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Proton (Steam Play)</string>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
</property>
</widget>
</item>
+ <item row="9" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLineEdit" name="wineprefix">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>450</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;prefix&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="placeholderText">
+ <string>/path_to_the_prefix/</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="browse_wine_prefix_button">
+ <property name="text">
+ <string>Browse Prefix</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="8" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLineEdit" name="wine_path">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>450</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;wine/runner exectuable path&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="inputMask">
+ <string/>
+ </property>
+ <property name="placeholderText">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="browse_wine_path_button">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Browse Wine Path</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="wine_path_combo"/>
+ </item>
</layout>
</widget>
</item>
diff --git a/proto-wine/lang/nl_NL.ts b/proto-wine/lang/nl_NL.ts
index e2183cc8..0298092b 100644
--- a/proto-wine/lang/nl_NL.ts
+++ b/proto-wine/lang/nl_NL.ts
@@ -2,17 +2,24 @@
<!DOCTYPE TS>
<TS version="2.1" language="nl_NL">
<context>
- <name>UICFTControls</name>
+ <name>FTControls</name>
<message>
- <source>Wine settings</source>
+ <source>Select path to Wine Binary</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine variant</source>
+ <source>Select Wine Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UICFTControls</name>
+ <message>
+ <source>Wine settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine (system)</source>
+ <source>Wine variant</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -55,6 +62,30 @@
<source>Both</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Wine (select path and prefix)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;prefix&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>/path_to_the_prefix/</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;wine/runner exectuable path&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Wine Path</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine</name>
@@ -70,6 +101,10 @@
<source>Wine prefix must be an absolute path (given &apos;%1&apos;)</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Failed to start Wine! Make sure the binary is set correctly.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine_metadata</name>
diff --git a/proto-wine/lang/ru_RU.ts b/proto-wine/lang/ru_RU.ts
index f3b44bd2..c7e9c52e 100644
--- a/proto-wine/lang/ru_RU.ts
+++ b/proto-wine/lang/ru_RU.ts
@@ -2,17 +2,24 @@
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
- <name>UICFTControls</name>
+ <name>FTControls</name>
<message>
- <source>Wine settings</source>
+ <source>Select path to Wine Binary</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine variant</source>
+ <source>Select Wine Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UICFTControls</name>
+ <message>
+ <source>Wine settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine (system)</source>
+ <source>Wine variant</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -55,6 +62,30 @@
<source>Both</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Wine (select path and prefix)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;prefix&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>/path_to_the_prefix/</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;wine/runner exectuable path&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Wine Path</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine</name>
@@ -70,6 +101,10 @@
<source>Wine prefix must be an absolute path (given &apos;%1&apos;)</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Failed to start Wine! Make sure the binary is set correctly.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine_metadata</name>
diff --git a/proto-wine/lang/stub.ts b/proto-wine/lang/stub.ts
index dd4f946f..3366b44b 100644
--- a/proto-wine/lang/stub.ts
+++ b/proto-wine/lang/stub.ts
@@ -2,17 +2,24 @@
<!DOCTYPE TS>
<TS version="2.1">
<context>
- <name>UICFTControls</name>
+ <name>FTControls</name>
<message>
- <source>Wine settings</source>
+ <source>Select path to Wine Binary</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine variant</source>
+ <source>Select Wine Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UICFTControls</name>
+ <message>
+ <source>Wine settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine (system)</source>
+ <source>Wine variant</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -55,6 +62,30 @@
<source>Both</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Wine (select path and prefix)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;prefix&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>/path_to_the_prefix/</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;wine/runner exectuable path&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Wine Path</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine</name>
@@ -70,6 +101,10 @@
<source>Wine prefix must be an absolute path (given &apos;%1&apos;)</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Failed to start Wine! Make sure the binary is set correctly.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine_metadata</name>
diff --git a/proto-wine/lang/zh_CN.ts b/proto-wine/lang/zh_CN.ts
index b7c9ea7d..0d285c7c 100644
--- a/proto-wine/lang/zh_CN.ts
+++ b/proto-wine/lang/zh_CN.ts
@@ -2,17 +2,24 @@
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
- <name>UICFTControls</name>
+ <name>FTControls</name>
<message>
- <source>Wine settings</source>
+ <source>Select path to Wine Binary</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine variant</source>
+ <source>Select Wine Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UICFTControls</name>
+ <message>
+ <source>Wine settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Wine (system)</source>
+ <source>Wine variant</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -55,6 +62,30 @@
<source>Both</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Wine (select path and prefix)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;prefix&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>/path_to_the_prefix/</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Prefix</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;wine/runner exectuable path&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse Wine Path</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine</name>
@@ -70,6 +101,10 @@
<source>Wine prefix must be an absolute path (given &apos;%1&apos;)</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Failed to start Wine! Make sure the binary is set correctly.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>wine_metadata</name>
diff --git a/sdk-paths-runner@GNU-Linux.cmake b/sdk-paths-runner@GNU-Linux.cmake
new file mode 100644
index 00000000..03c87ce4
--- /dev/null
+++ b/sdk-paths-runner@GNU-Linux.cmake
@@ -0,0 +1,3 @@
+set(SDK_WINE ON CACHE BOOL "" FORCE)
+set(OPENTRACK_WINE_ARCH -m64 CACHE STRING "" FORCE)
+set(ENV{PATH} "/usr/lib/wine:$ENV{PATH}")
diff --git a/sdk-paths-sthalik@MSVC-windows.cmake b/sdk-paths-sthalik@MSVC-windows.cmake
index 7df31152..340b78ad 100644
--- a/sdk-paths-sthalik@MSVC-windows.cmake
+++ b/sdk-paths-sthalik@MSVC-windows.cmake
@@ -18,27 +18,39 @@ function(setq name value)
endfunction()
set(opentrack_install-debug-info TRUE CACHE INTERNAL "" FORCE)
-set(opentrack_maintainer-mode TRUE CACHE INTERNAL "" FORCE)
setq(EIGEN3_INCLUDE_DIR "eigen")
-setq(OpenCV_DIR "opencv/build/install")
-setq(SDL2_DIR "SDL2-win32")
-setq(SDK_ARUCO_LIBPATH "aruco/build/src/aruco.lib")
-setq(SDK_FSUIPC "fsuipc")
-setq(SDK_HYDRA "SixenseSDK")
+setq(SDK_RIFT_140 "ovr_sdk_win_23.0.0/LibOVR")
setq(SDK_KINECT20 "Kinect-v2.0")
-setq(SDK_LIBUSB "libusb-msvc-x86")
+setq(SDK_VJOYSTICK "vjoystick")
setq(SDK_PS3EYEDRIVER "PS3EYEDriver")
setq(SDK_REALSENSE "RSSDK-R2")
-setq(SDK_RIFT_140 "ovr_sdk_win_23.0.0/LibOVR")
setq(SDK_VALVE_STEAMVR "steamvr")
-setq(SDK_VJOYSTICK "vjoystick")
-setq(ONNXRuntime_DIR "onnxruntime-1.12.1")
-setq(SDK_TRACKHAT_SENSOR "../trackhat/trackhat-c-library-driver/build/install")
+setq(SDK_FSUIPC "fsuipc")
+setq(SDK_HYDRA "SixenseSDK")
+setq(SDK_EYEWARE_BEAM "eyeware-beam-sdk")
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+setq(Qt5_DIR "../qt-5.15-kde-amd64/lib/cmake/Qt5")
+setq(OpenCV_DIR "opencv/build-amd64/install")
+setq(SDK_ARUCO_LIBPATH "aruco/build-amd64/src/aruco.lib")
+setq(SDK_LIBUSB "libusb-msvc-amd64")
+setq(ONNXRuntime_DIR "onnxruntime-1.14.1-amd64")
+setq(SDK_TRACKHAT_SENSOR "trackhat-c-library-driver/build-amd64/install")
+setq(SDK_OSCPACK "oscpack/build-amd64")
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+setq(Qt5_DIR "../qt-5.15-kde/lib/cmake/Qt5")
+setq(OpenCV_DIR "opencv/build/install")
+setq(SDK_ARUCO_LIBPATH "aruco/build/src/aruco.lib")
+setq(SDK_LIBUSB "libusb-msvc-x86")
+setq(ONNXRuntime_DIR "onnxruntime-1.14.1")
+setq(SDK_TRACKHAT_SENSOR "trackhat-c-library-driver/build/install")
+setq(SDK_OSCPACK "oscpack/build")
+else()
+ message(FATAL_ERROR "unknown word size ${CMAKE_SIZEOF_VOID_P}b")
+endif()
set(CMAKE_ASM_NASM_COMPILER nasm.exe CACHE FILEPATH "" FORCE)
-setq(Qt5_DIR "../qt-5.15-kde/lib/cmake/Qt5")
set(Qt5Core_DIR "${Qt5_DIR}Core" CACHE PATH "" FORCE)
set(Qt5Gui_DIR "${Qt5_DIR}Gui" CACHE PATH "" FORCE)
diff --git a/tracker-eyeware-beam/CMakeLists.txt b/tracker-eyeware-beam/CMakeLists.txt
new file mode 100644
index 00000000..e041c131
--- /dev/null
+++ b/tracker-eyeware-beam/CMakeLists.txt
@@ -0,0 +1,27 @@
+# The Eyeware Beam SDK can be found at https://beam.eyeware.tech/developers/
+# The latest version can be downloaded at https://eyewarecistorage.blob.core.windows.net/beam-sdk/BeamSDK-Windows64-1.1.0.zip
+set(SDK_EYEWARE_BEAM "" CACHE PATH "Eyeware Beam SDK path")
+if(WIN32 AND SDK_EYEWARE_BEAM)
+ if(MSVC)
+ add_compile_options(-EHsc)
+ endif()
+ otr_module(tracker-eyeware-beam)
+
+ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
+ set(arch "x86")
+ else()
+ set(arch "x64")
+ endif()
+
+ target_include_directories(${self} SYSTEM PRIVATE "${SDK_EYEWARE_BEAM}/API/cpp/include")
+ target_link_directories(${self} PRIVATE "${SDK_EYEWARE_BEAM}/API/cpp/lib/${arch}")
+ set(dll "${SDK_EYEWARE_BEAM}/API/cpp/lib/${arch}/tracker_client.dll")
+ set(lib tracker_client.lib)
+
+ #message(${self})
+ #message(${dll})
+ #message(${lib})
+
+ target_link_libraries(${self} ${lib})
+ install(FILES ${dll} DESTINATION ${opentrack-libexec})
+endif()
diff --git a/tracker-eyeware-beam/eyeware_beam.cpp b/tracker-eyeware-beam/eyeware_beam.cpp
new file mode 100644
index 00000000..f48b5d4d
--- /dev/null
+++ b/tracker-eyeware-beam/eyeware_beam.cpp
@@ -0,0 +1,116 @@
+/* Copyright (c) 2023 Eyeware Tech SA https://www.eyeware.tech
+ *
+ * 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 "eyeware_beam.h"
+
+#include <QMutexLocker>
+
+static constexpr double rad_to_deg = 180.0 / M_PI;
+static constexpr double m_to_cm = 100.0;
+static constexpr double epsilon = 0.000001;
+
+eyeware_beam_tracker::eyeware_beam_tracker()
+{
+}
+
+eyeware_beam_tracker::~eyeware_beam_tracker()
+{
+ QMutexLocker lck(&mtx);
+ release_tracker_instance(tracker_client);
+ tracker_client = nullptr;
+}
+
+module_status eyeware_beam_tracker::start_tracker(QFrame* videoframe)
+{
+ QMutexLocker lck(&mtx);
+ try
+ {
+ tracker_client = create_tracker_instance("127.0.0.1", 12010);
+ }
+ catch (...)
+ {
+ return error("Eyeware Beam initialization has failed");
+ }
+
+ return status_ok();
+}
+
+void eyeware_beam_tracker::extract_translation(const eyeware::Vector3D& t,
+ double& translation_x_cm,
+ double& translation_y_cm,
+ double& translation_z_cm)
+{
+ translation_x_cm = +t.x * m_to_cm;
+ translation_y_cm = -t.y * m_to_cm;
+ translation_z_cm = +t.z * m_to_cm;
+}
+
+void eyeware_beam_tracker::extract_rotation_angles(const eyeware::Matrix3x3& R,
+ double& pitch_deg,
+ double& roll_deg,
+ double& yaw_deg)
+{
+ double r00 = static_cast<double>(R[0][0]);
+ double r01 = static_cast<double>(R[0][1]);
+ double r02 = static_cast<double>(R[0][2]);
+ double r10 = static_cast<double>(R[1][0]);
+ double r11 = static_cast<double>(R[1][1]);
+ double r12 = static_cast<double>(R[1][2]);
+ double r20 = static_cast<double>(R[2][0]);
+ double r21 = static_cast<double>(R[2][1]);
+ double r22 = static_cast<double>(R[2][2]);
+
+ double dy = std::sqrt(r00 * r00 + r10 * r10);
+ last_yaw_deg = -std::atan2(-r20, dy) * rad_to_deg;
+ last_roll_deg = 0.0;
+ if (dy > epsilon)
+ {
+ last_pitch_deg = -std::atan2(r21, r22) * rad_to_deg;
+ last_roll_deg = +std::atan2(r10, r00) * rad_to_deg;
+ }
+ else
+ {
+ last_pitch_deg = -std::atan2(-r12, r11) * rad_to_deg;
+ }
+}
+
+void eyeware_beam_tracker::data(double *data)
+{
+ QMutexLocker lck(&mtx);
+
+ if (connected(tracker_client))
+ {
+ eyeware::HeadPoseInfo head_pose_info = get_head_pose_info(tracker_client);
+ if (!head_pose_info.is_lost)
+ {
+ extract_translation(head_pose_info.transform.translation, last_translation_x_cm,
+ last_translation_y_cm, last_translation_z_cm);
+ extract_rotation_angles(head_pose_info.transform.rotation, last_pitch_deg, last_roll_deg, last_yaw_deg);
+ }
+ }
+
+ data[TX] = last_translation_x_cm;
+ data[TY] = last_translation_y_cm;
+ data[TZ] = last_translation_z_cm;
+ data[Yaw] = last_yaw_deg;
+ data[Pitch] = last_pitch_deg;
+ data[Roll] = last_roll_deg;
+}
+
+eyeware_beam_dialog::eyeware_beam_dialog()
+{
+ ui.setupUi(this);
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+}
+
+void eyeware_beam_dialog::doOK()
+{
+ close();
+}
+
+OPENTRACK_DECLARE_TRACKER(eyeware_beam_tracker, eyeware_beam_dialog, eyeware_beam_metadata)
diff --git a/tracker-eyeware-beam/eyeware_beam.h b/tracker-eyeware-beam/eyeware_beam.h
new file mode 100644
index 00000000..9ebf1f3c
--- /dev/null
+++ b/tracker-eyeware-beam/eyeware_beam.h
@@ -0,0 +1,70 @@
+/* Copyright (c) 2023 Eyeware Tech SA https://www.eyeware.tech
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#pragma once
+
+#include "api/plugin-api.hpp"
+
+#include "ui_eyeware_beam.h"
+
+#include "eyeware/tracker_client.h"
+
+#include <QObject>
+#include <QMutex>
+
+class eyeware_beam_tracker : public QObject, public ITracker
+{
+ Q_OBJECT
+
+public:
+ eyeware_beam_tracker();
+ ~eyeware_beam_tracker() override;
+ module_status start_tracker(QFrame* frame) override;
+ void data(double *data) override;
+
+private:
+ void extract_translation(const eyeware::Vector3D& t,
+ double& translation_x_cm,
+ double& translation_y_cm,
+ double& translation_z_cm);
+ void extract_rotation_angles(const eyeware::Matrix3x3& R, double& pitch_deg, double& roll_deg, double& yaw_deg);
+
+ eyeware::TrackerClient* tracker_client = nullptr;
+
+ QMutex mtx;
+
+ double last_pitch_deg = 0.0;
+ double last_roll_deg = 0.0;
+ double last_yaw_deg = 0.0;
+ double last_translation_x_cm = 0.0;
+ double last_translation_y_cm = 0.0;
+ double last_translation_z_cm = 0.0;
+};
+
+class eyeware_beam_dialog : public ITrackerDialog
+{
+ Q_OBJECT
+
+public:
+ eyeware_beam_dialog();
+ void register_tracker(ITracker * x) override { tracker = static_cast<eyeware_beam_tracker*>(x); }
+ void unregister_tracker() override { tracker = nullptr; }
+
+private:
+ Ui::eyeware_beam_ui ui;
+ eyeware_beam_tracker* tracker = nullptr;
+
+private Q_SLOTS:
+ void doOK();
+};
+
+class eyeware_beam_metadata : public Metadata
+{
+ Q_OBJECT
+ QString name() override { return QString("Eyeware Beam"); }
+ QIcon icon() override { return QIcon(":/images/eyeware_beam_logo.png"); }
+};
diff --git a/tracker-eyeware-beam/eyeware_beam.qrc b/tracker-eyeware-beam/eyeware_beam.qrc
new file mode 100644
index 00000000..ae20865e
--- /dev/null
+++ b/tracker-eyeware-beam/eyeware_beam.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/images">
+ <file>eyeware_beam_logo.png</file>
+ </qresource>
+</RCC>
diff --git a/tracker-eyeware-beam/eyeware_beam.ui b/tracker-eyeware-beam/eyeware_beam.ui
new file mode 100644
index 00000000..475db6a0
--- /dev/null
+++ b/tracker-eyeware-beam/eyeware_beam.ui
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>eyeware_beam_ui</class>
+ <widget class="QWidget" name="eyeware_beam_ui">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>433</width>
+ <height>180</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Eyeware Beam</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="eyeware_beam.qrc">
+ <normaloff>:/images/eyeware_beam_logo.png</normaloff>:/images/eyeware_beam_logo.png</iconset>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QFrame" name="frame_2">
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please make sure the Eyeware Beam application is running and tracking is active.&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;To download, visit &lt;a href=&quot;https://beam.eyeware.tech/opentrack&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://beam.eyeware.tech/opentrack&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="eyeware_beam.qrc"/>
+ </resources>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/tracker-eyeware-beam/eyeware_beam_logo.png b/tracker-eyeware-beam/eyeware_beam_logo.png
new file mode 100644
index 00000000..6a611cac
--- /dev/null
+++ b/tracker-eyeware-beam/eyeware_beam_logo.png
Binary files differ
diff --git a/tracker-eyeware-beam/lang/nl_NL.ts b/tracker-eyeware-beam/lang/nl_NL.ts
new file mode 100644
index 00000000..d70f58ed
--- /dev/null
+++ b/tracker-eyeware-beam/lang/nl_NL.ts
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="nl_NL">
+<context>
+ <name>eyeware_beam_ui</name>
+ <message>
+ <source>Eyeware Beam</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please make sure the Eyeware Beam application is running and tracking is active.&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;To download, visit &lt;a href=&quot;https://beam.eyeware.tech/opentrack&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://beam.eyeware.tech/opentrack&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/tracker-eyeware-beam/lang/ru_RU.ts b/tracker-eyeware-beam/lang/ru_RU.ts
new file mode 100644
index 00000000..0bff47ae
--- /dev/null
+++ b/tracker-eyeware-beam/lang/ru_RU.ts
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+ <name>eyeware_beam_ui</name>
+ <message>
+ <source>Eyeware Beam</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please make sure the Eyeware Beam application is running and tracking is active.&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;To download, visit &lt;a href=&quot;https://beam.eyeware.tech/opentrack&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://beam.eyeware.tech/opentrack&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/tracker-eyeware-beam/lang/stub.ts b/tracker-eyeware-beam/lang/stub.ts
new file mode 100644
index 00000000..c64ff83e
--- /dev/null
+++ b/tracker-eyeware-beam/lang/stub.ts
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+ <name>eyeware_beam_ui</name>
+ <message>
+ <source>Eyeware Beam</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please make sure the Eyeware Beam application is running and tracking is active.&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;To download, visit &lt;a href=&quot;https://beam.eyeware.tech/opentrack&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://beam.eyeware.tech/opentrack&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/tracker-eyeware-beam/lang/zh_CN.ts b/tracker-eyeware-beam/lang/zh_CN.ts
new file mode 100644
index 00000000..aed44317
--- /dev/null
+++ b/tracker-eyeware-beam/lang/zh_CN.ts
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="zh_CN">
+<context>
+ <name>eyeware_beam_ui</name>
+ <message>
+ <source>Eyeware Beam</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please make sure the Eyeware Beam application is running and tracking is active.&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;To download, visit &lt;a href=&quot;https://beam.eyeware.tech/opentrack&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://beam.eyeware.tech/opentrack&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/tracker-neuralnet/CMakeLists.txt b/tracker-neuralnet/CMakeLists.txt
index f414c920..db568fae 100644
--- a/tracker-neuralnet/CMakeLists.txt
+++ b/tracker-neuralnet/CMakeLists.txt
@@ -1,4 +1,9 @@
include(opentrack-opencv)
+set(host-spec "${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_SIZEOF_VOID_P}")
+if(host-spec MATCHES "^Linux i[3-6]86 4$")
+ return()
+endif()
+
find_package(OpenCV QUIET)
find_package(OpenMP QUIET) # Used to control number of onnx threads.
find_package(ONNXRuntime QUIET)
@@ -11,16 +16,21 @@ if(OpenCV_FOUND AND ONNXRuntime_FOUND AND OpenMP_FOUND)
otr_module(tracker-neuralnet)
- target_link_libraries(${self}
+ target_link_libraries(${self}
opentrack-cv
onnxruntime::onnxruntime
opencv_calib3d
opencv_imgproc
opencv_imgcodecs
opencv_core
- OpenMP::OpenMP_C
+ OpenMP::OpenMP_CXX
)
+ # OpenMP::OpenMP_CXX doesn't set up the -fopenmp linking option, so set it up ourselves.
+ if(NOT MSVC)
+ target_link_options(${self} PUBLIC ${OpenMP_CXX_FLAGS})
+ endif()
+
install(
FILES "models/head-localizer.onnx"
"models/head-pose.onnx"
diff --git a/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp b/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp
index a1a3526b..59e17063 100644
--- a/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp
+++ b/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp
@@ -13,7 +13,6 @@
#include "compat/math-imports.hpp"
#include "compat/timer.hpp"
#include "compat/check-visible.hpp"
-#include "compat/camera-names.hpp"
#include "cv/init.hpp"
#include <omp.h>
@@ -84,8 +83,7 @@ struct OnScopeExit
CamIntrinsics make_intrinsics(const cv::Mat& img, const Settings& settings)
{
const int w = img.cols, h = img.rows;
- //const double diag_fov = settings.fov * M_PI / 180.;
- const double diag_fov = 60 * M_PI / 180.; (void)settings;
+ const double diag_fov = settings.fov * M_PI / 180.;
const double fov_w = 2.*atan(tan(diag_fov/2.)/sqrt(1. + h/(double)w * h/(double)w));
const double fov_h = 2.*atan(tan(diag_fov/2.)/sqrt(1. + w/(double)h * w/(double)h));
const double focal_length_w = 1. / tan(.5 * fov_w);
@@ -353,7 +351,7 @@ bool NeuralNetTracker::detect()
last_pose_affine_ = pose_affine;
}
- draw_gizmos(*face, pose_affine);
+ draw_gizmos(*face, last_pose_affine_);
return true;
}
@@ -503,38 +501,17 @@ bool NeuralNetTracker::load_and_initialize_model()
bool NeuralNetTracker::open_camera()
{
-#if 0
int rint = std::clamp(*settings_.resolution, 0, (int)std::size(resolution_choices)-1);
resolution_tuple res = resolution_choices[rint];
int fps = enum_to_fps(settings_.force_fps);
-#endif
-
- video::impl::camera::info args {};
- args.width = 640;
- args.height = 480;
- args.fps = 60;
- args.use_mjpeg = true;
QMutexLocker l(&camera_mtx_);
- camera_ = nullptr;
- const QString name = settings_.camera_name;
-
- if (name.isEmpty() || name == "TrackHat sensor")
- {
- camera_ = video::make_camera_("TrackHat sensor");
- if (camera_ && camera_->start(args))
- return true;
- if (!name.isEmpty())
- return false;
- }
-
- camera_ = video::make_camera(name);
+ camera_ = video::make_camera(settings_.camera_name);
if (!camera_)
return false;
-#if 0
video::impl::camera::info args {};
if (res.width)
@@ -546,7 +523,6 @@ bool NeuralNetTracker::open_camera()
args.fps = fps;
args.use_mjpeg = settings_.use_mjpeg;
-#endif
if (!camera_->start(args))
{
@@ -624,8 +600,6 @@ void NeuralNetTracker::run()
std::chrono::duration_cast<std::chrono::milliseconds>(
clk.now() - t).count()*1.e-3);
}
-
- camera_ = nullptr;
}
@@ -670,23 +644,19 @@ void NeuralNetTracker::update_fps(double dt)
void NeuralNetTracker::data(double *data)
{
- auto tmp2 = [&]()
+ Affine tmp = [&]()
{
QMutexLocker lck(&mtx_);
return last_pose_affine_;
}();
- if (!tmp2)
- return;
- const auto& tmp = *tmp2;
-
const auto& mx = tmp.R.col(0);
const auto& my = tmp.R.col(1);
const auto& mz = -tmp.R.col(2);
const float yaw = std::atan2(mx(2), mx(0));
const float pitch = -std::atan2(-mx(1), std::sqrt(mx(2)*mx(2)+mx(0)*mx(0)));
- const float roll = -std::atan2(-my(2), mz(2));
+ const float roll = std::atan2(-my(2), mz(2));
{
constexpr double rad2deg = 180/M_PI;
data[Yaw] = rad2deg * yaw;
@@ -704,7 +674,7 @@ void NeuralNetTracker::data(double *data)
Affine NeuralNetTracker::pose()
{
QMutexLocker lck(&mtx_);
- return last_pose_affine_ ? *last_pose_affine_ : Affine{};
+ return last_pose_affine_;
}
std::tuple<cv::Size,double, double> NeuralNetTracker::stats() const
@@ -715,19 +685,16 @@ std::tuple<cv::Size,double, double> NeuralNetTracker::stats() const
void NeuralNetDialog::make_fps_combobox()
{
-#if 0
for (int k = 0; k < fps_MAX; k++)
{
const int hz = enum_to_fps(k);
const QString name = (hz == 0) ? tr("Default") : QString::number(hz);
ui_.cameraFPS->addItem(name, k);
}
-#endif
}
void NeuralNetDialog::make_resolution_combobox()
{
-#if 0
int k=0;
for (const auto [w, h] : resolution_choices)
{
@@ -736,7 +703,6 @@ void NeuralNetDialog::make_resolution_combobox()
: QString::number(w) + " x " + QString::number(h);
ui_.resolution->addItem(s, k++);
}
-#endif
}
@@ -748,44 +714,21 @@ NeuralNetDialog::NeuralNetDialog() :
make_fps_combobox();
make_resolution_combobox();
- ui_.cameraName->addItem(QString{});
for (const auto& str : video::camera_names())
ui_.cameraName->addItem(str);
tie_setting(settings_.camera_name, ui_.cameraName);
-#if 0
tie_setting(settings_.fov, ui_.cameraFOV);
-#endif
tie_setting(settings_.offset_fwd, ui_.tx_spin);
tie_setting(settings_.offset_up, ui_.ty_spin);
tie_setting(settings_.offset_right, ui_.tz_spin);
tie_setting(settings_.show_network_input, ui_.showNetworkInput);
tie_setting(settings_.roi_filter_alpha, ui_.roiFilterAlpha);
-#if 0
tie_setting(settings_.use_mjpeg, ui_.use_mjpeg);
-#endif
tie_setting(settings_.roi_zoom, ui_.roiZoom);
tie_setting(settings_.num_threads, ui_.threadCount);
-#if 0
tie_setting(settings_.resolution, ui_.resolution);
tie_setting(settings_.force_fps, ui_.cameraFPS);
-#endif
-
- {
- const struct {
- QString label;
- exposure_preset preset;
- } presets[] = {
- { QStringLiteral("Near (1-4ft)"), exposure_preset::near },
- { QStringLiteral("Far (4-8ft)"), exposure_preset::far },
- { QStringLiteral("Custom"), exposure_preset::ignored },
- };
-
- for (const auto& [label, preset] : presets)
- ui_.exposure_preset->addItem(label, int(preset));
-
- tie_setting(cs_.exposure, ui_.exposure_preset);
- }
connect(ui_.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
connect(ui_.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
@@ -807,13 +750,11 @@ NeuralNetDialog::NeuralNetDialog() :
void NeuralNetDialog::save()
{
settings_.b->save();
- cs_.b->save();
}
void NeuralNetDialog::reload()
{
settings_.b->reload();
- cs_.b->reload();
}
void NeuralNetDialog::doOK()
diff --git a/tracker-neuralnet/lang/ru_RU.ts b/tracker-neuralnet/lang/ru_RU.ts
index 4c9cec04..b191e769 100644
--- a/tracker-neuralnet/lang/ru_RU.ts
+++ b/tracker-neuralnet/lang/ru_RU.ts
@@ -5,123 +5,150 @@
<name>Form</name>
<message>
<source>Tracker settings</source>
- <translation type="unfinished"></translation>
+ <translation>Настройки трекера</translation>
+ </message>
+ <message>
+ <source>Diagonal FOV</source>
+ <translation>Угол обзора</translation>
</message>
<message>
<source>Camera settings</source>
- <translation type="unfinished"></translation>
+ <translation>Настройки камеры</translation>
+ </message>
+ <message>
+ <source>Frames per second</source>
+ <translation>Кадры в секунду</translation>
+ </message>
+ <message>
+ <source>Camera name</source>
+ <translation>Камера</translation>
+ </message>
+ <message>
+ <source>Camera Configuration</source>
+ <translation>Конфигурация камеры</translation>
</message>
<message>
<source>Head Center Offset</source>
- <translation type="unfinished"></translation>
+ <translation>Смещение центра головы</translation>
</message>
<message>
<source> mm</source>
- <translation type="unfinished"></translation>
+ <translation> мм</translation>
</message>
<message>
<source>Use only yaw and pitch while calibrating.
Don&apos;t roll or change position.</source>
- <translation type="unfinished"></translation>
+ <translation>Поворачивайте голову влево-вправо и наклоняйте вверх-вниз.
+Не наклоняйте набок и не смещайте голову в сторону.</translation>
</message>
<message>
<source>Start calibration</source>
- <translation type="unfinished"></translation>
+ <translation>Начать калибровку</translation>
</message>
<message>
<source>Right</source>
- <translation type="unfinished"></translation>
+ <translation>Вправо</translation>
</message>
<message>
<source>Forward</source>
- <translation type="unfinished"></translation>
+ <translation>Вперед</translation>
</message>
<message>
<source>Up</source>
- <translation type="unfinished"></translation>
+ <translation>Вверх</translation>
</message>
<message>
- <source>Exposure preset</source>
- <translation type="unfinished"></translation>
+ <source>Show Network Input</source>
+ <translation>Показать входные данные</translation>
</message>
<message>
- <source>Camera Configuration</source>
- <translation type="unfinished"></translation>
+ <source>MJPEG</source>
+ <translation>Использовать MJPEG</translation>
</message>
<message>
<source>Tuning / Debug</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Number of threads. Can be used to balance the CPU load between the game and the tracker.</source>
- <translation type="unfinished"></translation>
+ <translation>Тонкая настройка</translation>
</message>
<message>
<source>ROI Smoothing Alpha</source>
- <translation type="unfinished"></translation>
+ <translation>Сглаживание ROI</translation>
</message>
<message>
<source>ROI Zoom</source>
- <translation type="unfinished"></translation>
+ <translation>Масштабирование ROI</translation>
</message>
<message>
- <source>Show the image patch that the pose estimation model sees.</source>
- <translation type="unfinished"></translation>
+ <source>Thread Count</source>
+ <translation>Количество потоков</translation>
</message>
<message>
- <source>Show Network Input</source>
- <translation type="unfinished"></translation>
+ <source>Resolution</source>
+ <translation>Разрешение</translation>
</message>
<message>
- <source>Amount of smoothing of the face region coordinates. Can help stabilize the pose.</source>
- <translation type="unfinished"></translation>
+ <source>Field of view. Needed to transform the pose to world coordinates.</source>
+ <translation>Угол обзора камеры. Требуется для преобразования положения головы в глобальные координаты</translation>
</message>
<message>
- <source>Thread Count</source>
- <translation type="unfinished"></translation>
+ <source>Requested video frame rate. Actual setting may not be supported by the camera.</source>
+ <translation>Частота кадров. Реальные значения могут не поддерживаться камерой.</translation>
</message>
<message>
- <source>Zoom factor for the face region. Applied before the patch is fed into the pose estimation model. There is a sweet spot near 1.</source>
- <translation type="unfinished"></translation>
+ <source>The requested resolution for cases where the camera delivers maximum frame rate only for a particular resolution. The image may still be downscaled to the internal resolution.</source>
+ <translation>Разрешение камеры, для тех случаев, когда быстродействие камеры максимально в определенном разрешении. Может быть масштабировано до внутреннего разрешения.</translation>
+ </message>
+ <message>
+ <source>Number of threads. Can be used to balance the CPU load between the game and the tracker.</source>
+ <translation>Количество потоков. Используется для балансировки нагрузки на процессор между игрой и трекером.</translation>
</message>
<message>
- <source>Camera override</source>
- <translation type="unfinished"></translation>
+ <source>Show the image patch that the pose estimation model sees.</source>
+ <translation>Показать изображение, используемое моделью определения позиции</translation>
+ </message>
+ <message>
+ <source>Amount of smoothing of the face region coordinates. Can help stabilize the pose.</source>
+ <translation>Сглаживание координат области лица. Может помочь стабилизировать позицию.</translation>
+ </message>
+ <message>
+ <source>Zoom factor for the face region. Applied before the patch is fed into the pose estimation model. There is a sweet spot near 1.</source>
+ <translation>Фактор масштабирования области лица. Применяется перед передачей кадра в модель определения позиции. Наилучшие результаты близки к 1</translation>
</message>
</context>
<context>
<name>neuralnet_tracker_ns::NeuralNetDialog</name>
<message>
<source>Default</source>
- <translation type="unfinished"></translation>
+ <translation>По умолчанию</translation>
</message>
<message>
<source>Tracker Offline</source>
- <translation type="unfinished"></translation>
+ <translation>Трекер выключен</translation>
</message>
<message>
<source>%1x%2 @ %3 FPS / Inference: %4 ms</source>
- <translation type="unfinished"></translation>
+ <translation>%1x%2 @ %3 FPS; Время оценки: %4 мс</translation>
</message>
<message>
<source>%1 yaw samples. Yaw more to %2 samples for stable calibration.</source>
- <translation type="unfinished"></translation>
+ <translation>Сэмплов поворота: %1.
+Поворачивайте голову в стороны до %2 сэмплов для стабильной калибрации.</translation>
</message>
<message>
<source>%1 pitch samples. Pitch more to %2 samples for stable calibration.</source>
- <translation type="unfinished"></translation>
+ <translation>Сэмплов наклона: %1.
+Наклоняйте голову вниз/вверх до %2 сэмплов для стабильной калибрации.</translation>
</message>
<message>
<source>%1 samples. Over %2, good!</source>
- <translation type="unfinished"></translation>
+ <translation>%1 сэмплов. Более %2, достаточно.</translation>
</message>
<message>
<source>Stop calibration</source>
- <translation type="unfinished"></translation>
+ <translation>Остановить калибровку</translation>
</message>
<message>
<source>Start calibration</source>
- <translation type="unfinished"></translation>
+ <translation>Начать калибровку</translation>
</message>
</context>
</TS>
diff --git a/tracker-neuralnet/model_adapters.cpp b/tracker-neuralnet/model_adapters.cpp
index af599321..a8580a89 100644
--- a/tracker-neuralnet/model_adapters.cpp
+++ b/tracker-neuralnet/model_adapters.cpp
@@ -8,7 +8,6 @@
#include <QDebug>
-
namespace neuralnet_tracker_ns
{
@@ -165,6 +164,24 @@ double Localizer::last_inference_time_millis() const
}
+std::string PoseEstimator::get_network_input_name(size_t i) const
+{
+#if ORT_API_VERSION >= 12
+ return std::string(&*session_.GetInputNameAllocated(i, allocator_));
+#else
+ return std::string(session_.GetInputName(i, allocator_));
+#endif
+}
+
+std::string PoseEstimator::get_network_output_name(size_t i) const
+{
+#if ORT_API_VERSION >= 12
+ return std::string(&*session_.GetOutputNameAllocated(i, allocator_));
+#else
+ return std::string(session_.GetOutputName(i, allocator_));
+#endif
+}
+
PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&session)
: model_version_{session.GetModelMetadata().GetVersion()}
, session_{std::move(session)}
@@ -215,14 +232,16 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses
qDebug() << "Pose model inputs (" << session_.GetInputCount() << ")";
qDebug() << "Pose model outputs (" << session_.GetOutputCount() << "):";
+ output_names_.resize(session_.GetOutputCount());
+ output_c_names_.resize(session_.GetOutputCount());
for (size_t i=0; i<session_.GetOutputCount(); ++i)
{
- const char* name = session_.GetOutputName(i, allocator_);
+ std::string name = get_network_output_name(i);
const auto& output_info = session_.GetOutputTypeInfo(i);
const auto& onnx_tensor_spec = output_info.GetTensorTypeAndShapeInfo();
auto my_tensor_spec = understood_outputs.find(name);
- qDebug() << "\t" << name << " (" << onnx_tensor_spec.GetShape() << ") dtype: " << onnx_tensor_spec.GetElementType() << " " <<
+ qDebug() << "\t" << name.c_str() << " (" << onnx_tensor_spec.GetShape() << ") dtype: " << onnx_tensor_spec.GetElementType() << " " <<
(my_tensor_spec != understood_outputs.end() ? "ok" : "unknown");
if (my_tensor_spec != understood_outputs.end())
@@ -240,7 +259,8 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses
// Create tensor regardless and ignore output
output_val_.push_back(create_tensor(output_info, allocator_));
}
- output_names_.push_back(name);
+ output_names_[i] = name;
+ output_c_names_[i] = output_names_[i].c_str();
}
has_uncertainty_ = understood_outputs.at("rotaxis_scales_tril").available ||
@@ -270,9 +290,12 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses
// output_val_.push_back(create_tensor(output_info, allocator_));
// }
+ input_names_.resize(session_.GetInputCount());
+ input_c_names_.resize(session_.GetInputCount());
for (size_t i = 0; i < session_.GetInputCount(); ++i)
{
- input_names_.push_back(session_.GetInputName(i, allocator_));
+ input_names_[i] = get_network_input_name(i);
+ input_c_names_[i] = input_names_[i].c_str();
}
assert (input_names_.size() == input_val_.size());
@@ -312,11 +335,11 @@ std::optional<PoseEstimator::Face> PoseEstimator::run(
{
session_.Run(
Ort::RunOptions{ nullptr },
- input_names_.data(),
+ input_c_names_.data(),
input_val_.data(),
input_val_.size(),
- output_names_.data(),
- output_val_.data(),
+ output_c_names_.data(),
+ output_val_.data(),
output_val_.size());
}
catch (const Ort::Exception &e)
@@ -430,4 +453,4 @@ double PoseEstimator::last_inference_time_millis() const
-} // namespace neuralnet_tracker_ns \ No newline at end of file
+} // namespace neuralnet_tracker_ns
diff --git a/tracker-neuralnet/model_adapters.h b/tracker-neuralnet/model_adapters.h
index 3fbfb861..820330cf 100644
--- a/tracker-neuralnet/model_adapters.h
+++ b/tracker-neuralnet/model_adapters.h
@@ -3,6 +3,7 @@
#include <optional>
#include <array>
#include <vector>
+#include <string>
#include <onnxruntime_cxx_api.h>
#include <opencv2/core.hpp>
@@ -21,7 +22,7 @@ class Localizer
public:
Localizer(Ort::MemoryInfo &allocator_info,
Ort::Session &&session);
-
+
// Returns bounding wrt image coordinate of the input image
// The preceeding float is the score for being a face normalized to [0,1].
std::pair<float, cv::Rect2f> run(
@@ -68,13 +69,16 @@ class PoseEstimator
bool has_uncertainty() const { return has_uncertainty_; }
private:
+ std::string get_network_input_name(size_t i) const;
+ std::string get_network_output_name(size_t i) const;
int64_t model_version_ = 0; // Queried meta data from the ONNX file
Ort::Session session_{nullptr}; // ONNX's runtime context for running the model
Ort::Allocator allocator_; // Memory allocator for tensors
// Inputs
cv::Mat scaled_frame_{}, input_mat_{}; // Input. One is the original crop, the other is rescaled (?)
std::vector<Ort::Value> input_val_; // Tensors to put into the model
- std::vector<const char*> input_names_; // Refers to the names in the onnx model.
+ std::vector<std::string> input_names_; // Refers to the names in the onnx model.
+ std::vector<const char *> input_c_names_; // Refers to the C names in the onnx model.
// Outputs
cv::Vec<float, 3> output_coord_{}; // 2d Coordinate and head size output.
cv::Vec<float, 4> output_quat_{}; // Quaternion output
@@ -83,7 +87,8 @@ class PoseEstimator
cv::Vec<float, 2> output_eyes_{};
cv::Vec<float, 3> output_coord_scales_{};
std::vector<Ort::Value> output_val_; // Tensors to put the model outputs in.
- std::vector<const char*> output_names_; // Refers to the names in the onnx model.
+ std::vector<std::string> output_names_; // Refers to the names in the onnx model.
+ std::vector<const char *> output_c_names_; // Refers to the C names in the onnx model.
// More bookkeeping
size_t num_recurrent_states_ = 0;
double last_inference_time_ = 0;
@@ -99,4 +104,4 @@ int find_input_intensity_quantile(const cv::Mat& frame, float percentage);
void normalize_brightness(const cv::Mat& frame, cv::Mat& out);
-} // namespace neuralnet_tracker_ns \ No newline at end of file
+} // namespace neuralnet_tracker_ns
diff --git a/tracker-trackhat/lang/nl_NL.ts b/tracker-trackhat/lang/nl_NL.ts
index 9cc67677..ebc53a27 100644
--- a/tracker-trackhat/lang/nl_NL.ts
+++ b/tracker-trackhat/lang/nl_NL.ts
@@ -147,7 +147,7 @@
<context>
<name>trackhat_module</name>
<message>
- <source>TrackHat Point Tracker</source>
+ <source>TrackHat v1 Sensor</source>
<translation type="unfinished"></translation>
</message>
</context>
diff --git a/tracker-trackhat/lang/ru_RU.ts b/tracker-trackhat/lang/ru_RU.ts
index 844c5519..49d247be 100644
--- a/tracker-trackhat/lang/ru_RU.ts
+++ b/tracker-trackhat/lang/ru_RU.ts
@@ -147,7 +147,7 @@
<context>
<name>trackhat_module</name>
<message>
- <source>TrackHat Point Tracker</source>
+ <source>TrackHat v1 Sensor</source>
<translation type="unfinished"></translation>
</message>
</context>
diff --git a/tracker-trackhat/lang/stub.ts b/tracker-trackhat/lang/stub.ts
index 127d0691..adb23557 100644
--- a/tracker-trackhat/lang/stub.ts
+++ b/tracker-trackhat/lang/stub.ts
@@ -147,7 +147,7 @@
<context>
<name>trackhat_module</name>
<message>
- <source>TrackHat Point Tracker</source>
+ <source>TrackHat v1 Sensor</source>
<translation type="unfinished"></translation>
</message>
</context>
diff --git a/tracker-trackhat/lang/zh_CN.ts b/tracker-trackhat/lang/zh_CN.ts
index 179d4261..5837eeb1 100644
--- a/tracker-trackhat/lang/zh_CN.ts
+++ b/tracker-trackhat/lang/zh_CN.ts
@@ -147,7 +147,7 @@
<context>
<name>trackhat_module</name>
<message>
- <source>TrackHat Point Tracker</source>
+ <source>TrackHat v1 Sensor</source>
<translation type="unfinished"></translation>
</message>
</context>
diff --git a/video-ps3eye/shm-layout.hpp b/video-ps3eye/shm-layout.hpp
index 9eee6db4..0b6c132e 100644
--- a/video-ps3eye/shm-layout.hpp
+++ b/video-ps3eye/shm-layout.hpp
@@ -31,12 +31,8 @@ struct shm_out
};
struct shm {
- static constexpr unsigned _cacheline_len = 64;
- static constexpr unsigned _padding_len =
- (_cacheline_len - (sizeof(shm_in) & (_cacheline_len - 1))) & (_cacheline_len - 1);
-
shm_out out;
- const char* _padding[_padding_len];
+ [[maybe_unused]] const char _padding[128 - sizeof(shm_out) % 128]; // NOLINT
shm_in in;
};
diff --git a/x-plane-plugin/plugin.c b/x-plane-plugin/plugin.c
index ed72e50e..e43ee0ef 100644
--- a/x-plane-plugin/plugin.c
+++ b/x-plane-plugin/plugin.c
@@ -134,6 +134,8 @@ static int TrackToggleHandler(XPLMCommandRef inCommand,
XPLMCommandPhase inPhase,
void* inRefCon)
{
+ if (inPhase != xplm_CommandBegin) return 0;
+
if (track_disabled)
{
//Enable
@@ -156,6 +158,8 @@ static int TranslationToggleHandler(XPLMCommandRef inCommand,
XPLMCommandPhase inPhase,
void* inRefCon)
{
+ if (inPhase != xplm_CommandBegin) return 0;
+
translation_disabled = !translation_disabled;
if (!translation_disabled)
{