SDL: gamepad hot-plugging

This commit is contained in:
Flyinghead 2019-02-12 15:56:44 +01:00
parent 8b5c2a3fac
commit 85b428c2e1
5 changed files with 78 additions and 48 deletions

View File

@ -137,7 +137,7 @@ unsigned int GamepadDevice::get_axis_range(u32 axis) {
std::string GamepadDevice::make_mapping_filename()
{
std::string mapping_file = std::string(api_name()) + "_" + name();
std::string mapping_file = api_name() + "_" + name();
std::replace(mapping_file.begin(), mapping_file.end(), '/', '-');
std::replace(mapping_file.begin(), mapping_file.end(), '\\', '-');
std::replace(mapping_file.begin(), mapping_file.end(), ':', '-');

View File

@ -26,8 +26,8 @@ class GamepadDevice
{
typedef void (*input_detected_cb)(u32 code);
public:
virtual const char* api_name() = 0;
virtual const char* name() = 0;
const std::string& api_name() { return _api_name; }
const std::string& name() { return _name; }
int maple_port() { return _maple_port; }
void set_maple_port(int port) { _maple_port = port; }
void gamepad_btn_input(u32 code, bool pressed);
@ -64,7 +64,7 @@ public:
static GamepadDevice *GetGamepad(int index);
protected:
GamepadDevice(int maple_port) : _maple_port(maple_port), input_mapper(NULL), _input_detected(NULL) {
GamepadDevice(int maple_port, const char *api_name) : _api_name(api_name), _maple_port(maple_port), input_mapper(NULL), _input_detected(NULL) {
_gamepads_mutex.lock();
_gamepads.push_back(this);
_gamepads_mutex.unlock();
@ -73,6 +73,7 @@ protected:
virtual void load_axis_min_max(u32 axis) {}
std::string _name;
InputMapping *input_mapper;
std::map<u32, int> axis_min_values;
std::map<u32, unsigned int> axis_ranges;
@ -82,6 +83,7 @@ private:
unsigned int get_axis_range(u32 axis);
std::string make_mapping_filename();
std::string _api_name;
int _maple_port;
bool _detecting_button = false;
input_detected_cb _input_detected;

View File

@ -616,9 +616,9 @@ static void gui_display_settings()
GamepadDevice *gamepad = GamepadDevice::GetGamepad(i);
if (gamepad == NULL)
continue;
ImGui::Text("%s", gamepad->api_name());
ImGui::Text("%s", gamepad->api_name().c_str());
ImGui::NextColumn();
ImGui::Text("%s", gamepad->name());
ImGui::Text("%s", gamepad->name().c_str());
ImGui::NextColumn();
char port_name[32];
sprintf(port_name, "##mapleport%d", i);

View File

@ -10,6 +10,7 @@
#include "khronos/GL3/gl3w.h"
#endif
#endif
#include "hw/maple/maple_devs.h"
#include "sdl_gamepad.h"
#include "sdl_keyboard.h"
@ -23,8 +24,6 @@ static SDL_GLContext glcontext;
#endif
#define WINDOW_HEIGHT 480
static SDLGamepadDevice* sdl_gamepads[4] = { NULL };
static SDL_JoystickID joystick_ids[ARRAY_SIZE(sdl_gamepads)] = { 0 };
static SDLMouseGamepadDevice* sdl_mouse_gamepad = NULL;
static SDLKbGamepadDevice* sdl_kb_gamepad = NULL;
static SDLKeyboardDevice* sdl_keyboard = NULL;
@ -44,6 +43,25 @@ extern s32 mo_y_abs;
extern int screen_width, screen_height;
static void sdl_open_joystick(int index)
{
SDL_Joystick *pJoystick = SDL_JoystickOpen(index);
if (pJoystick == NULL)
{
printf("SDL: Cannot open joystick %d\n", index + 1);
return;
}
new SDLGamepadDevice(index < MAPLE_PORTS ? index : -1, pJoystick); // TODO save/restore maple port
}
static void sdl_close_joystick(SDL_JoystickID instance)
{
SDLGamepadDevice *device = SDLGamepadDevice::GetSDLGamepad(instance);
if (device != NULL)
delete device;
}
void input_sdl_init()
{
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
@ -53,25 +71,10 @@ void input_sdl_init()
die("error initializing SDL Joystick subsystem");
}
}
// Open joystick device
int numjoys = SDL_NumJoysticks();
printf("Number of Joysticks found = %i\n", numjoys);
for (int i = 0; i < numjoys && i < ARRAY_SIZE(sdl_gamepads); i++)
{
SDL_Joystick *pJoystick = SDL_JoystickOpen(i);
if (pJoystick == NULL)
{
printf("Cannot open joystick %d\n", i + 1);
continue;
}
joystick_ids[i] = SDL_JoystickInstanceID(pJoystick);
sdl_gamepads[i] = new SDLGamepadDevice(i, pJoystick);
}
SDL_SetRelativeMouseMode(SDL_FALSE);
sdl_keyboard = new SDLKeyboardDevice(0); // FIXME ports!
sdl_keyboard = new SDLKeyboardDevice(0); // FIXME maple ports!
sdl_kb_gamepad = new SDLKbGamepadDevice(0);
sdl_mouse_gamepad = new SDLMouseGamepadDevice(0);
}
@ -113,20 +116,18 @@ void input_sdl_handle(u32 port)
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
for (int i = 0; i < ARRAY_SIZE(sdl_gamepads); i++)
if (joystick_ids[i] == event.jbutton.which)
{
sdl_gamepads[i]->gamepad_btn_input(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN);
break;
}
{
SDLGamepadDevice *device = SDLGamepadDevice::GetSDLGamepad((SDL_JoystickID)event.jbutton.which);
if (device != NULL)
device->gamepad_btn_input(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN);
}
break;
case SDL_JOYAXISMOTION:
for (int i = 0; i < ARRAY_SIZE(sdl_gamepads); i++)
if (joystick_ids[i] == event.jaxis.which)
{
sdl_gamepads[i]->gamepad_axis_input(event.jaxis.axis, event.jaxis.value);
break;
}
{
SDLGamepadDevice *device = SDLGamepadDevice::GetSDLGamepad((SDL_JoystickID)event.jaxis.which);
if (device != NULL)
device->gamepad_axis_input(event.jaxis.axis, event.jaxis.value);
}
break;
case SDL_MOUSEMOTION:
@ -153,6 +154,14 @@ void input_sdl_handle(u32 port)
}
sdl_mouse_gamepad->gamepad_btn_input(event.button.button, event.button.state == SDL_PRESSED);
break;
case SDL_JOYDEVICEADDED:
sdl_open_joystick(event.jdevice.which);
break;
case SDL_JOYDEVICEREMOVED:
sdl_close_joystick((SDL_JoystickID)event.jdevice.which);
break;
}
}
}

View File

@ -44,29 +44,47 @@ public:
class SDLGamepadDevice : public GamepadDevice
{
public:
SDLGamepadDevice(int maple_port, SDL_Joystick* sdl_joystick) : GamepadDevice(maple_port), sdl_joystick(sdl_joystick)
SDLGamepadDevice(int maple_port, SDL_Joystick* sdl_joystick) : GamepadDevice(maple_port, "SDL"), sdl_joystick(sdl_joystick)
{
_name = SDL_JoystickName(sdl_joystick);
sdl_joystick_instance = SDL_JoystickInstanceID(sdl_joystick);
printf("SDL: Opened joystick on port %d: '%s' ", maple_port, _name.c_str());
if (!find_mapping())
{
if (_name == "Microsoft X-Box 360 pad")
{
input_mapper = new Xbox360InputMapping();
printf("Using Xbox 360 mapping\n");
printf("using Xbox 360 mapping\n");
}
else
{
input_mapper = new DefaultInputMapping();
printf("Using default mapping\n");
printf("using default mapping\n");
}
save_mapping();
}
else
printf("using custom mapping '%s'\n", input_mapper->name.c_str());
auto it = sdl_gamepads.find(sdl_joystick_instance);
if (it != sdl_gamepads.end())
delete it->second;
sdl_gamepads[sdl_joystick_instance] = this;
}
virtual const char* api_name() override { return "SDL"; }
virtual const char* name() override { return _name.c_str(); }
virtual ~SDLGamepadDevice() override
{
printf("SDL: Joystick '%s' on port %d disconnected\n", _name.c_str(), maple_port());
SDL_JoystickClose(sdl_joystick);
sdl_gamepads.erase(sdl_joystick_instance);
}
SDL_JoystickID sdl_instance() { return sdl_joystick_instance; }
static SDLGamepadDevice *GetSDLGamepad(SDL_JoystickID id)
{
auto it = sdl_gamepads.find(id);
if (it != sdl_gamepads.end())
return it->second;
else
return NULL;
}
protected:
@ -77,10 +95,13 @@ protected:
}
private:
std::string _name;
SDL_Joystick* sdl_joystick;
SDL_JoystickID sdl_joystick_instance;
static std::map<SDL_JoystickID, SDLGamepadDevice*> sdl_gamepads;
};
std::map<SDL_JoystickID, SDLGamepadDevice*> SDLGamepadDevice::sdl_gamepads;
class KbInputMapping : public InputMapping
{
public:
@ -107,13 +128,12 @@ public:
class SDLKbGamepadDevice : public GamepadDevice
{
public:
SDLKbGamepadDevice(int maple_port) : GamepadDevice(maple_port)
SDLKbGamepadDevice(int maple_port) : GamepadDevice(maple_port, "SDL")
{
_name = "Keyboard";
if (!find_mapping())
input_mapper = new KbInputMapping();
}
virtual const char* api_name() override { return "SDL"; }
virtual const char* name() override { return "Keyboard"; }
virtual ~SDLKbGamepadDevice() {}
};
@ -134,13 +154,12 @@ public:
class SDLMouseGamepadDevice : public GamepadDevice
{
public:
SDLMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port)
SDLMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port, "SDL")
{
_name = "Mouse";
if (!find_mapping())
input_mapper = new MouseInputMapping();
}
virtual const char* api_name() override { return "SDL"; }
virtual const char* name() override { return "Mouse"; }
virtual ~SDLMouseGamepadDevice() {}
};