From c97b69b5f3dfc01ea45878022ec6ba110436ee55 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Thu, 21 Apr 2016 14:54:00 +0100 Subject: [PATCH 01/21] Activating Joystick module for all builds --- qgroundcontrol.pro | 4 ++-- src/Joystick/Joystick.cc | 19 +++++-------------- src/Joystick/Joystick.h | 2 -- src/Joystick/JoystickManager.cc | 13 ++----------- src/QGCApplication.cc | 5 ++--- src/Vehicle/Vehicle.cc | 4 ---- 6 files changed, 11 insertions(+), 36 deletions(-) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 895ca89..8dbedee 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -265,6 +265,7 @@ HEADERS += \ src/HomePositionManager.h \ src/Joystick/Joystick.h \ src/Joystick/JoystickManager.h \ + src/VehicleSetup/JoystickConfigController.h \ src/FollowMe/FollowMe.h \ src/JsonHelper.h \ src/LogCompressor.h \ @@ -387,7 +388,6 @@ HEADERS += \ src/GPS/GPSManager.h \ src/GPS/GPSPositionMessage.h \ src/GPS/GPSProvider.h \ - src/VehicleSetup/JoystickConfigController.h \ src/ViewWidgets/CustomCommandWidget.h \ src/ViewWidgets/CustomCommandWidgetController.h \ src/ViewWidgets/LogDownload.h \ @@ -420,6 +420,7 @@ SOURCES += \ src/HomePositionManager.cc \ src/Joystick/Joystick.cc \ src/Joystick/JoystickManager.cc \ + src/VehicleSetup/JoystickConfigController.cc \ src/JsonHelper.cc \ src/FollowMe/FollowMe.cc \ src/LogCompressor.cc \ @@ -526,7 +527,6 @@ SOURCES += \ src/GPS/RTCM/RTCMMavlink.cc \ src/GPS/GPSManager.cc \ src/GPS/GPSProvider.cc \ - src/VehicleSetup/JoystickConfigController.cc \ src/ViewWidgets/CustomCommandWidget.cc \ src/ViewWidgets/CustomCommandWidgetController.cc \ src/ViewWidgets/LogDownload.cc \ diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index 37d6140..f499e83 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -29,6 +29,7 @@ #include #ifndef __mobile__ + #define __sdljoystick__ #ifdef Q_OS_MAC #include #else @@ -52,7 +53,6 @@ const char* Joystick::_rgFunctionSettingsKey[Joystick::maxFunction] = { }; Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlIndex, MultiVehicleManager* multiVehicleManager) -#ifndef __mobile__ : _sdlIndex(sdlIndex) , _exitThread(false) , _name(name) @@ -68,15 +68,8 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlI , _activeVehicle(NULL) , _pollingStartedForCalibration(false) , _multiVehicleManager(multiVehicleManager) -#endif // __mobile__ { -#ifdef __mobile__ - Q_UNUSED(name) - Q_UNUSED(axisCount) - Q_UNUSED(buttonCount) - Q_UNUSED(sdlIndex) - Q_UNUSED(multiVehicleManager) -#else + _rgAxisValues = new int[_axisCount]; _rgCalibration = new Calibration_t[_axisCount]; _rgButtonValues = new bool[_buttonCount]; @@ -90,20 +83,17 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlI } _loadSettings(); -#endif // __mobile __ + } Joystick::~Joystick() { -#ifndef __mobile__ delete _rgAxisValues; delete _rgCalibration; delete _rgButtonValues; delete _rgButtonActions; -#endif } -#ifndef __mobile__ void Joystick::_loadSettings(void) { @@ -257,6 +247,7 @@ float Joystick::_adjustRange(int value, Calibration_t calibration) void Joystick::run(void) { +#ifdef __sdljoystick__ SDL_Joystick* sdlJoystick = SDL_JoystickOpen(_sdlIndex); if (!sdlJoystick) { @@ -363,6 +354,7 @@ void Joystick::run(void) } SDL_JoystickClose(sdlJoystick); +#endif } void Joystick::startPolling(Vehicle* vehicle) @@ -579,4 +571,3 @@ bool Joystick::_validButton(int button) return button >= 0 && button < _buttonCount; } -#endif // __mobile__ diff --git a/src/Joystick/Joystick.h b/src/Joystick/Joystick.h index c26752f..6eb2d40 100644 --- a/src/Joystick/Joystick.h +++ b/src/Joystick/Joystick.h @@ -63,7 +63,6 @@ public: ThrottleModeMax } ThrottleMode_t; -#ifndef __mobile__ Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(bool calibrated MEMBER _calibrated NOTIFY calibratedChanged) @@ -174,7 +173,6 @@ private: bool _pollingStartedForCalibration; MultiVehicleManager* _multiVehicleManager; -#endif // __mobile__ private: static const char* _rgFunctionSettingsKey[maxFunction]; diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 70defba..ae16d0a 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -27,6 +27,7 @@ #include #ifndef __mobile__ + #define __sdljoystick__ #ifdef Q_OS_MAC #include #else @@ -55,7 +56,7 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); -#ifndef __mobile__ +#ifdef __sdljoystick__ if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError(); return; @@ -95,7 +96,6 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) void JoystickManager::_setActiveJoystickFromSettings(void) { -#ifndef __mobile__ QSettings settings; settings.beginGroup(_settingsGroup); @@ -107,7 +107,6 @@ void JoystickManager::_setActiveJoystickFromSettings(void) setActiveJoystick(_name2JoystickMap.value(name, _name2JoystickMap.first())); settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name()); -#endif } Joystick* JoystickManager::activeJoystick(void) @@ -117,9 +116,6 @@ Joystick* JoystickManager::activeJoystick(void) void JoystickManager::setActiveJoystick(Joystick* joystick) { -#ifdef __mobile__ - Q_UNUSED(joystick) -#else QSettings settings; if (!_name2JoystickMap.contains(joystick->name())) { @@ -138,7 +134,6 @@ void JoystickManager::setActiveJoystick(Joystick* joystick) emit activeJoystickChanged(_activeJoystick); emit activeJoystickNameChanged(_activeJoystick->name()); -#endif } QVariantList JoystickManager::joysticks(void) @@ -159,11 +154,7 @@ QStringList JoystickManager::joystickNames(void) QString JoystickManager::activeJoystickName(void) { -#ifdef __mobile__ - return QString(); -#else return _activeJoystick ? _activeJoystick->name() : QString(); -#endif } void JoystickManager::setActiveJoystickName(const QString& name) diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 3a12a5c..17df42f 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -103,6 +103,7 @@ #include "PX4AirframeLoader.h" #include "ValuesWidgetController.h" #include "AppMessages.h" +#include "JoystickConfigController.h" #ifndef __ios__ #include "SerialLink.h" @@ -112,7 +113,6 @@ #include "QGCFileDialog.h" #include "QGCMessageBox.h" #include "FirmwareUpgradeController.h" - #include "JoystickConfigController.h" #include "MainWindow.h" #endif @@ -459,12 +459,11 @@ void QGCApplication::_initCommon(void) qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ValuesWidgetController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "QGCMobileFileDialogController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "RCChannelMonitorController"); - + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "JoystickConfigController"); #ifndef __mobile__ qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ViewWidgetController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "CustomCommandWidgetController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "FirmwareUpgradeController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "JoystickConfigController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "LogDownloadController"); #endif diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index 0c062ae..05132aa 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -1095,7 +1095,6 @@ void Vehicle::setJoystickEnabled(bool enabled) void Vehicle::_startJoystick(bool start) { -#ifndef __mobile__ Joystick* joystick = _joystickManager->activeJoystick(); if (joystick) { if (start) { @@ -1106,9 +1105,6 @@ void Vehicle::_startJoystick(bool start) joystick->stopPolling(); } } -#else - Q_UNUSED(start); -#endif } bool Vehicle::active(void) From 877cef558a7d073627008d340b16fcd538fa1a2b Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Thu, 21 Apr 2016 14:54:59 +0100 Subject: [PATCH 02/21] Android JoystickManager --- src/Joystick/JoystickManager.cc | 81 +++++++++++++++++++++++++++++++++++++++++ src/Joystick/JoystickManager.h | 14 +++++++ 2 files changed, 95 insertions(+) diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index ae16d0a..96c83e3 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -83,6 +83,56 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) qCDebug(JoystickManagerLog) << "\tSkipping duplicate" << name; } } +#elif defined(__android__) + QMutexLocker lock(&m_mutex); + + computePossibleButtons(); //this is just needed to get number of supported buttons + + QAndroidJniEnvironment env; + QAndroidJniObject o = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDeviceIds"); + jintArray jarr = o.object(); + size_t sz = env->GetArrayLength(jarr); + jint *buff = env->GetIntArrayElements(jarr, nullptr); + + int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); + int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); + + for (size_t i = 0; i < sz; ++i) { + int axisCount, buttonCount; + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); + int sources = inputDevice.callMethod("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(); + + //get number of buttons + jintArray a = env->NewIntArray(31); + env->SetIntArrayRegion(a,0,31,_possibleButtons); + + //QAndroidJniObject keyMap = inputDevice.callObjectMethod("getKeyCharacterMap", "()Landroid/view/KeyCharacterMap;"); + //QAndroidJniObject btns = keyMap.callStaticObjectMethod("android/view/KeyCharacterMap","deviceHasKeys", "([I)[Z", a); + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + jbooleanArray jSupportedButtons = btns.object(); + size_t btn_sz = env->GetArrayLength(jSupportedButtons); + jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); + buttonCount=0; + for (size_t j=0;jReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); + + //get number of axis + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); + axisCount = rangeListNative.callMethod("size"); + + qCDebug(JoystickManagerLog) << "\t" << name << "axes:" << axisCount << "buttons:" << buttonCount; + _name2JoystickMap[name] = new Joystick(name, axisCount, buttonCount, buff[i], _multiVehicleManager); + } + + env->ReleaseIntArrayElements(jarr, buff, 0); #endif if (!_name2JoystickMap.count()) { @@ -93,6 +143,37 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) _setActiveJoystickFromSettings(); } +void JoystickManager::computePossibleButtons() { + static int ret[31]; + int i; + + for (i=1;i<=16;i++) { + QString name = "KEYCODE_BUTTON_"+QString::number(i); + ret[i-1] = QAndroidJniObject::getStaticField("android/view/KeyEvent", name.toStdString().c_str()); + } + i--; + + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_A"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_B"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_C"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_MODE"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_SELECT"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_START"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBL"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBR"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_X"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); + + for (int j=0;j +#ifdef __android__ + #include + #include + #include + #include + #include +#endif + Q_DECLARE_LOGGING_CATEGORY(JoystickManagerLog) class QGCApplicaiton; @@ -78,6 +86,12 @@ private: static const char * _settingsGroup; static const char * _settingsKeyActiveJoystick; + +#ifdef __android__ + void computePossibleButtons(); + int * _possibleButtons; + QMutex m_mutex; +#endif }; #endif From 7af1f46c164370da6ae236d61ce2925776ad2b73 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Fri, 22 Apr 2016 19:43:11 +0100 Subject: [PATCH 03/21] Restructuring + Initial Android handler --- qgroundcontrol.pro | 9 ++ src/Joystick/Joystick.cc | 229 +++++++++++++++++++--------------------- src/Joystick/Joystick.h | 17 ++- src/Joystick/JoystickAndroid.cc | 199 ++++++++++++++++++++++++++++++++++ src/Joystick/JoystickAndroid.h | 48 +++++++++ src/Joystick/JoystickManager.cc | 129 +++------------------- src/Joystick/JoystickManager.h | 15 +-- src/Joystick/JoystickSDL.cc | 73 +++++++++++++ src/Joystick/joysticksdl.h | 34 ++++++ 9 files changed, 498 insertions(+), 255 deletions(-) create mode 100644 src/Joystick/JoystickAndroid.cc create mode 100644 src/Joystick/JoystickAndroid.h create mode 100644 src/Joystick/JoystickSDL.cc create mode 100644 src/Joystick/joysticksdl.h diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 8dbedee..c312b10 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -312,6 +312,11 @@ HEADERS += \ src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ +AndroidBuild { +HEADERS += \ + src/Joystick/JoystickAndroid.h \ +} + DebugBuild { HEADERS += \ src/comm/MockLink.h \ @@ -344,6 +349,7 @@ HEADERS += \ src/comm/QGCHilLink.h \ src/comm/QGCJSBSimLink.h \ src/comm/QGCXPlaneLink.h \ + src/Joystick/JoystickSDL.h \ src/QGCFileDialog.h \ src/QGCMessageBox.h \ src/uas/FileManager.h \ @@ -400,8 +406,10 @@ iOSBuild { src/audio/QGCAudioWorker_iOS.mm \ src/MobileScreenMgr.mm \ } + AndroidBuild { SOURCES += src/MobileScreenMgr.cc \ + src/Joystick/JoystickAndroid.cc \ } @@ -497,6 +505,7 @@ SOURCES += \ src/comm/QGCFlightGearLink.cc \ src/comm/QGCJSBSimLink.cc \ src/comm/QGCXPlaneLink.cc \ + src/Joystick/JoystickSDL.cc \ src/ui/HILDockWidget.cc \ src/ui/linechart/ChartPlot.cc \ src/ui/linechart/IncrementalPlot.cc \ diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index f499e83..0e1abea 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -28,15 +28,6 @@ #include -#ifndef __mobile__ - #define __sdljoystick__ - #ifdef Q_OS_MAC - #include - #else - #include - #endif -#endif - QGC_LOGGING_CATEGORY(JoystickLog, "JoystickLog") QGC_LOGGING_CATEGORY(JoystickValuesLog, "JoystickValuesLog") @@ -52,9 +43,8 @@ const char* Joystick::_rgFunctionSettingsKey[Joystick::maxFunction] = { "ThrottleAxis" }; -Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlIndex, MultiVehicleManager* multiVehicleManager) - : _sdlIndex(sdlIndex) - , _exitThread(false) +Joystick::Joystick(const QString& name, int axisCount, int buttonCount, MultiVehicleManager* multiVehicleManager) + : _exitThread(false) , _name(name) , _axisCount(axisCount) , _buttonCount(buttonCount) @@ -94,6 +84,110 @@ Joystick::~Joystick() delete _rgButtonActions; } +void Joystick::run(void) +{ + open(); + + while (!_exitThread) { + update(); + + // Update axes + for (int axisIndex=0; axisIndex<_axisCount; axisIndex++) { + int newAxisValue = getAxis(axisIndex); + // Calibration code requires signal to be emitted even if value hasn't changed + _rgAxisValues[axisIndex] = newAxisValue; + emit rawAxisValueChanged(axisIndex, newAxisValue); + } + + // Update buttons + for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { + bool newButtonValue = getButton(buttonIndex); + if (newButtonValue != _rgButtonValues[buttonIndex]) { + _rgButtonValues[buttonIndex] = newButtonValue; + emit rawButtonPressedChanged(buttonIndex, newButtonValue); + } + } + + if (_calibrationMode != CalibrationModeCalibrating) { + int axis = _rgFunctionAxis[rollFunction]; + float roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + axis = _rgFunctionAxis[pitchFunction]; + float pitch = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + axis = _rgFunctionAxis[yawFunction]; + float yaw = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + axis = _rgFunctionAxis[throttleFunction]; + float throttle = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + float roll_limited = std::max(static_cast(-M_PI_4), std::min(roll, static_cast(M_PI_4))); + float pitch_limited = std::max(static_cast(-M_PI_4), std::min(pitch, static_cast(M_PI_4))); + float yaw_limited = std::max(static_cast(-M_PI_4), std::min(yaw, static_cast(M_PI_4))); + float throttle_limited = std::max(static_cast(-M_PI_4), std::min(throttle, static_cast(M_PI_4))); + + // Map from unit circle to linear range and limit + roll = std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f)); + pitch = std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f)); + yaw = std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f)); + throttle = std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f)); + + // Adjust throttle to 0:1 range + if (_throttleMode == ThrottleModeCenterZero) { + throttle = std::max(0.0f, throttle); + } else { + throttle = (throttle + 1.0f) / 2.0f; + } + + // Set up button pressed information + + // We only send the buttons the firmwware has reserved + int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount(); + if (reservedButtonCount == -1) { + reservedButtonCount = _buttonCount; + } + + quint16 newButtonBits = 0; // New set of button which are down + quint16 buttonPressedBits = 0; // Buttons pressed for manualControl signal + + for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { + quint16 buttonBit = 1 << buttonIndex; + + if (!_rgButtonValues[buttonIndex]) { + // Button up, just record it + newButtonBits |= buttonBit; + } else { + if (_lastButtonBits & buttonBit) { + // Button was up last time through, but is now down which indicates a button press + qCDebug(JoystickLog) << "button triggered" << buttonIndex; + + if (buttonIndex >= reservedButtonCount) { + // Button is above firmware reserved set + QString buttonAction =_rgButtonActions[buttonIndex]; + if (!buttonAction.isEmpty()) { + _buttonAction(buttonAction); + } + } + } + + // Mark the button as pressed as long as its pressed + buttonPressedBits |= buttonBit; + } + } + + _lastButtonBits = newButtonBits; + + //qCDebug(JoystickValuesLog) << "name:roll:pitch:yaw:throttle" << name() << roll << -pitch << yaw << throttle; + + emit manualControl(roll, -pitch, yaw, throttle, buttonPressedBits, _activeVehicle->joystickMode()); + } + + // Sleep, update rate of joystick is approx. 25 Hz (1000 ms / 25 = 40 ms) + QGC::SLEEP::msleep(40); + } + + close(); +} void Joystick::_loadSettings(void) { @@ -245,117 +339,6 @@ float Joystick::_adjustRange(int value, Calibration_t calibration) } -void Joystick::run(void) -{ -#ifdef __sdljoystick__ - SDL_Joystick* sdlJoystick = SDL_JoystickOpen(_sdlIndex); - - if (!sdlJoystick) { - qCWarning(JoystickLog) << "SDL_JoystickOpen failed:" << SDL_GetError(); - return; - } - - while (!_exitThread) { - SDL_JoystickUpdate(); - - // Update axes - for (int axisIndex=0; axisIndex<_axisCount; axisIndex++) { - int newAxisValue = SDL_JoystickGetAxis(sdlJoystick, axisIndex); - // Calibration code requires signal to be emitted even if value hasn't changed - _rgAxisValues[axisIndex] = newAxisValue; - emit rawAxisValueChanged(axisIndex, newAxisValue); - } - - // Update buttons - for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { - bool newButtonValue = !!SDL_JoystickGetButton(sdlJoystick, buttonIndex); - if (newButtonValue != _rgButtonValues[buttonIndex]) { - _rgButtonValues[buttonIndex] = newButtonValue; - emit rawButtonPressedChanged(buttonIndex, newButtonValue); - } - } - - if (_calibrationMode != CalibrationModeCalibrating) { - int axis = _rgFunctionAxis[rollFunction]; - float roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - axis = _rgFunctionAxis[pitchFunction]; - float pitch = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - axis = _rgFunctionAxis[yawFunction]; - float yaw = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - axis = _rgFunctionAxis[throttleFunction]; - float throttle = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - float roll_limited = std::max(static_cast(-M_PI_4), std::min(roll, static_cast(M_PI_4))); - float pitch_limited = std::max(static_cast(-M_PI_4), std::min(pitch, static_cast(M_PI_4))); - float yaw_limited = std::max(static_cast(-M_PI_4), std::min(yaw, static_cast(M_PI_4))); - float throttle_limited = std::max(static_cast(-M_PI_4), std::min(throttle, static_cast(M_PI_4))); - - // Map from unit circle to linear range and limit - roll = std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f)); - pitch = std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f)); - yaw = std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f)); - throttle = std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f)); - - // Adjust throttle to 0:1 range - if (_throttleMode == ThrottleModeCenterZero) { - throttle = std::max(0.0f, throttle); - } else { - throttle = (throttle + 1.0f) / 2.0f; - } - - // Set up button pressed information - - // We only send the buttons the firmwware has reserved - int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount(); - if (reservedButtonCount == -1) { - reservedButtonCount = _buttonCount; - } - - quint16 newButtonBits = 0; // New set of button which are down - quint16 buttonPressedBits = 0; // Buttons pressed for manualControl signal - - for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { - quint16 buttonBit = 1 << buttonIndex; - - if (!_rgButtonValues[buttonIndex]) { - // Button up, just record it - newButtonBits |= buttonBit; - } else { - if (_lastButtonBits & buttonBit) { - // Button was up last time through, but is now down which indicates a button press - qCDebug(JoystickLog) << "button triggered" << buttonIndex; - - if (buttonIndex >= reservedButtonCount) { - // Button is above firmware reserved set - QString buttonAction =_rgButtonActions[buttonIndex]; - if (!buttonAction.isEmpty()) { - _buttonAction(buttonAction); - } - } - } - - // Mark the button as pressed as long as its pressed - buttonPressedBits |= buttonBit; - } - } - - _lastButtonBits = newButtonBits; - - qCDebug(JoystickValuesLog) << "name:roll:pitch:yaw:throttle" << name() << roll << -pitch << yaw << throttle; - - emit manualControl(roll, -pitch, yaw, throttle, buttonPressedBits, _activeVehicle->joystickMode()); - } - - // Sleep, update rate of joystick is approx. 25 Hz (1000 ms / 25 = 40 ms) - QGC::SLEEP::msleep(40); - } - - SDL_JoystickClose(sdlJoystick); -#endif -} void Joystick::startPolling(Vehicle* vehicle) { diff --git a/src/Joystick/Joystick.h b/src/Joystick/Joystick.h index 6eb2d40..389a737 100644 --- a/src/Joystick/Joystick.h +++ b/src/Joystick/Joystick.h @@ -39,9 +39,9 @@ class Joystick : public QThread Q_OBJECT public: - Joystick(const QString& name, int axisCount, int buttonCount, int sdlIndex, MultiVehicleManager* multiVehicleManager); + Joystick(const QString& name, int axisCount, int buttonCount, MultiVehicleManager* multiVehicleManager); ~Joystick(); - + typedef struct { int min; int max; @@ -136,7 +136,7 @@ signals: void buttonActionTriggered(int action); -private: +protected: void _saveSettings(void); void _loadSettings(void); float _adjustRange(int value, Calibration_t calibration); @@ -144,11 +144,18 @@ private: bool _validAxis(int axis); bool _validButton(int button); +private: + virtual bool open() = 0; + virtual void close() = 0; + virtual bool update() = 0; + + virtual bool getButton(int i) = 0; + virtual int getAxis(int i) = 0; + // Override from QThread virtual void run(void); -private: - int _sdlIndex; ///< Index for SDL_JoystickOpen +protected: bool _exitThread; ///< true: signal thread to exit diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc new file mode 100644 index 0000000..3de7ce4 --- /dev/null +++ b/src/Joystick/JoystickAndroid.cc @@ -0,0 +1,199 @@ +#include "JoystickAndroid.h" + +#include "QGCApplication.h" + +#include + +int JoystickAndroid::_androidBtnListCount; +int *JoystickAndroid::_androidBtnList; +QMutex JoystickAndroid::m_mutex; + +JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager) + : Joystick(name,0,0,multiVehicleManager) //buttonCount and axisCount is computed below + , deviceId(id) +{ + int i; + + QAndroidJniEnvironment env; + + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); + + //get number of buttons + jintArray a = env->NewIntArray(_androidBtnListCount); + env->SetIntArrayRegion(a,0,_androidBtnListCount,_androidBtnList); + + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + jbooleanArray jSupportedButtons = btns.object(); + int btn_sz = env->GetArrayLength(jSupportedButtons); + jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); + _buttonCount=0; + for (i=0;iReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); + + //get number of axis + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); + _axisCount = rangeListNative.callMethod("size"); + axisValue = new int[_axisCount]; + axisCode = new int[_axisCount]; + for (i=0;i<_axisCount;i++) { + QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); + if (range.isValid()) + axisCode[i] = range.callMethod("getAxis"); + axisValue[i] = 0; + } + + qDebug() << "joystick constructor:" << _name; + + QtAndroidPrivate::registerGenericMotionEventListener(this); + QtAndroidPrivate::registerKeyEventListener(this); +} + +JoystickAndroid::~JoystickAndroid() { + qDebug() << "joystick destructor" << _name; + + delete btnCode; + delete axisCode; + delete btnValue; + delete axisValue; + + QtAndroidPrivate::unregisterGenericMotionEventListener(this); + QtAndroidPrivate::unregisterKeyEventListener(this); +} + +bool JoystickAndroid::handleKeyEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + qDebug() << "handleKeyEvent!" << deviceId; + return true; +} + +bool JoystickAndroid::handleGenericMotionEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + qDebug() << "handleMotionEvent!" << deviceId; + return true; +} + +QMap JoystickAndroid::discover(MultiVehicleManager* _multiVehicleManager) { + bool joystickFound = false; + static QMap ret; + + _buttonList(); //it's enough to run it once, should be in a static constructor + + QMutexLocker lock(&m_mutex); + + QAndroidJniEnvironment env; + QAndroidJniObject o = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDeviceIds"); + jintArray jarr = o.object(); + size_t sz = env->GetArrayLength(jarr); + jint *buff = env->GetIntArrayElements(jarr, nullptr); + + int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); + int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); + + for (size_t i = 0; i < sz; ++i) { + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); + int sources = inputDevice.callMethod("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(); + + + if (joystickFound) { //skipping { + qWarning() << "Skipping joystick:" << name; + continue; + } + + qDebug() << "\t" << name << "id:" << buff[i]; + ret[name] = new JoystickAndroid(name, buff[i], _multiVehicleManager); + joystickFound = true; + } + + env->ReleaseIntArrayElements(jarr, buff, 0); + + + return ret; +} + +bool JoystickAndroid::open(void) { + return true; +} + +void JoystickAndroid::close(void) { +} + +bool JoystickAndroid::update(void) +{ + return true; +} + +bool JoystickAndroid::getButton(int i) { + return btnValue[ btnCode[i] ]; +} + +int JoystickAndroid::getAxis(int i) { + return axisValue[ axisCode[i] ]; +} + + +//helper method +void JoystickAndroid::_buttonList() { + //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 + + //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; + + for (i=1;i<=16;i++) { + QString name = "KEYCODE_BUTTON_"+QString::number(i); + ret[i-1] = QAndroidJniObject::getStaticField("android/view/KeyEvent", name.toStdString().c_str()); + } + i--; + + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_A"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_B"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_C"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_MODE"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_SELECT"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_START"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBL"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBR"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_X"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); + + for (int j=0;j<_androidBtnListCount;j++) + qDebug() << "\tpossible button: "+QString::number(_androidBtnList[j]); + +} + diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h new file mode 100644 index 0000000..48f83ec --- /dev/null +++ b/src/Joystick/JoystickAndroid.h @@ -0,0 +1,48 @@ +#ifndef JOYSTICKANDROID_H +#define JOYSTICKANDROID_H + +#include "Joystick.h" +#include "Vehicle.h" +#include "MultiVehicleManager.h" + +#include +#include +#include +#include +#include + + +class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener +{ +public: + JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager); + ~JoystickAndroid(); + + static QMap discover(MultiVehicleManager* _multiVehicleManager); + +private: + bool handleKeyEvent(jobject event); + bool handleGenericMotionEvent(jobject event); + + virtual bool open(); + virtual void close(); + virtual bool update(); + + virtual bool getButton(int i); + virtual int getAxis(int i); + + int *btnCode; + int *axisCode; + bool *btnValue; + int *axisValue; + + static void _buttonList(); + static int * _androidBtnList; //list of all possible android buttons + static int _androidBtnListCount; + + static QMutex m_mutex; + + int deviceId; +}; + +#endif // JOYSTICKANDROID_H diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 96c83e3..3828c30 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -27,12 +27,12 @@ #include #ifndef __mobile__ + #include "JoystickSDL.h" #define __sdljoystick__ - #ifdef Q_OS_MAC - #include - #else - #include - #endif +#endif + +#ifdef __android__ + #include "JoystickAndroid.h" #endif QGC_LOGGING_CATEGORY(JoystickManagerLog, "JoystickManagerLog") @@ -45,7 +45,15 @@ JoystickManager::JoystickManager(QGCApplication* app) , _activeJoystick(NULL) , _multiVehicleManager(NULL) { - +} + +JoystickManager::~JoystickManager() { + QMap::iterator i; + for (i = _name2JoystickMap.begin(); i != _name2JoystickMap.end(); ++i) { + qDebug() << "Releasing joystick:" << i.key(); + delete i.value(); + } + qDebug() << "Done"; } void JoystickManager::setToolbox(QGCToolbox *toolbox) @@ -57,82 +65,9 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); #ifdef __sdljoystick__ - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { - qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError(); - return; - } - - // Load available joysticks - - qCDebug(JoystickManagerLog) << "Available joysticks"; - - for (int i=0; i("android/view/InputDevice", "getDeviceIds"); - jintArray jarr = o.object(); - size_t sz = env->GetArrayLength(jarr); - jint *buff = env->GetIntArrayElements(jarr, nullptr); - - int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); - int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); - - for (size_t i = 0; i < sz; ++i) { - int axisCount, buttonCount; - QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); - int sources = inputDevice.callMethod("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(); - - //get number of buttons - jintArray a = env->NewIntArray(31); - env->SetIntArrayRegion(a,0,31,_possibleButtons); - - //QAndroidJniObject keyMap = inputDevice.callObjectMethod("getKeyCharacterMap", "()Landroid/view/KeyCharacterMap;"); - //QAndroidJniObject btns = keyMap.callStaticObjectMethod("android/view/KeyCharacterMap","deviceHasKeys", "([I)[Z", a); - QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); - jbooleanArray jSupportedButtons = btns.object(); - size_t btn_sz = env->GetArrayLength(jSupportedButtons); - jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); - buttonCount=0; - for (size_t j=0;jReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); - - //get number of axis - QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); - axisCount = rangeListNative.callMethod("size"); - - qCDebug(JoystickManagerLog) << "\t" << name << "axes:" << axisCount << "buttons:" << buttonCount; - _name2JoystickMap[name] = new Joystick(name, axisCount, buttonCount, buff[i], _multiVehicleManager); - } - - env->ReleaseIntArrayElements(jarr, buff, 0); + _name2JoystickMap = JoystickAndroid::discover(_multiVehicleManager); #endif if (!_name2JoystickMap.count()) { @@ -143,38 +78,6 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) _setActiveJoystickFromSettings(); } -void JoystickManager::computePossibleButtons() { - static int ret[31]; - int i; - - for (i=1;i<=16;i++) { - QString name = "KEYCODE_BUTTON_"+QString::number(i); - ret[i-1] = QAndroidJniObject::getStaticField("android/view/KeyEvent", name.toStdString().c_str()); - } - i--; - - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_A"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_B"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_C"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L1"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L2"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R1"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R2"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_MODE"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_SELECT"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_START"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBL"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBR"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_X"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); - - for (int j=0;j -#ifdef __android__ - #include - #include - #include - #include - #include -#endif - Q_DECLARE_LOGGING_CATEGORY(JoystickManagerLog) class QGCApplicaiton; @@ -49,6 +41,7 @@ class JoystickManager : public QGCTool public: JoystickManager(QGCApplication* app); + ~JoystickManager(); /// List of available joysticks Q_PROPERTY(QVariantList joysticks READ joysticks CONSTANT) @@ -86,12 +79,6 @@ private: static const char * _settingsGroup; static const char * _settingsKeyActiveJoystick; - -#ifdef __android__ - void computePossibleButtons(); - int * _possibleButtons; - QMutex m_mutex; -#endif }; #endif diff --git a/src/Joystick/JoystickSDL.cc b/src/Joystick/JoystickSDL.cc new file mode 100644 index 0000000..db90c11 --- /dev/null +++ b/src/Joystick/JoystickSDL.cc @@ -0,0 +1,73 @@ +#include "JoystickSDL.h" + +#include "QGCApplication.h" + +#include + +JoystickSDL::JoystickSDL(const QString& name, int axisCount, int buttonCount, int index, MultiVehicleManager* multiVehicleManager) + : Joystick(name,axisCount,buttonCount,multiVehicleManager) + , _index(index) +{ +} + +QMap JoystickSDL::discover(MultiVehicleManager* _multiVehicleManager) { + static QMap ret; + + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { + qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError(); + return ret; + } + + // Load available joysticks + + qCDebug(JoystickLog) << "Available joysticks"; + + for (int i=0; i +#else + #include +#endif + + +class JoystickSDL : public Joystick +{ +public: + JoystickSDL(const QString& name, int axisCount, int buttonCount, int index, MultiVehicleManager* multiVehicleManager); + + static QMap discover(MultiVehicleManager* _multiVehicleManager); + +private: + virtual bool open(); + virtual void close(); + virtual bool update(); + + virtual bool getButton(int i); + virtual int getAxis(int i); + + SDL_Joystick *sdlJoystick; + int _index; ///< Index for SDL_JoystickOpen +}; + +#endif // JOYSTICKSDL_H From bce432eff650f3cea0316f694ff3231107d522a4 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Fri, 22 Apr 2016 22:34:34 +0100 Subject: [PATCH 04/21] Cleanup --- src/Joystick/Joystick.cc | 6 +++--- src/Joystick/JoystickAndroid.cc | 16 ++++++++-------- src/VehicleSetup/SetupView.qml | 1 + 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index 0e1abea..a320cb2 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -89,7 +89,7 @@ void Joystick::run(void) open(); while (!_exitThread) { - update(); + update(); // Update axes for (int axisIndex=0; axisIndex<_axisCount; axisIndex++) { @@ -143,9 +143,9 @@ void Joystick::run(void) // We only send the buttons the firmwware has reserved int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount(); - if (reservedButtonCount == -1) { + if (reservedButtonCount == -1) reservedButtonCount = _buttonCount; - } + quint16 newButtonBits = 0; // New set of button which are down quint16 buttonPressedBits = 0; // Buttons pressed for manualControl signal diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index 3de7ce4..14bdcf9 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -49,20 +49,20 @@ JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManage axisValue = new int[_axisCount]; axisCode = new int[_axisCount]; for (i=0;i<_axisCount;i++) { - QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); - if (range.isValid()) - axisCode[i] = range.callMethod("getAxis"); - axisValue[i] = 0; + QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); + if (range.isValid()) + axisCode[i] = range.callMethod("getAxis"); + axisValue[i] = 0; } - qDebug() << "joystick constructor:" << _name; + _axisCount = 4; + qDebug() << "axis:" <<_axisCount << "buttons:" <<_buttonCount; QtAndroidPrivate::registerGenericMotionEventListener(this); QtAndroidPrivate::registerKeyEventListener(this); } JoystickAndroid::~JoystickAndroid() { - qDebug() << "joystick destructor" << _name; delete btnCode; delete axisCode; @@ -150,11 +150,11 @@ bool JoystickAndroid::update(void) } bool JoystickAndroid::getButton(int i) { - return btnValue[ btnCode[i] ]; + return btnValue[ i ]; } int JoystickAndroid::getAxis(int i) { - return axisValue[ axisCode[i] ]; + return axisValue[ i ]; } diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index 18e50da..a5713a8 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -279,6 +279,7 @@ Rectangle { setupComplete: joystickManager.activeJoystick ? joystickManager.activeJoystick.calibrated : false exclusiveGroup: setupButtonGroup visible: _fullParameterVehicleAvailable && joystickManager.joysticks.length != 0 + //visible: true text: "Joystick" onClicked: showJoystickPanel() From 3c6a4bc17ab8e798c55cc11e1dfa9372ebc2f1ba Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Sat, 23 Apr 2016 08:36:04 +0100 Subject: [PATCH 05/21] Fixing issue with initialization --- qgroundcontrol.pro | 4 +++ src/Joystick/JoystickAndroid.cc | 74 +++++++++++++++++++++++------------------ src/Joystick/JoystickAndroid.h | 2 +- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index c312b10..0db9bfc 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -17,6 +17,10 @@ # along with QGroundControl. If not, see . # ------------------------------------------------- +#QMAKE_CFLAGS_DEBUG += -g +#QMAKE_CXXFLAGS += -g +#QMAKE_CXXFLAGS_DEBUG += -g + exists($${OUT_PWD}/qgroundcontrol.pro) { error("You must use shadow build (e.g. mkdir build; cd build; qmake ../qgroundcontrol.pro).") } diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index 14bdcf9..3036ce8 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -8,46 +8,42 @@ int JoystickAndroid::_androidBtnListCount; int *JoystickAndroid::_androidBtnList; QMutex JoystickAndroid::m_mutex; -JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager) - : Joystick(name,0,0,multiVehicleManager) //buttonCount and axisCount is computed below +JoystickAndroid::JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager) + : Joystick(name,axisCount,buttonCount,multiVehicleManager) , deviceId(id) { int i; QAndroidJniEnvironment env; - QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); + //if we define inputDevice in here this will fail for some reason, hence passing through argument + //QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); - //get number of buttons - jintArray a = env->NewIntArray(_androidBtnListCount); - env->SetIntArrayRegion(a,0,_androidBtnListCount,_androidBtnList); - QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + //set button mapping (number->code) + jintArray b = env->NewIntArray(_androidBtnListCount); + env->SetIntArrayRegion(b,0,_androidBtnListCount,_androidBtnList); + + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", b); jbooleanArray jSupportedButtons = btns.object(); - int btn_sz = env->GetArrayLength(jSupportedButtons); jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); - _buttonCount=0; - for (i=0;iReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); - //get number of axis - QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); - _axisCount = rangeListNative.callMethod("size"); + //set axis mapping (number->code) axisValue = new int[_axisCount]; axisCode = new int[_axisCount]; + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); for (i=0;i<_axisCount;i++) { QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); if (range.isValid()) @@ -55,7 +51,6 @@ JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManage axisValue[i] = 0; } - _axisCount = 4; qDebug() << "axis:" <<_axisCount << "buttons:" <<_buttonCount; QtAndroidPrivate::registerGenericMotionEventListener(this); @@ -63,7 +58,6 @@ JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManage } JoystickAndroid::~JoystickAndroid() { - delete btnCode; delete axisCode; delete btnValue; @@ -79,7 +73,7 @@ bool JoystickAndroid::handleKeyEvent(jobject event) { const int _deviceId = ev.callMethod("getDeviceId", "()I"); if (_deviceId!=deviceId) return false; - qDebug() << "handleKeyEvent!" << deviceId; + //qDebug() << "handleKeyEvent!" << deviceId; return true; } @@ -89,7 +83,7 @@ bool JoystickAndroid::handleGenericMotionEvent(jobject event) { const int _deviceId = ev.callMethod("getDeviceId", "()I"); if (_deviceId!=deviceId) return false; - qDebug() << "handleMotionEvent!" << deviceId; + //qDebug() << "handleMotionEvent!" << deviceId; return true; } @@ -104,13 +98,13 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe QAndroidJniEnvironment env; QAndroidJniObject o = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDeviceIds"); jintArray jarr = o.object(); - size_t sz = env->GetArrayLength(jarr); + int sz = env->GetArrayLength(jarr); jint *buff = env->GetIntArrayElements(jarr, nullptr); int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); - for (size_t i = 0; i < sz; ++i) { + for (int i = 0; i < sz; ++i) { QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); int sources = inputDevice.callMethod("getSources", "()I"); if (((sources & SOURCE_GAMEPAD) != SOURCE_GAMEPAD) //check if the input device is interesting to us @@ -121,13 +115,29 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe QString name = inputDevice.callObjectMethod("getName", "()Ljava/lang/String;").toString(); - if (joystickFound) { //skipping { - qWarning() << "Skipping joystick:" << name; - continue; - } + if (joystickFound) { //skipping { + qWarning() << "Skipping joystick:" << name; + continue; + } + + //get number of axis + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); + int axisCount = rangeListNative.callMethod("size"); + + //get number of buttons + jintArray a = env->NewIntArray(_androidBtnListCount); + env->SetIntArrayRegion(a,0,_androidBtnListCount,_androidBtnList); + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + jbooleanArray jSupportedButtons = btns.object(); + jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); + int buttonCount = 0; + for (i=0;i<_androidBtnListCount;i++) + if (supportedButtons[i]) buttonCount++; + env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); + + qDebug() << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount; - qDebug() << "\t" << name << "id:" << buff[i]; - ret[name] = new JoystickAndroid(name, buff[i], _multiVehicleManager); + ret[name] = new JoystickAndroid(inputDevice, name, axisCount, buttonCount, buff[i], _multiVehicleManager); joystickFound = true; } diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h index 48f83ec..7afca41 100644 --- a/src/Joystick/JoystickAndroid.h +++ b/src/Joystick/JoystickAndroid.h @@ -15,7 +15,7 @@ class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener { public: - JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager); + JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager); ~JoystickAndroid(); static QMap discover(MultiVehicleManager* _multiVehicleManager); From 1c19920f4f736f623c696e5ff633caf212532ead Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Sat, 23 Apr 2016 10:17:24 +0100 Subject: [PATCH 06/21] Implementing handlers --- src/Joystick/JoystickAndroid.cc | 89 +++++++++++++++++++++++------------------ src/Joystick/JoystickAndroid.h | 5 ++- 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index 3036ce8..f9eef36 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -6,19 +6,18 @@ int JoystickAndroid::_androidBtnListCount; int *JoystickAndroid::_androidBtnList; +int JoystickAndroid::ACTION_DOWN; +int JoystickAndroid::ACTION_UP; QMutex JoystickAndroid::m_mutex; -JoystickAndroid::JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager) +JoystickAndroid::JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager) : Joystick(name,axisCount,buttonCount,multiVehicleManager) , deviceId(id) { int i; QAndroidJniEnvironment env; - - //if we define inputDevice in here this will fail for some reason, hence passing through argument - //QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); - + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); //set button mapping (number->code) jintArray b = env->NewIntArray(_androidBtnListCount); @@ -44,15 +43,14 @@ JoystickAndroid::JoystickAndroid(const QAndroidJniObject &inputDevice, const QSt axisValue = new int[_axisCount]; axisCode = new int[_axisCount]; QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); - for (i=0;i<_axisCount;i++) { - QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); - if (range.isValid()) - axisCode[i] = range.callMethod("getAxis"); + for (i=0;i<_axisCount;i++) { + QAndroidJniObject range = rangeListNative.callObjectMethod("get", "(I)Ljava/lang/Object;",i); + axisCode[i] = range.callMethod("getAxis"); axisValue[i] = 0; } - qDebug() << "axis:" <<_axisCount << "buttons:" <<_buttonCount; + qCDebug(JoystickLog) << "axis:" <<_axisCount << "buttons:" <<_buttonCount; QtAndroidPrivate::registerGenericMotionEventListener(this); QtAndroidPrivate::registerKeyEventListener(this); } @@ -67,31 +65,11 @@ JoystickAndroid::~JoystickAndroid() { QtAndroidPrivate::unregisterKeyEventListener(this); } -bool JoystickAndroid::handleKeyEvent(jobject event) { - QJNIObjectPrivate ev(event); - QMutexLocker lock(&m_mutex); - const int _deviceId = ev.callMethod("getDeviceId", "()I"); - if (_deviceId!=deviceId) return false; - - //qDebug() << "handleKeyEvent!" << deviceId; - return true; -} - -bool JoystickAndroid::handleGenericMotionEvent(jobject event) { - QJNIObjectPrivate ev(event); - QMutexLocker lock(&m_mutex); - const int _deviceId = ev.callMethod("getDeviceId", "()I"); - if (_deviceId!=deviceId) return false; - - //qDebug() << "handleMotionEvent!" << deviceId; - return true; -} - QMap JoystickAndroid::discover(MultiVehicleManager* _multiVehicleManager) { bool joystickFound = false; static QMap ret; - _buttonList(); //it's enough to run it once, should be in a static constructor + _initStatic(); //it's enough to run it once, should be in a static constructor QMutexLocker lock(&m_mutex); @@ -131,13 +109,13 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe jbooleanArray jSupportedButtons = btns.object(); jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); int buttonCount = 0; - for (i=0;i<_androidBtnListCount;i++) - if (supportedButtons[i]) buttonCount++; + for (int j=0;j<_androidBtnListCount;j++) + if (supportedButtons[j]) buttonCount++; env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); - qDebug() << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount; + qCDebug(JoystickLog) << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount; - ret[name] = new JoystickAndroid(inputDevice, name, axisCount, buttonCount, buff[i], _multiVehicleManager); + ret[name] = new JoystickAndroid(name, axisCount, buttonCount, buff[i], _multiVehicleManager); joystickFound = true; } @@ -147,6 +125,40 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe return ret; } + +bool JoystickAndroid::handleKeyEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + const int action = ev.callMethod("getAction", "()I"); + const int keyCode = ev.callMethod("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; + } + } + return false; +} + +bool JoystickAndroid::handleGenericMotionEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + for (int i=0;i<_axisCount;i++) { + const float v = ev.callMethod("getAxisValue", "(I)F",axisCode[i]); + axisValue[i] = (int)(v*32767.f); + } + return true; +} + + bool JoystickAndroid::open(void) { return true; } @@ -169,7 +181,7 @@ int JoystickAndroid::getAxis(int i) { //helper method -void JoystickAndroid::_buttonList() { +void JoystickAndroid::_initStatic() { //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 @@ -202,8 +214,7 @@ void JoystickAndroid::_buttonList() { ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); - for (int j=0;j<_androidBtnListCount;j++) - qDebug() << "\tpossible button: "+QString::number(_androidBtnList[j]); - + ACTION_DOWN = QAndroidJniObject::getStaticField("android/view/KeyEvent", "ACTION_DOWN"); + ACTION_UP = QAndroidJniObject::getStaticField("android/view/KeyEvent", "ACTION_UP"); } diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h index 7afca41..75ea813 100644 --- a/src/Joystick/JoystickAndroid.h +++ b/src/Joystick/JoystickAndroid.h @@ -15,7 +15,7 @@ class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener { public: - JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager); + JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager); ~JoystickAndroid(); static QMap discover(MultiVehicleManager* _multiVehicleManager); @@ -36,10 +36,11 @@ private: bool *btnValue; int *axisValue; - static void _buttonList(); + static void _initStatic(); static int * _androidBtnList; //list of all possible android buttons static int _androidBtnListCount; + static int ACTION_DOWN, ACTION_UP; static QMutex m_mutex; int deviceId; From c9ce6c6a396ce823b8d6ab00775f39c02fc657f7 Mon Sep 17 00:00:00 2001 From: Gregory D Date: Tue, 26 Apr 2016 21:34:38 +0100 Subject: [PATCH 07/21] Update SetupView.qml --- src/VehicleSetup/SetupView.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index a5713a8..18e50da 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -279,7 +279,6 @@ Rectangle { setupComplete: joystickManager.activeJoystick ? joystickManager.activeJoystick.calibrated : false exclusiveGroup: setupButtonGroup visible: _fullParameterVehicleAvailable && joystickManager.joysticks.length != 0 - //visible: true text: "Joystick" onClicked: showJoystickPanel() From c753cb8ff7311f427f2f8259e89127d529dd8546 Mon Sep 17 00:00:00 2001 From: Gregory D Date: Tue, 26 Apr 2016 21:35:06 +0100 Subject: [PATCH 08/21] Update qgroundcontrol.pro --- qgroundcontrol.pro | 4 ---- 1 file changed, 4 deletions(-) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 0db9bfc..c312b10 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -17,10 +17,6 @@ # along with QGroundControl. If not, see . # ------------------------------------------------- -#QMAKE_CFLAGS_DEBUG += -g -#QMAKE_CXXFLAGS += -g -#QMAKE_CXXFLAGS_DEBUG += -g - exists($${OUT_PWD}/qgroundcontrol.pro) { error("You must use shadow build (e.g. mkdir build; cd build; qmake ../qgroundcontrol.pro).") } From bf4ab002e023484f768dc3287880e8fc3e73cb0a Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Thu, 21 Apr 2016 14:54:00 +0100 Subject: [PATCH 09/21] Activating Joystick module for all builds --- qgroundcontrol.pro | 4 ++-- src/Joystick/Joystick.cc | 19 +++++-------------- src/Joystick/Joystick.h | 2 -- src/Joystick/JoystickManager.cc | 13 ++----------- src/QGCApplication.cc | 5 ++--- src/Vehicle/Vehicle.cc | 4 ---- 6 files changed, 11 insertions(+), 36 deletions(-) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 68a3370..6a2df9f 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -266,6 +266,7 @@ HEADERS += \ src/HomePositionManager.h \ src/Joystick/Joystick.h \ src/Joystick/JoystickManager.h \ + src/VehicleSetup/JoystickConfigController.h \ src/FollowMe/FollowMe.h \ src/PositionManager/SimulatedPosition.h \ src/JsonHelper.h \ @@ -390,7 +391,6 @@ HEADERS += \ src/GPS/GPSManager.h \ src/GPS/GPSPositionMessage.h \ src/GPS/GPSProvider.h \ - src/VehicleSetup/JoystickConfigController.h \ src/ViewWidgets/CustomCommandWidget.h \ src/ViewWidgets/CustomCommandWidgetController.h \ src/ViewWidgets/LogDownload.h \ @@ -423,6 +423,7 @@ SOURCES += \ src/HomePositionManager.cc \ src/Joystick/Joystick.cc \ src/Joystick/JoystickManager.cc \ + src/VehicleSetup/JoystickConfigController.cc \ src/JsonHelper.cc \ src/FollowMe/FollowMe.cc \ src/LogCompressor.cc \ @@ -531,7 +532,6 @@ SOURCES += \ src/GPS/RTCM/RTCMMavlink.cc \ src/GPS/GPSManager.cc \ src/GPS/GPSProvider.cc \ - src/VehicleSetup/JoystickConfigController.cc \ src/ViewWidgets/CustomCommandWidget.cc \ src/ViewWidgets/CustomCommandWidgetController.cc \ src/ViewWidgets/LogDownload.cc \ diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index 37d6140..f499e83 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -29,6 +29,7 @@ #include #ifndef __mobile__ + #define __sdljoystick__ #ifdef Q_OS_MAC #include #else @@ -52,7 +53,6 @@ const char* Joystick::_rgFunctionSettingsKey[Joystick::maxFunction] = { }; Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlIndex, MultiVehicleManager* multiVehicleManager) -#ifndef __mobile__ : _sdlIndex(sdlIndex) , _exitThread(false) , _name(name) @@ -68,15 +68,8 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlI , _activeVehicle(NULL) , _pollingStartedForCalibration(false) , _multiVehicleManager(multiVehicleManager) -#endif // __mobile__ { -#ifdef __mobile__ - Q_UNUSED(name) - Q_UNUSED(axisCount) - Q_UNUSED(buttonCount) - Q_UNUSED(sdlIndex) - Q_UNUSED(multiVehicleManager) -#else + _rgAxisValues = new int[_axisCount]; _rgCalibration = new Calibration_t[_axisCount]; _rgButtonValues = new bool[_buttonCount]; @@ -90,20 +83,17 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlI } _loadSettings(); -#endif // __mobile __ + } Joystick::~Joystick() { -#ifndef __mobile__ delete _rgAxisValues; delete _rgCalibration; delete _rgButtonValues; delete _rgButtonActions; -#endif } -#ifndef __mobile__ void Joystick::_loadSettings(void) { @@ -257,6 +247,7 @@ float Joystick::_adjustRange(int value, Calibration_t calibration) void Joystick::run(void) { +#ifdef __sdljoystick__ SDL_Joystick* sdlJoystick = SDL_JoystickOpen(_sdlIndex); if (!sdlJoystick) { @@ -363,6 +354,7 @@ void Joystick::run(void) } SDL_JoystickClose(sdlJoystick); +#endif } void Joystick::startPolling(Vehicle* vehicle) @@ -579,4 +571,3 @@ bool Joystick::_validButton(int button) return button >= 0 && button < _buttonCount; } -#endif // __mobile__ diff --git a/src/Joystick/Joystick.h b/src/Joystick/Joystick.h index c26752f..6eb2d40 100644 --- a/src/Joystick/Joystick.h +++ b/src/Joystick/Joystick.h @@ -63,7 +63,6 @@ public: ThrottleModeMax } ThrottleMode_t; -#ifndef __mobile__ Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(bool calibrated MEMBER _calibrated NOTIFY calibratedChanged) @@ -174,7 +173,6 @@ private: bool _pollingStartedForCalibration; MultiVehicleManager* _multiVehicleManager; -#endif // __mobile__ private: static const char* _rgFunctionSettingsKey[maxFunction]; diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 70defba..ae16d0a 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -27,6 +27,7 @@ #include #ifndef __mobile__ + #define __sdljoystick__ #ifdef Q_OS_MAC #include #else @@ -55,7 +56,7 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); -#ifndef __mobile__ +#ifdef __sdljoystick__ if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError(); return; @@ -95,7 +96,6 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) void JoystickManager::_setActiveJoystickFromSettings(void) { -#ifndef __mobile__ QSettings settings; settings.beginGroup(_settingsGroup); @@ -107,7 +107,6 @@ void JoystickManager::_setActiveJoystickFromSettings(void) setActiveJoystick(_name2JoystickMap.value(name, _name2JoystickMap.first())); settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name()); -#endif } Joystick* JoystickManager::activeJoystick(void) @@ -117,9 +116,6 @@ Joystick* JoystickManager::activeJoystick(void) void JoystickManager::setActiveJoystick(Joystick* joystick) { -#ifdef __mobile__ - Q_UNUSED(joystick) -#else QSettings settings; if (!_name2JoystickMap.contains(joystick->name())) { @@ -138,7 +134,6 @@ void JoystickManager::setActiveJoystick(Joystick* joystick) emit activeJoystickChanged(_activeJoystick); emit activeJoystickNameChanged(_activeJoystick->name()); -#endif } QVariantList JoystickManager::joysticks(void) @@ -159,11 +154,7 @@ QStringList JoystickManager::joystickNames(void) QString JoystickManager::activeJoystickName(void) { -#ifdef __mobile__ - return QString(); -#else return _activeJoystick ? _activeJoystick->name() : QString(); -#endif } void JoystickManager::setActiveJoystickName(const QString& name) diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 0ab1157..3b83070 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -85,6 +85,7 @@ #include "PX4/PX4FirmwarePlugin.h" #include "Vehicle.h" #include "MavlinkQmlSingleton.h" +#include "JoystickConfigController.h" #include "JoystickManager.h" #include "QmlObjectListModel.h" #include "MissionManager.h" @@ -115,7 +116,6 @@ #include "QGCFileDialog.h" #include "QGCMessageBox.h" #include "FirmwareUpgradeController.h" - #include "JoystickConfigController.h" #include "MainWindow.h" #endif @@ -463,12 +463,11 @@ void QGCApplication::_initCommon(void) qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ValuesWidgetController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "QGCMobileFileDialogController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "RCChannelMonitorController"); - + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "JoystickConfigController"); #ifndef __mobile__ qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ViewWidgetController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "CustomCommandWidgetController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "FirmwareUpgradeController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "JoystickConfigController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "LogDownloadController"); #endif diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index 30d5f74..4a6ccfa 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -1095,7 +1095,6 @@ void Vehicle::setJoystickEnabled(bool enabled) void Vehicle::_startJoystick(bool start) { -#ifndef __mobile__ Joystick* joystick = _joystickManager->activeJoystick(); if (joystick) { if (start) { @@ -1106,9 +1105,6 @@ void Vehicle::_startJoystick(bool start) joystick->stopPolling(); } } -#else - Q_UNUSED(start); -#endif } bool Vehicle::active(void) From fcf1b5d296b5b3daaa60333c744d5981d64f7961 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Thu, 21 Apr 2016 14:54:59 +0100 Subject: [PATCH 10/21] Android JoystickManager --- src/Joystick/JoystickManager.cc | 81 +++++++++++++++++++++++++++++++++++++++++ src/Joystick/JoystickManager.h | 14 +++++++ 2 files changed, 95 insertions(+) diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index ae16d0a..96c83e3 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -83,6 +83,56 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) qCDebug(JoystickManagerLog) << "\tSkipping duplicate" << name; } } +#elif defined(__android__) + QMutexLocker lock(&m_mutex); + + computePossibleButtons(); //this is just needed to get number of supported buttons + + QAndroidJniEnvironment env; + QAndroidJniObject o = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDeviceIds"); + jintArray jarr = o.object(); + size_t sz = env->GetArrayLength(jarr); + jint *buff = env->GetIntArrayElements(jarr, nullptr); + + int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); + int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); + + for (size_t i = 0; i < sz; ++i) { + int axisCount, buttonCount; + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); + int sources = inputDevice.callMethod("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(); + + //get number of buttons + jintArray a = env->NewIntArray(31); + env->SetIntArrayRegion(a,0,31,_possibleButtons); + + //QAndroidJniObject keyMap = inputDevice.callObjectMethod("getKeyCharacterMap", "()Landroid/view/KeyCharacterMap;"); + //QAndroidJniObject btns = keyMap.callStaticObjectMethod("android/view/KeyCharacterMap","deviceHasKeys", "([I)[Z", a); + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + jbooleanArray jSupportedButtons = btns.object(); + size_t btn_sz = env->GetArrayLength(jSupportedButtons); + jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); + buttonCount=0; + for (size_t j=0;jReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); + + //get number of axis + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); + axisCount = rangeListNative.callMethod("size"); + + qCDebug(JoystickManagerLog) << "\t" << name << "axes:" << axisCount << "buttons:" << buttonCount; + _name2JoystickMap[name] = new Joystick(name, axisCount, buttonCount, buff[i], _multiVehicleManager); + } + + env->ReleaseIntArrayElements(jarr, buff, 0); #endif if (!_name2JoystickMap.count()) { @@ -93,6 +143,37 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) _setActiveJoystickFromSettings(); } +void JoystickManager::computePossibleButtons() { + static int ret[31]; + int i; + + for (i=1;i<=16;i++) { + QString name = "KEYCODE_BUTTON_"+QString::number(i); + ret[i-1] = QAndroidJniObject::getStaticField("android/view/KeyEvent", name.toStdString().c_str()); + } + i--; + + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_A"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_B"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_C"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_MODE"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_SELECT"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_START"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBL"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBR"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_X"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); + + for (int j=0;j +#ifdef __android__ + #include + #include + #include + #include + #include +#endif + Q_DECLARE_LOGGING_CATEGORY(JoystickManagerLog) class QGCApplicaiton; @@ -78,6 +86,12 @@ private: static const char * _settingsGroup; static const char * _settingsKeyActiveJoystick; + +#ifdef __android__ + void computePossibleButtons(); + int * _possibleButtons; + QMutex m_mutex; +#endif }; #endif From e44fed2f4ad816427b7764ab30dbe3cf1360ef2e Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Fri, 22 Apr 2016 19:43:11 +0100 Subject: [PATCH 11/21] Restructuring + Initial Android handler --- qgroundcontrol.pro | 9 ++ src/Joystick/Joystick.cc | 229 +++++++++++++++++++--------------------- src/Joystick/Joystick.h | 17 ++- src/Joystick/JoystickAndroid.cc | 199 ++++++++++++++++++++++++++++++++++ src/Joystick/JoystickAndroid.h | 48 +++++++++ src/Joystick/JoystickManager.cc | 129 +++------------------- src/Joystick/JoystickManager.h | 15 +-- src/Joystick/JoystickSDL.cc | 73 +++++++++++++ src/Joystick/joysticksdl.h | 34 ++++++ 9 files changed, 498 insertions(+), 255 deletions(-) create mode 100644 src/Joystick/JoystickAndroid.cc create mode 100644 src/Joystick/JoystickAndroid.h create mode 100644 src/Joystick/JoystickSDL.cc create mode 100644 src/Joystick/joysticksdl.h diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 6a2df9f..5998e7f 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -315,6 +315,11 @@ HEADERS += \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ src/PositionManager/PositionManager.h +AndroidBuild { +HEADERS += \ + src/Joystick/JoystickAndroid.h \ +} + DebugBuild { HEADERS += \ src/comm/MockLink.h \ @@ -347,6 +352,7 @@ HEADERS += \ src/comm/QGCHilLink.h \ src/comm/QGCJSBSimLink.h \ src/comm/QGCXPlaneLink.h \ + src/Joystick/JoystickSDL.h \ src/QGCFileDialog.h \ src/QGCMessageBox.h \ src/uas/FileManager.h \ @@ -403,8 +409,10 @@ iOSBuild { src/audio/QGCAudioWorker_iOS.mm \ src/MobileScreenMgr.mm \ } + AndroidBuild { SOURCES += src/MobileScreenMgr.cc \ + src/Joystick/JoystickAndroid.cc \ } @@ -502,6 +510,7 @@ SOURCES += \ src/comm/QGCFlightGearLink.cc \ src/comm/QGCJSBSimLink.cc \ src/comm/QGCXPlaneLink.cc \ + src/Joystick/JoystickSDL.cc \ src/ui/HILDockWidget.cc \ src/ui/linechart/ChartPlot.cc \ src/ui/linechart/IncrementalPlot.cc \ diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index f499e83..0e1abea 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -28,15 +28,6 @@ #include -#ifndef __mobile__ - #define __sdljoystick__ - #ifdef Q_OS_MAC - #include - #else - #include - #endif -#endif - QGC_LOGGING_CATEGORY(JoystickLog, "JoystickLog") QGC_LOGGING_CATEGORY(JoystickValuesLog, "JoystickValuesLog") @@ -52,9 +43,8 @@ const char* Joystick::_rgFunctionSettingsKey[Joystick::maxFunction] = { "ThrottleAxis" }; -Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int sdlIndex, MultiVehicleManager* multiVehicleManager) - : _sdlIndex(sdlIndex) - , _exitThread(false) +Joystick::Joystick(const QString& name, int axisCount, int buttonCount, MultiVehicleManager* multiVehicleManager) + : _exitThread(false) , _name(name) , _axisCount(axisCount) , _buttonCount(buttonCount) @@ -94,6 +84,110 @@ Joystick::~Joystick() delete _rgButtonActions; } +void Joystick::run(void) +{ + open(); + + while (!_exitThread) { + update(); + + // Update axes + for (int axisIndex=0; axisIndex<_axisCount; axisIndex++) { + int newAxisValue = getAxis(axisIndex); + // Calibration code requires signal to be emitted even if value hasn't changed + _rgAxisValues[axisIndex] = newAxisValue; + emit rawAxisValueChanged(axisIndex, newAxisValue); + } + + // Update buttons + for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { + bool newButtonValue = getButton(buttonIndex); + if (newButtonValue != _rgButtonValues[buttonIndex]) { + _rgButtonValues[buttonIndex] = newButtonValue; + emit rawButtonPressedChanged(buttonIndex, newButtonValue); + } + } + + if (_calibrationMode != CalibrationModeCalibrating) { + int axis = _rgFunctionAxis[rollFunction]; + float roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + axis = _rgFunctionAxis[pitchFunction]; + float pitch = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + axis = _rgFunctionAxis[yawFunction]; + float yaw = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + axis = _rgFunctionAxis[throttleFunction]; + float throttle = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); + + float roll_limited = std::max(static_cast(-M_PI_4), std::min(roll, static_cast(M_PI_4))); + float pitch_limited = std::max(static_cast(-M_PI_4), std::min(pitch, static_cast(M_PI_4))); + float yaw_limited = std::max(static_cast(-M_PI_4), std::min(yaw, static_cast(M_PI_4))); + float throttle_limited = std::max(static_cast(-M_PI_4), std::min(throttle, static_cast(M_PI_4))); + + // Map from unit circle to linear range and limit + roll = std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f)); + pitch = std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f)); + yaw = std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f)); + throttle = std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f)); + + // Adjust throttle to 0:1 range + if (_throttleMode == ThrottleModeCenterZero) { + throttle = std::max(0.0f, throttle); + } else { + throttle = (throttle + 1.0f) / 2.0f; + } + + // Set up button pressed information + + // We only send the buttons the firmwware has reserved + int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount(); + if (reservedButtonCount == -1) { + reservedButtonCount = _buttonCount; + } + + quint16 newButtonBits = 0; // New set of button which are down + quint16 buttonPressedBits = 0; // Buttons pressed for manualControl signal + + for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { + quint16 buttonBit = 1 << buttonIndex; + + if (!_rgButtonValues[buttonIndex]) { + // Button up, just record it + newButtonBits |= buttonBit; + } else { + if (_lastButtonBits & buttonBit) { + // Button was up last time through, but is now down which indicates a button press + qCDebug(JoystickLog) << "button triggered" << buttonIndex; + + if (buttonIndex >= reservedButtonCount) { + // Button is above firmware reserved set + QString buttonAction =_rgButtonActions[buttonIndex]; + if (!buttonAction.isEmpty()) { + _buttonAction(buttonAction); + } + } + } + + // Mark the button as pressed as long as its pressed + buttonPressedBits |= buttonBit; + } + } + + _lastButtonBits = newButtonBits; + + //qCDebug(JoystickValuesLog) << "name:roll:pitch:yaw:throttle" << name() << roll << -pitch << yaw << throttle; + + emit manualControl(roll, -pitch, yaw, throttle, buttonPressedBits, _activeVehicle->joystickMode()); + } + + // Sleep, update rate of joystick is approx. 25 Hz (1000 ms / 25 = 40 ms) + QGC::SLEEP::msleep(40); + } + + close(); +} void Joystick::_loadSettings(void) { @@ -245,117 +339,6 @@ float Joystick::_adjustRange(int value, Calibration_t calibration) } -void Joystick::run(void) -{ -#ifdef __sdljoystick__ - SDL_Joystick* sdlJoystick = SDL_JoystickOpen(_sdlIndex); - - if (!sdlJoystick) { - qCWarning(JoystickLog) << "SDL_JoystickOpen failed:" << SDL_GetError(); - return; - } - - while (!_exitThread) { - SDL_JoystickUpdate(); - - // Update axes - for (int axisIndex=0; axisIndex<_axisCount; axisIndex++) { - int newAxisValue = SDL_JoystickGetAxis(sdlJoystick, axisIndex); - // Calibration code requires signal to be emitted even if value hasn't changed - _rgAxisValues[axisIndex] = newAxisValue; - emit rawAxisValueChanged(axisIndex, newAxisValue); - } - - // Update buttons - for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { - bool newButtonValue = !!SDL_JoystickGetButton(sdlJoystick, buttonIndex); - if (newButtonValue != _rgButtonValues[buttonIndex]) { - _rgButtonValues[buttonIndex] = newButtonValue; - emit rawButtonPressedChanged(buttonIndex, newButtonValue); - } - } - - if (_calibrationMode != CalibrationModeCalibrating) { - int axis = _rgFunctionAxis[rollFunction]; - float roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - axis = _rgFunctionAxis[pitchFunction]; - float pitch = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - axis = _rgFunctionAxis[yawFunction]; - float yaw = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - axis = _rgFunctionAxis[throttleFunction]; - float throttle = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis]); - - float roll_limited = std::max(static_cast(-M_PI_4), std::min(roll, static_cast(M_PI_4))); - float pitch_limited = std::max(static_cast(-M_PI_4), std::min(pitch, static_cast(M_PI_4))); - float yaw_limited = std::max(static_cast(-M_PI_4), std::min(yaw, static_cast(M_PI_4))); - float throttle_limited = std::max(static_cast(-M_PI_4), std::min(throttle, static_cast(M_PI_4))); - - // Map from unit circle to linear range and limit - roll = std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f)); - pitch = std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f)); - yaw = std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f)); - throttle = std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f)); - - // Adjust throttle to 0:1 range - if (_throttleMode == ThrottleModeCenterZero) { - throttle = std::max(0.0f, throttle); - } else { - throttle = (throttle + 1.0f) / 2.0f; - } - - // Set up button pressed information - - // We only send the buttons the firmwware has reserved - int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount(); - if (reservedButtonCount == -1) { - reservedButtonCount = _buttonCount; - } - - quint16 newButtonBits = 0; // New set of button which are down - quint16 buttonPressedBits = 0; // Buttons pressed for manualControl signal - - for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) { - quint16 buttonBit = 1 << buttonIndex; - - if (!_rgButtonValues[buttonIndex]) { - // Button up, just record it - newButtonBits |= buttonBit; - } else { - if (_lastButtonBits & buttonBit) { - // Button was up last time through, but is now down which indicates a button press - qCDebug(JoystickLog) << "button triggered" << buttonIndex; - - if (buttonIndex >= reservedButtonCount) { - // Button is above firmware reserved set - QString buttonAction =_rgButtonActions[buttonIndex]; - if (!buttonAction.isEmpty()) { - _buttonAction(buttonAction); - } - } - } - - // Mark the button as pressed as long as its pressed - buttonPressedBits |= buttonBit; - } - } - - _lastButtonBits = newButtonBits; - - qCDebug(JoystickValuesLog) << "name:roll:pitch:yaw:throttle" << name() << roll << -pitch << yaw << throttle; - - emit manualControl(roll, -pitch, yaw, throttle, buttonPressedBits, _activeVehicle->joystickMode()); - } - - // Sleep, update rate of joystick is approx. 25 Hz (1000 ms / 25 = 40 ms) - QGC::SLEEP::msleep(40); - } - - SDL_JoystickClose(sdlJoystick); -#endif -} void Joystick::startPolling(Vehicle* vehicle) { diff --git a/src/Joystick/Joystick.h b/src/Joystick/Joystick.h index 6eb2d40..389a737 100644 --- a/src/Joystick/Joystick.h +++ b/src/Joystick/Joystick.h @@ -39,9 +39,9 @@ class Joystick : public QThread Q_OBJECT public: - Joystick(const QString& name, int axisCount, int buttonCount, int sdlIndex, MultiVehicleManager* multiVehicleManager); + Joystick(const QString& name, int axisCount, int buttonCount, MultiVehicleManager* multiVehicleManager); ~Joystick(); - + typedef struct { int min; int max; @@ -136,7 +136,7 @@ signals: void buttonActionTriggered(int action); -private: +protected: void _saveSettings(void); void _loadSettings(void); float _adjustRange(int value, Calibration_t calibration); @@ -144,11 +144,18 @@ private: bool _validAxis(int axis); bool _validButton(int button); +private: + virtual bool open() = 0; + virtual void close() = 0; + virtual bool update() = 0; + + virtual bool getButton(int i) = 0; + virtual int getAxis(int i) = 0; + // Override from QThread virtual void run(void); -private: - int _sdlIndex; ///< Index for SDL_JoystickOpen +protected: bool _exitThread; ///< true: signal thread to exit diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc new file mode 100644 index 0000000..3de7ce4 --- /dev/null +++ b/src/Joystick/JoystickAndroid.cc @@ -0,0 +1,199 @@ +#include "JoystickAndroid.h" + +#include "QGCApplication.h" + +#include + +int JoystickAndroid::_androidBtnListCount; +int *JoystickAndroid::_androidBtnList; +QMutex JoystickAndroid::m_mutex; + +JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager) + : Joystick(name,0,0,multiVehicleManager) //buttonCount and axisCount is computed below + , deviceId(id) +{ + int i; + + QAndroidJniEnvironment env; + + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); + + //get number of buttons + jintArray a = env->NewIntArray(_androidBtnListCount); + env->SetIntArrayRegion(a,0,_androidBtnListCount,_androidBtnList); + + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + jbooleanArray jSupportedButtons = btns.object(); + int btn_sz = env->GetArrayLength(jSupportedButtons); + jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); + _buttonCount=0; + for (i=0;iReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); + + //get number of axis + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); + _axisCount = rangeListNative.callMethod("size"); + axisValue = new int[_axisCount]; + axisCode = new int[_axisCount]; + for (i=0;i<_axisCount;i++) { + QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); + if (range.isValid()) + axisCode[i] = range.callMethod("getAxis"); + axisValue[i] = 0; + } + + qDebug() << "joystick constructor:" << _name; + + QtAndroidPrivate::registerGenericMotionEventListener(this); + QtAndroidPrivate::registerKeyEventListener(this); +} + +JoystickAndroid::~JoystickAndroid() { + qDebug() << "joystick destructor" << _name; + + delete btnCode; + delete axisCode; + delete btnValue; + delete axisValue; + + QtAndroidPrivate::unregisterGenericMotionEventListener(this); + QtAndroidPrivate::unregisterKeyEventListener(this); +} + +bool JoystickAndroid::handleKeyEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + qDebug() << "handleKeyEvent!" << deviceId; + return true; +} + +bool JoystickAndroid::handleGenericMotionEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + qDebug() << "handleMotionEvent!" << deviceId; + return true; +} + +QMap JoystickAndroid::discover(MultiVehicleManager* _multiVehicleManager) { + bool joystickFound = false; + static QMap ret; + + _buttonList(); //it's enough to run it once, should be in a static constructor + + QMutexLocker lock(&m_mutex); + + QAndroidJniEnvironment env; + QAndroidJniObject o = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDeviceIds"); + jintArray jarr = o.object(); + size_t sz = env->GetArrayLength(jarr); + jint *buff = env->GetIntArrayElements(jarr, nullptr); + + int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); + int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); + + for (size_t i = 0; i < sz; ++i) { + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); + int sources = inputDevice.callMethod("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(); + + + if (joystickFound) { //skipping { + qWarning() << "Skipping joystick:" << name; + continue; + } + + qDebug() << "\t" << name << "id:" << buff[i]; + ret[name] = new JoystickAndroid(name, buff[i], _multiVehicleManager); + joystickFound = true; + } + + env->ReleaseIntArrayElements(jarr, buff, 0); + + + return ret; +} + +bool JoystickAndroid::open(void) { + return true; +} + +void JoystickAndroid::close(void) { +} + +bool JoystickAndroid::update(void) +{ + return true; +} + +bool JoystickAndroid::getButton(int i) { + return btnValue[ btnCode[i] ]; +} + +int JoystickAndroid::getAxis(int i) { + return axisValue[ axisCode[i] ]; +} + + +//helper method +void JoystickAndroid::_buttonList() { + //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 + + //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; + + for (i=1;i<=16;i++) { + QString name = "KEYCODE_BUTTON_"+QString::number(i); + ret[i-1] = QAndroidJniObject::getStaticField("android/view/KeyEvent", name.toStdString().c_str()); + } + i--; + + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_A"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_B"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_C"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R1"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R2"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_MODE"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_SELECT"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_START"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBL"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBR"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_X"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); + ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); + + for (int j=0;j<_androidBtnListCount;j++) + qDebug() << "\tpossible button: "+QString::number(_androidBtnList[j]); + +} + diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h new file mode 100644 index 0000000..48f83ec --- /dev/null +++ b/src/Joystick/JoystickAndroid.h @@ -0,0 +1,48 @@ +#ifndef JOYSTICKANDROID_H +#define JOYSTICKANDROID_H + +#include "Joystick.h" +#include "Vehicle.h" +#include "MultiVehicleManager.h" + +#include +#include +#include +#include +#include + + +class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener +{ +public: + JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager); + ~JoystickAndroid(); + + static QMap discover(MultiVehicleManager* _multiVehicleManager); + +private: + bool handleKeyEvent(jobject event); + bool handleGenericMotionEvent(jobject event); + + virtual bool open(); + virtual void close(); + virtual bool update(); + + virtual bool getButton(int i); + virtual int getAxis(int i); + + int *btnCode; + int *axisCode; + bool *btnValue; + int *axisValue; + + static void _buttonList(); + static int * _androidBtnList; //list of all possible android buttons + static int _androidBtnListCount; + + static QMutex m_mutex; + + int deviceId; +}; + +#endif // JOYSTICKANDROID_H diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 96c83e3..3828c30 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -27,12 +27,12 @@ #include #ifndef __mobile__ + #include "JoystickSDL.h" #define __sdljoystick__ - #ifdef Q_OS_MAC - #include - #else - #include - #endif +#endif + +#ifdef __android__ + #include "JoystickAndroid.h" #endif QGC_LOGGING_CATEGORY(JoystickManagerLog, "JoystickManagerLog") @@ -45,7 +45,15 @@ JoystickManager::JoystickManager(QGCApplication* app) , _activeJoystick(NULL) , _multiVehicleManager(NULL) { - +} + +JoystickManager::~JoystickManager() { + QMap::iterator i; + for (i = _name2JoystickMap.begin(); i != _name2JoystickMap.end(); ++i) { + qDebug() << "Releasing joystick:" << i.key(); + delete i.value(); + } + qDebug() << "Done"; } void JoystickManager::setToolbox(QGCToolbox *toolbox) @@ -57,82 +65,9 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); #ifdef __sdljoystick__ - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { - qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError(); - return; - } - - // Load available joysticks - - qCDebug(JoystickManagerLog) << "Available joysticks"; - - for (int i=0; i("android/view/InputDevice", "getDeviceIds"); - jintArray jarr = o.object(); - size_t sz = env->GetArrayLength(jarr); - jint *buff = env->GetIntArrayElements(jarr, nullptr); - - int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); - int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); - - for (size_t i = 0; i < sz; ++i) { - int axisCount, buttonCount; - QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); - int sources = inputDevice.callMethod("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(); - - //get number of buttons - jintArray a = env->NewIntArray(31); - env->SetIntArrayRegion(a,0,31,_possibleButtons); - - //QAndroidJniObject keyMap = inputDevice.callObjectMethod("getKeyCharacterMap", "()Landroid/view/KeyCharacterMap;"); - //QAndroidJniObject btns = keyMap.callStaticObjectMethod("android/view/KeyCharacterMap","deviceHasKeys", "([I)[Z", a); - QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); - jbooleanArray jSupportedButtons = btns.object(); - size_t btn_sz = env->GetArrayLength(jSupportedButtons); - jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); - buttonCount=0; - for (size_t j=0;jReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); - - //get number of axis - QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); - axisCount = rangeListNative.callMethod("size"); - - qCDebug(JoystickManagerLog) << "\t" << name << "axes:" << axisCount << "buttons:" << buttonCount; - _name2JoystickMap[name] = new Joystick(name, axisCount, buttonCount, buff[i], _multiVehicleManager); - } - - env->ReleaseIntArrayElements(jarr, buff, 0); + _name2JoystickMap = JoystickAndroid::discover(_multiVehicleManager); #endif if (!_name2JoystickMap.count()) { @@ -143,38 +78,6 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) _setActiveJoystickFromSettings(); } -void JoystickManager::computePossibleButtons() { - static int ret[31]; - int i; - - for (i=1;i<=16;i++) { - QString name = "KEYCODE_BUTTON_"+QString::number(i); - ret[i-1] = QAndroidJniObject::getStaticField("android/view/KeyEvent", name.toStdString().c_str()); - } - i--; - - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_A"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_B"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_C"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L1"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_L2"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R1"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_R2"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_MODE"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_SELECT"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_START"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBL"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBR"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_X"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); - ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); - - for (int j=0;j -#ifdef __android__ - #include - #include - #include - #include - #include -#endif - Q_DECLARE_LOGGING_CATEGORY(JoystickManagerLog) class QGCApplicaiton; @@ -49,6 +41,7 @@ class JoystickManager : public QGCTool public: JoystickManager(QGCApplication* app); + ~JoystickManager(); /// List of available joysticks Q_PROPERTY(QVariantList joysticks READ joysticks CONSTANT) @@ -86,12 +79,6 @@ private: static const char * _settingsGroup; static const char * _settingsKeyActiveJoystick; - -#ifdef __android__ - void computePossibleButtons(); - int * _possibleButtons; - QMutex m_mutex; -#endif }; #endif diff --git a/src/Joystick/JoystickSDL.cc b/src/Joystick/JoystickSDL.cc new file mode 100644 index 0000000..db90c11 --- /dev/null +++ b/src/Joystick/JoystickSDL.cc @@ -0,0 +1,73 @@ +#include "JoystickSDL.h" + +#include "QGCApplication.h" + +#include + +JoystickSDL::JoystickSDL(const QString& name, int axisCount, int buttonCount, int index, MultiVehicleManager* multiVehicleManager) + : Joystick(name,axisCount,buttonCount,multiVehicleManager) + , _index(index) +{ +} + +QMap JoystickSDL::discover(MultiVehicleManager* _multiVehicleManager) { + static QMap ret; + + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { + qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError(); + return ret; + } + + // Load available joysticks + + qCDebug(JoystickLog) << "Available joysticks"; + + for (int i=0; i +#else + #include +#endif + + +class JoystickSDL : public Joystick +{ +public: + JoystickSDL(const QString& name, int axisCount, int buttonCount, int index, MultiVehicleManager* multiVehicleManager); + + static QMap discover(MultiVehicleManager* _multiVehicleManager); + +private: + virtual bool open(); + virtual void close(); + virtual bool update(); + + virtual bool getButton(int i); + virtual int getAxis(int i); + + SDL_Joystick *sdlJoystick; + int _index; ///< Index for SDL_JoystickOpen +}; + +#endif // JOYSTICKSDL_H From 8c0e81d997e4929f0bce7343cf20b09f172438e3 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Fri, 22 Apr 2016 22:34:34 +0100 Subject: [PATCH 12/21] Cleanup --- src/Joystick/Joystick.cc | 6 +++--- src/Joystick/JoystickAndroid.cc | 16 ++++++++-------- src/VehicleSetup/SetupView.qml | 1 + 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index 0e1abea..a320cb2 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -89,7 +89,7 @@ void Joystick::run(void) open(); while (!_exitThread) { - update(); + update(); // Update axes for (int axisIndex=0; axisIndex<_axisCount; axisIndex++) { @@ -143,9 +143,9 @@ void Joystick::run(void) // We only send the buttons the firmwware has reserved int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount(); - if (reservedButtonCount == -1) { + if (reservedButtonCount == -1) reservedButtonCount = _buttonCount; - } + quint16 newButtonBits = 0; // New set of button which are down quint16 buttonPressedBits = 0; // Buttons pressed for manualControl signal diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index 3de7ce4..14bdcf9 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -49,20 +49,20 @@ JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManage axisValue = new int[_axisCount]; axisCode = new int[_axisCount]; for (i=0;i<_axisCount;i++) { - QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); - if (range.isValid()) - axisCode[i] = range.callMethod("getAxis"); - axisValue[i] = 0; + QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); + if (range.isValid()) + axisCode[i] = range.callMethod("getAxis"); + axisValue[i] = 0; } - qDebug() << "joystick constructor:" << _name; + _axisCount = 4; + qDebug() << "axis:" <<_axisCount << "buttons:" <<_buttonCount; QtAndroidPrivate::registerGenericMotionEventListener(this); QtAndroidPrivate::registerKeyEventListener(this); } JoystickAndroid::~JoystickAndroid() { - qDebug() << "joystick destructor" << _name; delete btnCode; delete axisCode; @@ -150,11 +150,11 @@ bool JoystickAndroid::update(void) } bool JoystickAndroid::getButton(int i) { - return btnValue[ btnCode[i] ]; + return btnValue[ i ]; } int JoystickAndroid::getAxis(int i) { - return axisValue[ axisCode[i] ]; + return axisValue[ i ]; } diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index 35c85d9..910aa14 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -287,6 +287,7 @@ Rectangle { setupComplete: joystickManager.activeJoystick ? joystickManager.activeJoystick.calibrated : false exclusiveGroup: setupButtonGroup visible: _fullParameterVehicleAvailable && joystickManager.joysticks.length != 0 + //visible: true text: "Joystick" onClicked: showJoystickPanel() From 51814a3d2f9c3924e26894217854193c3131e8fd Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Sat, 23 Apr 2016 08:36:04 +0100 Subject: [PATCH 13/21] Fixing issue with initialization --- qgroundcontrol.pro | 4 +++ src/Joystick/JoystickAndroid.cc | 74 +++++++++++++++++++++++------------------ src/Joystick/JoystickAndroid.h | 2 +- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 5998e7f..358241e 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -17,6 +17,10 @@ # along with QGroundControl. If not, see . # ------------------------------------------------- +#QMAKE_CFLAGS_DEBUG += -g +#QMAKE_CXXFLAGS += -g +#QMAKE_CXXFLAGS_DEBUG += -g + exists($${OUT_PWD}/qgroundcontrol.pro) { error("You must use shadow build (e.g. mkdir build; cd build; qmake ../qgroundcontrol.pro).") } diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index 14bdcf9..3036ce8 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -8,46 +8,42 @@ int JoystickAndroid::_androidBtnListCount; int *JoystickAndroid::_androidBtnList; QMutex JoystickAndroid::m_mutex; -JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager) - : Joystick(name,0,0,multiVehicleManager) //buttonCount and axisCount is computed below +JoystickAndroid::JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager) + : Joystick(name,axisCount,buttonCount,multiVehicleManager) , deviceId(id) { int i; QAndroidJniEnvironment env; - QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); + //if we define inputDevice in here this will fail for some reason, hence passing through argument + //QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); - //get number of buttons - jintArray a = env->NewIntArray(_androidBtnListCount); - env->SetIntArrayRegion(a,0,_androidBtnListCount,_androidBtnList); - QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + //set button mapping (number->code) + jintArray b = env->NewIntArray(_androidBtnListCount); + env->SetIntArrayRegion(b,0,_androidBtnListCount,_androidBtnList); + + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", b); jbooleanArray jSupportedButtons = btns.object(); - int btn_sz = env->GetArrayLength(jSupportedButtons); jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); - _buttonCount=0; - for (i=0;iReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); - //get number of axis - QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); - _axisCount = rangeListNative.callMethod("size"); + //set axis mapping (number->code) axisValue = new int[_axisCount]; axisCode = new int[_axisCount]; + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); for (i=0;i<_axisCount;i++) { QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); if (range.isValid()) @@ -55,7 +51,6 @@ JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManage axisValue[i] = 0; } - _axisCount = 4; qDebug() << "axis:" <<_axisCount << "buttons:" <<_buttonCount; QtAndroidPrivate::registerGenericMotionEventListener(this); @@ -63,7 +58,6 @@ JoystickAndroid::JoystickAndroid(const QString& name, int id, MultiVehicleManage } JoystickAndroid::~JoystickAndroid() { - delete btnCode; delete axisCode; delete btnValue; @@ -79,7 +73,7 @@ bool JoystickAndroid::handleKeyEvent(jobject event) { const int _deviceId = ev.callMethod("getDeviceId", "()I"); if (_deviceId!=deviceId) return false; - qDebug() << "handleKeyEvent!" << deviceId; + //qDebug() << "handleKeyEvent!" << deviceId; return true; } @@ -89,7 +83,7 @@ bool JoystickAndroid::handleGenericMotionEvent(jobject event) { const int _deviceId = ev.callMethod("getDeviceId", "()I"); if (_deviceId!=deviceId) return false; - qDebug() << "handleMotionEvent!" << deviceId; + //qDebug() << "handleMotionEvent!" << deviceId; return true; } @@ -104,13 +98,13 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe QAndroidJniEnvironment env; QAndroidJniObject o = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDeviceIds"); jintArray jarr = o.object(); - size_t sz = env->GetArrayLength(jarr); + int sz = env->GetArrayLength(jarr); jint *buff = env->GetIntArrayElements(jarr, nullptr); int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_GAMEPAD"); int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField("android/view/InputDevice", "SOURCE_JOYSTICK"); - for (size_t i = 0; i < sz; ++i) { + for (int i = 0; i < sz; ++i) { QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", buff[i]); int sources = inputDevice.callMethod("getSources", "()I"); if (((sources & SOURCE_GAMEPAD) != SOURCE_GAMEPAD) //check if the input device is interesting to us @@ -121,13 +115,29 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe QString name = inputDevice.callObjectMethod("getName", "()Ljava/lang/String;").toString(); - if (joystickFound) { //skipping { - qWarning() << "Skipping joystick:" << name; - continue; - } + if (joystickFound) { //skipping { + qWarning() << "Skipping joystick:" << name; + continue; + } + + //get number of axis + QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); + int axisCount = rangeListNative.callMethod("size"); + + //get number of buttons + jintArray a = env->NewIntArray(_androidBtnListCount); + env->SetIntArrayRegion(a,0,_androidBtnListCount,_androidBtnList); + QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", a); + jbooleanArray jSupportedButtons = btns.object(); + jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); + int buttonCount = 0; + for (i=0;i<_androidBtnListCount;i++) + if (supportedButtons[i]) buttonCount++; + env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); + + qDebug() << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount; - qDebug() << "\t" << name << "id:" << buff[i]; - ret[name] = new JoystickAndroid(name, buff[i], _multiVehicleManager); + ret[name] = new JoystickAndroid(inputDevice, name, axisCount, buttonCount, buff[i], _multiVehicleManager); joystickFound = true; } diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h index 48f83ec..7afca41 100644 --- a/src/Joystick/JoystickAndroid.h +++ b/src/Joystick/JoystickAndroid.h @@ -15,7 +15,7 @@ class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener { public: - JoystickAndroid(const QString& name, int id, MultiVehicleManager* multiVehicleManager); + JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager); ~JoystickAndroid(); static QMap discover(MultiVehicleManager* _multiVehicleManager); From 41fc119654f89eeb4aadde6393e7d8a7d3c1f786 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Sat, 23 Apr 2016 10:17:24 +0100 Subject: [PATCH 14/21] Implementing handlers --- src/Joystick/JoystickAndroid.cc | 89 +++++++++++++++++++++++------------------ src/Joystick/JoystickAndroid.h | 5 ++- 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index 3036ce8..f9eef36 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -6,19 +6,18 @@ int JoystickAndroid::_androidBtnListCount; int *JoystickAndroid::_androidBtnList; +int JoystickAndroid::ACTION_DOWN; +int JoystickAndroid::ACTION_UP; QMutex JoystickAndroid::m_mutex; -JoystickAndroid::JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager) +JoystickAndroid::JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager) : Joystick(name,axisCount,buttonCount,multiVehicleManager) , deviceId(id) { int i; QAndroidJniEnvironment env; - - //if we define inputDevice in here this will fail for some reason, hence passing through argument - //QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); - + QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); //set button mapping (number->code) jintArray b = env->NewIntArray(_androidBtnListCount); @@ -44,15 +43,14 @@ JoystickAndroid::JoystickAndroid(const QAndroidJniObject &inputDevice, const QSt axisValue = new int[_axisCount]; axisCode = new int[_axisCount]; QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); - for (i=0;i<_axisCount;i++) { - QAndroidJniObject range = rangeListNative.callObjectMethod("get", "()Landroid/view/InputDevice/MotionRange;"); - if (range.isValid()) - axisCode[i] = range.callMethod("getAxis"); + for (i=0;i<_axisCount;i++) { + QAndroidJniObject range = rangeListNative.callObjectMethod("get", "(I)Ljava/lang/Object;",i); + axisCode[i] = range.callMethod("getAxis"); axisValue[i] = 0; } - qDebug() << "axis:" <<_axisCount << "buttons:" <<_buttonCount; + qCDebug(JoystickLog) << "axis:" <<_axisCount << "buttons:" <<_buttonCount; QtAndroidPrivate::registerGenericMotionEventListener(this); QtAndroidPrivate::registerKeyEventListener(this); } @@ -67,31 +65,11 @@ JoystickAndroid::~JoystickAndroid() { QtAndroidPrivate::unregisterKeyEventListener(this); } -bool JoystickAndroid::handleKeyEvent(jobject event) { - QJNIObjectPrivate ev(event); - QMutexLocker lock(&m_mutex); - const int _deviceId = ev.callMethod("getDeviceId", "()I"); - if (_deviceId!=deviceId) return false; - - //qDebug() << "handleKeyEvent!" << deviceId; - return true; -} - -bool JoystickAndroid::handleGenericMotionEvent(jobject event) { - QJNIObjectPrivate ev(event); - QMutexLocker lock(&m_mutex); - const int _deviceId = ev.callMethod("getDeviceId", "()I"); - if (_deviceId!=deviceId) return false; - - //qDebug() << "handleMotionEvent!" << deviceId; - return true; -} - QMap JoystickAndroid::discover(MultiVehicleManager* _multiVehicleManager) { bool joystickFound = false; static QMap ret; - _buttonList(); //it's enough to run it once, should be in a static constructor + _initStatic(); //it's enough to run it once, should be in a static constructor QMutexLocker lock(&m_mutex); @@ -131,13 +109,13 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe jbooleanArray jSupportedButtons = btns.object(); jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); int buttonCount = 0; - for (i=0;i<_androidBtnListCount;i++) - if (supportedButtons[i]) buttonCount++; + for (int j=0;j<_androidBtnListCount;j++) + if (supportedButtons[j]) buttonCount++; env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); - qDebug() << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount; + qCDebug(JoystickLog) << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount; - ret[name] = new JoystickAndroid(inputDevice, name, axisCount, buttonCount, buff[i], _multiVehicleManager); + ret[name] = new JoystickAndroid(name, axisCount, buttonCount, buff[i], _multiVehicleManager); joystickFound = true; } @@ -147,6 +125,40 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe return ret; } + +bool JoystickAndroid::handleKeyEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + const int action = ev.callMethod("getAction", "()I"); + const int keyCode = ev.callMethod("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; + } + } + return false; +} + +bool JoystickAndroid::handleGenericMotionEvent(jobject event) { + QJNIObjectPrivate ev(event); + QMutexLocker lock(&m_mutex); + const int _deviceId = ev.callMethod("getDeviceId", "()I"); + if (_deviceId!=deviceId) return false; + + for (int i=0;i<_axisCount;i++) { + const float v = ev.callMethod("getAxisValue", "(I)F",axisCode[i]); + axisValue[i] = (int)(v*32767.f); + } + return true; +} + + bool JoystickAndroid::open(void) { return true; } @@ -169,7 +181,7 @@ int JoystickAndroid::getAxis(int i) { //helper method -void JoystickAndroid::_buttonList() { +void JoystickAndroid::_initStatic() { //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 @@ -202,8 +214,7 @@ void JoystickAndroid::_buttonList() { ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); ret[i++] = QAndroidJniObject::getStaticField("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); - for (int j=0;j<_androidBtnListCount;j++) - qDebug() << "\tpossible button: "+QString::number(_androidBtnList[j]); - + ACTION_DOWN = QAndroidJniObject::getStaticField("android/view/KeyEvent", "ACTION_DOWN"); + ACTION_UP = QAndroidJniObject::getStaticField("android/view/KeyEvent", "ACTION_UP"); } diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h index 7afca41..75ea813 100644 --- a/src/Joystick/JoystickAndroid.h +++ b/src/Joystick/JoystickAndroid.h @@ -15,7 +15,7 @@ class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener { public: - JoystickAndroid(const QAndroidJniObject &inputDevice, const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager); + JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager); ~JoystickAndroid(); static QMap discover(MultiVehicleManager* _multiVehicleManager); @@ -36,10 +36,11 @@ private: bool *btnValue; int *axisValue; - static void _buttonList(); + static void _initStatic(); static int * _androidBtnList; //list of all possible android buttons static int _androidBtnListCount; + static int ACTION_DOWN, ACTION_UP; static QMutex m_mutex; int deviceId; From 266d72f185ee383b8949b951c6476f749ff9f817 Mon Sep 17 00:00:00 2001 From: Gregory D Date: Tue, 26 Apr 2016 21:34:38 +0100 Subject: [PATCH 15/21] Update SetupView.qml --- src/VehicleSetup/SetupView.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index 910aa14..35c85d9 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -287,7 +287,6 @@ Rectangle { setupComplete: joystickManager.activeJoystick ? joystickManager.activeJoystick.calibrated : false exclusiveGroup: setupButtonGroup visible: _fullParameterVehicleAvailable && joystickManager.joysticks.length != 0 - //visible: true text: "Joystick" onClicked: showJoystickPanel() From b8e2f9802d7ea6b3984478f0a6066d368baef5e0 Mon Sep 17 00:00:00 2001 From: Gregory D Date: Tue, 26 Apr 2016 21:35:06 +0100 Subject: [PATCH 16/21] Update qgroundcontrol.pro --- qgroundcontrol.pro | 4 ---- 1 file changed, 4 deletions(-) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 358241e..5998e7f 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -17,10 +17,6 @@ # along with QGroundControl. If not, see . # ------------------------------------------------- -#QMAKE_CFLAGS_DEBUG += -g -#QMAKE_CXXFLAGS += -g -#QMAKE_CXXFLAGS_DEBUG += -g - exists($${OUT_PWD}/qgroundcontrol.pro) { error("You must use shadow build (e.g. mkdir build; cd build; qmake ../qgroundcontrol.pro).") } From 488fc264383415d7a2a1a9397adac14c404a7b57 Mon Sep 17 00:00:00 2001 From: Gregory D Date: Fri, 14 Oct 2016 10:55:10 +0100 Subject: [PATCH 17/21] Cleanup --- src/Joystick/joysticksdl.h | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 src/Joystick/joysticksdl.h diff --git a/src/Joystick/joysticksdl.h b/src/Joystick/joysticksdl.h deleted file mode 100644 index 2c4a9ca..0000000 --- a/src/Joystick/joysticksdl.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef JOYSTICKSDL_H -#define JOYSTICKSDL_H - -#include "Joystick.h" -#include "Vehicle.h" -#include "MultiVehicleManager.h" - -#include - -class JoystickSDL : public Joystick -{ -public: - JoystickSDL(const QString& name, int axisCount, int buttonCount, int hatCount, int index, bool isGameController, MultiVehicleManager* multiVehicleManager); - - static QMap discover(MultiVehicleManager* _multiVehicleManager); - -private: - static void _loadGameControllerMappings(); - - bool _open() final; - void _close() final; - bool _update() final; - - bool _getButton(int i) final; - int _getAxis(int i) final; - uint8_t _getHat(int hat,int i) final; - - SDL_Joystick *sdlJoystick; - SDL_GameController *sdlController; - bool _isGameController; - int _index; ///< Index for SDL_JoystickOpen -}; - -#endif // JOYSTICKSDL_H From 4bdae5121ef6d340a75bb2a1c767a38c0325f6e8 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Fri, 14 Oct 2016 11:23:23 +0100 Subject: [PATCH 18/21] Sync with upstream --- src/Joystick/JoystickAndroid.cc | 18 ++++++++++++------ src/Joystick/JoystickAndroid.h | 11 ++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index f9eef36..157acae 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -11,7 +11,7 @@ int JoystickAndroid::ACTION_UP; QMutex JoystickAndroid::m_mutex; JoystickAndroid::JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager) - : Joystick(name,axisCount,buttonCount,multiVehicleManager) + : Joystick(name,axisCount,buttonCount,0,multiVehicleManager) , deviceId(id) { int i; @@ -159,26 +159,32 @@ bool JoystickAndroid::handleGenericMotionEvent(jobject event) { } -bool JoystickAndroid::open(void) { +bool JoystickAndroid::_open(void) { return true; } -void JoystickAndroid::close(void) { +void JoystickAndroid::_close(void) { } -bool JoystickAndroid::update(void) +bool JoystickAndroid::_update(void) { return true; } -bool JoystickAndroid::getButton(int i) { +bool JoystickAndroid::_getButton(int i) { return btnValue[ i ]; } -int JoystickAndroid::getAxis(int i) { +int JoystickAndroid::_getAxis(int i) { return axisValue[ i ]; } +uint8_t JoystickAndroid::_getHat(int hat,int i) { + Q_UNUSED(hat); + Q_UNUSED(i); + + return 0; +} //helper method void JoystickAndroid::_initStatic() { diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h index 75ea813..b50c7f9 100644 --- a/src/Joystick/JoystickAndroid.h +++ b/src/Joystick/JoystickAndroid.h @@ -24,12 +24,13 @@ private: bool handleKeyEvent(jobject event); bool handleGenericMotionEvent(jobject event); - virtual bool open(); - virtual void close(); - virtual bool update(); + virtual bool _open(); + virtual void _close(); + virtual bool _update(); - virtual bool getButton(int i); - virtual int getAxis(int i); + virtual bool _getButton(int i); + virtual int _getAxis(int i); + virtual uint8_t _getHat(int hat,int i); int *btnCode; int *axisCode; From 30e422531ade02ba08e3952e516527f9bced980b Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Sat, 22 Oct 2016 13:22:48 +0100 Subject: [PATCH 19/21] Syncing SYS_COMPANION definition with Firmware --- src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml b/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml index b68ea44..70b016f 100644 --- a/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml +++ b/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml @@ -6671,6 +6671,8 @@ This is used for gathering replay logs for the ekf2 module modules/systemlib FrSky Telemetry + Normal Telemetry (19200 baud, 8N1) + Normal Telemetry (38400 baud, 8N1) Normal Telemetry (57600 baud, 8N1) Command Receiver (57600 baud, 8N1) OSD (57600 baud, 8N1) From 4a49c702aeaeebf3d209723e5e71da7b0068c42c Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Sat, 4 Mar 2017 10:14:36 +0000 Subject: [PATCH 20/21] Fixing compilation issues --- src/Joystick/Joystick.h | 4 ++-- src/Joystick/JoystickAndroid.cc | 1 + src/Joystick/JoystickManager.cc | 7 +++---- src/Joystick/JoystickSDL.cc | 5 +++-- src/Joystick/JoystickSDL.h | 1 + 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Joystick/Joystick.h b/src/Joystick/Joystick.h index 10d65fb..def702b 100644 --- a/src/Joystick/Joystick.h +++ b/src/Joystick/Joystick.h @@ -95,12 +95,12 @@ public: QVariantList buttonActions(void); QString name(void) { return _name; } - +/* // Joystick index used by sdl library // Settable because sdl library remaps indicies after certain events virtual int index(void) = 0; virtual void setIndex(int index) = 0; - +*/ virtual bool requiresCalibration(void) { return true; } int throttleMode(void); diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index 157acae..b965820 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -65,6 +65,7 @@ JoystickAndroid::~JoystickAndroid() { QtAndroidPrivate::unregisterKeyEventListener(this); } + QMap JoystickAndroid::discover(MultiVehicleManager* _multiVehicleManager) { bool joystickFound = false; static QMap ret; diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 8e51c98..389c90b 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -61,9 +61,8 @@ void JoystickManager::init() _joystickCheckTimer.start(250); } #elif defined(__android__) - /* - * Android Joystick not yet supported - */ + _setActiveJoystickFromSettings(); + //TODO: Investigate Android events for Joystick hot plugging & run _joystickCheckTimer if possible #endif } @@ -205,7 +204,7 @@ void JoystickManager::_updateAvailableJoysticks(void) } #elif defined(__android__) /* - * Android Joystick not yet supported + * TODO: Investigate Android events for Joystick hot plugging */ #endif } diff --git a/src/Joystick/JoystickSDL.cc b/src/Joystick/JoystickSDL.cc index cf7f105..3a230e4 100644 --- a/src/Joystick/JoystickSDL.cc +++ b/src/Joystick/JoystickSDL.cc @@ -68,8 +68,9 @@ QMap JoystickSDL::discover(MultiVehicleManager* _multiVehicl newRet[name] = new JoystickSDL(name, qMax(0,axisCount), qMax(0,buttonCount), qMax(0,hatCount), i, isGameController, _multiVehicleManager); } else { newRet[name] = ret[name]; - if (newRet[name]->index() != i) { - newRet[name]->setIndex(i); // This joystick index has been remapped by SDL + JoystickSDL *j = (JoystickSDL*)newRet[name]; + if (j->index() != i) { + j->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. diff --git a/src/Joystick/JoystickSDL.h b/src/Joystick/JoystickSDL.h index ba74e0a..905b01d 100644 --- a/src/Joystick/JoystickSDL.h +++ b/src/Joystick/JoystickSDL.h @@ -36,6 +36,7 @@ private: SDL_GameController *sdlController; bool _isGameController; int _index; ///< Index for SDL_JoystickOpen + }; #endif // JOYSTICKSDL_H From a18ca238cedf37647098d4280c5df35a16402e76 Mon Sep 17 00:00:00 2001 From: Gregory Dymarek Date: Sat, 4 Mar 2017 11:25:20 +0000 Subject: [PATCH 21/21] Comments --- src/Joystick/JoystickManager.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 389c90b..617d414 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -52,8 +52,7 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); } -void JoystickManager::init() -{ +void JoystickManager::init() { #ifdef __sdljoystick__ if (JoystickSDL::init()) { _setActiveJoystickFromSettings(); @@ -181,6 +180,9 @@ void JoystickManager::setActiveJoystickName(const QString& name) setActiveJoystick(_name2JoystickMap[name]); } +/* + * TODO: move this to the right place: JoystickSDL.cc and JoystickAndroid.cc respectively and call through Joystick.cc + */ void JoystickManager::_updateAvailableJoysticks(void) { #ifdef __sdljoystick__