/*===================================================================== QGroundControl Open Source Ground Control Station (c) 2009 - 2014 QGROUNDCONTROL PROJECT This file is part of the QGROUNDCONTROL project QGROUNDCONTROL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. QGROUNDCONTROL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with QGROUNDCONTROL. If not, see . ======================================================================*/ #include "JoystickManager.h" #include "QGCApplication.h" #include #ifndef __mobile__ #define __sdljoystick__ #ifdef Q_OS_MAC #include #else #include #endif #endif QGC_LOGGING_CATEGORY(JoystickManagerLog, "JoystickManagerLog") const char * JoystickManager::_settingsGroup = "JoystickManager"; const char * JoystickManager::_settingsKeyActiveJoystick = "ActiveJoystick"; JoystickManager::JoystickManager(QGCApplication* app) : QGCTool(app) , _activeJoystick(NULL) , _multiVehicleManager(NULL) { } void JoystickManager::setToolbox(QGCToolbox *toolbox) { QGCTool::setToolbox(toolbox); _multiVehicleManager = _toolbox->multiVehicleManager(); 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); #endif if (!_name2JoystickMap.count()) { qCDebug(JoystickManagerLog) << "\tnone found"; return; } _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;jname(); } setActiveJoystick(_name2JoystickMap.value(name, _name2JoystickMap.first())); settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name()); } Joystick* JoystickManager::activeJoystick(void) { return _activeJoystick; } void JoystickManager::setActiveJoystick(Joystick* joystick) { QSettings settings; if (!_name2JoystickMap.contains(joystick->name())) { qCWarning(JoystickManagerLog) << "Set active not in map" << joystick->name(); return; } if (_activeJoystick) { _activeJoystick->stopPolling(); } _activeJoystick = joystick; settings.beginGroup(_settingsGroup); settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name()); emit activeJoystickChanged(_activeJoystick); emit activeJoystickNameChanged(_activeJoystick->name()); } QVariantList JoystickManager::joysticks(void) { QVariantList list; foreach (const QString &name, _name2JoystickMap.keys()) { list += QVariant::fromValue(_name2JoystickMap[name]); } return list; } QStringList JoystickManager::joystickNames(void) { return _name2JoystickMap.keys(); } QString JoystickManager::activeJoystickName(void) { return _activeJoystick ? _activeJoystick->name() : QString(); } void JoystickManager::setActiveJoystickName(const QString& name) { if (!_name2JoystickMap.contains(name)) { qCWarning(JoystickManagerLog) << "Set active not in map" << name; return; } setActiveJoystick(_name2JoystickMap[name]); }