input: Use QTAILQ for available controllers list

This commit is contained in:
Matt Borgerson 2021-01-08 00:29:57 -07:00 committed by mborgerson
parent 5233f777cf
commit 64141f90e1
6 changed files with 46 additions and 54 deletions

View File

@ -198,7 +198,7 @@ static void update_output(USBXIDState *s)
return; return;
} }
struct controller_state *state = xemu_input_get_bound(s->device_index); ControllerState *state = xemu_input_get_bound(s->device_index);
assert(state); assert(state);
state->rumble_l = s->out_state.left_actuator_strength; state->rumble_l = s->out_state.left_actuator_strength;
state->rumble_r = s->out_state.right_actuator_strength; state->rumble_r = s->out_state.right_actuator_strength;
@ -212,7 +212,7 @@ static void update_input(USBXIDState *s)
return; return;
} }
struct controller_state *state = xemu_input_get_bound(s->device_index); ControllerState *state = xemu_input_get_bound(s->device_index);
assert(state); assert(state);
const int button_map_analog[6][2] = { const int button_map_analog[6][2] = {

View File

@ -85,7 +85,7 @@ void render_meter(
render_decal(s, x, y, width*p, height ,0, 0, 1, 1, 0, 0, color_fg); render_decal(s, x, y, width*p, height ,0, 0, 1, 1, 0, 0, color_fg);
} }
void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, struct controller_state *state) void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, ControllerState *state)
{ {
// Location within the controller texture of masked button locations, // Location within the controller texture of masked button locations,
// relative to the origin of the controller // relative to the origin of the controller

View File

@ -34,7 +34,7 @@ extern struct fbo *logo_fbo;
void initialize_custom_ui_rendering(void); void initialize_custom_ui_rendering(void);
void render_meter(struct decal_shader *s, float x, float y, float width, float height, float p, uint32_t color_bg, uint32_t color_fg); void render_meter(struct decal_shader *s, float x, float y, float width, float height, float p, uint32_t color_bg, uint32_t color_fg);
void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, struct controller_state *state); void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, ControllerState *state);
void render_controller_port(float frame_x, float frame_y, int i, uint32_t port_color); void render_controller_port(float frame_x, float frame_y, int i, uint32_t port_color);
void render_logo(uint32_t time, uint32_t primary_color, uint32_t secondary_color, uint32_t fill_color); void render_logo(uint32_t time, uint32_t primary_color, uint32_t secondary_color, uint32_t fill_color);

View File

@ -437,7 +437,7 @@ public:
// List available input devices // List available input devices
const char *not_connected = "Not Connected"; const char *not_connected = "Not Connected";
struct controller_state *bound_state = xemu_input_get_bound(active); ControllerState *bound_state = xemu_input_get_bound(active);
// Get current controller name // Get current controller name
const char *name; const char *name;
@ -460,8 +460,8 @@ public:
} }
// Handle all available input devices // Handle all available input devices
struct controller_state *iter; ControllerState *iter;
for (iter=available_controllers; iter != NULL; iter=iter->next) { QTAILQ_FOREACH(iter, &available_controllers, entry) {
is_selected = bound_state == iter; is_selected = bound_state == iter;
ImGui::PushID(iter); ImGui::PushID(iter);
const char *selectable_label = iter->name; const char *selectable_label = iter->name;
@ -501,7 +501,7 @@ public:
device_selected = true; device_selected = true;
render_controller(0, 0, 0x81dc8a00, 0x0f0f0f00, bound_state); render_controller(0, 0, 0x81dc8a00, 0x0f0f0f00, bound_state);
} else { } else {
static struct controller_state state = { 0 }; static ControllerState state = { 0 };
render_controller(0, 0, 0x1f1f1f00, 0x0f0f0f00, &state); render_controller(0, 0, 0x1f1f1f00, 0x0f0f0f00, &state);
} }
@ -1753,12 +1753,13 @@ void xemu_hud_render(void)
{ {
uint32_t now = SDL_GetTicks(); uint32_t now = SDL_GetTicks();
bool ui_wakeup = false; bool ui_wakeup = false;
struct controller_state *iter;
// Combine all controller states to allow any controller to navigate // Combine all controller states to allow any controller to navigate
uint32_t buttons = 0; uint32_t buttons = 0;
int16_t axis[CONTROLLER_AXIS__COUNT] = {0}; int16_t axis[CONTROLLER_AXIS__COUNT] = {0};
for (iter=available_controllers; iter != NULL; iter=iter->next) {
ControllerState *iter;
QTAILQ_FOREACH(iter, &available_controllers, entry) {
if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue; if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue;
buttons |= iter->buttons; buttons |= iter->buttons;
// We simply take any axis that is >10 % activation // We simply take any axis that is >10 % activation

View File

@ -42,8 +42,9 @@
do { } while (0) do { } while (0)
#endif #endif
struct controller_state *available_controllers; ControllerStateList available_controllers =
struct controller_state *bound_controllers[4] = { NULL, NULL, NULL, NULL }; QTAILQ_HEAD_INITIALIZER(available_controllers);
ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL };
int test_mode; int test_mode;
static const enum xemu_settings_keys port_index_to_settings_key_map[] = { static const enum xemu_settings_keys port_index_to_settings_key_map[] = {
@ -68,8 +69,8 @@ void xemu_input_init(void)
} }
// Create the keyboard input (always first) // Create the keyboard input (always first)
struct controller_state *new_con = malloc(sizeof(struct controller_state)); ControllerState *new_con = malloc(sizeof(ControllerState));
memset(new_con, 0, sizeof(struct controller_state)); memset(new_con, 0, sizeof(ControllerState));
new_con->type = INPUT_DEVICE_SDL_KEYBOARD; new_con->type = INPUT_DEVICE_SDL_KEYBOARD;
new_con->name = "Keyboard"; new_con->name = "Keyboard";
new_con->bound = -1; new_con->bound = -1;
@ -83,10 +84,10 @@ void xemu_input_init(void)
xemu_queue_notification(buf); xemu_queue_notification(buf);
} }
available_controllers = new_con; QTAILQ_INSERT_TAIL(&available_controllers, new_con, entry);
} }
int xemu_input_get_controller_default_bind_port(struct controller_state *state, int start) int xemu_input_get_controller_default_bind_port(ControllerState *state, int start)
{ {
char guid[35] = { 0 }; char guid[35] = { 0 };
if (state->type == INPUT_DEVICE_SDL_GAMECONTROLLER) { if (state->type == INPUT_DEVICE_SDL_GAMECONTROLLER) {
@ -120,8 +121,8 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
} }
// Success! Create a new node to track this controller and continue init // Success! Create a new node to track this controller and continue init
struct controller_state *new_con = malloc(sizeof(struct controller_state)); ControllerState *new_con = malloc(sizeof(ControllerState));
memset(new_con, 0, sizeof(struct controller_state)); memset(new_con, 0, sizeof(ControllerState));
new_con->type = INPUT_DEVICE_SDL_GAMECONTROLLER; new_con->type = INPUT_DEVICE_SDL_GAMECONTROLLER;
new_con->name = SDL_GameControllerName(sdl_con); new_con->name = SDL_GameControllerName(sdl_con);
new_con->sdl_gamecontroller = sdl_con; new_con->sdl_gamecontroller = sdl_con;
@ -136,14 +137,7 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
SDL_JoystickGetGUIDString(new_con->sdl_joystick_guid, guid_buf, sizeof(guid_buf)); SDL_JoystickGetGUIDString(new_con->sdl_joystick_guid, guid_buf, sizeof(guid_buf));
DPRINTF("Opened %s (%s)\n", new_con->name, guid_buf); DPRINTF("Opened %s (%s)\n", new_con->name, guid_buf);
// Add to the list of controllers QTAILQ_INSERT_TAIL(&available_controllers, new_con, entry);
if (available_controllers == NULL) {
available_controllers = new_con;
} else {
struct controller_state *iter = available_controllers;
while (iter->next != NULL) iter = iter->next;
iter->next = new_con;
}
// Do not replace binding for a currently bound device. In the case that // Do not replace binding for a currently bound device. In the case that
// the same GUID is specified multiple times, on different ports, allow // the same GUID is specified multiple times, on different ports, allow
@ -178,8 +172,8 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) { } else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
DPRINTF("Controller Removed: %d\n", event->cdevice.which); DPRINTF("Controller Removed: %d\n", event->cdevice.which);
int handled = 0; int handled = 0;
struct controller_state *iter, *prev; ControllerState *iter, *next;
for (iter=available_controllers, prev=NULL; iter != NULL; prev = iter, iter = iter->next) { QTAILQ_FOREACH_SAFE(iter, &available_controllers, entry, next) {
if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue; if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue;
if (iter->sdl_joystick_id == event->cdevice.which) { if (iter->sdl_joystick_id == event->cdevice.which) {
@ -200,11 +194,7 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
} }
// Unlink // Unlink
if (prev) { QTAILQ_REMOVE(&available_controllers, iter, entry);
prev->next = iter->next;
} else {
available_controllers = iter->next;
}
// Deallocate // Deallocate
if (iter->sdl_haptic) { if (iter->sdl_haptic) {
@ -229,8 +219,8 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
void xemu_input_update_controllers(void) void xemu_input_update_controllers(void)
{ {
struct controller_state *iter; ControllerState *iter;
for (iter=available_controllers; iter != NULL; iter=iter->next) { QTAILQ_FOREACH(iter, &available_controllers, entry) {
if (iter->type == INPUT_DEVICE_SDL_KEYBOARD) { if (iter->type == INPUT_DEVICE_SDL_KEYBOARD) {
xemu_input_update_sdl_kbd_controller_state(iter); xemu_input_update_sdl_kbd_controller_state(iter);
} else if (iter->type == INPUT_DEVICE_SDL_GAMECONTROLLER) { } else if (iter->type == INPUT_DEVICE_SDL_GAMECONTROLLER) {
@ -240,7 +230,7 @@ void xemu_input_update_controllers(void)
} }
} }
void xemu_input_update_sdl_kbd_controller_state(struct controller_state *state) void xemu_input_update_sdl_kbd_controller_state(ControllerState *state)
{ {
state->buttons = 0; state->buttons = 0;
memset(state->axis, 0, sizeof(state->axis)); memset(state->axis, 0, sizeof(state->axis));
@ -293,7 +283,7 @@ void xemu_input_update_sdl_kbd_controller_state(struct controller_state *state)
if (kbd[SDL_SCANCODE_O]) state->axis[CONTROLLER_AXIS_RTRIG] = 32767; if (kbd[SDL_SCANCODE_O]) state->axis[CONTROLLER_AXIS_RTRIG] = 32767;
} }
void xemu_input_update_sdl_controller_state(struct controller_state *state) void xemu_input_update_sdl_controller_state(ControllerState *state)
{ {
state->buttons = 0; state->buttons = 0;
memset(state->axis, 0, sizeof(state->axis)); memset(state->axis, 0, sizeof(state->axis));
@ -338,7 +328,7 @@ void xemu_input_update_sdl_controller_state(struct controller_state *state)
state->axis[CONTROLLER_AXIS_RSTICK_Y] = -1 - state->axis[CONTROLLER_AXIS_RSTICK_Y]; state->axis[CONTROLLER_AXIS_RSTICK_Y] = -1 - state->axis[CONTROLLER_AXIS_RSTICK_Y];
} }
void xemu_input_update_rumble(struct controller_state *state) void xemu_input_update_rumble(ControllerState *state)
{ {
if (state->sdl_haptic == NULL) { if (state->sdl_haptic == NULL) {
// Haptic not supported for this joystick // Haptic not supported for this joystick
@ -358,12 +348,12 @@ void xemu_input_update_rumble(struct controller_state *state)
} }
} }
struct controller_state *xemu_input_get_bound(int index) ControllerState *xemu_input_get_bound(int index)
{ {
return bound_controllers[index]; return bound_controllers[index];
} }
void xemu_input_bind(int index, struct controller_state *state, int save) void xemu_input_bind(int index, ControllerState *state, int save)
{ {
// FIXME: Attempt to disable rumble when unbinding so it's not left // FIXME: Attempt to disable rumble when unbinding so it's not left
// in rumble mode // in rumble mode
@ -434,7 +424,7 @@ void xemu_input_bind(int index, struct controller_state *state, int save)
} }
#if 0 #if 0
static void xemu_input_print_controller_state(struct controller_state *state) static void xemu_input_print_controller_state(ControllerState *state)
{ {
DPRINTF(" A = %d, B = %d, X = %d, Y = %d\n" DPRINTF(" A = %d, B = %d, X = %d, Y = %d\n"
" Left = %d, Up = %d, Right = %d, Down = %d\n" " Left = %d, Up = %d, Right = %d, Down = %d\n"

View File

@ -26,6 +26,7 @@
#define XEMU_INPUT_H #define XEMU_INPUT_H
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include "qemu/queue.h"
enum controller_state_buttons_mask { enum controller_state_buttons_mask {
CONTROLLER_BUTTON_A = (1 << 0), CONTROLLER_BUTTON_A = (1 << 0),
@ -62,7 +63,9 @@ enum controller_input_device_type {
INPUT_DEVICE_SDL_GAMECONTROLLER, INPUT_DEVICE_SDL_GAMECONTROLLER,
}; };
struct controller_state { typedef struct ControllerState {
QTAILQ_ENTRY(ControllerState) entry;
// Input state // Input state
uint16_t buttons; uint16_t buttons;
int16_t axis[CONTROLLER_AXIS__COUNT]; int16_t axis[CONTROLLER_AXIS__COUNT];
@ -86,13 +89,11 @@ struct controller_state {
int bound; // Which port this input device is bound to int bound; // Which port this input device is bound to
void *device; // DeviceState opaque void *device; // DeviceState opaque
} ControllerState;
struct controller_state *next; typedef QTAILQ_HEAD(, ControllerState) ControllerStateList;
}; extern ControllerStateList available_controllers;
extern ControllerState *bound_controllers[4];
extern int num_available_controllers;
extern struct controller_state *available_controllers;
extern struct controller_state *bound_controllers[4];
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -101,12 +102,12 @@ extern "C" {
void xemu_input_init(void); void xemu_input_init(void);
void xemu_input_process_sdl_events(const SDL_Event *event); // SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED void xemu_input_process_sdl_events(const SDL_Event *event); // SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED
void xemu_input_update_controllers(void); void xemu_input_update_controllers(void);
void xemu_input_update_sdl_kbd_controller_state(struct controller_state *state); void xemu_input_update_sdl_kbd_controller_state(ControllerState *state);
void xemu_input_update_sdl_controller_state(struct controller_state *state); void xemu_input_update_sdl_controller_state(ControllerState *state);
void xemu_input_update_rumble(struct controller_state *state); void xemu_input_update_rumble(ControllerState *state);
struct controller_state *xemu_input_get_bound(int index); ControllerState *xemu_input_get_bound(int index);
void xemu_input_bind(int index, struct controller_state *state, int save); void xemu_input_bind(int index, ControllerState *state, int save);
int xemu_input_get_controller_default_bind_port(struct controller_state *state, int start); int xemu_input_get_controller_default_bind_port(ControllerState *state, int start);
void xemu_input_set_test_mode(int enabled); void xemu_input_set_test_mode(int enabled);
int xemu_input_get_test_mode(void); int xemu_input_get_test_mode(void);