11LPDIRECTINPUT8 DIinterf;
22 mRumbleEffect =
nullptr;
25 ZeroMemory(&mRumbleState,
sizeof(XINPUT_VIBRATION));
30 mThread = boost::thread(boost::bind(&
Joypad::run,
this));
46 boost::mutex::scoped_lock l(mMutex);
47 mTick = GetTickCount();
49 if (mIsrunning && !mConnected)
50 boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
52 if (mIsrunning && !mConnected && SUCCEEDED(InitDirectInput()))
56 if (UpdateInputState() != S_OK)
62 int elapsedTime = 33 - (int)(GetTickCount() -
mTick);
64 boost::this_thread::sleep_for(boost::chrono::milliseconds(elapsedTime));
68 catch (std::exception ex)
70 MMechostr(MSKDEBUG,
"Joypad > error thread : %s \n", ex.what());
76 boost::mutex::scoped_lock l(mMutex);
82 boost::mutex::scoped_lock l(mMutex);
92 mRumbleState.wLeftMotorSpeed =
static_cast<WORD
>(intensity * 65535.0f);
93 mRumbleState.wRightMotorSpeed =
static_cast<WORD
>(intensity * 65535.0f);
95 XInputSetState(mControllerId, &mRumbleState);
100 effect.dwSize =
sizeof(DIEFFECT);
101 effect.dwDuration = INFINITE;
102 effect.dwGain = DWORD(10000.0f * intensity);
103 effect.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
105 effect.rgdwAxes =
new DWORD[2];
106 effect.rgdwAxes[0] = DIJOFS_X;
107 effect.rgdwAxes[1] = DIJOFS_Y;
108 effect.rglDirection =
new LONG[2];
109 effect.rglDirection[0] = -200;
110 effect.rglDirection[1] = 200;
112 HRESULT hr = pJoystick->CreateEffect(GUID_Sine, &effect, &mRumbleEffect,
nullptr);
120 hr = mRumbleEffect->Start(1, 0);
123 mRumbleEffect->Release();
124 mRumbleEffect =
nullptr;
140 ZeroMemory(&mRumbleState,
sizeof(XINPUT_VIBRATION));
141 XInputSetState(mControllerId, &mRumbleState);
147 HRESULT hr = mRumbleEffect->Stop();
154 mRumbleEffect->Release();
155 mRumbleEffect =
nullptr;
164VOID Joypad::FreeDirectInput()
166 boost::mutex::scoped_lock l(gMutex);
173 pJoystick->Unacquire();
176 SAFE_RELEASE(pJoystick);
178 std::set<GUID>::iterator iJoystickIdSearched = lJoyId.find(mInstanceId);
179 if (iJoystickIdSearched != lJoyId.end())
180 lJoyId.erase(iJoystickIdSearched);
183 SAFE_RELEASE(DIinterf);
191HRESULT Joypad::InitDirectInput()
193 boost::mutex::scoped_lock l(gMutex);
200 if (DIinterf == NULL)
202 if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
203 IID_IDirectInput8, (VOID**)&DIinterf, NULL)))
207 DIJOYCONFIG PreferredJoyCfg;
208 ZeroMemory((
void*)&PreferredJoyCfg,
sizeof(DIJOYCONFIG));
209 PreferredJoyCfg.dwSize =
sizeof(DIJOYCONFIG) + 1;
211 pEnumContext.pPreferredJoyCfg = &PreferredJoyCfg;
212 pEnumContext.bPreferredJoyCfgValid =
false;
214 IDirectInputJoyConfig8* pJoyConfig = NULL;
215 if (FAILED(hr = DIinterf->QueryInterface(IID_IDirectInputJoyConfig8, (
void**)&pJoyConfig)))
218 if (SUCCEEDED(pJoyConfig->GetConfig(0, &PreferredJoyCfg, DIJC_GUIDINSTANCE)))
219 pEnumContext.bPreferredJoyCfgValid =
true;
220 SAFE_RELEASE(pJoyConfig);
222 if (DIinterf == NULL)
228 if (FAILED(hr = DIinterf->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback,
this, DIEDFL_ATTACHEDONLY)))
232 if (NULL == pJoystick)
243 if (FAILED(hr = pJoystick->SetDataFormat(&c_dfDIJoystick2)))
248 if (FAILED(hr = pJoystick->SetCooperativeLevel((HWND)SCgetExtra(
"hscol"), DISCL_EXCLUSIVE | DISCL_BACKGROUND)))
254 if (FAILED(hr = pJoystick->EnumObjects(EnumObjectsCallback, (VOID*)
this, DIDFT_ALL)))
266HRESULT Joypad::UpdateInputState()
270 if (NULL == pJoystick)
274 hr = pJoystick->Poll();
275 if (FAILED(hr) && (DIinterf != NULL))
281 hr = pJoystick->Acquire();
287 if ((pJoystick->GetDeviceState(
sizeof(
DIJOYSTATE2), &mDIJoyState)) != DI_OK)
291 *ndata = mDIJoyState;
312BOOL CALLBACK EnumJoysticksCallback(
const DIDEVICEINSTANCE* pdidInstance,
321 joypad->mControllerId++;
323 if (joypad->
mIndex != 0 && ((joypad->
mIndex - 1) != joypad->mControllerId))
324 return DIENUM_CONTINUE;
329 std::set<GUID>::iterator iJoystickIdSearched = lJoyId.find(pdidInstance->guidInstance);
330 if (iJoystickIdSearched != lJoyId.end())
331 return DIENUM_CONTINUE;
333 if (DIinterf == NULL)
337 hr = DIinterf->CreateDevice(pdidInstance->guidInstance, &joypad->pJoystick, NULL);
342 return DIENUM_CONTINUE;
345 dipdw.diph.dwSize =
sizeof(DIPROPDWORD);
346 dipdw.diph.dwHeaderSize =
sizeof(DIPROPHEADER);
347 dipdw.diph.dwObj = 0;
348 dipdw.diph.dwHow = DIPH_DEVICE;
350 hr = joypad->pJoystick->GetProperty(DIPROP_VIDPID, &dipdw.diph);
353 SAFE_RELEASE(joypad->pJoystick);
354 joypad->pJoystick = NULL;
355 return DIENUM_CONTINUE;
358 DWORD vendorID = LOWORD(dipdw.dwData);
359 DWORD productID = HIWORD(dipdw.dwData);
362 if (vendorID == 0x057e)
364 SAFE_RELEASE(joypad->pJoystick);
365 joypad->pJoystick = NULL;
366 return DIENUM_CONTINUE;
369 lJoyId.insert(pdidInstance->guidInstance);
370 joypad->mInstanceId = pdidInstance->guidInstance;
372 XINPUT_STATE xInputState;
373 joypad->mIsXInput = XInputGetState(joypad->mControllerId, &xInputState) == ERROR_SUCCESS;
388BOOL CALLBACK EnumObjectsCallback(
const DIDEVICEOBJECTINSTANCE* pdidoi,
393 static int nSliderCount = 0;
394 static int nPOVCount = 0;
398 if (pdidoi->dwType & DIDFT_AXIS)
401 diprg.diph.dwSize =
sizeof(DIPROPRANGE);
402 diprg.diph.dwHeaderSize =
sizeof(DIPROPHEADER);
403 diprg.diph.dwHow = DIPH_BYID;
404 diprg.diph.dwObj = pdidoi->dwType;
409 if (FAILED(joypad->pJoystick->SetProperty(DIPROP_RANGE, &diprg.diph)))
413 return DIENUM_CONTINUE;
416#elif defined(ANDROID)
417#include <android/input.h>
419extern AInputQueue* AndroidInputQueue;
421std::list<Joypad*> Joypad::lJoypad;
423void Joypad::updateInputEvent(AInputEvent* event)
425 std::list<Joypad*>::iterator it;
426 for (it = lJoypad.begin(); it != lJoypad.end(); it++)
428 (*it)->updateEvent(event);
441 for (
size_t i = 0; i < 16; i++)
444 for (
size_t i = 0; i < 4; i++)
455 lJoypad.push_back(
this);
464 std::set<int>::iterator iJoystickIdSearched = lJoyId.find(mDeviceId);
465 if (iJoystickIdSearched != lJoyId.end())
466 lJoyId.erase(iJoystickIdSearched);
469 lJoypad.remove(
this);
475 for (
size_t i = 0; i < 16; i++)
480 for (
size_t i = 0; i < 4; i++)
483 data->
lX = mDIJoyState.
lX;
484 data->
lY = mDIJoyState.
lY;
485 data->
lRx = mDIJoyState.
lRx;
486 data->
lRy = mDIJoyState.
lRy;
493void Joypad::configAxis()
495 struct android_app* androidApp = (
struct android_app*)SCgetExtra(
"this_inst");
500 ANativeActivity* nativeActivity = androidApp->activity;
501 nativeActivity->vm->AttachCurrentThread(&env, NULL);
508 jclass cInputDevice = env->FindClass(
"android/view/InputDevice");
509 jmethodID mGetInputDevice = env->GetStaticMethodID(cInputDevice,
"getDevice",
"(I)Landroid/view/InputDevice;");
510 jmethodID mGetMotionRanges = env->GetMethodID(cInputDevice,
"getMotionRanges",
"()Ljava/util/List;");
512 jclass cRange = env->FindClass(
"android/view/InputDevice$MotionRange");
513 jmethodID mGetAxis = env->GetMethodID(cRange,
"getAxis",
"()I");
515 jobject oDevice = (jobject)env->CallStaticObjectMethod(cInputDevice, mGetInputDevice, (jint)mDeviceId);
516 if (!env->ExceptionCheck() && oDevice)
518 jobject oMotionRanges = (jobject)env->CallObjectMethod(oDevice, mGetMotionRanges);
519 jclass cList = env->FindClass(
"java/util/List");
520 jmethodID mSize = env->GetMethodID(cList,
"size",
"()I");
521 jmethodID mGet = env->GetMethodID(cList,
"get",
"(I)Ljava/lang/Object;");
523 if (!env->ExceptionCheck() && oMotionRanges)
525 int length = env->CallIntMethod(oMotionRanges, mSize);
526 for (
int i = 0; i < length; i++)
528 jobject oRange = (jobject)env->CallObjectMethod(oMotionRanges, mGet, (jint)i);
529 int axis = (int)env->CallIntMethod(oRange, mGetAxis);
531 if (axis == AMOTION_EVENT_AXIS_RX || axis == AMOTION_EVENT_AXIS_RY)
534 env->DeleteLocalRef(oRange);
537 env->DeleteLocalRef(oMotionRanges);
539 env->DeleteLocalRef(oDevice);
542 if (env->ExceptionCheck())
543 env->ExceptionClear();
546 nativeActivity->vm->DetachCurrentThread();
550void Joypad::updateEvent(AInputEvent* event)
552 bool haveData =
false;
553 int32_t source = AInputEvent_getSource(event);
554 int32_t eventType = AInputEvent_getType(event);
555 int deviceid = AInputEvent_getDeviceId(event);
559 case AINPUT_EVENT_TYPE_KEY:
561 int32_t keycode = AKeyEvent_getKeyCode(event);
562 int32_t action = AKeyEvent_getAction(event);
564 int state = (action == AKEY_EVENT_ACTION_DOWN) ? 1 : 0;
569 case AKEYCODE_BUTTON_A:
570 case AKEYCODE_BUTTON_1:
573 case AKEYCODE_BUTTON_B:
574 case AKEYCODE_BUTTON_2:
577 case AKEYCODE_BUTTON_X:
578 case AKEYCODE_BUTTON_3:
581 case AKEYCODE_BUTTON_Y:
582 case AKEYCODE_BUTTON_4:
585 case AKEYCODE_BUTTON_L1:
586 case AKEYCODE_BUTTON_5:
589 case AKEYCODE_BUTTON_L2:
590 case AKEYCODE_BUTTON_6:
593 case AKEYCODE_BUTTON_SELECT:
594 case AKEYCODE_BUTTON_7:
597 case AKEYCODE_BUTTON_START:
598 case AKEYCODE_BUTTON_8:
601 case AKEYCODE_BUTTON_THUMBL:
602 case AKEYCODE_BUTTON_9:
605 case AKEYCODE_BUTTON_THUMBR:
606 case AKEYCODE_BUTTON_10:
609 case AKEYCODE_BUTTON_C:
610 case AKEYCODE_BUTTON_11:
613 case AKEYCODE_BUTTON_Z:
614 case AKEYCODE_BUTTON_12:
617 case AKEYCODE_BUTTON_R1:
618 case AKEYCODE_BUTTON_13:
621 case AKEYCODE_BUTTON_R2:
622 case AKEYCODE_BUTTON_14:
625 case AKEYCODE_BUTTON_MODE:
626 case AKEYCODE_BUTTON_15:
629 case AKEYCODE_BUTTON_16:
637 std::set<int>::iterator iJoystickIdSearched = lJoyId.find(deviceid);
638 if (mDeviceId == -1 && iJoystickIdSearched == lJoyId.end())
640 mDeviceId = deviceid;
641 lJoyId.insert(mDeviceId);
644 else if (mDeviceId != deviceid)
652 case AINPUT_EVENT_TYPE_MOTION:
654 if ((source != AINPUT_SOURCE_GAMEPAD) && (source != AINPUT_SOURCE_JOYSTICK))
657 std::set<int>::iterator iJoystickIdSearched = lJoyId.find(deviceid);
658 if (mDeviceId == -1 && iJoystickIdSearched == lJoyId.end())
660 mDeviceId = deviceid;
661 lJoyId.insert(mDeviceId);
664 else if (mDeviceId != deviceid)
668 for (
size_t p = 0; p < AMotionEvent_getPointerCount(event); p++)
670 mDIJoyState.
lX = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, p) * 1000.0f);
671 mDIJoyState.
lY = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, p) * 1000.0f);
676 mDIJoyState.
lRx = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RX, p) * 1000.0f);
677 mDIJoyState.
lRy = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RY, p) * 1000.0f);
678 mDIJoyState.
rglSlider[0] = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Z, p) * 1000.0f);
679 mDIJoyState.
rglSlider[1] = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RZ, p) * 1000.0f);
684 mDIJoyState.
lRx = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Z, p) * 1000.0f);
685 mDIJoyState.
lRy = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RZ, p) * 1000.0f);
686 mDIJoyState.
rglSlider[0] = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_LTRIGGER, p) * 1000.0f);
687 mDIJoyState.
rglSlider[1] = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RTRIGGER, p) * 1000.0f);
692 float px = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, p) * 1000.0f);
693 float py = (int)(AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_Y, p) * 1000.0f);
695 if (px == 0.0f && py == 0.0f)
697 else if (px == 0.0f && py < 0.0f)
699 else if (px > 0.0f && py < 0.0f)
701 else if (px > 0.0f && py == 0.0f)
703 else if (px > 0.0f && py > 0.0f)
705 else if (px == 0.0f && py > 0.0f)
707 else if (px < 0.0f && py > 0.0f)
709 else if (px < 0.0f && py == 0.0f)
711 else if (px < 0.0f && py < 0.0f)
720 int elapsedTime = (GetTickCount() -
mTick);
721 if (haveData && ((elapsedTime > 16) ||
mTick == 0))
725 mTick = GetTickCount();
757Q_IMPORT_PLUGIN(QXInputGamepadBackendPlugin)
758# elif defined(ANDROID)
759Q_IMPORT_PLUGIN(QAndroidGamepadBackendPlugin)
760# elif defined (OSX) || defined(APPLE_IOS)
761Q_IMPORT_PLUGIN(QDarwinGamepadBackendPlugin)
763Q_IMPORT_PLUGIN(QEvdevGamepadBackendPlugin)
773 for (
size_t i = 0; i < 16; i++)
776 for (
size_t i = 0; i < 4; i++)
801 SAFE_DELETE(mGamepad);
804void Joypad::initData()
806 mConnected = mGamepad->isConnected();
809 mDIJoyState.
rgbButtons[0] = mGamepad->buttonA();
810 mDIJoyState.
rgbButtons[1] = mGamepad->buttonB();
811 mDIJoyState.
rgbButtons[2] = mGamepad->buttonX();
812 mDIJoyState.
rgbButtons[3] = mGamepad->buttonY();
813 mDIJoyState.
rgbButtons[4] = mGamepad->buttonL1();
814 mDIJoyState.
rgbButtons[5] = mGamepad->buttonL2();
815 mDIJoyState.
rgbButtons[6] = mGamepad->buttonSelect();
816 mDIJoyState.
rgbButtons[7] = mGamepad->buttonStart();
817 mDIJoyState.
rgbButtons[8] = mGamepad->buttonL3();
818 mDIJoyState.
rgbButtons[9] = mGamepad->buttonR3();
821 mDIJoyState.
rgbButtons[12] = mGamepad->buttonR1();
822 mDIJoyState.
rgbButtons[13] = mGamepad->buttonR2();
823 mDIJoyState.
rgbButtons[14] = mGamepad->buttonGuide();
825 mDIJoyState.
lX = (int)(mGamepad->axisLeftX() * 1000.0f);
826 mDIJoyState.
lY = (int)(mGamepad->axisLeftY() * 1000.0f);
827 mDIJoyState.
lRx = (int)(mGamepad->axisRightX() * 1000.0f);
828 mDIJoyState.
lRy = (int)(mGamepad->axisRightY() * 1000.0f);
833 if (mGamepad->buttonCenter())
835 else if (!mGamepad->buttonLeft() && !mGamepad->buttonRight() && mGamepad->buttonUp())
837 else if (mGamepad->buttonRight() && mGamepad->buttonUp())
839 else if (mGamepad->buttonRight() && !mGamepad->buttonDown() && !mGamepad->buttonUp())
841 else if (mGamepad->buttonRight() && mGamepad->buttonDown())
843 else if (!mGamepad->buttonLeft() && !mGamepad->buttonRight() && mGamepad->buttonDown())
845 else if (mGamepad->buttonLeft() && mGamepad->buttonDown())
847 else if (mGamepad->buttonLeft() && !mGamepad->buttonDown() && !mGamepad->buttonUp())
849 else if (mGamepad->buttonLeft() && mGamepad->buttonUp())
855 for (
size_t i = 0; i < 16; i++)
860 for (
size_t i = 0; i < 4; i++)
863 data->
lX = mDIJoyState.
lX;
864 data->
lY = mDIJoyState.
lY;
865 data->
lRx = mDIJoyState.
lRx;
866 data->
lRy = mDIJoyState.
lRy;
875void Joypad::updateDoubleData(
double value)
880void Joypad::updateBoolData(
bool value)
889 const QList<int> gamepads = QGamepadManager::instance()->connectedGamepads();
890 if (gamepads.isEmpty())
897 mGamepad =
new QGamepad(*gamepads.begin(),
this);
899 connect(mGamepad, SIGNAL(connectedChanged(
bool)),
this, SLOT(updateBoolData(
double)));
900 connect(mGamepad, SIGNAL(axisLeftXChanged(
double)),
this, SLOT(updateDoubleData(
double)));
901 connect(mGamepad, SIGNAL(axisLeftYChanged(
double)),
this, SLOT(updateDoubleData(
double)));
902 connect(mGamepad, SIGNAL(axisRightXChanged(
double)),
this, SLOT(updateDoubleData(
double)));
903 connect(mGamepad, SIGNAL(axisRightYChanged(
double)),
this, SLOT(updateDoubleData(
double)));
904 connect(mGamepad, SIGNAL(buttonAChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
905 connect(mGamepad, SIGNAL(buttonBChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
906 connect(mGamepad, SIGNAL(buttonYChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
907 connect(mGamepad, SIGNAL(buttonL1Changed(
bool)),
this, SLOT(updateBoolData(
bool)));
908 connect(mGamepad, SIGNAL(buttonR1Changed(
bool)),
this, SLOT(updateBoolData(
bool)));
909 connect(mGamepad, SIGNAL(buttonL2Changed(
double)),
this, SLOT(updateDoubleData(
double)));
910 connect(mGamepad, SIGNAL(buttonR2Changed(
double)),
this, SLOT(updateDoubleData(
double)));
911 connect(mGamepad, SIGNAL(buttonL3Changed(
bool)),
this, SLOT(updateBoolData(
bool)));
912 connect(mGamepad, SIGNAL(buttonR3Changed(
bool)),
this, SLOT(updateBoolData(
bool)));
913 connect(mGamepad, SIGNAL(buttonSelectChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
914 connect(mGamepad, SIGNAL(buttonStartChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
915 connect(mGamepad, SIGNAL(buttonGuideChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
916 connect(mGamepad, SIGNAL(buttonUpChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
917 connect(mGamepad, SIGNAL(buttonDownChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
918 connect(mGamepad, SIGNAL(buttonLeftChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
919 connect(mGamepad, SIGNAL(buttonRightChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
920 connect(mGamepad, SIGNAL(buttonCenterChanged(
bool)),
this, SLOT(updateBoolData(
bool)));
bool StartRumble(float intensity)