Files
itgmania212121/stepmania/src/arch/InputHandler/InputHandler_DirectInputHelper.cpp
T
2004-06-16 20:26:45 +00:00

339 lines
9.8 KiB
C++

#include "global.h"
#include "SDL_utils.h"
#define COMPAT_KEYSYMS
#include "InputHandler_DirectInputHelper.h"
#include "RageUtil.h"
#include "RageLog.h"
#pragma comment(lib, "dinput.lib")
#if defined(_WINDOWS)
#pragma comment(lib, "dxguid.lib")
#endif
LPDIRECTINPUT dinput = NULL;
static int ConvertScancodeToKey( int scancode );
static BOOL CALLBACK DIJoystick_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID data);
static HWND GetHwnd();
DIDevice::DIDevice()
{
buttons = axes = hats = 0;
dev = DEVICE_NONE;
buffered = true;
memset(&JoystickInst, 0, sizeof(JoystickInst));
Device = NULL;
}
bool DIDevice::Open()
{
LOG->Trace( "Opening device '%s'", JoystickInst.tszProductName );
buffered = true;
LPDIRECTINPUTDEVICE tmpdevice;
HRESULT hr = IDirectInput_CreateDevice(dinput, JoystickInst.guidInstance,
&tmpdevice, NULL);
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice: IDirectInput_CreateDevice") );
return false;
}
hr = IDirectInputDevice_QueryInterface(tmpdevice,
IID_IDirectInputDevice2, (LPVOID *) &Device);
IDirectInputDevice_Release(tmpdevice);
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice_QueryInterface", JoystickInst.tszProductName) );
return false;
}
int coop = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
if( type == KEYBOARD )
coop = DISCL_FOREGROUND|DISCL_NONEXCLUSIVE;
hr = IDirectInputDevice2_SetCooperativeLevel( Device, GetHwnd(), coop );
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2_SetCooperativeLevel", JoystickInst.tszProductName) );
return false;
}
hr = IDirectInputDevice2_SetDataFormat(Device,
type == JOYSTICK? &c_dfDIJoystick: &c_dfDIKeyboard);
if ( hr != DI_OK )
{
LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2_SetDataFormat", JoystickInst.tszProductName) );
return false;
}
switch( type )
{
case JOYSTICK:
IDirectInputDevice2_EnumObjects(Device, 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;
}
{
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 = IDirectInputDevice2_SetProperty(Device,
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", JoystickInst.tszProductName) );
return false;
}
}
return true;
}
void DIDevice::Close()
{
/* Don't try to close a device that isn't open. */
ASSERT( Device != NULL );
IDirectInputDevice2_Unacquire(Device);
IDirectInputDevice2_Release(Device);
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))
return DIENUM_CONTINUE; /* unsupported */
in.ofs = dev->dwOfs;
if(dev->dwType & DIDFT_BUTTON) {
if( device->buttons == 24 )
return DIENUM_CONTINUE; /* too many buttons */
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 */
DIPROPRANGE diprg;
DIPROPDWORD dilong;
in.type = in.AXIS;
in.num = device->axes;
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 = IDirectInputDevice2_SetProperty(device->Device, DIPROP_RANGE, &diprg.diph);
if ( hr != DI_OK )
return DIENUM_CONTINUE; /* don't use this axis */
/* Set dead zone to 0. */
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 = IDirectInputDevice2_SetProperty(device->Device, 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 SDLK_ESCAPE;
case DIK_1: return SDLK_1;
case DIK_2: return SDLK_2;
case DIK_3: return SDLK_3;
case DIK_4: return SDLK_4;
case DIK_5: return SDLK_5;
case DIK_6: return SDLK_6;
case DIK_7: return SDLK_7;
case DIK_8: return SDLK_8;
case DIK_9: return SDLK_9;
case DIK_0: return SDLK_0;
case DIK_MINUS: return SDLK_MINUS;
case DIK_EQUALS: return SDLK_EQUALS;
case DIK_BACK: return SDLK_BACKSPACE;
case DIK_TAB: return SDLK_TAB;
case DIK_Q: return SDLK_q;
case DIK_W: return SDLK_w;
case DIK_E: return SDLK_e;
case DIK_R: return SDLK_r;
case DIK_T: return SDLK_t;
case DIK_Y: return SDLK_y;
case DIK_U: return SDLK_u;
case DIK_I: return SDLK_i;
case DIK_O: return SDLK_o;
case DIK_P: return SDLK_p;
case DIK_LBRACKET: return SDLK_LEFTBRACKET;
case DIK_RBRACKET: return SDLK_RIGHTBRACKET;
case DIK_RETURN: return SDLK_RETURN;
case DIK_LCONTROL: return SDLK_LCTRL;
case DIK_A: return SDLK_a;
case DIK_S: return SDLK_s;
case DIK_D: return SDLK_d;
case DIK_F: return SDLK_f;
case DIK_G: return SDLK_g;
case DIK_H: return SDLK_h;
case DIK_J: return SDLK_j;
case DIK_K: return SDLK_k;
case DIK_L: return SDLK_l;
case DIK_SEMICOLON: return SDLK_SEMICOLON;
case DIK_APOSTROPHE: return SDLK_QUOTE;
case DIK_GRAVE: return SDLK_BACKQUOTE;
case DIK_LSHIFT: return SDLK_LSHIFT;
case DIK_BACKSLASH: return SDLK_BACKSLASH;
case DIK_OEM_102: return SDLK_BACKSLASH;
case DIK_Z: return SDLK_z;
case DIK_X: return SDLK_x;
case DIK_C: return SDLK_c;
case DIK_V: return SDLK_v;
case DIK_B: return SDLK_b;
case DIK_N: return SDLK_n;
case DIK_M: return SDLK_m;
case DIK_COMMA: return SDLK_COMMA;
case DIK_PERIOD: return SDLK_PERIOD;
case DIK_SLASH: return SDLK_SLASH;
case DIK_RSHIFT: return SDLK_RSHIFT;
case DIK_MULTIPLY: return SDLK_KP_MULTIPLY;
case DIK_LMENU: return SDLK_LALT;
case DIK_SPACE: return SDLK_SPACE;
case DIK_CAPITAL: return SDLK_CAPSLOCK;
case DIK_F1: return SDLK_F1;
case DIK_F2: return SDLK_F2;
case DIK_F3: return SDLK_F3;
case DIK_F4: return SDLK_F4;
case DIK_F5: return SDLK_F5;
case DIK_F6: return SDLK_F6;
case DIK_F7: return SDLK_F7;
case DIK_F8: return SDLK_F8;
case DIK_F9: return SDLK_F9;
case DIK_F10: return SDLK_F10;
case DIK_NUMLOCK: return SDLK_NUMLOCK;
case DIK_SCROLL: return SDLK_SCROLLOCK;
case DIK_NUMPAD7: return SDLK_KP7;
case DIK_NUMPAD8: return SDLK_KP8;
case DIK_NUMPAD9: return SDLK_KP9;
case DIK_SUBTRACT: return SDLK_KP_MINUS;
case DIK_NUMPAD4: return SDLK_KP4;
case DIK_NUMPAD5: return SDLK_KP5;
case DIK_NUMPAD6: return SDLK_KP6;
case DIK_ADD: return SDLK_KP_PLUS;
case DIK_NUMPAD1: return SDLK_KP1;
case DIK_NUMPAD2: return SDLK_KP2;
case DIK_NUMPAD3: return SDLK_KP3;
case DIK_NUMPAD0: return SDLK_KP0;
case DIK_DECIMAL: return SDLK_KP_PERIOD;
case DIK_F11: return SDLK_F11;
case DIK_F12: return SDLK_F12;
case DIK_F13: return SDLK_F13;
case DIK_F14: return SDLK_F14;
case DIK_F15: return SDLK_F15;
case DIK_NUMPADEQUALS: return SDLK_KP_EQUALS;
case DIK_NUMPADENTER: return SDLK_KP_ENTER;
case DIK_RCONTROL: return SDLK_RCTRL;
case DIK_DIVIDE: return SDLK_KP_DIVIDE;
case DIK_SYSRQ: return SDLK_PRINT;
case DIK_RMENU: return SDLK_RALT;
case DIK_PAUSE: return SDLK_PAUSE;
case DIK_HOME: return SDLK_HOME;
case DIK_UP: return SDLK_UP;
case DIK_PRIOR: return SDLK_PAGEUP;
case DIK_LEFT: return SDLK_LEFT;
case DIK_RIGHT: return SDLK_RIGHT;
case DIK_END: return SDLK_END;
case DIK_DOWN: return SDLK_DOWN;
case DIK_NEXT: return SDLK_PAGEDOWN;
case DIK_INSERT: return SDLK_INSERT;
case DIK_DELETE: return SDLK_DELETE;
case DIK_LWIN: return SDLK_LMETA;
case DIK_RWIN: return SDLK_RMETA;
case DIK_APPS: return SDLK_MENU;
default: return '?';
};
}
static HWND GetHwnd()
{
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if( SDL_GetWMInfo(&info) < 0 )
RageException::Throw( "SDL_GetWMInfo failed" );
return info.window;
}
/*
* (c) 2003-2004 Glenn Maynard
* 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.
*/