Joystick: SDL & Android cleanup
This commit is contained in:
+1
-1
@@ -20,5 +20,5 @@
|
||||
path = libs/qmdnsengine
|
||||
url = https://github.com/nitroshare/qmdnsengine.git
|
||||
[submodule "resources/SDL_GameControllerDB"]
|
||||
path = resources/SDL_GameControllerDB
|
||||
path = libs/SDL_GameControllerDB
|
||||
url = https://github.com/mdqinc/SDL_GameControllerDB.git
|
||||
|
||||
@@ -100,9 +100,6 @@
|
||||
<file alias="radioYawLeft.png">resources/calibration/mode2/radioYawLeft.png</file>
|
||||
<file alias="radioYawRight.png">resources/calibration/mode2/radioYawRight.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/db/mapping/joystick">
|
||||
<file alias="gamecontrollerdb.txt">resources/SDL_GameControllerDB/gamecontrollerdb.txt</file>
|
||||
</qresource>
|
||||
<qresource prefix="/res/audio">
|
||||
<file alias="Alert">resources/audio/alert.wav</file>
|
||||
</qresource>
|
||||
|
||||
@@ -40,7 +40,7 @@ target_sources(Joystick
|
||||
JoystickSDL.h
|
||||
)
|
||||
|
||||
target_compile_definitions(Joystick PRIVATE QGC_SDL_JOYSTICK)
|
||||
target_compile_definitions(Joystick PRIVATE QGC_SDL_JOYSTICK SDL_MAIN_HANDLED)
|
||||
|
||||
FetchContent_Declare(SDL_GameControllerDB
|
||||
GIT_REPOSITORY https://github.com/mdqinc/SDL_GameControllerDB.git
|
||||
@@ -62,14 +62,10 @@ qt_add_resources(Joystick "gamecontrollerdb.txt"
|
||||
qt_add_qml_module(Joystick
|
||||
URI QGroundControl.JoystickManager
|
||||
VERSION 1.0
|
||||
OUTPUT_TARGETS Joystick_targets
|
||||
IMPORT_PATH ${QT_QML_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
cmake_print_variables(Joystick_targets)
|
||||
|
||||
set(MINIMUM_SDL2_VERSION 2.30.0)
|
||||
|
||||
set(MINIMUM_SDL2_VERSION 2.24.0)
|
||||
if(NOT QGC_BUILD_DEPENDENCIES)
|
||||
find_package(SDL2 ${MINIMUM_SDL2_VERSION})
|
||||
if(TARGET SDL2::SDL2)
|
||||
@@ -93,7 +89,7 @@ message(STATUS "Building JoystickSDL")
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(SDL
|
||||
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
|
||||
GIT_TAG release-2.30.7
|
||||
GIT_TAG release-2.30.10
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
// JoystickLog Category declaration moved to QGCLoggingCategory.cc to allow access in Vehicle
|
||||
QGC_LOGGING_CATEGORY(JoystickLog, "Joystick")
|
||||
QGC_LOGGING_CATEGORY(JoystickValuesLog, "JoystickValuesLog")
|
||||
|
||||
int Joystick::_transmitterMode = 2;
|
||||
@@ -41,8 +41,9 @@ AssignableButtonAction::AssignableButtonAction(QObject* parent, QString action_,
|
||||
{
|
||||
}
|
||||
|
||||
Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatCount)
|
||||
: _name (name)
|
||||
Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatCount, QObject *parent)
|
||||
: QThread(parent)
|
||||
, _name (name)
|
||||
, _axisCount (axisCount)
|
||||
, _buttonCount (buttonCount)
|
||||
, _hatCount (hatCount)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtQmlIntegration/QtQmlIntegration>
|
||||
|
||||
// JoystickLog Category declaration moved to QGCLoggingCategory.cc to allow access in Vehicle
|
||||
Q_DECLARE_LOGGING_CATEGORY(JoystickLog)
|
||||
Q_DECLARE_LOGGING_CATEGORY(JoystickValuesLog)
|
||||
Q_DECLARE_METATYPE(GRIPPER_ACTIONS)
|
||||
|
||||
@@ -62,7 +62,7 @@ class Joystick : public QThread
|
||||
Q_MOC_INCLUDE("QmlObjectListModel.h")
|
||||
Q_MOC_INCLUDE("Vehicle.h")
|
||||
public:
|
||||
Joystick(const QString& name, int axisCount, int buttonCount, int hatCount);
|
||||
Joystick(const QString& name, int axisCount, int buttonCount, int hatCount, QObject *parent = nullptr);
|
||||
|
||||
virtual ~Joystick();
|
||||
|
||||
|
||||
+134
-157
@@ -9,49 +9,39 @@
|
||||
|
||||
#include "JoystickAndroid.h"
|
||||
#include "JoystickManager.h"
|
||||
#include "AndroidInterface.h"
|
||||
#include "QGCLoggingCategory.h"
|
||||
|
||||
#include <QtCore/QJniEnvironment>
|
||||
#include <QtCore/QJniObject>
|
||||
|
||||
int JoystickAndroid::_androidBtnListCount;
|
||||
int *JoystickAndroid::_androidBtnList;
|
||||
int JoystickAndroid::ACTION_DOWN;
|
||||
int JoystickAndroid::ACTION_UP;
|
||||
int JoystickAndroid::AXIS_HAT_X;
|
||||
int JoystickAndroid::AXIS_HAT_Y;
|
||||
QMutex JoystickAndroid::m_mutex;
|
||||
QGC_LOGGING_CATEGORY(JoystickAndroidLog, "qgc.joystick.joystickandroid")
|
||||
|
||||
static void clear_jni_exception()
|
||||
{
|
||||
QJniEnvironment jniEnv;
|
||||
if (jniEnv->ExceptionCheck()) {
|
||||
jniEnv->ExceptionDescribe();
|
||||
jniEnv->ExceptionClear();
|
||||
}
|
||||
}
|
||||
QList<int> JoystickAndroid::_androidBtnList(_androidBtnListCount);
|
||||
int JoystickAndroid::ACTION_DOWN = 0;
|
||||
int JoystickAndroid::ACTION_UP = 0;
|
||||
int JoystickAndroid::AXIS_HAT_X = 0;
|
||||
int JoystickAndroid::AXIS_HAT_Y = 0;
|
||||
QMutex JoystickAndroid::_mutex;
|
||||
|
||||
JoystickAndroid::JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id)
|
||||
: Joystick(name,axisCount,buttonCount,0)
|
||||
JoystickAndroid::JoystickAndroid(const QString &name, int axisCount, int buttonCount, int id, QObject *parent)
|
||||
: Joystick(name, axisCount, buttonCount, 0, parent)
|
||||
, deviceId(id)
|
||||
{
|
||||
int i;
|
||||
|
||||
btnCode.resize(_buttonCount);
|
||||
axisCode.resize(_axisCount);
|
||||
btnValue.resize(_buttonCount);
|
||||
axisValue.resize(_axisCount);
|
||||
|
||||
QJniEnvironment env;
|
||||
QJniObject inputDevice = QJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id);
|
||||
|
||||
//set button mapping (number->code)
|
||||
jintArray b = env->NewIntArray(_androidBtnListCount);
|
||||
env->SetIntArrayRegion(b,0,_androidBtnListCount,_androidBtnList);
|
||||
|
||||
QJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", b);
|
||||
jbooleanArray jSupportedButtons = btns.object<jbooleanArray>();
|
||||
jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr);
|
||||
//create a mapping table (btnCode) that maps button number with button code
|
||||
btnValue = new bool[_buttonCount];
|
||||
btnCode = new int[_buttonCount];
|
||||
const jintArray btnArr = env->NewIntArray(_androidBtnListCount);
|
||||
env->SetIntArrayRegion(btnArr, 0, _androidBtnListCount, _androidBtnList.constData());
|
||||
const QJniObject inputDevice = QJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id);
|
||||
const QJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", btnArr);
|
||||
const jbooleanArray jSupportedButtons = btns.object<jbooleanArray>();
|
||||
jboolean *const supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr);
|
||||
int c = 0;
|
||||
for (i = 0; i < _androidBtnListCount; i++) {
|
||||
for (int i = 0; i < _androidBtnListCount; i++) {
|
||||
if (supportedButtons[i]) {
|
||||
btnValue[c] = false;
|
||||
btnCode[c] = _androidBtnList[i];
|
||||
@@ -61,14 +51,10 @@ JoystickAndroid::JoystickAndroid(const QString& name, int axisCount, int buttonC
|
||||
|
||||
env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0);
|
||||
|
||||
// set axis mapping (number->code)
|
||||
axisValue = new int[_axisCount];
|
||||
axisCode = new int[_axisCount];
|
||||
QJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;");
|
||||
for (i = 0; i < _axisCount; i++) {
|
||||
QJniObject range = rangeListNative.callObjectMethod("get", "(I)Ljava/lang/Object;",i);
|
||||
const QJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;");
|
||||
for (int i = 0; i < _axisCount; i++) {
|
||||
const QJniObject range = rangeListNative.callObjectMethod("get", "(I)Ljava/lang/Object;", i);
|
||||
axisCode[i] = range.callMethod<jint>("getAxis");
|
||||
// Don't allow two axis with the same code
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (axisCode[i] == axisCode[j]) {
|
||||
axisCode[i] = -1;
|
||||
@@ -77,48 +63,44 @@ JoystickAndroid::JoystickAndroid(const QString& name, int axisCount, int buttonC
|
||||
}
|
||||
axisValue[i] = 0;
|
||||
}
|
||||
qCDebug(JoystickAndroidLog) << "axis:" << _axisCount << "buttons:" << _buttonCount;
|
||||
|
||||
qCDebug(JoystickLog) << "axis:" <<_axisCount << "buttons:" <<_buttonCount;
|
||||
QtAndroidPrivate::registerGenericMotionEventListener(this);
|
||||
QtAndroidPrivate::registerKeyEventListener(this);
|
||||
}
|
||||
|
||||
JoystickAndroid::~JoystickAndroid() {
|
||||
delete btnCode;
|
||||
delete axisCode;
|
||||
delete btnValue;
|
||||
delete axisValue;
|
||||
|
||||
JoystickAndroid::~JoystickAndroid()
|
||||
{
|
||||
QtAndroidPrivate::unregisterGenericMotionEventListener(this);
|
||||
QtAndroidPrivate::unregisterKeyEventListener(this);
|
||||
}
|
||||
|
||||
|
||||
QMap<QString, Joystick*> JoystickAndroid::discover() {
|
||||
QMap<QString, Joystick*> JoystickAndroid::discover()
|
||||
{
|
||||
static QMap<QString, Joystick*> ret;
|
||||
|
||||
QMutexLocker lock(&m_mutex);
|
||||
QMutexLocker lock(&_mutex);
|
||||
|
||||
const QJniObject object = QJniObject::callStaticObjectMethod<jintArray>("android/view/InputDevice", "getDeviceIds");
|
||||
jintArray jarr = object.object<jintArray>();
|
||||
|
||||
QJniEnvironment env;
|
||||
QJniObject o = QJniObject::callStaticObjectMethod<jintArray>("android/view/InputDevice", "getDeviceIds");
|
||||
jintArray jarr = o.object<jintArray>();
|
||||
int sz = env->GetArrayLength(jarr);
|
||||
jint *buff = env->GetIntArrayElements(jarr, nullptr);
|
||||
const int len = env->GetArrayLength(jarr);
|
||||
jint *const buff = env->GetIntArrayElements(jarr, nullptr);
|
||||
|
||||
int SOURCE_GAMEPAD = QJniObject::getStaticField<jint>("android/view/InputDevice", "SOURCE_GAMEPAD");
|
||||
int SOURCE_JOYSTICK = QJniObject::getStaticField<jint>("android/view/InputDevice", "SOURCE_JOYSTICK");
|
||||
const int SOURCE_GAMEPAD = QJniObject::getStaticField<jint>("android/view/InputDevice", "SOURCE_GAMEPAD");
|
||||
const int SOURCE_JOYSTICK = QJniObject::getStaticField<jint>("android/view/InputDevice", "SOURCE_JOYSTICK");
|
||||
|
||||
QList<QString> names;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
const QJniObject inputDevice = QJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]);
|
||||
const int sources = inputDevice.callMethod<jint>("getSources", "()I");
|
||||
if (((sources & SOURCE_GAMEPAD) != SOURCE_GAMEPAD) && ((sources & SOURCE_JOYSTICK) != SOURCE_JOYSTICK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
QJniObject inputDevice = QJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]);
|
||||
int sources = inputDevice.callMethod<jint>("getSources", "()I");
|
||||
if (((sources & SOURCE_GAMEPAD) != SOURCE_GAMEPAD) //check if the input device is interesting to us
|
||||
&& ((sources & SOURCE_JOYSTICK) != SOURCE_JOYSTICK)) continue;
|
||||
|
||||
// get id and name
|
||||
QString id = inputDevice.callObjectMethod("getDescriptor", "()Ljava/lang/String;").toString();
|
||||
QString name = inputDevice.callObjectMethod("getName", "()Ljava/lang/String;").toString();
|
||||
const QString id = inputDevice.callObjectMethod("getDescriptor", "()Ljava/lang/String;").toString();
|
||||
const QString name = inputDevice.callObjectMethod("getName", "()Ljava/lang/String;").toString();
|
||||
|
||||
names.push_back(name);
|
||||
|
||||
@@ -126,22 +108,23 @@ QMap<QString, Joystick*> JoystickAndroid::discover() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get number of axis
|
||||
QJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;");
|
||||
int axisCount = rangeListNative.callMethod<jint>("size");
|
||||
const QJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;");
|
||||
const int axisCount = rangeListNative.callMethod<jint>("size");
|
||||
|
||||
// get number of buttons
|
||||
jintArray a = env->NewIntArray(_androidBtnListCount);
|
||||
env->SetIntArrayRegion(a,0,_androidBtnListCount,_androidBtnList);
|
||||
QJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a);
|
||||
jbooleanArray jSupportedButtons = btns.object<jbooleanArray>();
|
||||
jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr);
|
||||
jintArray arr = env->NewIntArray(_androidBtnListCount);
|
||||
env->SetIntArrayRegion(arr, 0, _androidBtnListCount, _androidBtnList.constData());
|
||||
const QJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", arr);
|
||||
const jbooleanArray jSupportedButtons = btns.object<jbooleanArray>();
|
||||
jboolean *const supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr);
|
||||
int buttonCount = 0;
|
||||
for (int j=0;j<_androidBtnListCount;j++)
|
||||
if (supportedButtons[j]) buttonCount++;
|
||||
for (int j = 0; j < _androidBtnListCount; j++) {
|
||||
if (supportedButtons[j]) {
|
||||
buttonCount++;
|
||||
}
|
||||
}
|
||||
env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0);
|
||||
|
||||
qCDebug(JoystickLog) << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount;
|
||||
qCDebug(JoystickAndroidLog) << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount;
|
||||
|
||||
ret[name] = new JoystickAndroid(name, axisCount, buttonCount, buff[i]);
|
||||
}
|
||||
@@ -159,104 +142,98 @@ QMap<QString, Joystick*> JoystickAndroid::discover() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool JoystickAndroid::handleKeyEvent(jobject event)
|
||||
{
|
||||
QMutexLocker lock(&_mutex);
|
||||
|
||||
bool JoystickAndroid::handleKeyEvent(jobject event) {
|
||||
QJniObject ev(event);
|
||||
QMutexLocker lock(&m_mutex);
|
||||
const int _deviceId = ev.callMethod<jint>("getDeviceId", "()I");
|
||||
if (_deviceId!=deviceId) return false;
|
||||
|
||||
if (_deviceId != deviceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int action = ev.callMethod<jint>("getAction", "()I");
|
||||
const int keyCode = ev.callMethod<jint>("getKeyCode", "()I");
|
||||
|
||||
for (int i = 0; i <_buttonCount; i++) {
|
||||
if (btnCode[i] == keyCode) {
|
||||
if (action == ACTION_DOWN) btnValue[i] = true;
|
||||
if (action == ACTION_UP) btnValue[i] = false;
|
||||
return true;
|
||||
for (int i = 0; i < _buttonCount; i++) {
|
||||
if (btnCode[i] != keyCode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (action == ACTION_DOWN) {
|
||||
btnValue[i] = true;
|
||||
} else if (action == ACTION_UP) {
|
||||
btnValue[i] = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JoystickAndroid::handleGenericMotionEvent(jobject event) {
|
||||
QJniObject ev(event);
|
||||
QMutexLocker lock(&m_mutex);
|
||||
const int _deviceId = ev.callMethod<jint>("getDeviceId", "()I");
|
||||
if (_deviceId!=deviceId) return false;
|
||||
|
||||
for (int i = 0; i <_axisCount; i++) {
|
||||
const float v = ev.callMethod<jfloat>("getAxisValue", "(I)F",axisCode[i]);
|
||||
axisValue[i] = static_cast<int>((v*32767.f));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JoystickAndroid::_open(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoystickAndroid::_close(void) {
|
||||
}
|
||||
|
||||
bool JoystickAndroid::_update(void)
|
||||
bool JoystickAndroid::handleGenericMotionEvent(jobject event)
|
||||
{
|
||||
QMutexLocker lock(&_mutex);
|
||||
|
||||
QJniObject ev(event);
|
||||
const int _deviceId = ev.callMethod<jint>("getDeviceId", "()I");
|
||||
if (_deviceId != deviceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _axisCount; i++) {
|
||||
const float v = ev.callMethod<jfloat>("getAxisValue", "(I)F", axisCode[i]);
|
||||
axisValue[i] = static_cast<int>(v * 32767.f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JoystickAndroid::_getButton(int i) {
|
||||
return btnValue[ i ];
|
||||
}
|
||||
|
||||
int JoystickAndroid::_getAxis(int i) {
|
||||
return axisValue[ i ];
|
||||
}
|
||||
|
||||
int JoystickAndroid::_getAndroidHatAxis(int axisHatCode) {
|
||||
for(int i = 0; i < _axisCount; i++) {
|
||||
int JoystickAndroid::_getAndroidHatAxis(int axisHatCode)
|
||||
{
|
||||
for (int i = 0; i < _axisCount; i++) {
|
||||
if (axisCode[i] == axisHatCode) {
|
||||
return _getAxis(i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool JoystickAndroid::_getHat(int hat,int i) {
|
||||
bool JoystickAndroid::_getHat(int hat, int i)
|
||||
{
|
||||
// Android supports only one hat button
|
||||
if (hat != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
return _getAndroidHatAxis(AXIS_HAT_Y) < 0;
|
||||
case 1:
|
||||
return _getAndroidHatAxis(AXIS_HAT_Y) > 0;
|
||||
case 2:
|
||||
return _getAndroidHatAxis(AXIS_HAT_X) < 0;
|
||||
case 3:
|
||||
return _getAndroidHatAxis(AXIS_HAT_X) > 0;
|
||||
default:
|
||||
return false;
|
||||
case 0:
|
||||
return (_getAndroidHatAxis(AXIS_HAT_Y) < 0);
|
||||
case 1:
|
||||
return (_getAndroidHatAxis(AXIS_HAT_Y) > 0);
|
||||
case 2:
|
||||
return (_getAndroidHatAxis(AXIS_HAT_X) < 0);
|
||||
case 3:
|
||||
return (_getAndroidHatAxis(AXIS_HAT_X) > 0);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//helper method
|
||||
bool JoystickAndroid::init() {
|
||||
//this gets list of all possible buttons - this is needed to check how many buttons our gamepad supports
|
||||
//instead of the whole logic below we could have just a simple array of hardcoded int values as these 'should' not change
|
||||
bool JoystickAndroid::init()
|
||||
{
|
||||
static QList<int> ret(_androidBtnListCount);
|
||||
|
||||
//int JoystickAndroid::_androidBtnListCount;
|
||||
_androidBtnListCount = 31;
|
||||
static int ret[31]; //there are 31 buttons in total accordingy to the API
|
||||
int i;
|
||||
//int *JoystickAndroid::
|
||||
_androidBtnList = ret;
|
||||
|
||||
clear_jni_exception();
|
||||
(void) AndroidInterface::cleanJavaException();
|
||||
|
||||
int i;
|
||||
for (i = 1; i <= 16; i++) {
|
||||
QString name = "KEYCODE_BUTTON_"+QString::number(i);
|
||||
ret[i-1] = QJniObject::getStaticField<jint>("android/view/KeyEvent", name.toStdString().c_str());
|
||||
const QString name = QStringLiteral("KEYCODE_BUTTON_") + QString::number(i);
|
||||
ret[i - 1] = QJniObject::getStaticField<jint>("android/view/KeyEvent", name.toStdString().c_str());
|
||||
}
|
||||
i--;
|
||||
|
||||
@@ -284,41 +261,41 @@ bool JoystickAndroid::init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char kJniClassName[] {"org/mavlink/qgroundcontrol/QGCUsbSerialManager"};
|
||||
|
||||
static void jniUpdateAvailableJoysticks(JNIEnv *envA, jobject thizA)
|
||||
{
|
||||
Q_UNUSED(envA);
|
||||
Q_UNUSED(thizA);
|
||||
Q_UNUSED(envA); Q_UNUSED(thizA);
|
||||
|
||||
qCDebug(JoystickAndroidLog) << "jniUpdateAvailableJoysticks triggered";
|
||||
|
||||
qCDebug(JoystickLog) << "jniUpdateAvailableJoysticks triggered";
|
||||
emit JoystickManager::instance()->updateAvailableJoysticksSignal();
|
||||
}
|
||||
|
||||
void JoystickAndroid::setNativeMethods()
|
||||
{
|
||||
qCDebug(JoystickLog) << "Registering Native Functions";
|
||||
qCDebug(JoystickAndroidLog) << "Registering Native Functions";
|
||||
|
||||
// REGISTER THE C++ FUNCTION WITH JNI
|
||||
JNINativeMethod javaMethods[] {
|
||||
{"nativeUpdateAvailableJoysticks", "()V", reinterpret_cast<void *>(jniUpdateAvailableJoysticks)}
|
||||
static const JNINativeMethod javaMethods[] {
|
||||
{"nativeUpdateAvailableJoysticks", "()V", reinterpret_cast<void*>(jniUpdateAvailableJoysticks)}
|
||||
};
|
||||
|
||||
clear_jni_exception();
|
||||
static constexpr const char *kJniClassName = "org/mavlink/qgroundcontrol/QGCUsbSerialManager";
|
||||
|
||||
(void) AndroidInterface::cleanJavaException();
|
||||
|
||||
QJniEnvironment jniEnv;
|
||||
jclass objectClass = jniEnv->FindClass(kJniClassName);
|
||||
if(!objectClass) {
|
||||
clear_jni_exception();
|
||||
qWarning() << "Couldn't find class:" << kJniClassName;
|
||||
if (!objectClass) {
|
||||
(void) AndroidInterface::cleanJavaException();
|
||||
qCWarning(JoystickAndroidLog) << "Couldn't find class:" << kJniClassName;
|
||||
return;
|
||||
}
|
||||
|
||||
jint val = jniEnv->RegisterNatives(objectClass, javaMethods, sizeof(javaMethods) / sizeof(javaMethods[0]));
|
||||
|
||||
const jint val = jniEnv->RegisterNatives(objectClass, javaMethods, std::size(javaMethods));
|
||||
if (val < 0) {
|
||||
qWarning() << "Error registering methods: " << val;
|
||||
qCWarning(JoystickAndroidLog) << "Error registering methods:" << val;
|
||||
} else {
|
||||
qCDebug(JoystickLog) << "Native Functions Registered";
|
||||
qCDebug(JoystickAndroidLog) << "Native Functions Registered";
|
||||
}
|
||||
clear_jni_exception();
|
||||
|
||||
(void) AndroidInterface::cleanJavaException();
|
||||
}
|
||||
|
||||
@@ -9,44 +9,47 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Joystick.h"
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/private/qandroidextras_p.h>
|
||||
|
||||
#include "Joystick.h"
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(JoystickAndroidLog)
|
||||
|
||||
class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener
|
||||
{
|
||||
public:
|
||||
JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id);
|
||||
JoystickAndroid(const QString &name, int axisCount, int buttonCount, int id, QObject *parent = nullptr);
|
||||
~JoystickAndroid();
|
||||
|
||||
static bool init();
|
||||
|
||||
static void setNativeMethods();
|
||||
|
||||
static QMap<QString, Joystick*> discover();
|
||||
|
||||
private:
|
||||
bool _open() final { return true; }
|
||||
void _close() final {}
|
||||
bool _update() final { return true; }
|
||||
|
||||
bool _getButton(int i) final { return btnValue[i]; }
|
||||
int _getAxis(int i) final { return axisValue[i]; }
|
||||
bool _getHat(int hat, int i) final;
|
||||
|
||||
int _getAndroidHatAxis(int axisHatCode);
|
||||
|
||||
bool handleKeyEvent(jobject event);
|
||||
bool handleGenericMotionEvent(jobject event);
|
||||
int _getAndroidHatAxis(int axisHatCode);
|
||||
|
||||
virtual bool _open ();
|
||||
virtual void _close ();
|
||||
virtual bool _update ();
|
||||
int deviceId = 0;
|
||||
|
||||
virtual bool _getButton (int i);
|
||||
virtual int _getAxis (int i);
|
||||
virtual bool _getHat (int hat,int i);
|
||||
QList<int> btnCode;
|
||||
QList<int> axisCode;
|
||||
QList<bool> btnValue;
|
||||
QList<int> axisValue;
|
||||
|
||||
int *btnCode;
|
||||
int *axisCode;
|
||||
bool *btnValue;
|
||||
int *axisValue;
|
||||
|
||||
static int * _androidBtnList; //list of all possible android buttons
|
||||
static int _androidBtnListCount;
|
||||
static constexpr int _androidBtnListCount = 31;
|
||||
static QList<int> _androidBtnList;
|
||||
|
||||
static int ACTION_DOWN, ACTION_UP, AXIS_HAT_X, AXIS_HAT_Y;
|
||||
static QMutex m_mutex;
|
||||
|
||||
int deviceId;
|
||||
static QMutex _mutex;
|
||||
};
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
#include "Joystick.h"
|
||||
#if defined(QGC_SDL_JOYSTICK)
|
||||
#include "JoystickSDL.h"
|
||||
#include <SDL.h>
|
||||
#elif defined(Q_OS_ANDROID)
|
||||
#include "JoystickAndroid.h"
|
||||
#endif
|
||||
#include "MultiVehicleManager.h"
|
||||
#include "QGCLoggingCategory.h"
|
||||
|
||||
#include <QtCore/qapplicationstatic.h>
|
||||
@@ -33,7 +33,7 @@ JoystickManager::JoystickManager(QObject *parent)
|
||||
{
|
||||
// qCDebug(JoystickManagerLog) << Q_FUNC_INFO << this;
|
||||
|
||||
_joystickCheckTimer->setInterval(1000);
|
||||
_joystickCheckTimer->setInterval(kTimerInterval);
|
||||
_joystickCheckTimer->setSingleShot(false);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ void JoystickManager::init()
|
||||
_joystickCheckTimer->start();
|
||||
});
|
||||
#endif
|
||||
|
||||
(void) connect(_joystickCheckTimer, &QTimer::timeout, this, &JoystickManager::_updateAvailableJoysticks);
|
||||
_joystickCheckTimerCounter = 5;
|
||||
_joystickCheckTimer->start();
|
||||
@@ -76,7 +77,7 @@ void JoystickManager::init()
|
||||
|
||||
void JoystickManager::_setActiveJoystickFromSettings()
|
||||
{
|
||||
QMap<QString,Joystick*> newMap;
|
||||
QMap<QString, Joystick*> newMap;
|
||||
|
||||
#ifdef QGC_SDL_JOYSTICK
|
||||
newMap = JoystickSDL::discover();
|
||||
@@ -95,7 +96,7 @@ void JoystickManager::_setActiveJoystickFromSettings()
|
||||
if (!newMap.contains(it->first)) {
|
||||
qCDebug(JoystickManagerLog) << "Releasing joystick:" << it->first;
|
||||
it->second->stopPolling();
|
||||
it->second->wait(1000);
|
||||
(void) it->second->wait(kTimeout);
|
||||
it->second->deleteLater();
|
||||
}
|
||||
}
|
||||
@@ -144,7 +145,7 @@ void JoystickManager::setActiveJoystick(Joystick *joystick)
|
||||
|
||||
_activeJoystick = joystick;
|
||||
|
||||
if (_activeJoystick != nullptr) {
|
||||
if (_activeJoystick) {
|
||||
qCDebug(JoystickManagerLog) << "Set active:" << _activeJoystick->name();
|
||||
|
||||
QSettings settings;
|
||||
@@ -192,10 +193,12 @@ void JoystickManager::_updateAvailableJoysticks()
|
||||
case SDL_QUIT:
|
||||
qCDebug(JoystickManagerLog) << "SDL ERROR:" << SDL_GetError();
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_JOYDEVICEADDED:
|
||||
qCDebug(JoystickManagerLog) << "Joystick added:" << event.jdevice.which;
|
||||
_setActiveJoystickFromSettings();
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
case SDL_JOYDEVICEREMOVED:
|
||||
qCDebug(JoystickManagerLog) << "Joystick removed:" << event.jdevice.which;
|
||||
_setActiveJoystickFromSettings();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
Q_DECLARE_LOGGING_CATEGORY(JoystickManagerLog)
|
||||
|
||||
class Joystick;
|
||||
class MultiVehicleManager;
|
||||
class QTimer;
|
||||
|
||||
class JoystickManager : public QObject
|
||||
@@ -68,6 +67,8 @@ private:
|
||||
int _joystickCheckTimerCounter = 0;;
|
||||
QTimer *_joystickCheckTimer = nullptr;
|
||||
|
||||
static constexpr int kTimerInterval = 1000;
|
||||
static constexpr int kTimeout = 1000;
|
||||
static constexpr const char *_settingsGroup = "JoystickManager";
|
||||
static constexpr const char *_settingsKeyActiveJoystick = "ActiveJoystick";
|
||||
};
|
||||
|
||||
+123
-99
@@ -8,184 +8,208 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "JoystickSDL.h"
|
||||
#include "MultiVehicleManager.h"
|
||||
#include "QGCLoggingCategory.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QIODevice>
|
||||
#include <QtCore/QTextStream>
|
||||
|
||||
JoystickSDL::JoystickSDL(const QString& name, int axisCount, int buttonCount, int hatCount, int index, bool isGameController)
|
||||
: Joystick(name,axisCount,buttonCount,hatCount)
|
||||
#include <SDL.h>
|
||||
|
||||
QGC_LOGGING_CATEGORY(JoystickSDLLog, "qgc.joystick.joysticksdl")
|
||||
|
||||
JoystickSDL::JoystickSDL(const QString &name, int axisCount, int buttonCount, int hatCount, int index, bool isGameController, QObject *parent)
|
||||
: Joystick(name, axisCount, buttonCount, hatCount, parent)
|
||||
, _isGameController(isGameController)
|
||||
, _index(index)
|
||||
{
|
||||
// qCDebug(JoystickLog) << Q_FUNC_INFO << this;
|
||||
// qCDebug(JoystickSDLLog) << Q_FUNC_INFO << this;
|
||||
|
||||
if(_isGameController) _setDefaultCalibration();
|
||||
if (_isGameController) {
|
||||
_setDefaultCalibration();
|
||||
}
|
||||
}
|
||||
|
||||
JoystickSDL::~JoystickSDL()
|
||||
{
|
||||
// qCDebug(JoystickLog) << Q_FUNC_INFO << this;
|
||||
// qCDebug(JoystickSDLLog) << Q_FUNC_INFO << this;
|
||||
}
|
||||
|
||||
bool JoystickSDL::init(void) {
|
||||
bool JoystickSDL::init()
|
||||
{
|
||||
SDL_SetMainReady();
|
||||
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK) < 0) {
|
||||
SDL_JoystickEventState(SDL_DISABLE);
|
||||
qCWarning(JoystickLog) << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError();
|
||||
(void) SDL_JoystickEventState(SDL_DISABLE);
|
||||
qCWarning(JoystickSDLLog) << "Failed to initialize SDL:" << SDL_GetError();
|
||||
return false;
|
||||
}
|
||||
|
||||
_loadGameControllerMappings();
|
||||
return true;
|
||||
}
|
||||
|
||||
QMap<QString, Joystick*> JoystickSDL::discover() {
|
||||
QMap<QString, Joystick*> JoystickSDL::discover()
|
||||
{
|
||||
static QMap<QString, Joystick*> ret;
|
||||
|
||||
QMap<QString,Joystick*> newRet;
|
||||
QMap<QString, Joystick*> newRet;
|
||||
|
||||
// Load available joysticks
|
||||
qCDebug(JoystickSDLLog) << "Discovering joysticks";
|
||||
|
||||
qCDebug(JoystickLog) << "Available joysticks";
|
||||
|
||||
for (int i=0; i<SDL_NumJoysticks(); i++) {
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
||||
QString name = SDL_JoystickNameForIndex(i);
|
||||
|
||||
if (!ret.contains(name)) {
|
||||
int axisCount, buttonCount, hatCount;
|
||||
bool isGameController = SDL_IsGameController(i);
|
||||
|
||||
if (SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i)) {
|
||||
SDL_ClearError();
|
||||
axisCount = SDL_JoystickNumAxes(sdlJoystick);
|
||||
buttonCount = SDL_JoystickNumButtons(sdlJoystick);
|
||||
hatCount = SDL_JoystickNumHats(sdlJoystick);
|
||||
if (axisCount < 0 || buttonCount < 0 || hatCount < 0) {
|
||||
qCWarning(JoystickLog) << "\t libsdl error parsing joystick features:" << SDL_GetError();
|
||||
}
|
||||
SDL_JoystickClose(sdlJoystick);
|
||||
} else {
|
||||
qCWarning(JoystickLog) << "\t libsdl failed opening joystick" << qPrintable(name) << "error:" << SDL_GetError();
|
||||
continue;
|
||||
}
|
||||
|
||||
qCDebug(JoystickLog) << "\t" << name << "axes:" << axisCount << "buttons:" << buttonCount << "hats:" << hatCount << "isGC:" << isGameController;
|
||||
|
||||
// Check for joysticks with duplicate names and differentiate the keys when necessary.
|
||||
// This is required when using an Xbox 360 wireless receiver that always identifies as
|
||||
// 4 individual joysticks, regardless of how many joysticks are actually connected to the
|
||||
// receiver. Using GUID does not help, all of these devices present the same GUID.
|
||||
QString originalName = name;
|
||||
uint8_t duplicateIdx = 1;
|
||||
while (newRet[name]) {
|
||||
name = QString("%1 %2").arg(originalName).arg(duplicateIdx++);
|
||||
}
|
||||
|
||||
newRet[name] = new JoystickSDL(name, qMax(0,axisCount), qMax(0,buttonCount), qMax(0,hatCount), i, isGameController);
|
||||
} else {
|
||||
if (ret.contains(name)) {
|
||||
newRet[name] = ret[name];
|
||||
JoystickSDL *j = static_cast<JoystickSDL*>(newRet[name]);
|
||||
if (j->index() != i) {
|
||||
j->setIndex(i); // This joystick index has been remapped by SDL
|
||||
JoystickSDL *const joystick = static_cast<JoystickSDL*>(newRet[name]);
|
||||
if (joystick->index() != i) {
|
||||
joystick->setIndex(i); // This joystick index has been remapped by SDL
|
||||
}
|
||||
|
||||
// Anything left in ret after we exit the loop has been removed (unplugged) and needs to be cleaned up.
|
||||
// We will handle that in JoystickManager in case the removed joystick was in use.
|
||||
ret.remove(name);
|
||||
qCDebug(JoystickLog) << "\tSkipping duplicate" << name;
|
||||
(void) ret.remove(name);
|
||||
|
||||
qCDebug(JoystickSDLLog) << "Skipping duplicate" << name;
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_Joystick *const sdlJoystick = SDL_JoystickOpen(i);
|
||||
if (!sdlJoystick) {
|
||||
qCWarning(JoystickSDLLog) << "SDL failed opening joystick" << qPrintable(name) << "error:" << SDL_GetError();
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_ClearError();
|
||||
const int axisCount = SDL_JoystickNumAxes(sdlJoystick);
|
||||
const int buttonCount = SDL_JoystickNumButtons(sdlJoystick);
|
||||
const int hatCount = SDL_JoystickNumHats(sdlJoystick);
|
||||
if ((axisCount < 0) || (buttonCount < 0) || (hatCount < 0)) {
|
||||
qCWarning(JoystickSDLLog) << "SDL error parsing joystick features:" << SDL_GetError();
|
||||
}
|
||||
SDL_JoystickClose(sdlJoystick);
|
||||
|
||||
const bool isGameController = SDL_IsGameController(i);
|
||||
qCDebug(JoystickSDLLog) << name << "axes:" << axisCount << "buttons:" << buttonCount << "hats:" << hatCount << "isGC:" << isGameController;
|
||||
|
||||
// Check for joysticks with duplicate names and differentiate the keys when necessary.
|
||||
// This is required when using an Xbox 360 wireless receiver that always identifies as
|
||||
// 4 individual joysticks, regardless of how many joysticks are actually connected to the
|
||||
// receiver. Using GUID does not help, all of these devices present the same GUID.
|
||||
const QString originalName = name;
|
||||
uint8_t duplicateIdx = 1;
|
||||
while (newRet[name]) {
|
||||
name = QString("%1 %2").arg(originalName).arg(duplicateIdx++);
|
||||
}
|
||||
|
||||
newRet[name] = new JoystickSDL(name, qMax(0, axisCount), qMax(0, buttonCount), qMax(0, hatCount), i, isGameController);
|
||||
}
|
||||
|
||||
if (!newRet.count()) {
|
||||
qCDebug(JoystickLog) << "\tnone found";
|
||||
if (newRet.isEmpty()) {
|
||||
qCDebug(JoystickSDLLog) << "None found";
|
||||
}
|
||||
|
||||
ret = newRet;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JoystickSDL::_loadGameControllerMappings(void) {
|
||||
QFile file(":/db/mapping/joystick/gamecontrollerdb.txt");
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
qWarning() << "Couldn't load GameController mapping database.";
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream s(&file);
|
||||
|
||||
while (!s.atEnd()) {
|
||||
SDL_GameControllerAddMapping(s.readLine().toStdString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool JoystickSDL::_open(void) {
|
||||
if ( _isGameController ) {
|
||||
sdlController = SDL_GameControllerOpen(_index);
|
||||
sdlJoystick = SDL_GameControllerGetJoystick(sdlController);
|
||||
bool JoystickSDL::_open()
|
||||
{
|
||||
if (_isGameController) {
|
||||
_sdlController = SDL_GameControllerOpen(_index);
|
||||
_sdlJoystick = SDL_GameControllerGetJoystick(_sdlController);
|
||||
} else {
|
||||
sdlJoystick = SDL_JoystickOpen(_index);
|
||||
_sdlJoystick = SDL_JoystickOpen(_index);
|
||||
}
|
||||
|
||||
if (!sdlJoystick) {
|
||||
qCWarning(JoystickLog) << "SDL_JoystickOpen failed:" << SDL_GetError();
|
||||
if (!_sdlJoystick) {
|
||||
qCWarning(JoystickSDLLog) << "SDL_JoystickOpen failed:" << SDL_GetError();
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(JoystickLog) << "Opened joystick at" << sdlJoystick;
|
||||
qCDebug(JoystickSDLLog) << "Opened" << SDL_JoystickName(_sdlJoystick) << "joystick at" << _sdlJoystick;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoystickSDL::_close(void) {
|
||||
if (sdlJoystick == nullptr) {
|
||||
qCDebug(JoystickLog) << "Attempt to close null joystick!";
|
||||
void JoystickSDL::_close()
|
||||
{
|
||||
if (!_sdlJoystick) {
|
||||
qCWarning(JoystickSDLLog) << "Attempt to close null joystick!";
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(JoystickLog) << "Closing" << SDL_JoystickName(sdlJoystick) << "at" << sdlJoystick;
|
||||
qCDebug(JoystickSDLLog) << "Closing" << SDL_JoystickName(_sdlJoystick) << "joystick at" << _sdlJoystick;
|
||||
|
||||
if (_isGameController) {
|
||||
SDL_GameControllerClose(sdlController);
|
||||
SDL_GameControllerClose(_sdlController);
|
||||
} else {
|
||||
SDL_JoystickClose(sdlJoystick);
|
||||
SDL_JoystickClose(_sdlJoystick);
|
||||
}
|
||||
|
||||
sdlJoystick = nullptr;
|
||||
sdlController = nullptr;
|
||||
_sdlJoystick = nullptr;
|
||||
_sdlController = nullptr;
|
||||
}
|
||||
|
||||
bool JoystickSDL::_update(void)
|
||||
bool JoystickSDL::_update()
|
||||
{
|
||||
if (_isGameController) {
|
||||
SDL_GameControllerUpdate();
|
||||
} else {
|
||||
SDL_JoystickUpdate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JoystickSDL::_getButton(int i) {
|
||||
bool JoystickSDL::_getButton(int i)
|
||||
{
|
||||
int button = -1;
|
||||
|
||||
if (_isGameController) {
|
||||
return SDL_GameControllerGetButton(sdlController, SDL_GameControllerButton(i)) == 1;
|
||||
button = SDL_GameControllerGetButton(_sdlController, SDL_GameControllerButton(i));
|
||||
} else {
|
||||
return SDL_JoystickGetButton(sdlJoystick, i) == 1;
|
||||
button = SDL_JoystickGetButton(_sdlJoystick, i);
|
||||
}
|
||||
|
||||
return (button == 1);
|
||||
}
|
||||
|
||||
int JoystickSDL::_getAxis(int i) {
|
||||
int JoystickSDL::_getAxis(int i)
|
||||
{
|
||||
int axis = -1;
|
||||
|
||||
if (_isGameController) {
|
||||
return SDL_GameControllerGetAxis(sdlController, SDL_GameControllerAxis(i));
|
||||
axis = SDL_GameControllerGetAxis(_sdlController, SDL_GameControllerAxis(i));
|
||||
} else {
|
||||
return SDL_JoystickGetAxis(sdlJoystick, i);
|
||||
axis = SDL_JoystickGetAxis(_sdlJoystick, i);
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
bool JoystickSDL::_getHat(int hat, int i) {
|
||||
uint8_t hatButtons[] = {SDL_HAT_UP,SDL_HAT_DOWN,SDL_HAT_LEFT,SDL_HAT_RIGHT};
|
||||
if (i < int(sizeof(hatButtons))) {
|
||||
return (SDL_JoystickGetHat(sdlJoystick, hat) & hatButtons[i]) != 0;
|
||||
bool JoystickSDL::_getHat(int hat, int i)
|
||||
{
|
||||
static constexpr uint8_t hatButtons[] = {SDL_HAT_UP, SDL_HAT_DOWN, SDL_HAT_LEFT, SDL_HAT_RIGHT};
|
||||
|
||||
if (i >= std::size(hatButtons)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SDL_JoystickGetHat(_sdlJoystick, hat) & hatButtons[i]) != 0);
|
||||
}
|
||||
|
||||
void JoystickSDL::_loadGameControllerMappings()
|
||||
{
|
||||
QFile file(QStringLiteral(":/db/mapping/joystick/gamecontrollerdb.txt"));
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qCWarning(JoystickSDLLog) << "Couldn't load GameController mapping database.";
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
while (!stream.atEnd()) {
|
||||
if (SDL_GameControllerAddMapping(stream.readLine().toStdString().c_str()) == -1) {
|
||||
qCWarning(JoystickSDLLog) << "Couldn't add GameController mapping:" << SDL_GetError();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+25
-27
@@ -7,50 +7,48 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/// @file
|
||||
/// @brief SDL Joystick Interface
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
#include "Joystick.h"
|
||||
|
||||
#define SDL_MAIN_HANDLED
|
||||
struct _SDL_Joystick;
|
||||
typedef struct _SDL_Joystick SDL_Joystick;
|
||||
|
||||
#include <SDL.h>
|
||||
struct _SDL_GameController;
|
||||
typedef struct _SDL_GameController SDL_GameController;
|
||||
|
||||
class MultiVehicleManager;
|
||||
Q_DECLARE_LOGGING_CATEGORY(JoystickSDLLog)
|
||||
|
||||
/// @brief SDL Joystick Interface
|
||||
class JoystickSDL : public Joystick
|
||||
{
|
||||
public:
|
||||
JoystickSDL(const QString& name, int axisCount, int buttonCount, int hatCount, int index, bool isGameController);
|
||||
JoystickSDL(const QString &name, int axisCount, int buttonCount, int hatCount, int index, bool isGameController, QObject *parent = nullptr);
|
||||
~JoystickSDL();
|
||||
|
||||
static QMap<QString, Joystick*> discover();
|
||||
static bool init(void);
|
||||
|
||||
int index(void) const { return _index; }
|
||||
int index() const { return _index; }
|
||||
void setIndex(int index) { _index = index; }
|
||||
|
||||
// This can be uncommented to hide the calibration buttons for gamecontrollers in the future
|
||||
// bool requiresCalibration(void) final { return !_isGameController; }
|
||||
// bool requiresCalibration() final { return !_isGameController; }
|
||||
|
||||
static bool init();
|
||||
static QMap<QString, Joystick*> discover();
|
||||
|
||||
private:
|
||||
bool _open() final;
|
||||
void _close() final;
|
||||
bool _update() final;
|
||||
|
||||
bool _getButton(int i) final;
|
||||
int _getAxis(int i) final;
|
||||
bool _getHat(int hat, int i) final;
|
||||
|
||||
static void _loadGameControllerMappings();
|
||||
|
||||
bool _open () final;
|
||||
void _close () final;
|
||||
bool _update () final;
|
||||
|
||||
bool _getButton (int i) final;
|
||||
int _getAxis (int i) final;
|
||||
bool _getHat (int hat,int i) final;
|
||||
|
||||
SDL_Joystick* sdlJoystick;
|
||||
SDL_GameController* sdlController;
|
||||
|
||||
bool _isGameController;
|
||||
int _index; ///< Index for SDL_JoystickOpen
|
||||
bool _isGameController = false;
|
||||
int _index = -1;
|
||||
|
||||
SDL_Joystick *_sdlJoystick = nullptr;
|
||||
SDL_GameController *_sdlController = nullptr;
|
||||
};
|
||||
|
||||
@@ -26,8 +26,6 @@ QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog")
|
||||
QGC_LOGGING_CATEGORY(GuidedActionsControllerLog, "GuidedActionsControllerLog")
|
||||
QGC_LOGGING_CATEGORY(LocalizationLog, "LocalizationLog")
|
||||
QGC_LOGGING_CATEGORY(VideoAllLog, kVideoAllLogCategory)
|
||||
QGC_LOGGING_CATEGORY(JoystickLog, "JoystickLog")
|
||||
|
||||
|
||||
QGCLoggingCategoryRegister* _instance = nullptr;
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ Q_DECLARE_LOGGING_CATEGORY(ParameterManagerLog)
|
||||
Q_DECLARE_LOGGING_CATEGORY(GuidedActionsControllerLog)
|
||||
Q_DECLARE_LOGGING_CATEGORY(LocalizationLog)
|
||||
Q_DECLARE_LOGGING_CATEGORY(VideoAllLog) // turns on all individual QGC video logs
|
||||
Q_DECLARE_LOGGING_CATEGORY(JoystickLog)
|
||||
|
||||
/// @def QGC_LOGGING_CATEGORY
|
||||
/// This is a QGC specific replacement for Q_LOGGING_CATEGORY. It will register the category name into a
|
||||
|
||||
Reference in New Issue
Block a user