diff --git a/configuration.c b/configuration.c index 7730905106fe..286df58dafc1 100644 --- a/configuration.c +++ b/configuration.c @@ -3737,6 +3737,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); + } } @@ -5270,7 +5274,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); @@ -5290,6 +5293,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 */ @@ -5624,6 +5630,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]; diff --git a/configuration.h b/configuration.h index 1c1016b4e7f6..ed2f61caa3cd 100644 --- a/configuration.h +++ b/configuration.h @@ -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]; diff --git a/input/drivers_joypad/test_joypad.c b/input/drivers_joypad/test_joypad.c index 141ce230eb40..08bceda0b4f7 100644 --- a/input/drivers_joypad/test_joypad.c +++ b/input/drivers_joypad/test_joypad.c @@ -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 @@ -286,17 +287,18 @@ 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_joypad_name(autoconf_pad), "(") + 1, "%04x:%04x", &vid, &pid); - //sscanf(test_joypad_name(autoconf_pad), "%04x:%04x ", &vid, &pid); + 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( @@ -309,6 +311,13 @@ static void test_joypad_autodetect_add(unsigned autoconf_pad) ); } +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(); @@ -412,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) { diff --git a/input/input_defines.h b/input/input_defines.h index 44cf2c8284ff..5ba2f88fe8d3 100644 --- a/input/input_defines.h +++ b/input/input_defines.h @@ -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 diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 887a643c0133..9bfb8c1fba0f 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -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" diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index f66510b0f9cf..2ae177cda6ad 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -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 @@ -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 diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 6a164858055a..3a68b72fc9f3 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -316,6 +316,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; @@ -869,6 +871,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; @@ -7318,6 +7329,60 @@ 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(); + 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); + unsigned 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_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) @@ -9249,6 +9314,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); diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index a2a3a7f9b073..0f7f77f41a48 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -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) @@ -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 diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index 82ea16c7bdf7..f0a50f84a117 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -334,6 +334,16 @@ static int action_get_title_dropdown_item( (enum_idx <= MENU_ENUM_LABEL_INPUT_DEVICE_INDEX_LAST)) enum_idx = MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_INDEX; + /* Device Reservation Type */ + if ((enum_idx >= MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE) && + (enum_idx <= MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE_LAST)) + enum_idx = MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVATION_TYPE; + + /* Reserved Device Name */ + if ((enum_idx >= MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME) && + (enum_idx <= MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME_LAST)) + enum_idx = MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVED_DEVICE_NAME; + /* Mouse Index */ if ((enum_idx >= MENU_ENUM_LABEL_INPUT_MOUSE_INDEX) && (enum_idx <= MENU_ENUM_LABEL_INPUT_MOUSE_INDEX_LAST)) @@ -1832,6 +1842,7 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs, {MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE, action_get_title_dropdown_item}, {MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION, action_get_title_dropdown_input_description}, {MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD, action_get_title_dropdown_input_description_kbd}, + {MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE, action_get_title_dropdown_item}, #ifdef ANDROID {MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, action_get_title_dropdown_item}, #endif diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c index cd1737ac6e21..58fde4ba414c 100644 --- a/menu/drivers/ozone.c +++ b/menu/drivers/ozone.c @@ -2369,22 +2369,22 @@ static uintptr_t ozone_entries_icon_get_texture( /* account for the additional split joycon option in Input User # Binds */ input_id++; #endif - if (type == input_id + 1) + if (type >= input_id + 1 && type <= input_id + 3) return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_SETTINGS]; - if (type == input_id + 2) + if (type == input_id + 4) return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_MOUSE]; - if (type == input_id + 3) + if (type == input_id + 5) return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BIND_ALL]; - if (type == input_id + 4) + if (type == input_id + 6) return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_RELOAD]; - if (type == input_id + 5) + if (type == input_id + 7) return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_SAVING]; - if ((type > (input_id + 29)) && (type < (input_id + 41))) + if ((type > (input_id + 31)) && (type < (input_id + 43))) return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_LGUN]; - if (type == input_id + 41) + if (type == input_id + 43) return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_TURBO]; /* align to use the same code of Quickmenu controls*/ - input_id = input_id + 6; + input_id = input_id + 8; } else { diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 787588a139ec..f489b73ade2b 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -3532,22 +3532,22 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, option in Input # Binds */ input_id++; #endif - if (type == input_id + 1) + if (type >= input_id + 1 && type <= input_id + 3) return xmb->textures.list[XMB_TEXTURE_INPUT_SETTINGS]; - if (type == input_id + 2) + if (type == input_id + 4) return xmb->textures.list[XMB_TEXTURE_INPUT_MOUSE]; - if (type == input_id + 3) + if (type == input_id + 5) return xmb->textures.list[XMB_TEXTURE_INPUT_BIND_ALL]; - if (type == input_id + 4) + if (type == input_id + 6) return xmb->textures.list[XMB_TEXTURE_RELOAD]; - if (type == input_id + 5) + if (type == input_id + 7) return xmb->textures.list[XMB_TEXTURE_SAVING]; - if ((type > (input_id + 29)) && (type < (input_id + 41))) + if ((type > (input_id + 31)) && (type < (input_id + 43))) return xmb->textures.list[XMB_TEXTURE_INPUT_LGUN]; - if (type == input_id + 41) + if (type == input_id + 43) return xmb->textures.list[XMB_TEXTURE_INPUT_TURBO]; /* Align to use the same code of Quickmenu controls */ - input_id = input_id + 6; + input_id = input_id + 8; } else { diff --git a/menu/menu_cbs.h b/menu/menu_cbs.h index e5e6fe6834fa..515803bbb328 100644 --- a/menu/menu_cbs.h +++ b/menu/menu_cbs.h @@ -57,6 +57,7 @@ enum ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE, ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION, ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD, + ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE, #ifdef ANDROID ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, #endif diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index e2fac7b8f1b5..cce12078a9e2 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -5562,6 +5562,111 @@ static int menu_displaylist_parse_input_device_type_list( return count; } +static int menu_displaylist_parse_input_select_reserved_device_list( + file_list_t *info_list, const char *info_path, + settings_t *settings) +{ + char device_label[128]; + const char *val_disabled = NULL; + enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info_path); + struct menu_state *menu_st = menu_state_get_ptr(); + rarch_setting_t *setting = menu_setting_find_enum(enum_idx); + size_t menu_index = 0; + unsigned count = 0; + int i = 0; + char reserved_device_name[sizeof(settings->arrays.input_reserved_devices[0])]; + bool device_added = false; + + device_label[0] = '\0'; + + if (!settings || !setting) + return 0; + + val_disabled = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE); + if (string_is_empty(settings->arrays.input_reserved_devices[enum_idx - MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME])) + strlcpy(reserved_device_name, val_disabled, sizeof(reserved_device_name)); + else + strlcpy(reserved_device_name, settings->arrays.input_reserved_devices[enum_idx - MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME], sizeof(reserved_device_name)); + + /* List elements: none/disabled, all existing reservations, all existing devices */ + for (i = MAX_INPUT_DEVICES+MAX_USERS; i >= 0; --i) + { + device_label[0] = '\0'; + + if (i == MAX_INPUT_DEVICES + MAX_USERS) + strlcpy(device_label, val_disabled, sizeof(device_label)); + else if (i < MAX_INPUT_DEVICES) + { + 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_empty(device_name)) + { + unsigned idx = input_config_get_device_name_index(i); + size_t _len = strlcpy(device_label, device_name, + sizeof(device_label)); + /* If idx is non-zero, it's part of a set*/ + if (idx > 0) + snprintf(device_label + _len, + sizeof(device_label) - _len, " (#%u)", idx); + } + } + else + { + if (!string_is_empty(settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES])) + { + unsigned int vendor_id; + unsigned int product_id; + if (sscanf(settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES], "%04x:%04x ", &vendor_id, &product_id) != 2) + strlcpy(device_label, settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES], sizeof(reserved_device_name)); + else + /* If the vendor_id:product_id is encoded in the name, ignore them. */ + strlcpy(device_label, &settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES][10], sizeof(reserved_device_name)); + } + } + + if (!string_is_empty(device_label)) + { + size_t previous_position; + if (file_list_search(info_list, device_label, &previous_position)) + continue; + + /* Add menu entry */ + if (menu_entries_append(info_list, + device_label, + device_label, + MSG_UNKNOWN, + MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_RESERVED_DEVICE, + 0, menu_index, NULL)) + { + /* Add checkmark if input is currently + * mapped to this entry */ + if (string_is_equal(device_label, reserved_device_name)) + { + menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; + if (cbs) + cbs->checked = true; + menu_st->selection_ptr = menu_index; + device_added = true; + } + count++; + menu_index++; + } + } + } + + /* if nothing is configured, select None by default */ + if (!device_added) + { + menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[0].actiondata; + if (cbs) + cbs->checked = true; + menu_st->selection_ptr = 0; + } + return count; +} + #ifdef ANDROID static int menu_displaylist_parse_input_select_physical_keyboard_list( file_list_t *info_list, const char *info_path, @@ -13983,6 +14088,20 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_entries_clear(info->list); count = menu_displaylist_parse_input_device_type_list(info->list, info->path, settings); + if (count == 0) + if (menu_entries_append(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), + msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), + MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, + FILE_TYPE_NONE, 0, 0, NULL)) + count++; + info->flags |= MD_FLAG_NEED_REFRESH + | MD_FLAG_NEED_PUSH; + break; + case DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_RESERVED_DEVICE: + menu_entries_clear(info->list); + count = menu_displaylist_parse_input_select_reserved_device_list(info->list, info->path, settings); + if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), diff --git a/menu/menu_displaylist.h b/menu/menu_displaylist.h index d3bba901ccf2..8a27ccbb9ebc 100644 --- a/menu/menu_displaylist.h +++ b/menu/menu_displaylist.h @@ -78,6 +78,7 @@ enum menu_displaylist_ctl_state DISPLAYLIST_DROPDOWN_LIST_INPUT_DEVICE_TYPE, DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION, DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION_KBD, + DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_RESERVED_DEVICE, #ifdef ANDROID DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, #endif diff --git a/menu/menu_driver.h b/menu/menu_driver.h index e56be9fdd75b..254afafc1e25 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -110,6 +110,7 @@ enum menu_settings_type MENU_SETTING_DROPDOWN_ITEM_DISK_INDEX, MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_TYPE, MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_INDEX, + MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_RESERVED_DEVICE, #ifdef ANDROID MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_PHYSICAL_KEYBOARD, #endif diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 33bd9a7733ca..51ad76ad0eaa 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -184,6 +184,10 @@ if (SETTINGS_LIST_APPEND(a, b)) \ config_string(a, b, c, d, e, f, g, h, i, j, k, l) +#define CONFIG_STRING_ALT(a, b, c, d, e, f, g, h, i, j, k, l) \ + if (SETTINGS_LIST_APPEND(a, b)) \ + config_string_alt(a, b, c, d, e, f, g, h, i, j, k, l) + #define CONFIG_FLOAT(a, b, c, d, e, f, g, h, i, j, k, l) \ if (SETTINGS_LIST_APPEND(a, b)) \ config_float(a, b, c, d, e, f, g, h, i, j, k, l) @@ -2398,6 +2402,26 @@ static void config_string( MENU_SETTINGS_LIST_CURRENT_ADD_ENUM_VALUE_IDX(list, list_info, SHORT_enum_idx); } +static void config_string_alt( + rarch_setting_t **list, + rarch_setting_info_t *list_info, + char *target, size_t len, + char *label, + char* shortname, + const char *default_value, + rarch_setting_group_info_t *group_info, + rarch_setting_group_info_t *subgroup_info, + const char *parent_group, + change_handler_t change_handler, change_handler_t read_handler) +{ + (*list)[list_info->index++] = setting_string_setting(ST_STRING, + label, + shortname, + target, (unsigned)len, default_value, "", + group_info->name, subgroup_info->name, parent_group, + change_handler, read_handler, true); +} + static void config_string_options( rarch_setting_t **list, rarch_setting_info_t *list_info, @@ -2750,6 +2774,20 @@ static int setting_action_ok_select_physical_keyboard( } #endif +static int setting_action_ok_select_reserved_device( + rarch_setting_t *setting, size_t idx, bool wraparound) +{ + char enum_idx[16]; + if (!setting) + return -1; + snprintf(enum_idx, sizeof(enum_idx), "%d", setting->enum_idx); + generic_action_ok_displaylist_push( + enum_idx, /* we will pass the enumeration index of the string as a path */ + NULL, NULL, 0, idx, 0, + ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE); + return 0; +} + #if !defined(RARCH_CONSOLE) static int setting_string_action_ok_audio_device( rarch_setting_t *setting, size_t idx, bool wraparound) @@ -5705,6 +5743,27 @@ static int setting_action_left_input_device_index( return 0; } +static int setting_action_left_input_device_reservation_type( + rarch_setting_t *setting, size_t idx, bool wraparound) +{ + settings_t *settings = config_get_ptr(); + unsigned *p = NULL; + + if (!setting || !settings) + return -1; + + p = &settings->uints.input_device_reservation_type[setting->index_offset]; + + if (*p) + (*p)--; + else + *p = INPUT_DEVICE_RESERVATION_LAST - 1; + + settings->modified = true; + return 0; +} + + static int setting_action_left_input_mouse_index( rarch_setting_t *setting, size_t idx, bool wraparound) { @@ -7649,6 +7708,32 @@ static int setting_action_start_input_device_index(rarch_setting_t *setting) return 0; } +static int setting_action_start_input_device_reservation_type(rarch_setting_t *setting) +{ + settings_t *settings = config_get_ptr(); + + if (!setting || !settings) + return -1; + + configuration_set_uint(settings, + settings->uints.input_device_reservation_type[setting->index_offset], + INPUT_DEVICE_RESERVATION_NONE); + return 0; +} + +static int setting_action_start_input_device_reserved_device_name(rarch_setting_t *setting) +{ + settings_t *settings = config_get_ptr(); + + if (!setting || !settings) + return -1; + + configuration_set_string(settings, + settings->arrays.input_reserved_devices[setting->index_offset], + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE)); + return 0; +} + static int setting_action_start_custom_viewport_width(rarch_setting_t *setting) { video_viewport_t vp; @@ -7913,6 +7998,26 @@ static int setting_action_right_input_device_index( return 0; } +static int setting_action_right_input_device_reservation_type( + rarch_setting_t *setting, size_t idx, bool wraparound) +{ + settings_t *settings = config_get_ptr(); + unsigned *p = NULL; + + if (!setting || !settings) + return -1; + + p = &settings->uints.input_device_reservation_type[setting->index_offset]; + + if (*p < INPUT_DEVICE_RESERVATION_LAST - 1) + (*p)++; + else + *p = 0; + + settings->modified = true; + return 0; +} + static int setting_action_right_input_mouse_index( rarch_setting_t *setting, size_t idx, bool wraparound) { @@ -8018,6 +8123,51 @@ static void get_string_representation_input_device_index( strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISABLED), len); } +static void get_string_representation_input_device_reservation_type( + rarch_setting_t *setting, char *s, size_t len) +{ + settings_t *settings = config_get_ptr(); + unsigned map = 0; + + if (!setting || !settings) + return; + + map = settings->uints.input_device_reservation_type[setting->index_offset]; + + if (map == INPUT_DEVICE_RESERVATION_NONE) + { + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_NONE), len); + } + else if (map == INPUT_DEVICE_RESERVATION_PREFERRED) + { + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_PREFERRED), len); + } + else if (map == INPUT_DEVICE_RESERVATION_RESERVED) + { + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_RESERVED), len); + } + else + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISABLED), len); +} + +static void setting_get_string_representation_input_device_reserved_device_name( + rarch_setting_t *setting, + char *s, size_t len) +{ + if (!setting) + return; + + settings_t *settings = config_get_ptr(); + + int dev_vendor_id; + int dev_product_id; + + if (sscanf(setting->value.target.string, "%04x:%04x ", &dev_vendor_id, &dev_product_id) != 2) + strlcpy(s, setting->value.target.string, len); + else + strlcpy(s, &setting->value.target.string[10], len); +} + static void get_string_representation_input_mouse_index( rarch_setting_t *setting, char *s, size_t len) { @@ -9331,6 +9481,8 @@ static bool setting_append_list_input_player_options( { static char device_index[MAX_USERS][64]; + static char device_reservation_type[MAX_USERS][64]; + static char device_reserved_device[MAX_USERS][64]; static char mouse_index[MAX_USERS][64]; static char analog_to_digital[MAX_USERS][64]; static char bind_all[MAX_USERS][64]; @@ -9338,6 +9490,8 @@ static bool setting_append_list_input_player_options( static char bind_defaults[MAX_USERS][64]; static char label_device_index[MAX_USERS][64]; + static char label_device_reservation_type[MAX_USERS][64]; + static char label_device_reserved_device[MAX_USERS][64]; static char label_mouse_index[MAX_USERS][64]; static char label_analog_to_digital[MAX_USERS][64]; static char label_bind_all[MAX_USERS][64]; @@ -9350,17 +9504,21 @@ static bool setting_append_list_input_player_options( #endif snprintf(analog_to_digital[user], sizeof(analog_to_digital[user]), - msg_hash_to_str(MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE), user + 1); + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE), user + 1); snprintf(device_index[user], sizeof(device_index[user]), - msg_hash_to_str(MENU_ENUM_LABEL_INPUT_JOYPAD_INDEX), user + 1); + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_JOYPAD_INDEX), user + 1); + snprintf(device_reservation_type[user], sizeof(device_reservation_type[user]), + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE), user + 1); + snprintf(device_reserved_device[user], sizeof(device_reserved_device[user]), + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME), user + 1); snprintf(mouse_index[user], sizeof(mouse_index[user]), - msg_hash_to_str(MENU_ENUM_LABEL_INPUT_MOUSE_INDEX), user + 1); + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_MOUSE_INDEX), user + 1); snprintf(bind_all[user], sizeof(bind_all[user]), - msg_hash_to_str(MENU_ENUM_LABEL_INPUT_BIND_ALL_INDEX), user + 1); + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_BIND_ALL_INDEX), user + 1); snprintf(bind_all_save_autoconfig[user], sizeof(bind_all_save_autoconfig[user]), - msg_hash_to_str(MENU_ENUM_LABEL_INPUT_SAVE_AUTOCONFIG_INDEX), user + 1); + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_SAVE_AUTOCONFIG_INDEX), user + 1); snprintf(bind_defaults[user], sizeof(bind_defaults[user]), - msg_hash_to_str(MENU_ENUM_LABEL_INPUT_BIND_DEFAULTS_INDEX), user + 1); + msg_hash_to_str(MENU_ENUM_LABEL_INPUT_BIND_DEFAULTS_INDEX), user + 1); strlcpy(label_analog_to_digital[user], msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_ADC_TYPE), @@ -9368,6 +9526,12 @@ static bool setting_append_list_input_player_options( strlcpy(label_device_index[user], msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_INDEX), sizeof(label_device_index[user])); + strlcpy(label_device_reservation_type[user], + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVATION_TYPE), + sizeof(label_device_reservation_type[user])); + strlcpy(label_device_reserved_device[user], + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVED_DEVICE_NAME), + sizeof(label_device_reserved_device[user])); strlcpy(label_mouse_index[user], msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_INDEX), sizeof(label_mouse_index[user])); @@ -9461,6 +9625,54 @@ static bool setting_append_list_input_player_options( MENU_SETTINGS_LIST_CURRENT_ADD_ENUM_IDX_PTR(list, list_info, (enum msg_hash_enums)(MENU_ENUM_LABEL_INPUT_DEVICE_INDEX + user)); + CONFIG_UINT_ALT( + list, list_info, + &settings->uints.input_device_reservation_type[user], + device_reservation_type[user], + label_device_reservation_type[user], + INPUT_DEVICE_RESERVATION_NONE, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].index = user + 1; + (*list)[list_info->index - 1].index_offset = user; + (*list)[list_info->index - 1].action_start = &setting_action_start_input_device_reservation_type; + (*list)[list_info->index - 1].action_left = &setting_action_left_input_device_reservation_type; + (*list)[list_info->index - 1].action_right = &setting_action_right_input_device_reservation_type; + (*list)[list_info->index - 1].action_select = &setting_action_right_input_device_reservation_type; + (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; + (*list)[list_info->index - 1].get_string_representation = + &get_string_representation_input_device_reservation_type; + menu_settings_list_current_add_range(list, list_info, 0, INPUT_DEVICE_RESERVATION_LAST - 1, 1.0, true, true); + MENU_SETTINGS_LIST_CURRENT_ADD_ENUM_IDX_PTR(list, list_info, + (enum msg_hash_enums)(MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE + user)); + + CONFIG_STRING_ALT( + list, list_info, + settings->arrays.input_reserved_devices[user], + sizeof(settings->arrays.input_reserved_devices[user]), + device_reserved_device[user], + label_device_reserved_device[user], + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE), + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].index = user + 1; + (*list)[list_info->index - 1].index_offset = user; + (*list)[list_info->index - 1].action_ok = &setting_action_ok_select_reserved_device; + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_input_device_reserved_device_name; + (*list)[list_info->index - 1].action_start = &setting_action_start_input_device_reserved_device_name; + + MENU_SETTINGS_LIST_CURRENT_ADD_ENUM_IDX_PTR(list, list_info, + (enum msg_hash_enums)(MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME + user)); + MENU_SETTINGS_LIST_CURRENT_ADD_ENUM_VALUE_IDX(list, list_info, + (enum msg_hash_enums)(MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVED_DEVICE_NAME)); + CONFIG_UINT_ALT( list, list_info, &settings->uints.input_mouse_index[user], diff --git a/msg_hash.h b/msg_hash.h index 9b12f46e1cfd..2920e25b5678 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -871,6 +871,10 @@ enum msg_hash_enums MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE_LAST = MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE + MAX_USERS, MENU_ENUM_LABEL_INPUT_DEVICE_INDEX, MENU_ENUM_LABEL_INPUT_DEVICE_INDEX_LAST = MENU_ENUM_LABEL_INPUT_DEVICE_INDEX + MAX_USERS, + MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE, + MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE_LAST = MENU_ENUM_LABEL_INPUT_DEVICE_RESERVATION_TYPE + MAX_USERS, + MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME, + MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME_LAST = MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME + MAX_USERS, MENU_ENUM_LABEL_INPUT_MOUSE_INDEX, MENU_ENUM_LABEL_INPUT_MOUSE_INDEX_LAST = MENU_ENUM_LABEL_INPUT_MOUSE_INDEX + MAX_USERS, MENU_ENUM_LABEL_INPUT_REMAP_PORT, @@ -1156,6 +1160,11 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_INPUT_SAVE_AUTOCONFIG, MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_INDEX, MENU_ENUM_LABEL_INPUT_JOYPAD_INDEX, + MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVED_DEVICE_NAME, + MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_RESERVATION_TYPE, + MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_NONE, + MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_PREFERRED, + MENU_ENUM_LABEL_VALUE_DEVICE_RESERVATION_RESERVED, MENU_ENUM_LABEL_INPUT_BIND_ALL_INDEX, MENU_ENUM_LABEL_INPUT_SAVE_AUTOCONFIG_INDEX, MENU_ENUM_LABEL_INPUT_BIND_DEFAULTS_INDEX, @@ -1163,6 +1172,9 @@ enum msg_hash_enums MENU_ENUM_SUBLABEL_INPUT_DEVICE_TYPE, MENU_ENUM_SUBLABEL_INPUT_DEVICE_INDEX, + MENU_ENUM_SUBLABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME, + MENU_ENUM_SUBLABEL_INPUT_DEVICE_RESERVATION_TYPE, + MENU_ENUM_LABEL_HELP_INPUT_DEVICE_RESERVATION_TYPE, MENU_ENUM_SUBLABEL_INPUT_MOUSE_INDEX, MENU_ENUM_SUBLABEL_INPUT_ADC_TYPE, MENU_ENUM_LABEL_HELP_INPUT_ADC_TYPE, @@ -1969,8 +1981,9 @@ enum msg_hash_enums MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE, MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION, MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD, + MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_RESERVED_DEVICE, #ifdef ANDROID - MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, + MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, #endif MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_NETPLAY_MITM_SERVER, MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST, diff --git a/tasks/task_autodetect.c b/tasks/task_autodetect.c index 5f39f2c21e21..40770bf20de5 100644 --- a/tasks/task_autodetect.c +++ b/tasks/task_autodetect.c @@ -354,52 +354,117 @@ static bool input_autoconfigure_scan_config_files_internal( return false; } -static void set_reserved_port(unsigned detected_port, int vendor_id, +/* Reallocate the automatically assigned player <-> port mapping if needed. + * Objectives: + * - if there is no reservation, do not change anything + * - if detected port is reserved for something else (reserved mode), change it to first free player + * - if there is reservation for the device, assign it to the reserved player +*/ +static void reallocate_port_if_needed(unsigned detected_port, int vendor_id, int product_id, const char *device_name) { settings_t *settings = config_get_ptr(); - unsigned port; - bool is_reserved; - char settings_value[256]; + unsigned player; + unsigned first_free_player_slot = MAX_USERS + 1; + unsigned prev_assigned_player_slots[MAX_USERS]; + bool device_has_reserved_slot = false; + char settings_value[256] = {0}; int settings_value_vendor_id; int settings_value_product_id; char settings_value_device_name[256]; - for (port = 0; port < MAX_USERS; port++) + for (player = 0; player < MAX_USERS; player++) { - strlcpy(settings_value, settings->arrays.input_reserved_devices[port], sizeof(settings_value)); + if (first_free_player_slot > settings->uints.input_max_users && + (detected_port == settings->uints.input_joypad_index[player] || !input_config_get_device_name(settings->uints.input_joypad_index[player])) && + settings->uints.input_device_reservation_type[player] != INPUT_DEVICE_RESERVATION_RESERVED ) + { + first_free_player_slot = player; + RARCH_DBG("[Autoconf]: First unconfigured / unreserved player is %d\n", player+1); + } + prev_assigned_player_slots[settings->uints.input_joypad_index[player]] = player; + } + if (first_free_player_slot > settings->uints.input_max_users) { + RARCH_ERR( "[Autoconf]: No free and unreserved player slots found for adding new device \"%s\"! Detected port %d, max_users: %d, first free slot %d\n", + device_name, detected_port, settings->uints.input_max_users, first_free_player_slot+1); + RARCH_WARN("[Autoconf]: Leaving detected player slot in place: %d\n", prev_assigned_player_slots[detected_port]); + return; + } + + for (player = 0; player < MAX_USERS; player++) + { + if (settings->uints.input_device_reservation_type[player] != INPUT_DEVICE_RESERVATION_NONE) + strlcpy(settings_value, settings->arrays.input_reserved_devices[player], sizeof(settings_value)); + else + settings_value[0] = '\0'; if (!string_is_empty(settings_value)) { - RARCH_LOG("[Autoconfig]: Examining reserved device for port %d: %s against %x:%x\n",port, settings_value, vendor_id, product_id); + RARCH_DBG("[Autoconf]: Examining reserved device for player %d type %d: %s against %04x:%04x\n", + player+1, settings->uints.input_device_reservation_type[player], + settings_value, vendor_id, product_id); + if (sscanf(settings_value, "%04x:%04x ", &settings_value_vendor_id, &settings_value_product_id) != 2) { strlcpy(settings_value_device_name, settings_value, sizeof(settings_value_device_name)); - is_reserved = string_is_equal(device_name, settings_value_device_name); + device_has_reserved_slot = string_is_equal(device_name, settings_value_device_name); } else - is_reserved = (vendor_id == settings_value_vendor_id && product_id == settings_value_product_id); + device_has_reserved_slot = (vendor_id == settings_value_vendor_id && product_id == settings_value_product_id); - if (is_reserved) + if (device_has_reserved_slot) { - unsigned prev_assigned_port = settings->uints.input_joypad_index[port]; - RARCH_LOG("[Autoconfig]: Device \"%s\" (%x:%x) is reserved for port %d, setting.\n", - device_name, vendor_id, product_id, port+1); - if(detected_port != prev_assigned_port) - { - // todo: swap unused ports around, fix the pushed info message - settings->uints.input_joypad_index[port] = detected_port; - if(settings->uints.input_joypad_index[detected_port] == detected_port) - settings->uints.input_joypad_index[detected_port] = prev_assigned_port; - } - return; + RARCH_DBG("[Autoconf]: Reserved device matched\n"); + break; } } } - RARCH_LOG("[Autoconfig]: Device \"%s\" (%d:%d) has no reserved port.\n", - device_name, vendor_id, product_id); + if (device_has_reserved_slot) + { + unsigned prev_assigned_port = settings->uints.input_joypad_index[player]; + if(detected_port != prev_assigned_port) + { + RARCH_LOG("[Autoconf]: Device \"%s\" (%x:%x) is reserved for player %d, updating.\n", + device_name, vendor_id, product_id, player+1); + + // todo: fix the pushed info message + settings->uints.input_joypad_index[player] = detected_port; + + /*if ((settings->uints.input_device_reservation_type[player] == INPUT_DEVICE_RESERVATION_PREFERRED) && + input_config_get_device_name(prev_assigned_port))*/ + { + RARCH_LOG("[Autoconf]: Preferred slot was taken earlier by \"%s\", reassigning that to %d\n", + input_config_get_device_name(prev_assigned_port), prev_assigned_player_slots[detected_port]+1); + settings->uints.input_joypad_index[prev_assigned_player_slots[detected_port]] = prev_assigned_port; + } + + } + else + { + RARCH_DBG("[Autoconf]: Device \"%s\" (%x:%x) is reserved for player %d, same as default assignment.\n", + device_name, vendor_id, product_id, player+1); + } + return; + } + else + { + RARCH_DBG("[Autoconf]: Device \"%s\" (%d:%d) is not reserved for any player slot.\n", + device_name, vendor_id, product_id); + if (prev_assigned_player_slots[detected_port] == first_free_player_slot) + { + return; + } + else + { + unsigned prev_assigned_port = settings->uints.input_joypad_index[first_free_player_slot]; + settings->uints.input_joypad_index[first_free_player_slot] = detected_port; + settings->uints.input_joypad_index[prev_assigned_player_slots[detected_port]] = prev_assigned_port; + RARCH_DBG("[Autoconf]: Earlier free player slot found, reassigning to player %d.\n", + first_free_player_slot+1); + } + } return; } @@ -477,7 +542,7 @@ static void cb_input_autoconfigure_connect( input_config_set_autoconfig_binds(port, autoconfig_handle->autoconfig_file); - set_reserved_port(port,autoconfig_handle->device_info.vid, autoconfig_handle->device_info.pid,autoconfig_handle->device_info.name); + reallocate_port_if_needed(port,autoconfig_handle->device_info.vid, autoconfig_handle->device_info.pid,autoconfig_handle->device_info.name); } diff --git a/tests-other/autoconf/TestpadA.cfg b/tests-other/autoconf/TestpadA.cfg index 5d285d1b1c5e..29f801fce3e4 100644 --- a/tests-other/autoconf/TestpadA.cfg +++ b/tests-other/autoconf/TestpadA.cfg @@ -1,5 +1,5 @@ input_driver = "test" -input_device = "Test joypad device A (0001:0002)" +input_device = "Test joypad device A" input_b_btn = "0" input_y_btn = "1" input_select_btn = "2" diff --git a/tests-other/autoconf/TestpadB.cfg b/tests-other/autoconf/TestpadB.cfg index c2ed36cb6cef..9ace48b8a820 100644 --- a/tests-other/autoconf/TestpadB.cfg +++ b/tests-other/autoconf/TestpadB.cfg @@ -1,5 +1,5 @@ input_driver = "test" -input_device = "Test joypad device B (0003:0004)" +input_device = "Test joypad device B" input_b_btn = "0" input_y_btn = "1" input_select_btn = "2" diff --git a/tests-other/autoconf/TestpadC.cfg b/tests-other/autoconf/TestpadC.cfg index 450ddc3f4405..1fb363c3ca34 100644 --- a/tests-other/autoconf/TestpadC.cfg +++ b/tests-other/autoconf/TestpadC.cfg @@ -1,5 +1,5 @@ input_driver = "test" -input_device = "Test joypad device C (0005:0006)" +input_device = "Test joypad device C" input_b_btn = "0" input_y_btn = "1" input_select_btn = "2" diff --git a/tests-other/test_input_joypad.ratst b/tests-other/test_input_joypad.ratst index 587286ff21b7..8be712c808b0 100644 --- a/tests-other/test_input_joypad.ratst +++ b/tests-other/test_input_joypad.ratst @@ -2,18 +2,18 @@ { "action": 1, "param_num": 0, - "param_str": "Test joypad device A (0001:0002)" + "param_str": "(0001:0002) Test joypad device A", }, { "action": 1, "param_num": 1, - "param_str": "Test joypad device B (0003:0004)", + "param_str": "(0003:0004) Test joypad device B" "frame": 0 }, { "action": 1, "param_num": 2, - "param_str": "Test joypad device C (0005:0006)" + "param_str": "(0005:0006) Test joypad device C" }, { "action": 16, diff --git a/tests-other/testinput.cfg b/tests-other/testinput.cfg index b7c587bdf0b5..494b04e197bc 100644 --- a/tests-other/testinput.cfg +++ b/tests-other/testinput.cfg @@ -11,4 +11,9 @@ frontend_log_level = "0" libretro_log_level = "0" log_verbosity = "true" config_save_on_exit = "false" -input_player4_reserved_device = "0003:0004 " +input_player4_reserved_device = "Test joypad device B" +input_player4_device_reservation_type = "2" +input_player1_reserved_device = "Test joypad device C" +input_player1_device_reservation_type = "1" +input_player2_reserved_device = "fake reservation 2" +input_player3_reserved_device = "fake reservation 3"