summaryrefslogtreecommitdiffhomepage
path: root/proto-vjoystick
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2016-08-08 16:12:18 +0200
committerStanislaw Halik <sthalik@misaki.pl>2016-08-08 16:14:12 +0200
commit744574a36be2914c6d4641a9fa6e76359a4e218e (patch)
treef85c0c028f93bb1362e95d4b636faaa4e0bc35da /proto-vjoystick
parent5598520e24e978b55428f6da4a5dd9617844f152 (diff)
proto/vjoystick: add new vjoystick protocol to replace vjoy
Diffstat (limited to 'proto-vjoystick')
-rw-r--r--proto-vjoystick/CMakeLists.txt16
-rw-r--r--proto-vjoystick/images/vjoystick.pngbin0 -> 6327 bytes
-rw-r--r--proto-vjoystick/vjoystick.cpp147
-rw-r--r--proto-vjoystick/vjoystick.h79
-rw-r--r--proto-vjoystick/vjoystick.qrc5
-rw-r--r--proto-vjoystick/vjoystick.ui56
-rw-r--r--proto-vjoystick/vjoystick_dialog.cpp8
7 files changed, 311 insertions, 0 deletions
diff --git a/proto-vjoystick/CMakeLists.txt b/proto-vjoystick/CMakeLists.txt
new file mode 100644
index 00000000..d0cfe591
--- /dev/null
+++ b/proto-vjoystick/CMakeLists.txt
@@ -0,0 +1,16 @@
+if(WIN32)
+ set(SDK_VJOYSTICK "" CACHE PATH "vjoystick SDK path")
+ if(SDK_VJOYSTICK)
+ if(opentrack-64bit)
+ set(arch "amd64/")
+ else()
+ set(arch "")
+ endif()
+ set(lib "${SDK_VJOYSTICK}/lib/${arch}vJoyInterface.lib")
+ set(dll "${SDK_VJOYSTICK}/lib/${arch}vJoyInterface.dll")
+ opentrack_boilerplate(opentrack-proto-vjoy)
+ target_link_libraries(opentrack-proto-vjoy ${lib})
+ target_include_directories(opentrack-proto-vjoy SYSTEM PUBLIC "${SDK_VJOYSTICK}/inc")
+ install(FILES "${dll}" DESTINATION ${opentrack-hier-pfx})
+ endif()
+endif()
diff --git a/proto-vjoystick/images/vjoystick.png b/proto-vjoystick/images/vjoystick.png
new file mode 100644
index 00000000..c3def49f
--- /dev/null
+++ b/proto-vjoystick/images/vjoystick.png
Binary files differ
diff --git a/proto-vjoystick/vjoystick.cpp b/proto-vjoystick/vjoystick.cpp
new file mode 100644
index 00000000..46d45bfb
--- /dev/null
+++ b/proto-vjoystick/vjoystick.cpp
@@ -0,0 +1,147 @@
+#include "vjoystick.h"
+#include "opentrack/plugin-api.hpp"
+
+#include <cstring>
+#include <QDebug>
+
+#include <QPushButton>
+#include <QMessageBox>
+#include <QDesktopServices>
+#include <QUrl>
+
+// required for api headers
+#include <windows.h>
+
+#undef PPJOY_MODE
+#include <public.h>
+#include <vjoyinterface.h>
+
+#define OPENTRACK_VJOYSTICK_ID 1
+
+template<typename t, typename u, typename v>
+static t clamp(t val, u min, v max)
+{
+ if (val < min)
+ return t(min);
+ if (val > max)
+ return t(max);
+ return val;
+}
+
+const unsigned char handle::axis_ids[6] =
+{
+ HID_USAGE_X,
+ HID_USAGE_Y,
+ HID_USAGE_Z,
+ HID_USAGE_RX,
+ HID_USAGE_RY,
+ HID_USAGE_RZ,
+// HID_USAGE_SL0,
+// HID_USAGE_SL1,
+// HID_USAGE_WHL,
+};
+
+constexpr double handle::val_minmax[6];
+
+void handle::init()
+{
+ bool ret = true;
+
+ for (unsigned i = 0; i < axis_count; i++)
+ {
+ ret &= GetVJDAxisExist(OPENTRACK_VJOYSTICK_ID, axis_ids[i]);
+ if (!ret) { qDebug() << "axis" << i << "doesn't exist"; break; }
+ ret &= GetVJDAxisMin(OPENTRACK_VJOYSTICK_ID, axis_ids[i], &axis_min[i]);
+ if (!ret) { qDebug() << "axis" << i << "can't get min value"; break; };
+ ret &= GetVJDAxisMax(OPENTRACK_VJOYSTICK_ID, axis_ids[i], &axis_max[i]);
+ if (!ret) { qDebug() << "axis" << i << "can't get max value"; break; };
+ }
+
+ if (!ret)
+ {
+ (void) RelinquishVJD(OPENTRACK_VJOYSTICK_ID);
+ joy_state = state_fail;
+ }
+ else
+ (void) ResetVJD(OPENTRACK_VJOYSTICK_ID);
+}
+
+handle::handle()
+{
+ const bool ret = AcquireVJD(OPENTRACK_VJOYSTICK_ID);
+ if (!ret)
+ {
+ if (!isVJDExists(OPENTRACK_VJOYSTICK_ID))
+ joy_state = state_notent;
+ else
+ joy_state = state_fail;
+ }
+ else
+ {
+ joy_state = state_success;
+ init();
+ }
+}
+
+handle::~handle()
+{
+ if (joy_state == state_success)
+ {
+ (void) RelinquishVJD(OPENTRACK_VJOYSTICK_ID);
+ joy_state = state_fail;
+ }
+}
+
+LONG handle::to_axis_value(unsigned axis_id, double val)
+{
+ const double minmax = val_minmax[axis_id];
+ const double min = axis_min[axis_id];
+ const double max = axis_max[axis_id];
+
+ return LONG(clamp((val+minmax) * max / (2*minmax) - min, min, max));
+}
+
+vjoystick_proto::vjoystick_proto()
+{
+ if (h.get_state() != state_success)
+ {
+ QMessageBox msgbox;
+ msgbox.setIcon(QMessageBox::Critical);
+ msgbox.setText("vjoystick driver missing");
+ msgbox.setInformativeText("vjoystick won't work without the driver installed.");
+
+ QPushButton* driver_button = msgbox.addButton("Download the driver", QMessageBox::ActionRole);
+ QPushButton* project_site_button = msgbox.addButton("Visit project site", QMessageBox::ActionRole);
+ msgbox.addButton(QMessageBox::Close);
+
+ (void) msgbox.exec();
+
+ if (msgbox.clickedButton() == driver_button)
+ {
+ static const char* download_driver_url = "https://sourceforge.net/projects/vjoystick/files/latest/download";
+ QDesktopServices::openUrl(QUrl(download_driver_url, QUrl::StrictMode));
+ }
+ else if (msgbox.clickedButton() == project_site_button)
+ {
+ static const char* project_site_url = "http://vjoystick.sourceforge.net/site/";
+ QDesktopServices::openUrl(QUrl(project_site_url, QUrl::StrictMode));
+ }
+ }
+}
+
+vjoystick_proto::~vjoystick_proto()
+{
+}
+
+void vjoystick_proto::pose(const double *pose)
+{
+ if (h.get_state() != state_success)
+ return;
+
+ for (unsigned i = 0; i < handle::axis_count; i++)
+ {
+ SetAxis(h.to_axis_value(i, pose[i]), OPENTRACK_VJOYSTICK_ID, handle::axis_ids[i]);
+ }
+}
+
+OPENTRACK_DECLARE_PROTOCOL(vjoystick_proto, vjoystick_dialog, vjoystick_metadata)
diff --git a/proto-vjoystick/vjoystick.h b/proto-vjoystick/vjoystick.h
new file mode 100644
index 00000000..c4cb7e69
--- /dev/null
+++ b/proto-vjoystick/vjoystick.h
@@ -0,0 +1,79 @@
+/* Copyright (c) 2016, 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.
+ */
+#pragma once
+#include "ui_vjoystick.h"
+#include "opentrack/plugin-api.hpp"
+
+#include <windows.h>
+
+enum state : signed char
+{
+ state_notent = -1,
+ state_fail = -2,
+ state_success = 1,
+};
+
+class handle final
+{
+public:
+ static constexpr unsigned axis_count = 6;
+ static const unsigned char axis_ids[axis_count];
+
+private:
+ state joy_state;
+ LONG axis_min[6];
+ LONG axis_max[6];
+
+ static constexpr double val_minmax[6] =
+ {
+ 50,
+ 50,
+ 50,
+ 180,
+ 180,
+ 180
+ };
+
+ void init();
+public:
+ handle();
+ ~handle();
+ state get_state() { return joy_state; }
+ LONG to_axis_value(unsigned axis_id, double val);
+};
+
+class vjoystick_proto : public IProtocol
+{
+ handle h;
+public:
+ vjoystick_proto();
+ ~vjoystick_proto() override;
+ bool correct() override { return h.get_state() == state_success; }
+ void pose( const double *headpose ) override;
+ QString game_name() override { return "Virtual joystick"; }
+private:
+};
+
+class vjoystick_dialog final : public IProtocolDialog
+{
+ Q_OBJECT
+public:
+
+ vjoystick_dialog();
+ void register_protocol(IProtocol *) override {}
+ void unregister_protocol() override {}
+private:
+ Ui::vjoystick ui;
+};
+
+class vjoystick_metadata : public Metadata
+{
+public:
+ QString name() { return QString("Joystick emulation -- vjoystick"); }
+ QIcon icon() { return QIcon(":/images/vjoystick.png"); }
+};
diff --git a/proto-vjoystick/vjoystick.qrc b/proto-vjoystick/vjoystick.qrc
new file mode 100644
index 00000000..9c73169f
--- /dev/null
+++ b/proto-vjoystick/vjoystick.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/vjoystick.png</file>
+ </qresource>
+</RCC>
diff --git a/proto-vjoystick/vjoystick.ui b/proto-vjoystick/vjoystick.ui
new file mode 100644
index 00000000..6e6a2b33
--- /dev/null
+++ b/proto-vjoystick/vjoystick.ui
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>vjoystick</class>
+ <widget class="QWidget" name="vjoystick">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>283</width>
+ <height>66</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>VJoy</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="vjoystick.qrc">
+ <normaloff>:/images/vjoystick.png</normaloff>:/images/vjoystick.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="QLabel" name="label">
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Go to the &lt;a href=&quot;http://vjoystick.sourceforge.net/site/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;vjoystick&lt;/span&gt;&lt;/a&gt; project site or &lt;a href=&quot;https://sourceforge.net/projects/vjoystick/files/latest/download&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;download directly&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="vjoystick.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/proto-vjoystick/vjoystick_dialog.cpp b/proto-vjoystick/vjoystick_dialog.cpp
new file mode 100644
index 00000000..136e898b
--- /dev/null
+++ b/proto-vjoystick/vjoystick_dialog.cpp
@@ -0,0 +1,8 @@
+#include "vjoystick.h"
+#include "opentrack/plugin-api.hpp"
+
+vjoystick_dialog::vjoystick_dialog()
+{
+ ui.setupUi(this);
+ connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &QWidget::close);
+}