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;
}
struct controller_state *state = xemu_input_get_bound(s->device_index);
ControllerState *state = xemu_input_get_bound(s->device_index);
assert(state);
state->rumble_l = s->out_state.left_actuator_strength;
state->rumble_r = s->out_state.right_actuator_strength;
@ -212,7 +212,7 @@ static void update_input(USBXIDState *s)
return;
}
struct controller_state *state = xemu_input_get_bound(s->device_index);
ControllerState *state = xemu_input_get_bound(s->device_index);
assert(state);
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);
}
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,
// 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 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_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
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
const char *name;
@ -460,8 +460,8 @@ public:
}
// Handle all available input devices
struct controller_state *iter;
for (iter=available_controllers; iter != NULL; iter=iter->next) {
ControllerState *iter;
QTAILQ_FOREACH(iter, &available_controllers, entry) {
is_selected = bound_state == iter;
ImGui::PushID(iter);
const char *selectable_label = iter->name;
@ -501,7 +501,7 @@ public:
device_selected = true;
render_controller(0, 0, 0x81dc8a00, 0x0f0f0f00, bound_state);
} else {
static struct controller_state state = { 0 };
static ControllerState state = { 0 };
render_controller(0, 0, 0x1f1f1f00, 0x0f0f0f00, &state);
}
@ -1753,12 +1753,13 @@ void xemu_hud_render(void)
{
uint32_t now = SDL_GetTicks();
bool ui_wakeup = false;
struct controller_state *iter;
// Combine all controller states to allow any controller to navigate
uint32_t buttons = 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;
buttons |= iter->buttons;
// We simply take any axis that is >10 % activation

View File

@ -42,8 +42,9 @@
do { } while (0)
#endif
struct controller_state *available_controllers;
struct controller_state *bound_controllers[4] = { NULL, NULL, NULL, NULL };
ControllerStateList available_controllers =
QTAILQ_HEAD_INITIALIZER(available_controllers);
ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL };
int test_mode;
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)
struct controller_state *new_con = malloc(sizeof(struct controller_state));
memset(new_con, 0, sizeof(struct controller_state));
ControllerState *new_con = malloc(sizeof(ControllerState));
memset(new_con, 0, sizeof(ControllerState));
new_con->type = INPUT_DEVICE_SDL_KEYBOARD;
new_con->name = "Keyboard";
new_con->bound = -1;
@ -83,10 +84,10 @@ void xemu_input_init(void)
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 };
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
struct controller_state *new_con = malloc(sizeof(struct controller_state));
memset(new_con, 0, sizeof(struct controller_state));
ControllerState *new_con = malloc(sizeof(ControllerState));
memset(new_con, 0, sizeof(ControllerState));
new_con->type = INPUT_DEVICE_SDL_GAMECONTROLLER;
new_con->name = SDL_GameControllerName(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));
DPRINTF("Opened %s (%s)\n", new_con->name, guid_buf);
// Add to the list of controllers
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;
}
QTAILQ_INSERT_TAIL(&available_controllers, new_con, entry);
// Do not replace binding for a currently bound device. In the case that
// 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) {
DPRINTF("Controller Removed: %d\n", event->cdevice.which);
int handled = 0;
struct controller_state *iter, *prev;
for (iter=available_controllers, prev=NULL; iter != NULL; prev = iter, iter = iter->next) {
ControllerState *iter, *next;
QTAILQ_FOREACH_SAFE(iter, &available_controllers, entry, next) {
if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue;
if (iter->sdl_joystick_id == event->cdevice.which) {
@ -200,11 +194,7 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
}
// Unlink
if (prev) {
prev->next = iter->next;
} else {
available_controllers = iter->next;
}
QTAILQ_REMOVE(&available_controllers, iter, entry);
// Deallocate
if (iter->sdl_haptic) {
@ -229,8 +219,8 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
void xemu_input_update_controllers(void)
{
struct controller_state *iter;
for (iter=available_controllers; iter != NULL; iter=iter->next) {
ControllerState *iter;
QTAILQ_FOREACH(iter, &available_controllers, entry) {
if (iter->type == INPUT_DEVICE_SDL_KEYBOARD) {
xemu_input_update_sdl_kbd_controller_state(iter);
} 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;
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;
}
void xemu_input_update_sdl_controller_state(struct controller_state *state)
void xemu_input_update_sdl_controller_state(ControllerState *state)
{
state->buttons = 0;
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];
}
void xemu_input_update_rumble(struct controller_state *state)
void xemu_input_update_rumble(ControllerState *state)
{
if (state->sdl_haptic == NULL) {
// 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];
}
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
// in rumble mode
@ -434,7 +424,7 @@ void xemu_input_bind(int index, struct controller_state *state, int save)
}
#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"
" Left = %d, Up = %d, Right = %d, Down = %d\n"

View File

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