diff options
-rwxr-xr-x[-rw-r--r--] | proto-ft/ftnoir_protocol_ft.cpp | 42 | ||||
-rwxr-xr-x[-rw-r--r--] | proto-ft/ftnoir_protocol_ft.h | 16 | ||||
-rwxr-xr-x | proto-ft/mutex.cpp | 64 |
3 files changed, 107 insertions, 15 deletions
diff --git a/proto-ft/ftnoir_protocol_ft.cpp b/proto-ft/ftnoir_protocol_ft.cpp index 05253174..134ffc53 100644..100755 --- a/proto-ft/ftnoir_protocol_ft.cpp +++ b/proto-ft/ftnoir_protocol_ft.cpp @@ -16,6 +16,7 @@ FTNoIR_Protocol::FTNoIR_Protocol() : viewsStop(nullptr), intGameID(0) { + runonce_check->try_runonce(); } FTNoIR_Protocol::~FTNoIR_Protocol() @@ -27,6 +28,7 @@ FTNoIR_Protocol::~FTNoIR_Protocol() dummyTrackIR.terminate(); dummyTrackIR.kill(); dummyTrackIR.waitForFinished(50); + runonce_check->try_exit(); } void FTNoIR_Protocol::pose(const double* headpose) { @@ -108,44 +110,54 @@ void FTNoIR_Protocol::start_tirviews() { } void FTNoIR_Protocol::start_dummy() { - - QString program = QCoreApplication::applicationDirPath() + "/TrackIR.exe"; dummyTrackIR.setProgram("\"" + program + "\""); dummyTrackIR.start(); } -bool FTNoIR_Protocol::correct() +void FTNoIR_Protocol::set_protocols(bool ft, bool npclient) { + const QString program_dir = QCoreApplication::applicationDirPath() + "/"; + // Registry settings (in HK_USER) - QSettings settings("Freetrack", "FreetrackClient"); - QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); + QSettings settings_ft("Freetrack", "FreetrackClient"); + QSettings settings_npclient("NaturalPoint", "NATURALPOINT\\NPClient Location"); + + if (ft) + settings_ft.setValue("Path", program_dir); + else + settings_ft.setValue("Path", ""); + + if (npclient) + settings_npclient.setValue("Path", program_dir); + else + settings_npclient.setValue("Path", ""); +} +bool FTNoIR_Protocol::correct() +{ if (!shm.success()) return false; - QString aLocation = QCoreApplication::applicationDirPath() + "/"; + bool use_ft = false, use_npclient = false; switch (s.intUsedInterface) { case 0: - // Use both interfaces - settings.setValue( "Path" , aLocation ); - settingsTIR.setValue( "Path" , aLocation ); + use_ft = true; + use_npclient = true; break; case 1: - // Use FreeTrack, disable TrackIR - settings.setValue( "Path" , aLocation ); - settingsTIR.setValue( "Path" , "" ); + use_ft = true; break; case 2: - // Use TrackIR, disable FreeTrack - settings.setValue( "Path" , "" ); - settingsTIR.setValue( "Path" , aLocation ); + use_npclient = true; break; default: break; } + set_protocols(use_ft, use_npclient); + if (s.useTIRViews) { start_tirviews(); } diff --git a/proto-ft/ftnoir_protocol_ft.h b/proto-ft/ftnoir_protocol_ft.h index 9cf16f03..8940e5d8 100644..100755 --- a/proto-ft/ftnoir_protocol_ft.h +++ b/proto-ft/ftnoir_protocol_ft.h @@ -21,6 +21,8 @@ #include "opentrack-compat/shm.h" #include "opentrack-compat/options.hpp" #include "freetrackclient/fttypes.h" +#include <memory> + using namespace options; struct settings : opts { @@ -36,6 +38,15 @@ struct settings : opts { typedef void (__stdcall *importTIRViewsStart)(void); typedef void (__stdcall *importTIRViewsStop)(void); +// for runonce, see mutex.cpp +struct runonce +{ + virtual void try_runonce() = 0; + virtual void try_exit() = 0; + virtual bool is_first_run() = 0; + virtual ~runonce() {} +}; + class FTNoIR_Protocol : public IProtocol { public: @@ -61,9 +72,14 @@ private: QString connected_game; QMutex game_name_mutex; + static std::unique_ptr<runonce> runonce_check; + static inline double getRadsFromDegrees(double degrees) { return degrees * 0.017453; } void start_tirviews(); void start_dummy(); + +public: + static void set_protocols(bool ft, bool npclient); }; class FTControls: public IProtocolDialog diff --git a/proto-ft/mutex.cpp b/proto-ft/mutex.cpp new file mode 100755 index 00000000..0d50c9bd --- /dev/null +++ b/proto-ft/mutex.cpp @@ -0,0 +1,64 @@ +#include "ftnoir_protocol_ft.h" +#include <windows.h> + +class check_for_first_run : public runonce +{ + bool checked_for_first_run; + bool is_first_instance; + +public: + bool is_first_run() override + { + return checked_for_first_run && is_first_instance; + } + + void try_runonce() override + { + constexpr const char* name = "opentrack-freetrack-runonce"; + + if (checked_for_first_run) + return; + + // just leak it, no issue + HANDLE h = CreateMutexA(nullptr, false, name); + + switch (WaitForSingleObject(h, 0)) + { + case WAIT_OBJECT_0: + is_first_instance = true; + checked_for_first_run = true; + break; + case WAIT_TIMEOUT: + checked_for_first_run = true; + break; + default: + checked_for_first_run = false; + break; + } + + if (checked_for_first_run && !is_first_instance) + CloseHandle(h); + + qDebug() << "ft runonce:" << "first-run" << is_first_instance << "checked" << checked_for_first_run; + } + + void try_exit() override + { + if (is_first_instance) + { + qDebug() << "ft runonce: removing registry keys"; + FTNoIR_Protocol::set_protocols(false, false); + } + } + +public: + check_for_first_run() : checked_for_first_run(false), is_first_instance(false) + { + } + ~check_for_first_run() + { + try_exit(); + } +}; + +std::unique_ptr<runonce> FTNoIR_Protocol::runonce_check = std::unique_ptr<runonce>(static_cast<runonce*>(new check_for_first_run())); |