Skip to content

Commit

Permalink
Controller device reservation / preference.
Browse files Browse the repository at this point in the history
For each player, 2 new options are added:
- a reservation type (no reservation, preferred, reserved)
- a reserved device name

When handling port - player assignments, reserved devices
will be assigned to the respective player port. If reservation
type is "reserved", no other device can take that port
automatically.

Reservation config option and matching function lifted from:
PatrickStankard #16269

Test joypad driver was extended for more tests.

Co-authored-by: Patrick Stankard <me@patrickstankard.com>
  • Loading branch information
2 people authored and LibretroAdmin committed Jun 5, 2024
1 parent e9682cb commit a9968e9
Show file tree
Hide file tree
Showing 26 changed files with 903 additions and 35 deletions.
46 changes: 45 additions & 1 deletion configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -1485,6 +1485,7 @@ bool config_overlay_enable_default(void)
static struct config_array_setting *populate_settings_array(
settings_t *settings, int *size)
{
unsigned i = 0;
unsigned count = 0;
struct config_array_setting *tmp = (struct config_array_setting*)calloc(1, (*size + 1) * sizeof(struct config_array_setting));

Expand Down Expand Up @@ -1515,6 +1516,24 @@ static struct config_array_setting *populate_settings_array(
SETTING_ARRAY("input_android_physical_keyboard", settings->arrays.input_android_physical_keyboard, false, NULL, true);
#endif

for (i = 0; i < MAX_USERS; i++)
{
size_t _len;
char formatted_number[4];
char prefix[16];
char key[32];

formatted_number[0] = '\0';

snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1);
_len = strlcpy(prefix, "input_player", sizeof(prefix));
strlcpy(prefix + _len, formatted_number, sizeof(prefix) - _len);
_len = strlcpy(key, prefix, sizeof(key));
strlcpy(key + _len, "_reserved_device", sizeof(key) - _len);

SETTING_ARRAY(strdup(key), settings->arrays.input_reserved_devices[i], false, NULL, true);
}

#ifdef HAVE_MENU
SETTING_ARRAY("menu_driver", settings->arrays.menu_driver, false, NULL, true);
#endif
Expand Down Expand Up @@ -3732,6 +3751,10 @@ static bool config_load_file(global_t *global,

strlcpy(buf + _len2, "_analog_dpad_mode", sizeof(buf) - _len2);
CONFIG_GET_INT_BASE(conf, settings, uints.input_analog_dpad_mode[i], buf);

strlcpy(buf + _len2, "_device_reservation_type", sizeof(buf) - _len2);
CONFIG_GET_INT_BASE(conf, settings, uints.input_device_reservation_type[i], buf);

}
}

Expand Down Expand Up @@ -5265,7 +5288,6 @@ bool config_save_file(const char *path)
size_t _len;
char cfg[64];
char formatted_number[4];

formatted_number[0] = '\0';

snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1);
Expand All @@ -5285,6 +5307,9 @@ bool config_save_file(const char *path)

strlcpy(cfg + _len, "_analog_dpad_mode", sizeof(cfg) - _len);
config_set_int(conf, cfg, settings->uints.input_analog_dpad_mode[i]);

strlcpy(cfg + _len, "_device_reservation_type", sizeof(cfg) - _len);
config_set_int(conf, cfg, settings->uints.input_device_reservation_type[i]);
}

/* Boolean settings */
Expand Down Expand Up @@ -5619,6 +5644,25 @@ int8_t config_save_overrides(enum override_type type,
RARCH_DBG("[Overrides]: %s = \"%u\"\n", cfg, overrides->uints.input_analog_dpad_mode[i]);
}

if (settings->uints.input_device_reservation_type[i]
!= overrides->uints.input_device_reservation_type[i])
{
strlcpy(cfg + _len, "_device_reservation_type", sizeof(cfg) - _len);
config_set_int(conf, cfg, overrides->uints.input_device_reservation_type[i]);
RARCH_DBG("[Overrides]: %s = \"%u\"\n", cfg, overrides->uints.input_device_reservation_type[i]);
}

/* TODO: is this whole section really necessary? Does the loop above not do this? */
if (!string_is_equal(settings->arrays.input_reserved_devices[i], overrides->arrays.input_reserved_devices[i]))
{
strlcpy(cfg + _len, "_device_reservation_type", sizeof(cfg) - _len);

config_set_string(conf, cfg,
overrides->arrays.input_reserved_devices[i]);
RARCH_DBG("[Overrides]: %s = \"%s\"\n",
cfg, overrides->arrays.input_reserved_devices[i]);
}

for (j = 0; j < RARCH_BIND_LIST_END; j++)
{
const struct retro_keybind *override_bind = &input_override_binds[i][j];
Expand Down
3 changes: 3 additions & 0 deletions configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ typedef struct settings

unsigned input_libretro_device[MAX_USERS];
unsigned input_analog_dpad_mode[MAX_USERS];
unsigned input_device_reservation_type[MAX_USERS];

unsigned input_remap_ports[MAX_USERS];
unsigned input_remap_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
Expand Down Expand Up @@ -476,6 +477,8 @@ typedef struct settings
char input_android_physical_keyboard[255];
#endif

char input_reserved_devices[MAX_USERS][255];

char audio_device[255];
char camera_device[255];
char netplay_mitm_server[255];
Expand Down
33 changes: 27 additions & 6 deletions input/drivers_joypad/test_joypad.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#endif

#define JOYPAD_TEST_COMMAND_ADD_CONTROLLER 1
#define JOYPAD_TEST_COMMAND_REMOVE_CONTROLLER 2
#define JOYPAD_TEST_COMMAND_BUTTON_PRESS_FIRST 16
#define JOYPAD_TEST_COMMAND_BUTTON_PRESS_LAST 31
#define JOYPAD_TEST_COMMAND_BUTTON_RELEASE_FIRST 32
Expand Down Expand Up @@ -71,8 +72,8 @@ typedef struct

static input_test_step_t input_test_steps[MAX_TEST_STEPS];

static unsigned current_frame = 0;
static unsigned next_teststep_frame = 0;
static uint32_t current_frame = 0;
static uint32_t next_teststep_frame = 0;
static unsigned current_test_step = 0;
static unsigned last_test_step = MAX_TEST_STEPS + 1;
static uint32_t input_state_validated = 0;
Expand Down Expand Up @@ -286,22 +287,37 @@ static const char *test_joypad_name(unsigned pad)
if (pad >= MAX_USERS || string_is_empty(test_joypads[pad].name))
return NULL;

return test_joypads[pad].name;
if (strstr(test_joypads[pad].name, ") "))
return strstr(test_joypads[pad].name, ") ") + 2;
else
return test_joypads[pad].name;
}


static void test_joypad_autodetect_add(unsigned autoconf_pad)
{
int vid = 0;
int pid = 0;

sscanf(strstr(test_joypads[autoconf_pad].name, "(") + 1, "%04x:%04x", &vid, &pid);
RARCH_DBG("[Test input driver]: Autoconf vid/pid %x:%x\n",vid,pid);

input_autoconfigure_connect(
test_joypad_name(autoconf_pad),
NULL,
"test",
autoconf_pad,
0,
0
vid,
pid
);
}

static void test_joypad_autodetect_remove(unsigned autoconf_pad)
{
RARCH_DBG("[Test input driver]: Autoremove port %d\n", autoconf_pad);

input_autoconfigure_disconnect(autoconf_pad, test_joypad_name(autoconf_pad));
}

static void *test_joypad_init(void *data)
{
settings_t *settings = config_get_ptr();
Expand Down Expand Up @@ -405,6 +421,11 @@ static void test_joypad_poll(void)
test_joypad_autodetect_add(input_test_steps[i].param_num);
input_test_steps[i].handled = true;
}
else if (input_test_steps[i].action == JOYPAD_TEST_COMMAND_REMOVE_CONTROLLER)
{
test_joypad_autodetect_remove(input_test_steps[i].param_num);
input_test_steps[i].handled = true;
}
else if( input_test_steps[i].action >= JOYPAD_TEST_COMMAND_BUTTON_PRESS_FIRST &&
input_test_steps[i].action <= JOYPAD_TEST_COMMAND_BUTTON_PRESS_LAST)
{
Expand Down
8 changes: 8 additions & 0 deletions input/input_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ enum input_turbo_default_button
INPUT_TURBO_DEFAULT_BUTTON_LAST
};

enum input_device_reservation_type
{
INPUT_DEVICE_RESERVATION_NONE = 0,
INPUT_DEVICE_RESERVATION_PREFERRED,
INPUT_DEVICE_RESERVATION_RESERVED,
INPUT_DEVICE_RESERVATION_LAST
};

RETRO_END_DECLS

#endif
12 changes: 12 additions & 0 deletions intl/msg_hash_lbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,10 @@ MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE,
"deferred_dropdown_box_list_input_device_type"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE,
"deferred_dropdown_box_list_input_select_reserved_device"
)
#ifdef ANDROID
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD,
Expand Down Expand Up @@ -1976,6 +1980,14 @@ MSG_HASH(
MENU_ENUM_LABEL_INPUT_DEVICE_INDEX,
"input_device_p%u"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME,
"input_device_reserved_device_p%u"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE,
"input_device_reservation_type_p%u"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_MOUSE_INDEX,
"input_player%u_mouse_index"
Expand Down
28 changes: 28 additions & 0 deletions intl/msg_hash_us.h
Original file line number Diff line number Diff line change
Expand Up @@ -4125,6 +4125,34 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_DEVICE_INDEX,
"The physical controller as recognized by RetroArch."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVED_DEVICE_NAME,
"Reserved Device for This Player"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME,
"This controller will be allocated for this player, according to reservation mode."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_NONE,
"No Reservation"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_PREFERRED,
"Preferred"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_RESERVED,
"Reserved"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVATION_TYPE,
"Device Reservation Type"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_DEVICE_RESERVATION_TYPE,
"Preferred: if specified device is present, it will be allocated for this player. Reserved: no other controller will be allocated for this player."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_REMAP_PORT,
"Mapped Port"
Expand Down
2 changes: 2 additions & 0 deletions menu/cbs/menu_cbs_deferred_push.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,7 @@ GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_disk_index, PUSH_D
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_device_type, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_DEVICE_TYPE)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_description, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_description_kbd, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION_KBD)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_select_reserved_device, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_RESERVED_DEVICE)
#ifdef ANDROID
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_select_physical_keyboard, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD)
#endif
Expand Down Expand Up @@ -726,6 +727,7 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE, deferred_push_dropdown_box_list_input_device_type},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION, deferred_push_dropdown_box_list_input_description},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD, deferred_push_dropdown_box_list_input_description_kbd},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE, deferred_push_dropdown_box_list_input_select_reserved_device},
#ifdef ANDROID
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, deferred_push_dropdown_box_list_input_select_physical_keyboard},
#endif
Expand Down
73 changes: 73 additions & 0 deletions menu/cbs/menu_cbs_ok.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION;
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD:
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD;
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE:
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE;
#ifdef ANDROID
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD:
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD;
Expand Down Expand Up @@ -845,6 +847,15 @@ int generic_action_ok_displaylist_push(
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE;
dl_type = DISPLAYLIST_GENERIC;
break;
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE:
info.type = type;
info.directory_ptr = idx;
info_path = path;
info_label = msg_hash_to_str(
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE);
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE;
dl_type = DISPLAYLIST_GENERIC;
break;
#ifdef ANDROID
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD:
info.type = type;
Expand Down Expand Up @@ -7310,6 +7321,65 @@ static int action_ok_push_dropdown_item_input_device_type(const char *path,
return action_cancel_pop_default(NULL, NULL, 0, 0);
}

static int action_ok_push_dropdown_item_input_select_reserved_device(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
char* device;
const char *no_device;
const char *reserved_device_name;
enum msg_hash_enums enum_idx;
rarch_setting_t *setting = NULL;
settings_t *settings = config_get_ptr();
const char *menu_path = NULL;
struct menu_state *menu_st = menu_state_get_ptr();
unsigned user;

menu_entries_get_last_stack(&menu_path, NULL, NULL, NULL, NULL);
enum_idx = (enum msg_hash_enums)atoi(menu_path);
setting = menu_setting_find_enum(enum_idx);
user = enum_idx - MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME;

if (!setting)
return -1;

reserved_device_name = path;
no_device = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE);

if (string_is_equal(reserved_device_name, no_device))
settings->arrays.input_reserved_devices[user][0] = '\0';
else
{
int i;
for (i = 0; i < MAX_INPUT_DEVICES; i++)
{
const char* device_name = input_config_get_device_display_name(i)
? input_config_get_device_display_name(i)
: input_config_get_device_name(i);

if (string_is_equal(device_name, reserved_device_name))
{
uint16_t vendor_id = input_config_get_device_vid(i);
uint16_t product_id = input_config_get_device_pid(i);
snprintf(settings->arrays.input_reserved_devices[user],
sizeof(settings->arrays.input_reserved_devices[user]),
"%04x:%04x %s",
vendor_id, product_id, reserved_device_name);
break;
}
}
}
settings->modified = true;

command_event(CMD_EVENT_REINIT, NULL);

/* Refresh menu */
menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH
| MENU_ST_FLAG_PREVENT_POPULATE;

return action_cancel_pop_default(NULL, NULL, 0, 0);
}


#ifdef ANDROID
static int action_ok_push_dropdown_item_input_select_physical_keyboard(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
Expand Down Expand Up @@ -9241,6 +9311,9 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
case MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_TYPE:
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_device_type);
break;
case MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_RESERVED_DEVICE:
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_select_reserved_device);
break;
#ifdef ANDROID
case MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_PHYSICAL_KEYBOARD:
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_select_physical_keyboard);
Expand Down
10 changes: 10 additions & 0 deletions menu/cbs/menu_cbs_sublabel.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,8 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_device_type, ME
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_device_index, MENU_ENUM_SUBLABEL_INPUT_DEVICE_INDEX)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_mouse_index, MENU_ENUM_SUBLABEL_INPUT_MOUSE_INDEX)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_adc_type, MENU_ENUM_SUBLABEL_INPUT_ADC_TYPE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_device_reservation_type, MENU_ENUM_SUBLABEL_INPUT_DEVICE_RESERVATION_TYPE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_device_reserved_device_name, MENU_ENUM_SUBLABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_bind_all, MENU_ENUM_SUBLABEL_INPUT_BIND_ALL)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_save_autoconfig, MENU_ENUM_SUBLABEL_INPUT_SAVE_AUTOCONFIG)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_bind_defaults, MENU_ENUM_SUBLABEL_INPUT_BIND_DEFAULTS)
Expand Down Expand Up @@ -5645,6 +5647,14 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
MENU_ENUM_LABEL_INPUT_DEVICE_INDEX,
NULL
},*/
{
MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE,
action_bind_sublabel_input_device_reservation_type
},
{
MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME,
action_bind_sublabel_input_device_reserved_device_name
},
{
MENU_ENUM_LABEL_INPUT_MOUSE_INDEX,
action_bind_sublabel_input_mouse_index
Expand Down
Loading

0 comments on commit a9968e9

Please sign in to comment.