summaryrefslogtreecommitdiffhomepage
path: root/opentrack
diff options
context:
space:
mode:
Diffstat (limited to 'opentrack')
-rw-r--r--opentrack/win32-joystick-shortcuts.hpp86
1 files changed, 45 insertions, 41 deletions
diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp
index 530545dc..3e384da5 100644
--- a/opentrack/win32-joystick-shortcuts.hpp
+++ b/opentrack/win32-joystick-shortcuts.hpp
@@ -1,5 +1,7 @@
#pragma once
+#ifdef _WIN32
+
#include <cstring>
#include <memory>
#include <vector>
@@ -17,7 +19,7 @@
struct win32_joy_ctx
{
using fn = std::function<void(const QString& guid, int btn, bool held)>;
-
+
void poll(fn f)
{
refresh(false);
@@ -27,13 +29,13 @@ struct win32_joy_ctx
joys.erase(joys.begin() + i);
}
}
-
+
struct joy
{
LPDIRECTINPUTDEVICE8 joy_handle;
QString guid;
bool pressed[128];
-
+
joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid)
{
qDebug() << "got joy" << guid;
@@ -41,13 +43,13 @@ struct win32_joy_ctx
pressed[i] = false;
poll([&](const QString&, int idx, bool held) -> void { pressed[idx] = held; });
}
-
+
~joy()
{
qDebug() << "nix joy" << guid;
release();
}
-
+
void release()
{
if (joy_handle)
@@ -57,12 +59,12 @@ struct win32_joy_ctx
joy_handle = nullptr;
}
}
-
+
bool poll(fn f)
{
HRESULT hr;
bool ok = false;
-
+
for (int i = 0; i < 5; i++)
{
if (!FAILED(joy_handle->Poll()))
@@ -76,22 +78,22 @@ struct win32_joy_ctx
ok = true;
break;
}
-
+
if (!ok)
{
qDebug() << "joy acquire failed" << guid << hr;
return false;
}
-
+
DIJOYSTATE2 js;
memset(&js, 0, sizeof(js));
-
+
if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js)))
{
qDebug() << "joy get state failed" << guid << hr;
return false;
}
-
+
for (int i = 0; i < 128; i++)
{
const bool state = !!(js.rgbButtons[i] & 0x80);
@@ -102,49 +104,49 @@ struct win32_joy_ctx
}
pressed[i] = state;
}
-
+
return true;
}
};
-
+
static QString guid_to_string(const GUID guid)
{
char buf[40] = {0};
wchar_t szGuidW[40] = {0};
-
+
StringFromGUID2(guid, szGuidW, 40);
WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL);
-
+
return QString(buf);
}
-
+
win32_joy_ctx() : dinput_handle(nullptr)
{
(void) CoInitialize(nullptr);
-
+
HRESULT hr;
-
+
if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr),
DIRECTINPUT_VERSION,
IID_IDirectInput8,
(void**) &dinput_handle,
nullptr)))
goto fail;
-
+
refresh(true);
-
+
return;
fail:
qDebug() << "dinput8 failed for shortcuts" << hr;
-
+
release();
}
-
+
~win32_joy_ctx()
{
release();
}
-
+
void release()
{
joys = std::vector<std::shared_ptr<joy>>();
@@ -154,32 +156,32 @@ fail:
dinput_handle = nullptr;
}
}
-
+
void refresh(bool first)
{
if (!dinput_handle)
return;
-
+
if (!first)
{
if (timer_joylist.elapsed_ms() < joylist_refresh_ms)
return;
timer_joylist.start();
}
-
+
enum_state st(dinput_handle, joys);
}
-
+
struct enum_state
{
std::vector<std::shared_ptr<joy>>& joys;
std::vector<QString> all;
LPDIRECTINPUT8 dinput_handle;
-
+
enum_state(LPDIRECTINPUT8 di, std::vector<std::shared_ptr<joy>>& joys) : joys(joys), dinput_handle(di)
{
HRESULT hr;
-
+
if(FAILED(hr = dinput_handle->EnumDevices(DI8DEVCLASS_GAMECTRL,
EnumJoysticksCallback,
this,
@@ -188,7 +190,7 @@ fail:
qDebug() << "failed enum joysticks" << hr;
return;
}
-
+
for (int i = joys.size() - 1; i >= 0; i--)
{
const auto& guid = joys[i]->guid;
@@ -196,7 +198,7 @@ fail:
joys.erase(joys.begin() + i);
}
}
-
+
static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext)
{
enum_state& state = *reinterpret_cast<enum_state*>(pContext);
@@ -207,13 +209,13 @@ fail:
const int cnt_names = std::count_if(state.joys.begin(), state.joys.end(), [&](const joy& j) -> bool { return j.name == name; });
// this is potentially bad since replugged sticks can change guids (?)
#endif
-
+
const bool exists = std::find_if(state.joys.cbegin(),
state.joys.cend(),
[&](const std::shared_ptr<joy>& j) -> bool { return j->guid == guid; }) != state.joys.cend();
-
+
state.all.push_back(guid);
-
+
if (!exists)
{
HRESULT hr;
@@ -229,7 +231,7 @@ fail:
h->Release();
goto end;
}
-
+
if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)))
{
qDebug() << "coop";
@@ -246,10 +248,10 @@ fail:
#endif
state.joys.push_back(std::make_shared<joy>(h, guid));
}
-
+
end: return DIENUM_CONTINUE;
}
-
+
#if 0
static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx)
{
@@ -263,18 +265,20 @@ end: return DIENUM_CONTINUE;
diprg.diph.dwObj = pdidoi->dwType;
diprg.lMax = 32;
diprg.lMin = -32;
-
+
if (FAILED(reinterpret_cast<LPDIRECTINPUTDEVICE8>(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph)))
return DIENUM_STOP;
}
-
+
return DIENUM_CONTINUE;
}
#endif
};
-
+
LPDIRECTINPUT8 dinput_handle;
std::vector<std::shared_ptr<joy>> joys;
Timer timer_joylist;
enum { joylist_refresh_ms = 250 };
-}; \ No newline at end of file
+};
+
+#endif