Files
itgmania212121/src/arch/InputHandler/InputHandler_DirectInputHelper.cpp
T

392 lines
11 KiB
C++
Raw Normal View History

2010-01-26 21:00:30 -06:00
#include "global.h"
#include "InputHandler_DirectInputHelper.h"
#include "RageUtil.h"
#include "RageLog.h"
#include "archutils/Win32/DirectXHelpers.h"
#include "archutils/Win32/ErrorStrings.h"
#include "archutils/Win32/GraphicsWindow.h"
#if defined(_MSC_VER)
#pragma comment(lib, "dinput.lib")
#if defined(_WINDOWS)
#pragma comment(lib, "dxguid.lib")
#endif
#endif
LPDIRECTINPUT g_dinput = NULL;
static int ConvertScancodeToKey( int scancode );
static BOOL CALLBACK DIJoystick_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID data);
static BOOL CALLBACK DIMouse_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID data);
2010-01-26 21:00:30 -06:00
DIDevice::DIDevice()
{
buttons = axes = hats = 0;
dev = InputDevice_Invalid;
buffered = true;
memset(&JoystickInst, 0, sizeof(JoystickInst));
//memset(&MouseInst, 0, sizeof(MouseInst));
2010-01-26 21:00:30 -06:00
Device = NULL;
}
bool DIDevice::Open()
{
m_sName = ConvertACPToUTF8( JoystickInst.tszProductName );
LOG->Trace( "Opening device '%s'", m_sName.c_str() );
buffered = true;
LPDIRECTINPUTDEVICE tmpdevice;
2011-02-14 01:43:41 -06:00
// load joystick
2010-01-26 21:00:30 -06:00
HRESULT hr = g_dinput->CreateDevice( JoystickInst.guidInstance, &tmpdevice, NULL );
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice: IDirectInput_CreateDevice") );
return false;
}
hr = tmpdevice->QueryInterface( IID_IDirectInputDevice2, (LPVOID *) &Device );
tmpdevice->Release();
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice::QueryInterface", m_sName.c_str()) );
return false;
}
// load mouse
/*
hr = g_dinput->CreateDevice( MouseInst.guidInstance, &tmpdevice, NULL );
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice: IDirectInput_CreateDevice") );
return false;
}
*/
// is this ok? -aj
//hr = tmpdevice->QueryInterface( IID_IDirectInputDevice2, (LPVOID *) &Device );
/*
tmpdevice->Release();
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice::QueryInterface", m_sName.c_str()) );
return false;
}
*/
2011-02-14 01:43:41 -06:00
// should mouse be foreground? -aj
2010-01-26 21:00:30 -06:00
int coop = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
if( type == KEYBOARD )
coop = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
hr = Device->SetCooperativeLevel( GraphicsWindow::GetHwnd(), coop );
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2::SetCooperativeLevel", m_sName.c_str()) );
return false;
}
2011-02-14 01:43:41 -06:00
switch(type)
{
case KEYBOARD:
hr = Device->SetDataFormat( &c_dfDIKeyboard );
break;
case JOYSTICK:
hr = Device->SetDataFormat( &c_dfDIJoystick );
break;
case MOUSE:
hr = Device->SetDataFormat( &c_dfDIMouse );
break;
}
2010-01-26 21:00:30 -06:00
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2::SetDataFormat", m_sName.c_str()) );
return false;
}
switch( type )
{
case JOYSTICK:
Device->EnumObjects( DIJoystick_EnumDevObjectsProc, this, DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
break;
case KEYBOARD:
// Always 256-button.
for( int b = 0; b < 256; ++b )
{
input_t in;
in.type = in.KEY;
in.num = ConvertScancodeToKey(b);
in.ofs = b;
buttons++;
Inputs.push_back(in);
}
break;
case MOUSE:
Device->EnumObjects( DIMouse_EnumDevObjectsProc, this, DIDFT_BUTTON | DIDFT_PSHBUTTON );
break;
2010-01-26 21:00:30 -06:00
}
{
DIPROPDWORD dipdw;
memset(&dipdw, 0, sizeof(dipdw));
dipdw.diph.dwSize = sizeof(dipdw);
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = INPUT_QSIZE;
hr = Device->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
if ( hr == DI_POLLEDDEVICE )
{
/* This device doesn't support buffering, so we're forced
* to use less reliable polling. */
buffered = false;
}
else if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2::SetProperty", m_sName.c_str()) );
return false;
}
}
return true;
}
void DIDevice::Close()
{
// Don't try to close a device that isn't open.
2010-01-26 21:00:30 -06:00
ASSERT( Device != NULL );
Device->Unacquire();
Device->Release();
Device = NULL;
buttons = axes = hats = NULL;
Inputs.clear();
}
static BOOL CALLBACK DIJoystick_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID data)
{
DIDevice *device = (DIDevice *) data;
HRESULT hr;
input_t in;
const int SupportedMask = DIDFT_BUTTON | DIDFT_POV | DIDFT_AXIS;
if(!(dev->dwType & SupportedMask))
2011-02-14 01:43:41 -06:00
return DIENUM_CONTINUE; // unsupported
2010-01-26 21:00:30 -06:00
in.ofs = dev->dwOfs;
if(dev->dwType & DIDFT_BUTTON) {
if( device->buttons == 24 )
return DIENUM_CONTINUE; // too many buttons
2010-01-26 21:00:30 -06:00
in.type = in.BUTTON;
in.num = device->buttons;
device->buttons++;
} else if(dev->dwType & DIDFT_POV) {
in.type = in.HAT;
in.num = device->hats;
device->hats++;
} else { // dev->dwType & DIDFT_AXIS
2010-01-26 21:00:30 -06:00
DIPROPRANGE diprg;
DIPROPDWORD dilong;
2010-01-26 21:00:30 -06:00
in.type = in.AXIS;
in.num = device->axes;
2010-01-26 21:00:30 -06:00
diprg.diph.dwSize = sizeof(diprg);
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
diprg.diph.dwObj = dev->dwOfs;
diprg.diph.dwHow = DIPH_BYOFFSET;
diprg.lMin = -100;
diprg.lMax = 100;
hr = device->Device->SetProperty( DIPROP_RANGE, &diprg.diph );
if ( hr != DI_OK )
return DIENUM_CONTINUE; // don't use this axis
// Set dead zone to 0.
2010-01-26 21:00:30 -06:00
dilong.diph.dwSize = sizeof(dilong);
dilong.diph.dwHeaderSize = sizeof(dilong.diph);
dilong.diph.dwObj = dev->dwOfs;
dilong.diph.dwHow = DIPH_BYOFFSET;
dilong.dwData = 0;
hr = device->Device->SetProperty( DIPROP_DEADZONE, &dilong.diph );
if ( hr != DI_OK )
return DIENUM_CONTINUE; /* don't use this axis */
device->axes++;
}
device->Inputs.push_back(in);
return DIENUM_CONTINUE;
}
static int ConvertScancodeToKey( int scancode )
{
switch(scancode)
{
case DIK_ESCAPE: return KEY_ESC;
case DIK_1: return KEY_C1;
case DIK_2: return KEY_C2;
case DIK_3: return KEY_C3;
case DIK_4: return KEY_C4;
case DIK_5: return KEY_C5;
case DIK_6: return KEY_C6;
case DIK_7: return KEY_C7;
case DIK_8: return KEY_C8;
case DIK_9: return KEY_C9;
case DIK_0: return KEY_C0;
case DIK_MINUS: return KEY_HYPHEN;
case DIK_EQUALS: return KEY_EQUAL;
case DIK_BACK: return KEY_BACK;
case DIK_TAB: return KEY_TAB;
case DIK_Q: return KEY_Cq;
case DIK_W: return KEY_Cw;
case DIK_E: return KEY_Ce;
case DIK_R: return KEY_Cr;
case DIK_T: return KEY_Ct;
case DIK_Y: return KEY_Cy;
case DIK_U: return KEY_Cu;
case DIK_I: return KEY_Ci;
case DIK_O: return KEY_Co;
case DIK_P: return KEY_Cp;
case DIK_LBRACKET: return KEY_LBRACKET;
case DIK_RBRACKET: return KEY_RBRACKET;
case DIK_RETURN: return KEY_ENTER;
case DIK_LCONTROL: return KEY_LCTRL;
case DIK_A: return KEY_Ca;
case DIK_S: return KEY_Cs;
case DIK_D: return KEY_Cd;
case DIK_F: return KEY_Cf;
case DIK_G: return KEY_Cg;
case DIK_H: return KEY_Ch;
case DIK_J: return KEY_Cj;
case DIK_K: return KEY_Ck;
case DIK_L: return KEY_Cl;
case DIK_SEMICOLON: return KEY_SEMICOLON;
case DIK_APOSTROPHE: return KEY_SQUOTE;
case DIK_GRAVE: return KEY_ACCENT;
case DIK_LSHIFT: return KEY_LSHIFT;
case DIK_BACKSLASH: return KEY_BACKSLASH;
case DIK_OEM_102: return KEY_BACKSLASH;
case DIK_Z: return KEY_Cz;
case DIK_X: return KEY_Cx;
case DIK_C: return KEY_Cc;
case DIK_V: return KEY_Cv;
case DIK_B: return KEY_Cb;
case DIK_N: return KEY_Cn;
case DIK_M: return KEY_Cm;
case DIK_COMMA: return KEY_COMMA;
case DIK_PERIOD: return KEY_PERIOD;
case DIK_SLASH: return KEY_SLASH;
case DIK_RSHIFT: return KEY_RSHIFT;
case DIK_MULTIPLY: return KEY_KP_ASTERISK;
case DIK_LMENU: return KEY_LALT;
case DIK_SPACE: return KEY_SPACE;
case DIK_CAPITAL: return KEY_CAPSLOCK;
case DIK_F1: return KEY_F1;
case DIK_F2: return KEY_F2;
case DIK_F3: return KEY_F3;
case DIK_F4: return KEY_F4;
case DIK_F5: return KEY_F5;
case DIK_F6: return KEY_F6;
case DIK_F7: return KEY_F7;
case DIK_F8: return KEY_F8;
case DIK_F9: return KEY_F9;
case DIK_F10: return KEY_F10;
case DIK_NUMLOCK: return KEY_NUMLOCK;
case DIK_SCROLL: return KEY_SCRLLOCK;
case DIK_NUMPAD7: return KEY_KP_C7;
case DIK_NUMPAD8: return KEY_KP_C8;
case DIK_NUMPAD9: return KEY_KP_C9;
case DIK_SUBTRACT: return KEY_KP_HYPHEN;
case DIK_NUMPAD4: return KEY_KP_C4;
case DIK_NUMPAD5: return KEY_KP_C5;
case DIK_NUMPAD6: return KEY_KP_C6;
case DIK_ADD: return KEY_KP_PLUS;
case DIK_NUMPAD1: return KEY_KP_C1;
case DIK_NUMPAD2: return KEY_KP_C2;
case DIK_NUMPAD3: return KEY_KP_C3;
case DIK_NUMPAD0: return KEY_KP_C0;
case DIK_DECIMAL: return KEY_KP_PERIOD;
case DIK_F11: return KEY_F11;
case DIK_F12: return KEY_F12;
case DIK_F13: return KEY_F13;
case DIK_F14: return KEY_F14;
case DIK_F15: return KEY_F15;
case DIK_NUMPADEQUALS: return KEY_KP_EQUAL;
case DIK_NUMPADENTER: return KEY_KP_ENTER;
case DIK_RCONTROL: return KEY_RCTRL;
case DIK_DIVIDE: return KEY_KP_SLASH;
case DIK_SYSRQ: return KEY_PRTSC;
case DIK_RMENU: return KEY_RALT;
case DIK_PAUSE: return KEY_PAUSE;
case DIK_HOME: return KEY_HOME;
case DIK_UP: return KEY_UP;
case DIK_PRIOR: return KEY_PGUP;
case DIK_LEFT: return KEY_LEFT;
case DIK_RIGHT: return KEY_RIGHT;
case DIK_END: return KEY_END;
case DIK_DOWN: return KEY_DOWN;
case DIK_NEXT: return KEY_PGDN;
case DIK_INSERT: return KEY_INSERT;
case DIK_DELETE: return KEY_DEL;
case DIK_LWIN: return KEY_LMETA;
case DIK_RWIN: return KEY_RMETA;
case DIK_APPS: return KEY_MENU;
default: return '?';
};
}
2011-02-14 01:43:41 -06:00
static BOOL CALLBACK DIMouse_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID data)
{
/*
2011-02-14 01:43:41 -06:00
DIDevice *device = (DIDevice *) data;
input_t in;
// todo: check mask for accuracy -aj
const int SupportedMask = DIDFT_BUTTON | DIDFT_PSHBUTTON;
2011-02-14 01:43:41 -06:00
if(!(dev->dwType & SupportedMask))
return DIENUM_CONTINUE; // unsupported
// xxx: does this check for scrollwheels? -aj
if(dev->dwType & (DIDFT_BUTTON | DIDFT_PSHBUTTON) ) {
2011-02-14 01:43:41 -06:00
in.type = in.BUTTON;
in.num = device->buttons;
device->buttons++;
}
device->Inputs.push_back(in);
*/
2011-02-14 01:43:41 -06:00
return DIENUM_CONTINUE;
}
/*
* (c) 2003-2011 Glenn Maynard, AJ Kelly
2010-01-26 21:00:30 -06:00
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/