From aac65283a2b254f0338a6ad1609e5d916ba9dcfc Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 17:44:19 +0100 Subject: opentrack/joystick: rename header to clarify usage --- opentrack/win32-joystick.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 opentrack/win32-joystick.cpp (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp new file mode 100644 index 00000000..b4a1f9cd --- /dev/null +++ b/opentrack/win32-joystick.cpp @@ -0,0 +1,30 @@ +#include "win32-joystick.hpp" + +LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() +{ + (void) CoInitialize(nullptr); + + static LPDIRECTINPUT8 dinput_handle_ = nullptr; + + if (dinput_handle_ == nullptr) + (void) DirectInput8Create(GetModuleHandle(nullptr), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (void**) &dinput_handle_, + nullptr); + + return dinput_handle_; +} + +std::unordered_map>& win32_joy_ctx::joys() +{ + static std::unordered_map> js; + + return js; +} + +win32_joy_ctx& win32_joy_ctx::make() +{ + static win32_joy_ctx ret; + return ret; +} -- cgit v1.2.3 From 5d4a9c78fbbbd59d366e91bfe4c4263d12833abe Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 18:01:06 +0100 Subject: api/joy: guard _WIN32 properly --- opentrack/keybinding-worker.hpp | 10 ++++++---- opentrack/shortcuts.h | 5 ++++- opentrack/win32-joystick.cpp | 4 ++++ 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index c4a39ec6..83ffadf1 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -59,19 +59,18 @@ struct Key { int foo; }; struct OPENTRACK_EXPORT KeybindingWorker : private QThread { private: +#ifdef _WIN32 LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; -#ifdef _WIN32 win32_joy_ctx& joy_ctx; -#endif volatile bool should_quit; using fun = std::function; std::vector receivers; QMutex mtx; - + void run() override; KeybindingWorker(); - + KeybindingWorker(const KeybindingWorker&) = delete; KeybindingWorker& operator=(KeybindingWorker&) = delete; static KeybindingWorker& make(); @@ -100,4 +99,7 @@ public: { return Token(receiver); } +#else + void run() override {} +#endif }; diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 930952e8..8acc5ba5 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -66,7 +66,10 @@ public: {} } s; - Shortcuts() : key_token(KeybindingWorker::add_receiver([&](const Key& k) { receiver(k); })) + Shortcuts() +#ifdef _WIN32 + : key_token(KeybindingWorker::add_receiver([&](const Key& k) { receiver(k); })) +#endif { reload(); } diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index b4a1f9cd..56a1b070 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -1,5 +1,7 @@ #include "win32-joystick.hpp" +#ifdef _WIN32 + LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() { (void) CoInitialize(nullptr); @@ -28,3 +30,5 @@ win32_joy_ctx& win32_joy_ctx::make() static win32_joy_ctx ret; return ret; } + +#endif -- cgit v1.2.3 From 3566dc23946b798b396946297cbf70f2d46fd242 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 26 Nov 2015 09:04:29 +0100 Subject: api/shortcuts: move to separate definition There's no need to have definitions in header for non-template classes --- opentrack/keybinding-worker.cpp | 10 ++ opentrack/keybinding-worker.hpp | 13 +- opentrack/win32-joystick.cpp | 275 +++++++++++++++++++++++++++++++++++ opentrack/win32-joystick.hpp | 308 ++++------------------------------------ 4 files changed, 315 insertions(+), 291 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index dcf5c1b6..59bc4afd 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -14,6 +14,15 @@ #include #include +bool Key::should_process() +{ + if (keycode == 0 && guid == "") + return false; + bool ret = timer.elapsed_ms() > 100; + timer.start(); + return ret; +} + KeybindingWorker::~KeybindingWorker() { qDebug() << "keybinding worker stop"; should_quit = true; @@ -172,6 +181,7 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) ok = true; qDebug() << "remove receiver" << (long) pos; receivers.erase(receivers.begin() + i); + break; } } if (!ok) diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 7661f88d..054182e7 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -35,18 +35,9 @@ struct Key { bool held; Timer timer; public: - Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) - { - } + Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) {} - bool should_process() - { - if (keycode == 0 && guid == "") - return false; - bool ret = timer.elapsed_ms() > 100; - timer.start(); - return ret; - } + bool should_process(); }; struct OPENTRACK_EXPORT KeybindingWorker : private QThread diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 56a1b070..29a51a43 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -31,4 +31,279 @@ win32_joy_ctx& win32_joy_ctx::make() return ret; } +void win32_joy_ctx::poll(fn f) +{ + QMutexLocker l(&mtx); + + refresh(false); + for (auto& j : joys()) + { + j.second->poll(f); + } +} + +bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) +{ + QMutexLocker l(&mtx); + + refresh(false); + + auto iter = joys().find(guid); + + if (iter == joys().end() || iter->second->joy_handle == nullptr) + return false; + + auto& j = iter->second; + + auto& joy_handle = j->joy_handle; + bool ok = false; + HRESULT hr; + + (void) joy_handle->Acquire(); + + if (!FAILED(hr = joy_handle->Poll())) + ok = true; + + if (!ok) + { + qDebug() << "joy acquire failed" << guid << hr; + (void) joy_handle->Unacquire(); + return false; + } + + DIJOYSTATE2 js; + memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + const int values[] = { + js.lX, + js.lY, + js.lZ, + js.lRx, + js.lRy, + js.lRz, + js.rglSlider[0], + js.rglSlider[1] + }; + + for (int i = 0; i < 8; i++) + axes[i] = values[i]; + + return true; +} + +win32_joy_ctx::~win32_joy_ctx() +{ + release(); +} + +std::vector win32_joy_ctx::get_joy_info() +{ + QMutexLocker l(&mtx); + + std::vector ret; + + for (auto& j : joys()) + ret.push_back(joy_info { j.second->name, j.first }); + + return ret; +} + +win32_joy_ctx::win32_joy_ctx() +{ + refresh(true); +} + +void win32_joy_ctx::release() +{ + qDebug() << "release joystick dinput handle"; + joys() = std::unordered_map>(); + { + auto& di = dinput_handle(); + di->Release(); + di = nullptr; + } +} + +void win32_joy_ctx::refresh(bool first) +{ + if (!first) + { + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + timer_joylist.start(); + } + + enum_state st(joys(), first); +} + +QString win32_joy_ctx::guid_to_string(const GUID guid) +{ + char buf[40] = {0}; + wchar_t szGuidW[40] = {0}; + + StringFromGUID2(guid, szGuidW, 40); + WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); + + return QString(buf); +} + +using fn = win32_joy_ctx::fn; + +void win32_joy_ctx::joy::release() +{ + if (joy_handle) + { + (void) joy_handle->Unacquire(); + joy_handle->Release(); + joy_handle = nullptr; + } +} + +bool win32_joy_ctx::joy::poll(fn f) +{ + HRESULT hr; + bool ok = false; + + if (joy_handle == nullptr) + return false; + + (void) joy_handle->Acquire(); + + if (!FAILED(joy_handle->Poll())) + ok = true; + + if (!ok) + { + qDebug() << "joy acquire failed" << guid << hr; + (void) joy_handle->Unacquire(); + return false; + } + + DIJOYSTATE2 js; + memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + first |= first_timer.elapsed_ms() > first_event_delay_ms; + + for (int i = 0; i < 128; i++) + { + const bool state = !!(js.rgbButtons[i] & 0x80); + if (state != pressed[i] && first) + { + f(guid, i, state); + qDebug() << "btn" << guid << i << state; + } + pressed[i] = state; + } + + return true; +} + +win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first) : joys(joys), first(first) +{ + HRESULT hr; + LPDIRECTINPUT8 di = dinput_handle(); + + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "failed enum joysticks" << hr; + return; + } + + for (auto it = joys.begin(); it != joys.end(); ) + { + if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) + it = joys.erase(it); + else + it++; + } +} + +win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) +{ + enum_state& state = *reinterpret_cast(pContext); + const QString guid = guid_to_string(pdidInstance->guidInstance); + const QString name = QString(pdidInstance->tszInstanceName); + + auto it = state.joys.find(guid); + const bool exists = it != state.joys.end() && it->second->joy_handle != nullptr; + + state.all.push_back(guid); + + if (!exists) + { + HRESULT hr; + LPDIRECTINPUTDEVICE8 h; + LPDIRECTINPUT8 di = dinput_handle(); + if (FAILED(hr = di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + { + qDebug() << "createdevice" << guid << hr; + goto end; + } + if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) + { + qDebug() << "format"; + h->Release(); + goto end; + } + + if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + { + qDebug() << "coop"; + h->Release(); + goto end; + } + if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) + { + qDebug() << "enum-objects"; + h->Release(); + goto end; + } + + qDebug() << "add joy" << guid; + state.joys[guid] = std::make_shared(h, guid, name, state.first); + } +end: + return DIENUM_CONTINUE; +} + +win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx) +{ + if (pdidoi->dwType & DIDFT_AXIS) + { + DIPROPRANGE diprg; + memset(&diprg, 0, sizeof(diprg)); + diprg.diph.dwSize = sizeof( DIPROPRANGE ); + diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; + diprg.lMax = joy_axis_size; + diprg.lMin = -joy_axis_size; + + HRESULT hr; + + if (FAILED(hr = reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) + { + qDebug() << "DIPROP_RANGE" << hr; + return DIENUM_STOP; + } + } + + return DIENUM_CONTINUE; +} + #endif diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index b08da6c8..334b617a 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -39,77 +39,6 @@ struct hash struct OPENTRACK_EXPORT win32_joy_ctx { using fn = std::function; - - void poll(fn f) - { - QMutexLocker l(&mtx); - - refresh(false); - for (auto& j : joys()) - { - j.second->poll(f); - } - } - - bool poll_axis(const QString& guid, int axes[8]) - { - QMutexLocker l(&mtx); - - refresh(false); - - auto iter = joys().find(guid); - - if (iter == joys().end() || iter->second->joy_handle == nullptr) - return false; - - auto& j = iter->second; - - auto& joy_handle = j->joy_handle; - bool ok = false; - HRESULT hr; - - (void) joy_handle->Acquire(); - - if (!FAILED(hr = joy_handle->Poll())) - ok = true; - - if (!ok) - { - qDebug() << "joy acquire failed" << guid << hr; - (void) joy_handle->Unacquire(); - return false; - } - - DIJOYSTATE2 js; - memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - qDebug() << "joy get state failed" << guid << hr; - return false; - } - - const int values[] = { - js.lX, - js.lY, - js.lZ, - js.lRx, - js.lRy, - js.lRz, - js.rglSlider[0], - js.rglSlider[1] - }; - - for (int i = 0; i < 8; i++) - axes[i] = values[i]; - - return true; - } - - ~win32_joy_ctx() - { - release(); - } enum { joy_axis_size = 65535 }; @@ -117,78 +46,42 @@ struct OPENTRACK_EXPORT win32_joy_ctx { QString name, guid; }; - - std::vector get_joy_info() - { - QMutexLocker l(&mtx); - - std::vector ret; - - for (auto& j : joys()) - ret.push_back(joy_info { j.second->name, j.first }); - - return ret; - } + void poll(fn f); + bool poll_axis(const QString& guid, int axes[8]); + ~win32_joy_ctx(); + std::vector get_joy_info(); static win32_joy_ctx& make(); - win32_joy_ctx(const win32_joy_ctx&) = delete; win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; -private: - static QString guid_to_string(const GUID guid) - { - char buf[40] = {0}; - wchar_t szGuidW[40] = {0}; - - StringFromGUID2(guid, szGuidW, 40); - WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); - - return QString(buf); - } - static LPDIRECTINPUT8& dinput_handle(); +private: + enum { joylist_refresh_ms = 250 }; - win32_joy_ctx() - { - refresh(true); - } - void release() - { - qDebug() << "release joystick dinput handle"; - joys() = std::unordered_map>(); - { - auto& di = dinput_handle(); - di->Release(); - di = nullptr; - } - } - - void refresh(bool first) - { - if (!first) - { - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } - - enum_state st(joys(), first); - } QMutex mtx; Timer timer_joylist; - enum { joylist_refresh_ms = 250 }; + + static QString guid_to_string(const GUID guid); + static LPDIRECTINPUT8& dinput_handle(); + win32_joy_ctx(); + void release(); + void refresh(bool first); + + struct joy; + static std::unordered_map>& joys(); struct joy { + enum { first_event_delay_ms = 3000 }; + LPDIRECTINPUTDEVICE8 joy_handle; QString guid, name; bool pressed[128]; Timer first_timer; bool first; - - enum { first_event_delay_ms = 3000 }; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) : joy_handle(handle), guid(guid), name(name), first(first) + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) + : joy_handle(handle), guid(guid), name(name), first(first) { qDebug() << "got joy" << guid; for (int i = 0; i < 128; i++) @@ -201,166 +94,21 @@ private: release(); } - void release() - { - if (joy_handle) - { - (void) joy_handle->Unacquire(); - joy_handle->Release(); - joy_handle = nullptr; - } - } - - bool poll(fn f) - { - HRESULT hr; - bool ok = false; - - if (joy_handle == nullptr) - return false; - - (void) joy_handle->Acquire(); - - if (!FAILED(joy_handle->Poll())) - ok = true; - - if (!ok) - { - qDebug() << "joy acquire failed" << guid << hr; - (void) joy_handle->Unacquire(); - return false; - } - - DIJOYSTATE2 js; - memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - qDebug() << "joy get state failed" << guid << hr; - return false; - } - - first |= first_timer.elapsed_ms() > first_event_delay_ms; - - for (int i = 0; i < 128; i++) - { - const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i] && first) - { - f(guid, i, state); - qDebug() << "btn" << guid << i << state; - } - pressed[i] = state; - } - - return true; - } + void release(); + bool poll(fn f); }; - struct enum_state + class enum_state { std::unordered_map>& joys; - std::vector all; bool first; - - enum_state(std::unordered_map>& joys, bool first) : joys(joys), first(first) - { - HRESULT hr; - LPDIRECTINPUT8 di = dinput_handle(); - - if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) - { - qDebug() << "failed enum joysticks" << hr; - return; - } - - for (auto it = joys.begin(); it != joys.end(); ) - { - if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) - it = joys.erase(it); - else - it++; - } - } - - static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) - { - enum_state& state = *reinterpret_cast(pContext); - const QString guid = guid_to_string(pdidInstance->guidInstance); - const QString name = QString(pdidInstance->tszInstanceName); - - auto it = state.joys.find(guid); - const bool exists = it != state.joys.end() && it->second->joy_handle != nullptr; - - state.all.push_back(guid); - - if (!exists) - { - HRESULT hr; - LPDIRECTINPUTDEVICE8 h; - LPDIRECTINPUT8 di = dinput_handle(); - if (FAILED(hr = di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) - { - qDebug() << "createdevice" << guid << hr; - goto end; - } - if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) - { - qDebug() << "format"; - h->Release(); - goto end; - } - - if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) - { - qDebug() << "coop"; - h->Release(); - goto end; - } - if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) - { - qDebug() << "enum-objects"; - h->Release(); - goto end; - } - - qDebug() << "add joy" << guid; - state.joys[guid] = std::make_shared(h, guid, name, state.first); - } - -end: return DIENUM_CONTINUE; - } - - static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx) - { - if (pdidoi->dwType & DIDFT_AXIS) - { - DIPROPRANGE diprg; - memset(&diprg, 0, sizeof(diprg)); - diprg.diph.dwSize = sizeof( DIPROPRANGE ); - diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); - diprg.diph.dwHow = DIPH_BYID; - diprg.diph.dwObj = pdidoi->dwType; - diprg.lMax = joy_axis_size; - diprg.lMin = -joy_axis_size; - - HRESULT hr; - - if (FAILED(hr = reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) - { - qDebug() << "DIPROP_RANGE" << hr; - return DIENUM_STOP; - } - } - - return DIENUM_CONTINUE; - } + + std::vector all; + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); + static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); + public: + enum_state(std::unordered_map>& joys, bool first); }; - - static std::unordered_map>& joys(); }; #endif -- cgit v1.2.3 From edb0e01947f67142c00c3f75a62df7af708cdf11 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 11:58:20 +0100 Subject: api/joystick: reduce mutex contention Don't look for changes in hotplug joysticks by freezing up polling for joysticks' axis and button. Issue: #267 --- opentrack/win32-joystick.cpp | 21 ++++++++++++++++----- opentrack/win32-joystick.hpp | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 29a51a43..0bd6bfda 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -33,9 +33,10 @@ win32_joy_ctx& win32_joy_ctx::make() void win32_joy_ctx::poll(fn f) { + refresh(false); + QMutexLocker l(&mtx); - refresh(false); for (auto& j : joys()) { j.second->poll(f); @@ -44,10 +45,10 @@ void win32_joy_ctx::poll(fn f) bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) { - QMutexLocker l(&mtx); - refresh(false); + QMutexLocker l(&mtx); + auto iter = joys().find(guid); if (iter == joys().end() || iter->second->joy_handle == nullptr) @@ -134,12 +135,14 @@ void win32_joy_ctx::refresh(bool first) { if (!first) { + QMutexLocker l(&mtx); + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) return; timer_joylist.start(); } - enum_state st(joys(), first); + enum_state st(joys(), first, mtx); } QString win32_joy_ctx::guid_to_string(const GUID guid) @@ -210,11 +213,16 @@ bool win32_joy_ctx::joy::poll(fn f) return true; } -win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first) : joys(joys), first(first) +win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first, QMutex& mtx) : first(first) { HRESULT hr; LPDIRECTINPUT8 di = dinput_handle(); + { + QMutexLocker l(&mtx); + this->joys = joys; + } + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, @@ -231,6 +239,9 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys; } win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 334b617a..3f47d170 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -100,14 +100,14 @@ private: class enum_state { - std::unordered_map>& joys; + std::unordered_map> joys; bool first; std::vector all; static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); public: - enum_state(std::unordered_map>& joys, bool first); + enum_state(std::unordered_map>& joys, bool first, QMutex &mtx); }; }; -- cgit v1.2.3 From c03c6f2bdb6a4f236c22a916753d4aa9728085fa Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 12:34:05 +0100 Subject: api/joystick: oops, access the right 'joys' variable --- opentrack/win32-joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 0bd6bfda..a705adbc 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -232,7 +232,7 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys.begin(); it != this->joys.end(); ) { if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) it = joys.erase(it); -- cgit v1.2.3 From a07eed2a0de09224adb1381d7744a2f98857836e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 12:34:19 +0100 Subject: api/joystick: drop locking, add comment --- opentrack/win32-joystick.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index a705adbc..6e64355c 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -135,8 +135,8 @@ void win32_joy_ctx::refresh(bool first) { if (!first) { - QMutexLocker l(&mtx); - + // accessing struct Timer without a lock. worst can happen is seconds + // and nanoseconds getting out of sync. no big deal. if (timer_joylist.elapsed_ms() < joylist_refresh_ms) return; timer_joylist.start(); -- cgit v1.2.3 From dd67c2971d4f41267d4d08ebd8c5aefdb675c6e5 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:27:01 +0100 Subject: api/joy: fix race erase from iterator referenced the wrong 'joys' variable --- opentrack/win32-joystick.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 6e64355c..0f8a08f8 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -222,7 +222,7 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys = joys; } - + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, @@ -232,10 +232,12 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys.begin(); it != this->joys.end(); ) + auto& js = this->joys; + + for (auto it = js.begin(); it != js.end(); ) { if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) - it = joys.erase(it); + it = js.erase(it); else it++; } -- cgit v1.2.3 From 22d4c7cc0cadf212052ef72c3bf8ddda6f73a647 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:31:57 +0100 Subject: api, compat: clean up verbose fprintf logspam --- opentrack-compat/shm.cpp | 1 - opentrack/keybinding-worker.cpp | 1 - opentrack/win32-joystick.cpp | 1 - 3 files changed, 3 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index fffb3709..a306d581 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -92,7 +92,6 @@ struct secattr attrs.lpSecurityDescriptor = pSD; attrs.nLength = sizeof(SECURITY_ATTRIBUTES); - fprintf(stderr, "security descriptor ok\n"); fflush(stderr); return; diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 59bc4afd..3c801cf2 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -24,7 +24,6 @@ bool Key::should_process() } KeybindingWorker::~KeybindingWorker() { - qDebug() << "keybinding worker stop"; should_quit = true; wait(); if (dinkeyboard) { diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 0f8a08f8..cd3502b4 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -122,7 +122,6 @@ win32_joy_ctx::win32_joy_ctx() void win32_joy_ctx::release() { - qDebug() << "release joystick dinput handle"; joys() = std::unordered_map>(); { auto& di = dinput_handle(); -- cgit v1.2.3 From fc9d0a76f47e97f2bdd35edc24695c95654a2a67 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:32:44 +0100 Subject: api/joy: there's no joy_handle == nullptr case, don't check for it --- opentrack/win32-joystick.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index cd3502b4..1c658c75 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -51,7 +51,7 @@ bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) auto iter = joys().find(guid); - if (iter == joys().end() || iter->second->joy_handle == nullptr) + if (iter == joys().end()) return false; auto& j = iter->second; @@ -172,9 +172,6 @@ bool win32_joy_ctx::joy::poll(fn f) HRESULT hr; bool ok = false; - if (joy_handle == nullptr) - return false; - (void) joy_handle->Acquire(); if (!FAILED(joy_handle->Poll())) @@ -252,7 +249,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns const QString name = QString(pdidInstance->tszInstanceName); auto it = state.joys.find(guid); - const bool exists = it != state.joys.end() && it->second->joy_handle != nullptr; + const bool exists = it != state.joys.end(); state.all.push_back(guid); -- cgit v1.2.3 From 0be7e0a4e6ec65800a12bff1e7384995592c226f Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 02:02:55 +0100 Subject: api/keys: initialize hresult --- opentrack/win32-joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 1c658c75..e3147929 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -174,7 +174,7 @@ bool win32_joy_ctx::joy::poll(fn f) (void) joy_handle->Acquire(); - if (!FAILED(joy_handle->Poll())) + if (!FAILED(hr = joy_handle->Poll())) ok = true; if (!ok) -- cgit v1.2.3 From acef508f0b6f16a7be987eeebbb3402455f9aef8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:16:39 +0100 Subject: joystick: no longer singleton, use fake window handle We can create arbitrary amount of dinput handles, given they're passed unique window handles. --- opentrack/win32-joystick.cpp | 60 ++++++++++++++++---------------------------- opentrack/win32-joystick.hpp | 23 +++++++++-------- 2 files changed, 33 insertions(+), 50 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index e3147929..89092403 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -1,23 +1,9 @@ +#undef NDEBUG +#include #include "win32-joystick.hpp" #ifdef _WIN32 -LPDIRECTINPUT8& win32_joy_ctx::dinput_handle() -{ - (void) CoInitialize(nullptr); - - static LPDIRECTINPUT8 dinput_handle_ = nullptr; - - if (dinput_handle_ == nullptr) - (void) DirectInput8Create(GetModuleHandle(nullptr), - DIRECTINPUT_VERSION, - IID_IDirectInput8, - (void**) &dinput_handle_, - nullptr); - - return dinput_handle_; -} - std::unordered_map>& win32_joy_ctx::joys() { static std::unordered_map> js; @@ -25,12 +11,6 @@ std::unordered_map>& win32_joy_ctx: return js; } -win32_joy_ctx& win32_joy_ctx::make() -{ - static win32_joy_ctx ret; - return ret; -} - void win32_joy_ctx::poll(fn f) { refresh(false); @@ -117,17 +97,18 @@ std::vector win32_joy_ctx::get_joy_info() win32_joy_ctx::win32_joy_ctx() { + if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL) != DI_OK) { + qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); + assert(!"direct input handle can't be created"); + } refresh(true); } void win32_joy_ctx::release() { joys() = std::unordered_map>(); - { - auto& di = dinput_handle(); - di->Release(); - di = nullptr; - } + di->Release(); + di = nullptr; } void win32_joy_ctx::refresh(bool first) @@ -141,7 +122,7 @@ void win32_joy_ctx::refresh(bool first) timer_joylist.start(); } - enum_state st(joys(), first, mtx); + enum_state st(joys(), mtx, fake_main_window, di); } QString win32_joy_ctx::guid_to_string(const GUID guid) @@ -193,12 +174,10 @@ bool win32_joy_ctx::joy::poll(fn f) return false; } - first |= first_timer.elapsed_ms() > first_event_delay_ms; - for (int i = 0; i < 128; i++) { const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i] && first) + if (state != pressed[i]) { f(guid, i, state); qDebug() << "btn" << guid << i << state; @@ -209,15 +188,19 @@ bool win32_joy_ctx::joy::poll(fn f) return true; } -win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first, QMutex& mtx) : first(first) +win32_joy_ctx::enum_state::enum_state(std::unordered_map> &joys, + QMutex& mtx, + QMainWindow &fake_main_window, + LPDIRECTINPUT8 di) : + fake_main_window(fake_main_window), + di(di) { - HRESULT hr; - LPDIRECTINPUT8 di = dinput_handle(); - { QMutexLocker l(&mtx); this->joys = joys; } + + HRESULT hr; if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, @@ -257,8 +240,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns { HRESULT hr; LPDIRECTINPUTDEVICE8 h; - LPDIRECTINPUT8 di = dinput_handle(); - if (FAILED(hr = di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + if (FAILED(hr = state.di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) { qDebug() << "createdevice" << guid << hr; goto end; @@ -270,7 +252,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns goto end; } - if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + if (FAILED(h->SetCooperativeLevel((HWND) state.fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) { qDebug() << "coop"; h->Release(); @@ -284,7 +266,7 @@ win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidIns } qDebug() << "add joy" << guid; - state.joys[guid] = std::make_shared(h, guid, name, state.first); + state.joys[guid] = std::make_shared(h, guid, name); } end: return DIENUM_CONTINUE; diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 421774a9..f7629c3d 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace std { template<> @@ -49,21 +50,23 @@ struct OPENTRACK_EXPORT win32_joy_ctx void poll(fn f); bool poll_axis(const QString& guid, int axes[8]); - ~win32_joy_ctx(); std::vector get_joy_info(); - static win32_joy_ctx& make(); + win32_joy_ctx(const win32_joy_ctx&) = delete; win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; + win32_joy_ctx(); + ~win32_joy_ctx(); + private: enum { joylist_refresh_ms = 100 }; QMutex mtx; Timer timer_joylist; + QMainWindow fake_main_window; + LPDIRECTINPUT8 di; static QString guid_to_string(const GUID guid); - static LPDIRECTINPUT8& dinput_handle(); - win32_joy_ctx(); void release(); void refresh(bool first); @@ -72,16 +75,13 @@ private: struct joy { - enum { first_event_delay_ms = 3000 }; - LPDIRECTINPUTDEVICE8 joy_handle; QString guid, name; bool pressed[128]; Timer first_timer; - bool first; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) - : joy_handle(handle), guid(guid), name(name), first(first) + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name) + : joy_handle(handle), guid(guid), name(name) { qDebug() << "got joy" << guid; for (int i = 0; i < 128; i++) @@ -101,13 +101,14 @@ private: class enum_state { std::unordered_map> joys; - bool first; + QMainWindow& fake_main_window; + LPDIRECTINPUT8 di; std::vector all; static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); public: - enum_state(std::unordered_map>& joys, bool first, QMutex &mtx); + enum_state(std::unordered_map>& joys, QMutex &mtx, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); }; }; -- cgit v1.2.3 From 5076d0c35eacb2e7b246e7bd5e6637086ea74a15 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:23:04 +0100 Subject: api/joy: nix static, now that we're not a singleton --- opentrack/win32-joystick.cpp | 19 ++++++------------- opentrack/win32-joystick.hpp | 5 ++--- 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 89092403..78720c79 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -4,20 +4,13 @@ #ifdef _WIN32 -std::unordered_map>& win32_joy_ctx::joys() -{ - static std::unordered_map> js; - - return js; -} - void win32_joy_ctx::poll(fn f) { refresh(false); QMutexLocker l(&mtx); - for (auto& j : joys()) + for (auto& j : joys) { j.second->poll(f); } @@ -29,9 +22,9 @@ bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) QMutexLocker l(&mtx); - auto iter = joys().find(guid); + auto iter = joys.find(guid); - if (iter == joys().end()) + if (iter == joys.end()) return false; auto& j = iter->second; @@ -89,7 +82,7 @@ std::vector win32_joy_ctx::get_joy_info() std::vector ret; - for (auto& j : joys()) + for (auto& j : joys) ret.push_back(joy_info { j.second->name, j.first }); return ret; @@ -106,7 +99,7 @@ win32_joy_ctx::win32_joy_ctx() void win32_joy_ctx::release() { - joys() = std::unordered_map>(); + joys = std::unordered_map>(); di->Release(); di = nullptr; } @@ -122,7 +115,7 @@ void win32_joy_ctx::refresh(bool first) timer_joylist.start(); } - enum_state st(joys(), mtx, fake_main_window, di); + enum_state st(joys, mtx, fake_main_window, di); } QString win32_joy_ctx::guid_to_string(const GUID guid) diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index f7629c3d..e68ea2c6 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -70,9 +70,6 @@ private: void release(); void refresh(bool first); - struct joy; - static std::unordered_map>& joys(); - struct joy { LPDIRECTINPUTDEVICE8 joy_handle; @@ -97,6 +94,8 @@ private: void release(); bool poll(fn f); }; + + std::unordered_map> joys; class enum_state { -- cgit v1.2.3 From b31e4997de81efc3941072cc48b5f09064e62e81 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:59:36 +0100 Subject: api/joy: speed up poll_axis path We don't really need to poll for joysticks in tracker/joy. --- opentrack/win32-joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 78720c79..f4bfba76 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -18,7 +18,7 @@ void win32_joy_ctx::poll(fn f) bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) { - refresh(false); + //refresh(false); QMutexLocker l(&mtx); -- cgit v1.2.3 From 75b4a6e3a32b4345941e15953d55572384eb210e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 20:13:42 +0100 Subject: api/joy: prevent idempotent keypressed passed to receiver --- opentrack/win32-joystick.cpp | 4 +++- opentrack/win32-joystick.hpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index f4bfba76..73e27f80 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -169,7 +169,7 @@ bool win32_joy_ctx::joy::poll(fn f) for (int i = 0; i < 128; i++) { - const bool state = !!(js.rgbButtons[i] & 0x80); + const bool state = !!(js.rgbButtons[i] & 0x80) && js.rgbButtons[i] != js_old.rgbButtons[i]; if (state != pressed[i]) { f(guid, i, state); @@ -178,6 +178,8 @@ bool win32_joy_ctx::joy::poll(fn f) pressed[i] = state; } + js_old = js; + return true; } diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index e68ea2c6..df00aee7 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -76,6 +76,7 @@ private: QString guid, name; bool pressed[128]; Timer first_timer; + DIJOYSTATE2 js_old; joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name) : joy_handle(handle), guid(guid), name(name) -- cgit v1.2.3 From 4864dfaa4b455905fece5cd93502b80890d1b2d2 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 20:13:56 +0100 Subject: api/joy: move from header --- opentrack/win32-joystick.cpp | 15 +++++++++++++++ opentrack/win32-joystick.hpp | 17 +++-------------- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 73e27f80..728e2f68 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -292,4 +292,19 @@ win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdi return DIENUM_CONTINUE; } +win32_joy_ctx::joy::joy(LPDIRECTINPUTDEVICE8 handle, const QString &guid, const QString &name) + : joy_handle(handle), guid(guid), name(name) +{ + qDebug() << "got joy" << guid; + for (int i = 0; i < 128; i++) + pressed[i] = false; + memset(&js_old, 0, sizeof(js_old)); +} + +win32_joy_ctx::joy::~joy() +{ + qDebug() << "nix joy" << guid; + release(); +} + #endif diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index df00aee7..6d5e1074 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -24,7 +24,7 @@ namespace std { template<> struct hash { - std::size_t operator()(const QString& value) const + inline std::size_t operator()(const QString& value) const { return qHash(value); } @@ -78,19 +78,8 @@ private: Timer first_timer; DIJOYSTATE2 js_old; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name) - : joy_handle(handle), guid(guid), name(name) - { - qDebug() << "got joy" << guid; - for (int i = 0; i < 128; i++) - pressed[i] = false; - } - - ~joy() - { - qDebug() << "nix joy" << guid; - release(); - } + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name); + ~joy(); void release(); bool poll(fn f); -- cgit v1.2.3 From 3e543b11f57aa6c010045fb9614eb2638ac6ae81 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 17 Dec 2015 22:52:54 +0100 Subject: api/joy: refresh only manually on certain events Refresh joylist when new listener arrives, and when the joy singleton just gets created. Enumerating joys all the time causes high CPU usage for some of the users. Issue: #279 Backtrace-by: @exulant Reported-by: @aka2k --- opentrack/keybinding-worker.cpp | 1 + opentrack/win32-joystick.cpp | 25 +++++++------------------ opentrack/win32-joystick.hpp | 8 ++------ 3 files changed, 10 insertions(+), 24 deletions(-) (limited to 'opentrack/win32-joystick.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index b0cef22d..39693a7c 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -164,6 +164,7 @@ KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) receivers.push_back(std::unique_ptr(new fun(receiver))); fun* f = receivers[receivers.size() - 1].get(); qDebug() << "add receiver" << (long) f; + joy_ctx.refresh(); return f; } diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 728e2f68..5e6f2011 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -6,7 +6,7 @@ void win32_joy_ctx::poll(fn f) { - refresh(false); + //refresh(false); QMutexLocker l(&mtx); @@ -94,7 +94,7 @@ win32_joy_ctx::win32_joy_ctx() qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); assert(!"direct input handle can't be created"); } - refresh(true); + refresh(); } void win32_joy_ctx::release() @@ -104,18 +104,12 @@ void win32_joy_ctx::release() di = nullptr; } -void win32_joy_ctx::refresh(bool first) +void win32_joy_ctx::refresh() { - if (!first) - { - // accessing struct Timer without a lock. worst can happen is seconds - // and nanoseconds getting out of sync. no big deal. - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } + QMutexLocker l(&mtx); - enum_state st(joys, mtx, fake_main_window, di); + qDebug() << "joy list refresh"; + enum_state st(joys, fake_main_window, di); } QString win32_joy_ctx::guid_to_string(const GUID guid) @@ -184,16 +178,12 @@ bool win32_joy_ctx::joy::poll(fn f) } win32_joy_ctx::enum_state::enum_state(std::unordered_map> &joys, - QMutex& mtx, QMainWindow &fake_main_window, LPDIRECTINPUT8 di) : fake_main_window(fake_main_window), di(di) { - { - QMutexLocker l(&mtx); - this->joys = joys; - } + this->joys = joys; HRESULT hr; @@ -216,7 +206,6 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys; } diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 6d5e1074..9c888326 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -57,18 +57,14 @@ struct OPENTRACK_EXPORT win32_joy_ctx win32_joy_ctx(); ~win32_joy_ctx(); - + void refresh(); private: - enum { joylist_refresh_ms = 100 }; - QMutex mtx; - Timer timer_joylist; QMainWindow fake_main_window; LPDIRECTINPUT8 di; static QString guid_to_string(const GUID guid); void release(); - void refresh(bool first); struct joy { @@ -97,7 +93,7 @@ private: static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); public: - enum_state(std::unordered_map>& joys, QMutex &mtx, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); + enum_state(std::unordered_map>& joys, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); }; }; -- cgit v1.2.3