4 changed files with 8 additions and 274 deletions
@ -1,221 +0,0 @@ |
|||||||
#include "JoystickAndroid.h" |
|
||||||
|
|
||||||
#include "QGCApplication.h" |
|
||||||
|
|
||||||
#include <QQmlEngine> |
|
||||||
|
|
||||||
int JoystickAndroid::_androidBtnListCount; |
|
||||||
int *JoystickAndroid::_androidBtnList; |
|
||||||
int JoystickAndroid::ACTION_DOWN; |
|
||||||
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) |
|
||||||
, deviceId(id) |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
QAndroidJniEnvironment env; |
|
||||||
QAndroidJniObject inputDevice = QAndroidJniObject::callStaticObjectMethod("android/view/InputDevice", "getDevice", "(I)Landroid/view/InputDevice;", id); |
|
||||||
|
|
||||||
//set button mapping (number->code)
|
|
||||||
jintArray b = env->NewIntArray(_androidBtnListCount); |
|
||||||
env->SetIntArrayRegion(b,0,_androidBtnListCount,_androidBtnList); |
|
||||||
|
|
||||||
QAndroidJniObject btns = inputDevice.callObjectMethod("hasKeys", "([I)[Z", b); |
|
||||||
jbooleanArray jSupportedButtons = btns.object<jbooleanArray>(); |
|
||||||
jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); |
|
||||||
//create a mapping table (btnCode) that maps button number with button code
|
|
||||||
btnValue = new bool[_buttonCount]; |
|
||||||
btnCode = new int[_buttonCount]; |
|
||||||
int c = 0; |
|
||||||
for (i=0;i<_androidBtnListCount;i++) |
|
||||||
if (supportedButtons[i]) { |
|
||||||
btnValue[c] = false; |
|
||||||
btnCode[c] = _androidBtnList[i]; |
|
||||||
c++; |
|
||||||
} |
|
||||||
|
|
||||||
env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); |
|
||||||
|
|
||||||
//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", "(I)Ljava/lang/Object;",i); |
|
||||||
axisCode[i] = range.callMethod<jint>("getAxis"); |
|
||||||
axisValue[i] = 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
qCDebug(JoystickLog) << "axis:" <<_axisCount << "buttons:" <<_buttonCount; |
|
||||||
QtAndroidPrivate::registerGenericMotionEventListener(this); |
|
||||||
QtAndroidPrivate::registerKeyEventListener(this); |
|
||||||
} |
|
||||||
|
|
||||||
JoystickAndroid::~JoystickAndroid() { |
|
||||||
delete btnCode; |
|
||||||
delete axisCode; |
|
||||||
delete btnValue; |
|
||||||
delete axisValue; |
|
||||||
|
|
||||||
QtAndroidPrivate::unregisterGenericMotionEventListener(this); |
|
||||||
QtAndroidPrivate::unregisterKeyEventListener(this); |
|
||||||
} |
|
||||||
|
|
||||||
QMap<QString, Joystick*> JoystickAndroid::discover(MultiVehicleManager* _multiVehicleManager) { |
|
||||||
bool joystickFound = false; |
|
||||||
static QMap<QString, Joystick*> ret; |
|
||||||
|
|
||||||
_initStatic(); //it's enough to run it once, should be in a static constructor
|
|
||||||
|
|
||||||
QMutexLocker lock(&m_mutex); |
|
||||||
|
|
||||||
QAndroidJniEnvironment env; |
|
||||||
QAndroidJniObject o = QAndroidJniObject::callStaticObjectMethod<jintArray>("android/view/InputDevice", "getDeviceIds"); |
|
||||||
jintArray jarr = o.object<jintArray>(); |
|
||||||
int sz = env->GetArrayLength(jarr); |
|
||||||
jint *buff = env->GetIntArrayElements(jarr, nullptr); |
|
||||||
|
|
||||||
int SOURCE_GAMEPAD = QAndroidJniObject::getStaticField<jint>("android/view/InputDevice", "SOURCE_GAMEPAD"); |
|
||||||
int SOURCE_JOYSTICK = QAndroidJniObject::getStaticField<jint>("android/view/InputDevice", "SOURCE_JOYSTICK"); |
|
||||||
|
|
||||||
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<jint>("getSources", "()I"); |
|
||||||
if (((sources & SOURCE_GAMEPAD) != SOURCE_GAMEPAD) //check if the input device is interesting to us
|
|
||||||
&& ((sources & SOURCE_JOYSTICK) != SOURCE_JOYSTICK)) continue; |
|
||||||
|
|
||||||
//get id and name
|
|
||||||
QString id = inputDevice.callObjectMethod("getDescriptor", "()Ljava/lang/String;").toString(); |
|
||||||
QString name = inputDevice.callObjectMethod("getName", "()Ljava/lang/String;").toString(); |
|
||||||
|
|
||||||
|
|
||||||
if (joystickFound) { //skipping {
|
|
||||||
qWarning() << "Skipping joystick:" << name; |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
//get number of axis
|
|
||||||
QAndroidJniObject rangeListNative = inputDevice.callObjectMethod("getMotionRanges", "()Ljava/util/List;"); |
|
||||||
int axisCount = rangeListNative.callMethod<jint>("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<jbooleanArray>(); |
|
||||||
jboolean* supportedButtons = env->GetBooleanArrayElements(jSupportedButtons, nullptr); |
|
||||||
int buttonCount = 0; |
|
||||||
for (int j=0;j<_androidBtnListCount;j++) |
|
||||||
if (supportedButtons[j]) buttonCount++; |
|
||||||
env->ReleaseBooleanArrayElements(jSupportedButtons, supportedButtons, 0); |
|
||||||
|
|
||||||
qCDebug(JoystickLog) << "\t" << name << "id:" << buff[i] << "axes:" << axisCount << "buttons:" << buttonCount; |
|
||||||
|
|
||||||
ret[name] = new JoystickAndroid(name, axisCount, buttonCount, buff[i], _multiVehicleManager); |
|
||||||
joystickFound = true; |
|
||||||
} |
|
||||||
|
|
||||||
env->ReleaseIntArrayElements(jarr, buff, 0); |
|
||||||
|
|
||||||
|
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool JoystickAndroid::handleKeyEvent(jobject event) { |
|
||||||
QJNIObjectPrivate ev(event); |
|
||||||
QMutexLocker lock(&m_mutex); |
|
||||||
const int _deviceId = ev.callMethod<jint>("getDeviceId", "()I"); |
|
||||||
if (_deviceId!=deviceId) return false; |
|
||||||
|
|
||||||
const int action = ev.callMethod<jint>("getAction", "()I"); |
|
||||||
const int keyCode = ev.callMethod<jint>("getKeyCode", "()I"); |
|
||||||
|
|
||||||
for (int i=0;i<_buttonCount;i++) { |
|
||||||
if (btnCode[i]==keyCode) { |
|
||||||
if (action==ACTION_DOWN) btnValue[i] = true; |
|
||||||
if (action==ACTION_UP) btnValue[i] = false; |
|
||||||
qWarning() << "Btn:"<<i; |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
bool JoystickAndroid::handleGenericMotionEvent(jobject event) { |
|
||||||
QJNIObjectPrivate ev(event); |
|
||||||
QMutexLocker lock(&m_mutex); |
|
||||||
const int _deviceId = ev.callMethod<jint>("getDeviceId", "()I"); |
|
||||||
if (_deviceId!=deviceId) return false; |
|
||||||
|
|
||||||
for (int i=0;i<_axisCount;i++) { |
|
||||||
const float v = ev.callMethod<jfloat>("getAxisValue", "(I)F",axisCode[i]); |
|
||||||
axisValue[i] = (int)(v*32767.f); |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool JoystickAndroid::open(void) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
void JoystickAndroid::close(void) { |
|
||||||
} |
|
||||||
|
|
||||||
bool JoystickAndroid::update(void) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
bool JoystickAndroid::getButton(int i) { |
|
||||||
return btnValue[ i ]; |
|
||||||
} |
|
||||||
|
|
||||||
int JoystickAndroid::getAxis(int i) { |
|
||||||
return axisValue[ i ]; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//helper method
|
|
||||||
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
|
|
||||||
|
|
||||||
//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<jint>("android/view/KeyEvent", name.toStdString().c_str()); |
|
||||||
} |
|
||||||
i--; |
|
||||||
|
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_A"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_B"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_C"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_L1"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_L2"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_R1"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_R2"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_MODE"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_SELECT"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_START"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBL"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_THUMBR"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_X"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_Y"); |
|
||||||
ret[i++] = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "KEYCODE_BUTTON_Z"); |
|
||||||
|
|
||||||
ACTION_DOWN = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "ACTION_DOWN"); |
|
||||||
ACTION_UP = QAndroidJniObject::getStaticField<jint>("android/view/KeyEvent", "ACTION_UP"); |
|
||||||
} |
|
||||||
|
|
@ -1,49 +0,0 @@ |
|||||||
#ifndef JOYSTICKANDROID_H |
|
||||||
#define JOYSTICKANDROID_H |
|
||||||
|
|
||||||
#include "Joystick.h" |
|
||||||
#include "Vehicle.h" |
|
||||||
#include "MultiVehicleManager.h" |
|
||||||
|
|
||||||
#include <jni.h> |
|
||||||
#include <QtCore/private/qjni_p.h> |
|
||||||
#include <QtCore/private/qjnihelpers_p.h> |
|
||||||
#include <QtAndroidExtras/QtAndroidExtras> |
|
||||||
#include <QtAndroidExtras/QAndroidJniObject> |
|
||||||
|
|
||||||
|
|
||||||
class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener |
|
||||||
{ |
|
||||||
public: |
|
||||||
JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager); |
|
||||||
~JoystickAndroid(); |
|
||||||
|
|
||||||
static QMap<QString, Joystick*> 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 _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; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // JOYSTICKANDROID_H
|
|
Loading…
Reference in new issue