diff --git a/configuration.c b/configuration.c index 7033e743bc..7492c9f45b 100644 --- a/configuration.c +++ b/configuration.c @@ -1132,8 +1132,6 @@ static struct config_array_setting *populate_settings_array(settings_t *settings return NULL; /* Arrays */ - SETTING_ARRAY("playlist_names", settings->arrays.playlist_names, false, NULL, true); - SETTING_ARRAY("playlist_cores", settings->arrays.playlist_cores, false, NULL, true); SETTING_ARRAY("video_driver", settings->arrays.video_driver, false, NULL, true); SETTING_ARRAY("record_driver", settings->arrays.record_driver, false, NULL, true); SETTING_ARRAY("camera_driver", settings->arrays.camera_driver, false, NULL, true); @@ -2181,8 +2179,6 @@ void config_set_defaults(void) *settings->paths.path_stream_url = '\0'; *settings->paths.path_softfilter_plugin = '\0'; - *settings->arrays.playlist_names = '\0'; - *settings->arrays.playlist_cores = '\0'; *settings->paths.directory_content_history = '\0'; *settings->paths.path_audio_dsp_plugin = '\0'; diff --git a/configuration.h b/configuration.h index f4f5611f42..3bbbe805ea 100644 --- a/configuration.h +++ b/configuration.h @@ -566,8 +566,6 @@ typedef struct settings char audio_device[255]; char camera_device[255]; - char playlist_names[8192]; - char playlist_cores[8192]; char bundle_assets_src[PATH_MAX_LENGTH]; char bundle_assets_dst[PATH_MAX_LENGTH]; char bundle_assets_dst_subdir[PATH_MAX_LENGTH]; diff --git a/core_info.c b/core_info.c index 37cc7d1827..13cea324d5 100644 --- a/core_info.c +++ b/core_info.c @@ -929,3 +929,82 @@ bool core_info_get_display_name(const char *path, char *s, size_t len) config_file_free(conf); return true; } + +static int core_info_qsort_func_path(const core_info_t *a, + const core_info_t *b) +{ + if (!a || !b) + return 0; + + if (string_is_empty(a->path) || string_is_empty(b->path)) + return 0; + + return strcasecmp(a->path, b->path); +} + +static int core_info_qsort_func_display_name(const core_info_t *a, + const core_info_t *b) +{ + if (!a || !b) + return 0; + + if (string_is_empty(a->display_name) || string_is_empty(b->display_name)) + return 0; + + return strcasecmp(a->display_name, b->display_name); +} + +static int core_info_qsort_func_core_name(const core_info_t *a, + const core_info_t *b) +{ + if (!a || !b) + return 0; + + if (string_is_empty(a->core_name) || string_is_empty(b->core_name)) + return 0; + + return strcasecmp(a->core_name, b->core_name); +} + +static int core_info_qsort_func_system_name(const core_info_t *a, + const core_info_t *b) +{ + if (!a || !b) + return 0; + + if (string_is_empty(a->systemname) || string_is_empty(b->systemname)) + return 0; + + return strcasecmp(a->systemname, b->systemname); +} + +void core_info_qsort(core_info_list_t *core_info_list, enum core_info_list_qsort_type qsort_type) +{ + if (!core_info_list) + return; + + if (core_info_list->count < 2) + return; + + switch (qsort_type) + { + case CORE_INFO_LIST_SORT_PATH: + qsort(core_info_list->list, core_info_list->count, sizeof(core_info_t), + (int (*)(const void *, const void *))core_info_qsort_func_path); + break; + case CORE_INFO_LIST_SORT_DISPLAY_NAME: + qsort(core_info_list->list, core_info_list->count, sizeof(core_info_t), + (int (*)(const void *, const void *))core_info_qsort_func_display_name); + break; + case CORE_INFO_LIST_SORT_CORE_NAME: + qsort(core_info_list->list, core_info_list->count, sizeof(core_info_t), + (int (*)(const void *, const void *))core_info_qsort_func_core_name); + break; + case CORE_INFO_LIST_SORT_SYSTEM_NAME: + qsort(core_info_list->list, core_info_list->count, sizeof(core_info_t), + (int (*)(const void *, const void *))core_info_qsort_func_system_name); + break; + default: + return; + } +} diff --git a/core_info.h b/core_info.h index 530405c719..bee6035564 100644 --- a/core_info.h +++ b/core_info.h @@ -88,6 +88,14 @@ typedef struct core_info_ctx_find const char *path; } core_info_ctx_find_t; +enum core_info_list_qsort_type +{ + CORE_INFO_LIST_SORT_PATH = 0, + CORE_INFO_LIST_SORT_DISPLAY_NAME, + CORE_INFO_LIST_SORT_CORE_NAME, + CORE_INFO_LIST_SORT_SYSTEM_NAME +}; + size_t core_info_list_num_info_files(core_info_list_t *list); /* Non-reentrant, does not allocate. Returns pointer to internal state. */ @@ -132,6 +140,8 @@ bool core_info_database_match_archive_member(const char *database_path); bool core_info_unsupported_content_path(const char *path); +void core_info_qsort(core_info_list_t *core_info_list, enum core_info_list_qsort_type qsort_type); + RETRO_END_DECLS #endif /* CORE_INFO_H_ */ diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 7216f94eb9..3b81c6471d 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -265,6 +265,8 @@ MSG_HASH(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_SPECIAL, "deferred_dropdown_box_list_special") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_RESOLUTION, "deferred_dropdown_box_list_resolution") +MSG_HASH(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE, + "deferred_dropdown_box_list_playlist_default_core") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_CONFIGURATIONS_LIST, "deferred_configurations_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_PLAYLIST_LIST, @@ -367,6 +369,10 @@ MSG_HASH(MENU_ENUM_LABEL_DEFERRED_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST, "deferred_onscreen_notifications_settings_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST, "deferred_playlist_settings") +MSG_HASH(MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST, + "deferred_playlist_manager_list") +MSG_HASH(MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS, + "deferred_playlist_manager_settings") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_PRIVACY_SETTINGS_LIST, "deferred_privacy_settings_list") MSG_HASH(MENU_ENUM_LABEL_DEFERRED_MIDI_SETTINGS_LIST, @@ -861,6 +867,12 @@ MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_ENTRY, "playlist_entry") MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SETTINGS, "playlist_settings") +MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST, + "playlist_manager_list") +MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS, + "playlist_manager_settings") +MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE, + "playlist_manager_default_core") MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SETTINGS_BEGIN, "playlist_settings_begin") MSG_HASH(MENU_ENUM_LABEL_POINTER_ENABLE, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 2ad7bc4b6b..d2a39a9f86 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2148,6 +2148,22 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_PLAYLIST_SETTINGS, "Playlists" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LIST, + "Playlist Management" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PLAYLIST_MANAGER_LIST, + "Perform maintenance tasks on selected playlist (e.g. set/reset default core associations)." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_DEFAULT_CORE, + "Default Core" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PLAYLIST_MANAGER_DEFAULT_CORE, + "Specify core to use when launching content via a playlist entry that does not have an existing core association." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_POINTER_ENABLE, "Touch Support" diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index 3982135d07..7bfed9f54d 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -175,6 +175,8 @@ generic_deferred_push(deferred_push_input_settings_list, DISPLAYLIST_ generic_deferred_push(deferred_push_latency_settings_list, DISPLAYLIST_LATENCY_SETTINGS_LIST) generic_deferred_push(deferred_push_recording_settings_list, DISPLAYLIST_RECORDING_SETTINGS_LIST) generic_deferred_push(deferred_push_playlist_settings_list, DISPLAYLIST_PLAYLIST_SETTINGS_LIST) +generic_deferred_push(deferred_push_playlist_manager_list, DISPLAYLIST_PLAYLIST_MANAGER_LIST) +generic_deferred_push(deferred_push_playlist_manager_settings, DISPLAYLIST_PLAYLIST_MANAGER_SETTINGS) generic_deferred_push(deferred_push_input_hotkey_binds_list, DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST) generic_deferred_push(deferred_push_accounts_cheevos_list, DISPLAYLIST_ACCOUNTS_CHEEVOS_LIST) generic_deferred_push(deferred_push_accounts_twitch_list, DISPLAYLIST_ACCOUNTS_TWITCH_LIST) @@ -631,6 +633,7 @@ generic_deferred_push_clear_general(deferred_video_history_list, PUSH_DEFAULT, D generic_deferred_push_clear_general(deferred_push_dropdown_box_list, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST) generic_deferred_push_clear_general(deferred_push_dropdown_box_list_special, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_SPECIAL) generic_deferred_push_clear_general(deferred_push_dropdown_box_list_resolution, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_RESOLUTION) +generic_deferred_push_clear_general(deferred_push_dropdown_box_list_playlist_default_core, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE) static int menu_cbs_init_bind_deferred_push_compare_label( menu_file_list_cbs_t *cbs, @@ -656,6 +659,11 @@ static int menu_cbs_init_bind_deferred_push_compare_label( BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_dropdown_box_list_resolution); return 0; } + else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE))) + { + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_dropdown_box_list_playlist_default_core); + return 0; + } else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_BROWSE_URL_LIST))) { BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_browse_url_list); @@ -1058,6 +1066,12 @@ static int menu_cbs_init_bind_deferred_push_compare_label( case MENU_ENUM_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_playlist_settings_list); break; + case MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST: + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_playlist_manager_list); + break; + case MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS: + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_playlist_manager_settings); + break; case MENU_ENUM_LABEL_DEFERRED_RECORDING_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_recording_settings_list); break; @@ -1376,6 +1390,12 @@ static int menu_cbs_init_bind_deferred_push_compare_label( case MENU_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_playlist_settings_list); break; + case MENU_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST: + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_playlist_manager_list); + break; + case MENU_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS: + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_playlist_manager_settings); + break; case MENU_LABEL_DEFERRED_RECORDING_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_recording_settings_list); break; diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c index 1f6e385744..db5805b6da 100644 --- a/menu/cbs/menu_cbs_get_value.c +++ b/menu/cbs/menu_cbs_get_value.c @@ -42,6 +42,7 @@ #include "../../retroarch.h" #include "../../verbosity.h" #include "../../wifi/wifi_driver.h" +#include "../../playlist.h" #ifdef HAVE_NETWORKING #include "../network/netplay/netplay.h" @@ -1071,54 +1072,24 @@ static void menu_action_setting_disp_set_label_playlist_associations(file_list_t const char *path, char *s2, size_t len2) { - char playlist_name_with_ext[255]; - bool found_matching_core_association = false; - settings_t *settings = config_get_ptr(); - struct string_list *str_list = string_split(settings->arrays.playlist_names, ";"); - struct string_list *str_list2 = string_split(settings->arrays.playlist_cores, ";"); + playlist_t *playlist = playlist_get_cached(); + const char *core_name = NULL; - strlcpy(s2, path, len2); - - playlist_name_with_ext[0] = '\0'; *s = '\0'; *w = 19; - fill_pathname_noext(playlist_name_with_ext, path, - file_path_str(FILE_PATH_LPL_EXTENSION), - sizeof(playlist_name_with_ext)); - - for (i = 0; i < str_list->size; i++) - { - if (string_is_equal(str_list->elems[i].data, playlist_name_with_ext)) - { - if (str_list->size != str_list2->size) - break; - - if (!str_list2->elems[i].data) - break; - - found_matching_core_association = true; - strlcpy(s, str_list2->elems[i].data, len); - } - } - - string_list_free(str_list); - string_list_free(str_list2); - - if (string_is_equal(s, file_path_str(FILE_PATH_DETECT)) || !found_matching_core_association) - strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), len); - else - { - char buf[PATH_MAX_LENGTH]; - core_info_list_t *list = NULL; - - core_info_get_list(&list); - - if (core_info_list_get_display_name(list, s, buf, sizeof(buf))) - strlcpy(s, buf, len); - } - strlcpy(s2, path, len2); + + if (!playlist) + return; + + core_name = playlist_get_default_core_name(playlist); + + if (!string_is_empty(core_name) && + !string_is_equal(core_name, file_path_str(FILE_PATH_DETECT))) + strlcpy(s, core_name, len); + else + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), len); } static void menu_action_setting_disp_set_label_core_options(file_list_t* list, @@ -1346,6 +1317,10 @@ static int menu_cbs_init_bind_get_string_representation_compare_label( BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_menu_more); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE: + BIND_ACTION_GET_VALUE(cbs, + menu_action_setting_disp_set_label_playlist_associations); + break; default: return - 1; } @@ -1628,12 +1603,6 @@ int menu_cbs_init_bind_get_string_representation(menu_file_list_cbs_t *cbs, } } - if (type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START) - { - BIND_ACTION_GET_VALUE(cbs, - menu_action_setting_disp_set_label_playlist_associations); - return 0; - } if (type >= MENU_SETTINGS_CORE_OPTION_START) { BIND_ACTION_GET_VALUE(cbs, diff --git a/menu/cbs/menu_cbs_label.c b/menu/cbs/menu_cbs_label.c index 266f970edd..fc09022103 100644 --- a/menu/cbs/menu_cbs_label.c +++ b/menu/cbs/menu_cbs_label.c @@ -15,6 +15,7 @@ #include #include +#include #include "../menu_driver.h" #include "../menu_cbs.h" @@ -55,7 +56,8 @@ static int action_bind_label_playlist_collection_entry( const char *label, const char *path, char *s, size_t len) { - if (strstr(path, file_path_str(FILE_PATH_LPL_EXTENSION))) + if (string_is_equal_noncase(path_get_extension(path), + file_path_str(FILE_PATH_LPL_EXTENSION_NO_DOT))) { char path_base[PATH_MAX_LENGTH]; path_base[0] = '\0'; @@ -93,6 +95,9 @@ int menu_cbs_init_bind_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_PLAYLIST_COLLECTION_ENTRY: BIND_ACTION_LABEL(cbs, action_bind_label_playlist_collection_entry); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS: + BIND_ACTION_LABEL(cbs, action_bind_label_playlist_collection_entry); + break; case MENU_ENUM_LABEL_CHEAT_BROWSE_MEMORY: BIND_ACTION_LABEL(cbs, action_bind_label_cheat_browse_address); break; diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index 305214903d..60c3433a93 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -38,6 +38,7 @@ #include "../../driver.h" #include "../../retroarch.h" #include "../../network/netplay/netplay.h" +#include "../../playlist.h" #ifndef BIND_ACTION_LEFT #define BIND_ACTION_LEFT(cbs, name) \ @@ -366,61 +367,59 @@ static int action_left_video_resolution(unsigned type, const char *label, static int playlist_association_left(unsigned type, const char *label, bool wraparound) { - size_t i, next, found, current = 0; - core_info_t *info = NULL; - struct string_list *stnames = NULL; - struct string_list *stcores = NULL; - settings_t *settings = config_get_ptr(); - const char *path = path_basename(label); - core_info_list_t *list = NULL; char core_path[PATH_MAX_LENGTH]; - char new_playlist_cores[sizeof(settings->arrays.playlist_cores) / sizeof(settings->arrays.playlist_cores[0])]; + size_t i, next, current = 0; + playlist_t *playlist = playlist_get_cached(); + core_info_list_t *core_info_list = NULL; + core_info_t *core_info = NULL; - core_info_get_list(&list); + core_path[0] = '\0'; - if (!list) + if (!playlist) + return -1; + + core_info_get_list(&core_info_list); + if (!core_info_list) return menu_cbs_exit(); - core_path[0] = new_playlist_cores[0] = '\0'; + /* Get current core path association */ + if (string_is_empty(playlist_get_default_core_path(playlist))) + strlcpy(core_path, file_path_str(FILE_PATH_DETECT), sizeof(core_path)); + else + strlcpy(core_path, playlist_get_default_core_path(playlist), sizeof(core_path)); - stnames = string_split(settings->arrays.playlist_names, ";"); - stcores = string_split(settings->arrays.playlist_cores, ";"); + /* Sort cores alphabetically */ + core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME); - if (!menu_content_playlist_find_associated_core(path, - core_path, sizeof(core_path))) - strlcpy(core_path, - file_path_str(FILE_PATH_DETECT), - sizeof(core_path)); - - for (i = 0; i < list->count; i++) + /* Get the index of the currently associated core */ + for (i = 0; i < core_info_list->count; i++) { - core_info_t *info = core_info_get(list, i); - if (string_is_equal(info->path, core_path)) + core_info = NULL; + core_info = core_info_get(core_info_list, i); + if (!core_info) + return -1; + if (string_is_equal(core_info->path, core_path)) current = i; } - next = current - 1; - if (next < 0) - { - if (wraparound) - next = (int)(list->count-1); - else - next = 0; - } + /* Decrement core index */ + if (current > 0) + next = current - 1; + else if (wraparound && (core_info_list->count > 1)) + next = core_info_list->count - 1; + else + next = 0; /* Silence 'next' may be used uninitialized warning */ - info = core_info_get(list, next); - found = string_list_find_elem(stnames, path); - if (found && info) - string_list_set(stcores, (unsigned)(found-1), info->path); + /* Get new core info */ + core_info = NULL; + core_info = core_info_get(core_info_list, next); + if (!core_info) + return -1; - string_list_join_concat(new_playlist_cores, - sizeof(new_playlist_cores), stcores, ";"); - - strlcpy(settings->arrays.playlist_cores, - new_playlist_cores, sizeof(settings->arrays.playlist_cores)); - - string_list_free(stnames); - string_list_free(stcores); + /* Update playlist */ + playlist_set_default_core_path(playlist, core_info->path); + playlist_set_default_core_name(playlist, core_info->display_name); + playlist_write_file(playlist); return 0; } @@ -654,6 +653,9 @@ static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_GPU_INDEX: BIND_ACTION_LEFT(cbs, action_left_video_gpu_index); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE: + BIND_ACTION_LEFT(cbs, playlist_association_left); + break; default: return -1; } @@ -701,10 +703,6 @@ static int menu_cbs_init_bind_left_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_LEFT(cbs, action_left_input_desc_kbd); } - else if ((type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START)) - { - BIND_ACTION_LEFT(cbs, playlist_association_left); - } else if ((type >= MENU_SETTINGS_CORE_OPTION_START)) { BIND_ACTION_LEFT(cbs, core_setting_left); diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index ef03fdd693..d3c0f2b46a 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -166,6 +166,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl) return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_SPECIAL; case ACTION_OK_DL_DROPDOWN_BOX_LIST_RESOLUTION: return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_RESOLUTION; + case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE: + return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE; case ACTION_OK_DL_MIXER_STREAM_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST; case ACTION_OK_DL_ACCOUNTS_LIST: @@ -254,6 +256,10 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl) return MENU_ENUM_LABEL_DEFERRED_RECORDING_SETTINGS_LIST; case ACTION_OK_DL_PLAYLIST_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST; + case ACTION_OK_DL_PLAYLIST_MANAGER_LIST: + return MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST; + case ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS: + return MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS; case ACTION_OK_DL_ACCOUNTS_CHEEVOS_LIST: return MENU_ENUM_LABEL_DEFERRED_ACCOUNTS_CHEEVOS_LIST; case ACTION_OK_DL_ACCOUNTS_TWITCH_LIST: @@ -358,6 +364,15 @@ int generic_action_ok_displaylist_push(const char *path, info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_RESOLUTION; dl_type = DISPLAYLIST_GENERIC; break; + case ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE: + info.type = type; + info.directory_ptr = idx; + info_path = path; + info_label = msg_hash_to_str( + MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE); + info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE; + dl_type = DISPLAYLIST_GENERIC; + break; case ACTION_OK_DL_USER_BINDS_LIST: info.type = type; info.directory_ptr = idx; @@ -915,6 +930,8 @@ int generic_action_ok_displaylist_push(const char *path, case ACTION_OK_DL_INPUT_HOTKEY_BINDS_LIST: case ACTION_OK_DL_RECORDING_SETTINGS_LIST: case ACTION_OK_DL_PLAYLIST_SETTINGS_LIST: + case ACTION_OK_DL_PLAYLIST_MANAGER_LIST: + case ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS: case ACTION_OK_DL_ACCOUNTS_CHEEVOS_LIST: case ACTION_OK_DL_ACCOUNTS_YOUTUBE_LIST: case ACTION_OK_DL_ACCOUNTS_TWITCH_LIST: @@ -1792,11 +1809,15 @@ static int action_ok_playlist_entry_collection(const char *path, { core_info_ctx_find_t core_info; const char *entry_path = NULL; - const char *path_base = - path_basename(menu->db_playlist_file); - bool found_associated_core = - menu_content_playlist_find_associated_core( - path_base, new_core_path, sizeof(new_core_path)); + const char *default_core_path = + playlist_get_default_core_path(playlist); + bool found_associated_core = false; + + if (!string_is_empty(default_core_path)) + { + strlcpy(new_core_path, default_core_path, sizeof(new_core_path)); + found_associated_core = true; + } core_info.inf = NULL; core_info.path = new_core_path; @@ -1855,14 +1876,15 @@ static int action_ok_playlist_entry(const char *path, { char new_core_path[PATH_MAX_LENGTH]; size_t selection_ptr = 0; - playlist_t *playlist = g_defaults.content_history; + playlist_t *playlist = playlist_get_cached(); menu_handle_t *menu = NULL; const struct playlist_entry *entry = NULL; const char *entry_label = NULL; new_core_path[0] = '\0'; - if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) + if (!playlist || + !menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) return menu_cbs_exit(); selection_ptr = entry_idx; @@ -1875,11 +1897,15 @@ static int action_ok_playlist_entry(const char *path, && string_is_equal(entry->core_name, file_path_str(FILE_PATH_DETECT))) { core_info_ctx_find_t core_info; - const char *path_base = - path_basename(menu->db_playlist_file); - bool found_associated_core = - menu_content_playlist_find_associated_core( - path_base, new_core_path, sizeof(new_core_path)); + const char *default_core_path = + playlist_get_default_core_path(playlist); + bool found_associated_core = false; + + if (!string_is_empty(default_core_path)) + { + strlcpy(new_core_path, default_core_path, sizeof(new_core_path)); + found_associated_core = true; + } core_info.inf = NULL; core_info.path = new_core_path; @@ -1946,15 +1972,17 @@ static int action_ok_playlist_entry_start_content(const char *path, core_info_ctx_find_t core_info; char new_core_path[PATH_MAX_LENGTH]; const char *entry_path = NULL; - const char *path_base = - path_basename(menu->db_playlist_file); - bool found_associated_core = false; + const char *default_core_path = + playlist_get_default_core_path(playlist); + bool found_associated_core = false; new_core_path[0] = '\0'; - found_associated_core = - menu_content_playlist_find_associated_core( - path_base, new_core_path, sizeof(new_core_path)); + if (!string_is_empty(default_core_path)) + { + strlcpy(new_core_path, default_core_path, sizeof(new_core_path)); + found_associated_core = true; + } core_info.inf = NULL; core_info.path = new_core_path; @@ -4308,6 +4336,8 @@ default_action_ok_func(action_ok_push_input_settings_list, ACTION_OK_DL_INPUT_SE default_action_ok_func(action_ok_push_latency_settings_list, ACTION_OK_DL_LATENCY_SETTINGS_LIST) default_action_ok_func(action_ok_push_recording_settings_list, ACTION_OK_DL_RECORDING_SETTINGS_LIST) default_action_ok_func(action_ok_push_playlist_settings_list, ACTION_OK_DL_PLAYLIST_SETTINGS_LIST) +default_action_ok_func(action_ok_push_playlist_manager_list, ACTION_OK_DL_PLAYLIST_MANAGER_LIST) +default_action_ok_func(action_ok_push_playlist_manager_settings, ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS) default_action_ok_func(action_ok_push_input_hotkey_binds_list, ACTION_OK_DL_INPUT_HOTKEY_BINDS_LIST) default_action_ok_func(action_ok_push_user_binds_list, ACTION_OK_DL_USER_BINDS_LIST) default_action_ok_func(action_ok_push_accounts_cheevos_list, ACTION_OK_DL_ACCOUNTS_CHEEVOS_LIST) @@ -5065,6 +5095,71 @@ static int action_ok_push_dropdown_item_resolution(const char *path, return 0; } +static int action_ok_push_dropdown_item_playlist_default_core(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ + core_info_list_t *core_info_list = NULL; + playlist_t *playlist = playlist_get_cached(); + const char* core_name = path; + + (void)label; + (void)type; + (void)idx; + (void)entry_idx; + + /* Get core list */ + core_info_get_list(&core_info_list); + + if (!core_info_list || !playlist) + return -1; + + /* Handle N/A or empty path input */ + if (string_is_empty(core_name) || + string_is_equal(core_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE))) + { + playlist_set_default_core_path(playlist, file_path_str(FILE_PATH_DETECT)); + playlist_set_default_core_name(playlist, file_path_str(FILE_PATH_DETECT)); + } + else + { + core_info_t *core_info = NULL; + bool found = false; + size_t i; + + /* Loop through cores until we find a match */ + for (i = 0; i < core_info_list->count; i++) + { + core_info = NULL; + core_info = core_info_get(core_info_list, i); + + if (core_info) + { + if (string_is_equal(core_name, core_info->display_name)) + { + /* Update playlist */ + playlist_set_default_core_path(playlist, core_info->path); + playlist_set_default_core_name(playlist, core_info->display_name); + + found = true; + break; + } + } + } + + /* Fallback... */ + if (!found) + { + playlist_set_default_core_path(playlist, file_path_str(FILE_PATH_DETECT)); + playlist_set_default_core_name(playlist, file_path_str(FILE_PATH_DETECT)); + } + } + + /* In all cases, update file on disk */ + playlist_write_file(playlist); + + return action_cancel_pop_default(NULL, NULL, 0, 0); +} + static int action_ok_push_default(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { @@ -5243,6 +5338,16 @@ static int action_ok_video_resolution(const char *path, return 0; } +static int action_ok_playlist_default_core(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ + generic_action_ok_displaylist_push( + NULL, + NULL, NULL, 0, 0, 0, + ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE); + return 0; +} + static int action_ok_netplay_enable_host(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { @@ -5757,6 +5862,12 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_PLAYLIST_SETTINGS: BIND_ACTION_OK(cbs, action_ok_push_playlist_settings_list); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST: + BIND_ACTION_OK(cbs, action_ok_push_playlist_manager_list); + break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS: + BIND_ACTION_OK(cbs, action_ok_push_playlist_manager_settings); + break; case MENU_ENUM_LABEL_RECORDING_SETTINGS: BIND_ACTION_OK(cbs, action_ok_push_recording_settings_list); break; @@ -5993,6 +6104,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_SCREEN_RESOLUTION: BIND_ACTION_OK(cbs, action_ok_video_resolution); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE: + BIND_ACTION_OK(cbs, action_ok_playlist_default_core); + break; case MENU_ENUM_LABEL_UPDATE_ASSETS: BIND_ACTION_OK(cbs, action_ok_update_assets); break; @@ -6140,6 +6254,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_LABEL_SCREEN_RESOLUTION: BIND_ACTION_OK(cbs, action_ok_video_resolution); break; + case MENU_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE: + BIND_ACTION_OK(cbs, action_ok_playlist_default_core); + break; default: return -1; } @@ -6201,10 +6318,6 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_OK(cbs, action_ok_cheat); } - else if ((type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START)) - { - return -1; - } else if ((type >= MENU_SETTINGS_CORE_OPTION_START)) { BIND_ACTION_OK(cbs, action_ok_core_option_dropdown_list); @@ -6249,6 +6362,9 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs, case MENU_SETTING_DROPDOWN_ITEM_RESOLUTION: BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_resolution); break; + case MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE: + BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_playlist_default_core); + break; case MENU_SETTING_ACTION_CORE_DISK_OPTIONS: BIND_ACTION_OK(cbs, action_ok_push_default); break; diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index 0200d672e1..0a15af8b60 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -39,6 +39,7 @@ #include "../../verbosity.h" #include "../../ui/ui_companion_driver.h" #include "../../network/netplay/netplay.h" +#include "../../playlist.h" #ifndef BIND_ACTION_RIGHT #define BIND_ACTION_RIGHT(cbs, name) \ @@ -470,59 +471,67 @@ static int action_right_video_resolution(unsigned type, const char *label, static int playlist_association_right(unsigned type, const char *label, bool wraparound) { - size_t i, next, found, current = 0; - core_info_t *info = NULL; - struct string_list *stnames = NULL; - struct string_list *stcores = NULL; - core_info_list_t *list = NULL; - settings_t *settings = config_get_ptr(); - const char *path = path_basename(label); char core_path[PATH_MAX_LENGTH]; - char new_playlist_cores[sizeof(settings->arrays.playlist_cores) / sizeof(settings->arrays.playlist_cores[0])]; + size_t i, next, current = 0; + playlist_t *playlist = playlist_get_cached(); + core_info_list_t *core_info_list = NULL; + core_info_t *core_info = NULL; - core_info_get_list(&list); - if (!list) + core_path[0] = '\0'; + + if (!playlist) + return -1; + + core_info_get_list(&core_info_list); + if (!core_info_list) return menu_cbs_exit(); - core_path[0] = new_playlist_cores[0] = '\0'; + /* Get current core path association */ + if (string_is_empty(playlist_get_default_core_path(playlist))) + strlcpy(core_path, file_path_str(FILE_PATH_DETECT), sizeof(core_path)); + else + strlcpy(core_path, playlist_get_default_core_path(playlist), sizeof(core_path)); - stnames = string_split(settings->arrays.playlist_names, ";"); - stcores = string_split(settings->arrays.playlist_cores, ";"); + /* Sort cores alphabetically */ + core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME); - if (!menu_content_playlist_find_associated_core(path, core_path, sizeof(core_path))) - strlcpy(core_path, - file_path_str(FILE_PATH_DETECT), sizeof(core_path)); - - for (i = 0; i < list->count; i++) + /* Get the index of the currently associated core */ + for (i = 0; i < core_info_list->count; i++) { - core_info_t *info = core_info_get(list, i); - if (string_is_equal(info->path, core_path)) + core_info = NULL; + core_info = core_info_get(core_info_list, i); + if (!core_info) + return -1; + if (string_is_equal(core_info->path, core_path)) current = i; } + /* Increment core index */ next = current + 1; - if (next >= list->count) + if (next >= core_info_list->count) { if (wraparound) next = 0; else - next = list->count-1; + { + if (core_info_list->count > 0) + next = core_info_list->count - 1; + else + next = 0; + } } - info = core_info_get(list, next); + /* Get new core info */ + core_info = NULL; + core_info = core_info_get(core_info_list, next); + if (!core_info) + return -1; - found = string_list_find_elem(stnames, path); - if (found && info) - string_list_set(stcores, (unsigned)(found-1), info->path); + /* Update playlist */ + playlist_set_default_core_path(playlist, core_info->path); + playlist_set_default_core_name(playlist, core_info->display_name); + playlist_write_file(playlist); - string_list_join_concat(new_playlist_cores, - sizeof(new_playlist_cores), stcores, ";"); - - strlcpy(settings->arrays.playlist_cores, - new_playlist_cores, sizeof(settings->arrays.playlist_cores)); - - string_list_free(stnames); - string_list_free(stcores); return 0; } @@ -583,10 +592,6 @@ static int menu_cbs_init_bind_right_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_RIGHT(cbs, action_right_input_desc_kbd); } - else if ((type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START)) - { - BIND_ACTION_RIGHT(cbs, playlist_association_right); - } else if ((type >= MENU_SETTINGS_CORE_OPTION_START)) { BIND_ACTION_RIGHT(cbs, core_setting_right); @@ -790,6 +795,9 @@ static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_GPU_INDEX: BIND_ACTION_RIGHT(cbs, action_right_video_gpu_index); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE: + BIND_ACTION_RIGHT(cbs, playlist_association_right); + break; default: return -1; } diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 71dd5ef813..aa82c7c269 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -35,6 +35,7 @@ #include "../../managers/cheat_manager.h" #include "../../retroarch.h" #include "../../performance_counters.h" +#include "../../playlist.h" #include "../../input/input_driver.h" #include "../../input/input_remapping.h" @@ -221,36 +222,17 @@ static int action_start_core_setting(unsigned type, static int action_start_playlist_association(unsigned type, const char *label) { - struct string_list *stnames = NULL; - struct string_list *stcores = NULL; - core_info_list_t *list = NULL; - settings_t *settings = config_get_ptr(); - const char *path = path_basename(label); - int found; - char new_playlist_cores[sizeof(settings->arrays.playlist_cores) / sizeof(settings->arrays.playlist_cores[0])]; + playlist_t *playlist = playlist_get_cached(); + bool load_playlist = false; - core_info_get_list(&list); - if (!list) + if (!playlist) return -1; - new_playlist_cores[0] = '\0'; + /* Set default core path + name to DETECT */ + playlist_set_default_core_path(playlist, file_path_str(FILE_PATH_DETECT)); + playlist_set_default_core_name(playlist, file_path_str(FILE_PATH_DETECT)); + playlist_write_file(playlist); - stnames = string_split(settings->arrays.playlist_names, ";"); - stcores = string_split(settings->arrays.playlist_cores, ";"); - found = string_list_find_elem(stnames, path); - - if (found) - string_list_set(stcores, found-1, - file_path_str(FILE_PATH_DETECT)); - - string_list_join_concat(new_playlist_cores, - sizeof(new_playlist_cores), stcores, ";"); - - strlcpy(settings->arrays.playlist_cores, - new_playlist_cores, sizeof(settings->arrays.playlist_cores)); - - string_list_free(stcores); - string_list_free(stnames); return 0; } @@ -318,6 +300,9 @@ static int menu_cbs_init_bind_start_compare_label(menu_file_list_cbs_t *cbs) case MENU_ENUM_LABEL_NETPLAY_MITM_SERVER: BIND_ACTION_START(cbs, action_start_netplay_mitm_server); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE: + BIND_ACTION_START(cbs, action_start_playlist_association); + break; default: return -1; } @@ -354,10 +339,6 @@ static int menu_cbs_init_bind_start_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_START(cbs, action_start_performance_counters_frontend); } - else if ((type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START)) - { - BIND_ACTION_START(cbs, action_start_playlist_association); - } else if ((type >= MENU_SETTINGS_CORE_OPTION_START)) { BIND_ACTION_START(cbs, action_start_core_setting); diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 9cac95fe16..7c379bc7fa 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -128,6 +128,8 @@ default_sublabel_macro(action_bind_sublabel_privacy_settings_list, MENU_ default_sublabel_macro(action_bind_sublabel_midi_settings_list, MENU_ENUM_SUBLABEL_MIDI_SETTINGS) default_sublabel_macro(action_bind_sublabel_directory_settings_list, MENU_ENUM_SUBLABEL_DIRECTORY_SETTINGS) default_sublabel_macro(action_bind_sublabel_playlist_settings_list, MENU_ENUM_SUBLABEL_PLAYLIST_SETTINGS) +default_sublabel_macro(action_bind_sublabel_playlist_manager_list, MENU_ENUM_SUBLABEL_PLAYLIST_MANAGER_LIST) +default_sublabel_macro(action_bind_sublabel_playlist_manager_default_core, MENU_ENUM_SUBLABEL_PLAYLIST_MANAGER_DEFAULT_CORE) default_sublabel_macro(action_bind_sublabel_network_settings_list, MENU_ENUM_SUBLABEL_NETWORK_SETTINGS) default_sublabel_macro(action_bind_sublabel_network_on_demand_thumbnails, MENU_ENUM_SUBLABEL_NETWORK_ON_DEMAND_THUMBNAILS) default_sublabel_macro(action_bind_sublabel_user_settings_list, MENU_ENUM_SUBLABEL_USER_SETTINGS) @@ -2383,6 +2385,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_PLAYLIST_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_settings_list); break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_manager_list); + break; + case MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_manager_default_core); + break; case MENU_ENUM_LABEL_USER_INTERFACE_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_user_interface_settings_list); break; diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index 34deb8ed7f..5e8c28acb2 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -119,6 +119,7 @@ default_title_macro(action_get_frontend_counters_list, MENU_ENUM_LABEL_ default_title_macro(action_get_core_counters_list, MENU_ENUM_LABEL_VALUE_CORE_COUNTERS) default_title_macro(action_get_recording_settings_list, MENU_ENUM_LABEL_VALUE_RECORDING_SETTINGS) default_title_macro(action_get_playlist_settings_list, MENU_ENUM_LABEL_VALUE_PLAYLIST_SETTINGS) +default_title_macro(action_get_playlist_manager_list, MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LIST) default_title_macro(action_get_input_hotkey_binds_settings_list,MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BINDS) default_title_macro(action_get_driver_settings_list, MENU_ENUM_LABEL_VALUE_DRIVER_SETTINGS) default_title_macro(action_get_core_settings_list, MENU_ENUM_LABEL_VALUE_CORE_SETTINGS) @@ -865,6 +866,9 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_playlist_settings_list); break; + case MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST: + BIND_ACTION_GET_TITLE(cbs, action_get_playlist_manager_list); + break; case MENU_ENUM_LABEL_MANAGEMENT: case MENU_ENUM_LABEL_ACHIEVEMENT_LIST: case MENU_ENUM_LABEL_ACHIEVEMENT_LIST_HARDCORE: @@ -1181,6 +1185,9 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, case MENU_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_playlist_settings_list); break; + case MENU_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST: + BIND_ACTION_GET_TITLE(cbs, action_get_playlist_manager_list); + break; case MENU_LABEL_PLAYLISTS_TAB: BIND_ACTION_GET_TITLE(cbs, action_get_title_collection); break; @@ -1329,6 +1336,12 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs, BIND_ACTION_GET_TITLE(cbs, action_get_title_dropdown_item); return 0; } + if (string_is_equal(label, + msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE))) + { + BIND_ACTION_GET_TITLE(cbs, action_get_title_dropdown_item); + return 0; + } if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS))) { BIND_ACTION_GET_TITLE(cbs, action_get_quick_menu_views_settings_list); @@ -1339,6 +1352,11 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs, BIND_ACTION_GET_TITLE(cbs, action_get_title_deferred_playlist_list); return 0; } + if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS))) + { + BIND_ACTION_GET_TITLE(cbs, action_get_title_deferred_playlist_list); + return 0; + } if (strstr(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RDB_ENTRY_DETAIL))) { BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_database_info); diff --git a/menu/menu_cbs.h b/menu/menu_cbs.h index e625b49644..1d7c9ed514 100644 --- a/menu/menu_cbs.h +++ b/menu/menu_cbs.h @@ -48,6 +48,7 @@ enum ACTION_OK_DL_DROPDOWN_BOX_LIST, ACTION_OK_DL_DROPDOWN_BOX_LIST_SPECIAL, ACTION_OK_DL_DROPDOWN_BOX_LIST_RESOLUTION, + ACTION_OK_DL_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE, ACTION_OK_DL_OPEN_ARCHIVE, ACTION_OK_DL_OPEN_ARCHIVE_DETECT_CORE, ACTION_OK_DL_MUSIC, @@ -87,6 +88,8 @@ enum ACTION_OK_DL_INPUT_HOTKEY_BINDS_LIST, ACTION_OK_DL_RECORDING_SETTINGS_LIST, ACTION_OK_DL_PLAYLIST_SETTINGS_LIST, + ACTION_OK_DL_PLAYLIST_MANAGER_LIST, + ACTION_OK_DL_PLAYLIST_MANAGER_SETTINGS, ACTION_OK_DL_ACCOUNTS_LIST, ACTION_OK_DL_ACCOUNTS_CHEEVOS_LIST, ACTION_OK_DL_ACCOUNTS_YOUTUBE_LIST, diff --git a/menu/menu_content.c b/menu/menu_content.c index dfb1ab02e4..260e3df21e 100644 --- a/menu/menu_content.c +++ b/menu/menu_content.c @@ -33,36 +33,5 @@ #include "../playlist.h" #include "../verbosity.h" -bool menu_content_playlist_find_associated_core(const char *path, char *s, size_t len) -{ - unsigned j; - bool ret = false; - settings_t *settings = config_get_ptr(); - struct string_list *existing_core_names = - string_split(settings->arrays.playlist_names, ";"); - struct string_list *existing_core_paths = - string_split(settings->arrays.playlist_cores, ";"); - - for (j = 0; j < existing_core_names->size; j++) - { - if (!string_is_equal(path, existing_core_names->elems[j].data)) - continue; - - if (existing_core_paths) - { - const char *existing_core = existing_core_paths->elems[j].data; - - if (existing_core) - { - strlcpy(s, existing_core, len); - ret = true; - } - } - - break; - } - - string_list_free(existing_core_names); - string_list_free(existing_core_paths); - return ret; -} +/* This file should probably be removed, but may need + * to add something to it in the future... */ diff --git a/menu/menu_content.h b/menu/menu_content.h index 230f94c624..bac1c4220d 100644 --- a/menu/menu_content.h +++ b/menu/menu_content.h @@ -34,9 +34,6 @@ typedef struct menu_content_ctx_defer_info size_t len; } menu_content_ctx_defer_info_t; -bool menu_content_playlist_find_associated_core(const char *path, - char *s, size_t len); - RETRO_END_DECLS #endif diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 6b8f890a93..92f168bc85 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -2560,78 +2560,82 @@ static unsigned menu_displaylist_parse_cores( return items_found; } -static void menu_displaylist_parse_playlist_associations( +static unsigned menu_displaylist_parse_playlist_manager_list( menu_displaylist_info_t *info) { settings_t *settings = config_get_ptr(); - struct string_list *str_list = dir_list_new_special( + unsigned count = 0; + struct string_list *str_list = NULL; + + if (!settings) + return count; + + str_list = dir_list_new_special( settings->paths.directory_playlist, DIR_LIST_COLLECTIONS, NULL); if (str_list && str_list->size) { unsigned i; - char new_playlist_names[sizeof(settings->arrays.playlist_names) / sizeof(settings->arrays.playlist_names[0])]; - char new_playlist_cores[sizeof(settings->arrays.playlist_cores) / sizeof(settings->arrays.playlist_cores[0])]; - struct string_list *stnames = string_split(settings->arrays.playlist_names, ";"); - struct string_list *stcores = string_split(settings->arrays.playlist_cores, ";"); - new_playlist_names[0] = new_playlist_cores[0] = '\0'; + dir_list_sort(str_list, true); for (i = 0; i < str_list->size; i++) { - char path_base[PATH_MAX_LENGTH]; - char core_path[PATH_MAX_LENGTH]; - union string_list_elem_attr attr; - unsigned found = 0; - const char *path = - path_basename(str_list->elems[i].data); + const char *path = str_list->elems[i].data; - attr.i = 0; - path_base[0] = core_path[0] = '\0'; + if (str_list->elems[i].attr.i == FILE_TYPE_DIRECTORY) + continue; - if (!menu_content_playlist_find_associated_core( - path, core_path, sizeof(core_path))) - strlcpy(core_path, file_path_str(FILE_PATH_DETECT), sizeof(core_path)); + if (string_is_empty(path)) + continue; - strlcpy(path_base, path, sizeof(path_base)); + if (!string_is_equal_noncase(path_get_extension(path), + file_path_str(FILE_PATH_LPL_EXTENSION_NO_DOT))) + continue; - found = string_list_find_elem(stnames, path_base); - - if (found) - string_list_set(stcores, found-1, core_path); - else - { - string_list_append(stnames, path_base, attr); - string_list_append(stcores, core_path, attr); - } - - path_remove_extension(path_base); menu_entries_append_enum(info->list, - path_base, path, - MENU_ENUM_LABEL_PLAYLIST_ENTRY, - MENU_SETTINGS_PLAYLIST_ASSOCIATION_START + i, + "", + MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS, + MENU_SETTING_ACTION, 0, 0); + count++; } - - string_list_join_concat(new_playlist_names, - sizeof(new_playlist_names), stnames, ";"); - string_list_join_concat(new_playlist_cores, - sizeof(new_playlist_cores), stcores, ";"); - - strlcpy(settings->arrays.playlist_names, - new_playlist_names, - sizeof(settings->arrays.playlist_names)); - strlcpy(settings->arrays.playlist_cores, - new_playlist_cores, - sizeof(settings->arrays.playlist_cores)); - - string_list_free(stnames); - string_list_free(stcores); } + /* Not necessary to check for NULL here */ string_list_free(str_list); + + return count; +} + +static bool menu_displaylist_parse_playlist_manager_settings( + menu_handle_t *menu, + menu_displaylist_info_t *info, + const char *playlist_path) +{ + playlist_t *playlist = NULL; + + menu_displaylist_set_new_playlist(menu, playlist_path); + + playlist = playlist_get_cached(); + + if (!playlist) + return false; + + /* Default core association */ + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_DEFAULT_CORE), + msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE), + MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE, + MENU_SETTING_PLAYLIST_MANAGER_DEFAULT_CORE, 0, 0); + + /* TODO: Add + * - Reset core associations + * - Remove invalid entries */ + + return true; } #ifdef HAVE_NETWORKING @@ -2663,9 +2667,16 @@ static unsigned menu_displaylist_parse_pl_thumbnail_download_list( path_base[0] = '\0'; + if (str_list->elems[i].attr.i == FILE_TYPE_DIRECTORY) + continue; + if (string_is_empty(path)) continue; + if (!string_is_equal_noncase(path_get_extension(path), + file_path_str(FILE_PATH_LPL_EXTENSION_NO_DOT))) + continue; + strlcpy(path_base, path, sizeof(path_base)); path_remove_extension(path_base); @@ -2703,8 +2714,9 @@ static unsigned menu_displaylist_parse_content_information( bool content_loaded = false; bool playlist_valid = false; unsigned count = 0; + int n = 0; char core_name[PATH_MAX_LENGTH]; - char tmp[8192]; + char tmp[PATH_MAX_LENGTH]; core_name[0] = '\0'; @@ -2764,9 +2776,14 @@ static unsigned menu_displaylist_parse_content_information( { tmp[0] = '\0'; - snprintf(tmp, sizeof(tmp), + n = snprintf(tmp, sizeof(tmp), "%s: %s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_LABEL), content_label); + /* Silence gcc compiler warning + * (getting so sick of these...) */ + if ((n < 0) || (n >= PATH_MAX_LENGTH)) + n = 0; + if (menu_entries_append_enum(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_LABEL), MENU_ENUM_LABEL_CONTENT_INFO_LABEL, @@ -2779,9 +2796,14 @@ static unsigned menu_displaylist_parse_content_information( { tmp[0] = '\0'; - snprintf(tmp, sizeof(tmp), + n = snprintf(tmp, sizeof(tmp), "%s: %s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_PATH), content_path); + /* Silence gcc compiler warning + * (getting so sick of these...) */ + if ((n < 0) || (n >= PATH_MAX_LENGTH)) + n = 0; + if (menu_entries_append_enum(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_PATH), MENU_ENUM_LABEL_CONTENT_INFO_PATH, @@ -2793,7 +2815,6 @@ static unsigned menu_displaylist_parse_content_information( if (!string_is_empty(core_name) && !string_is_equal(core_name, file_path_str(FILE_PATH_DETECT))) { - int n = 0; tmp[0] = '\0'; n = snprintf(tmp, sizeof(tmp), @@ -2829,9 +2850,14 @@ static unsigned menu_displaylist_parse_content_information( { tmp[0] = '\0'; - snprintf(tmp, sizeof(tmp), + n = snprintf(tmp, sizeof(tmp), "%s: %s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_DATABASE), db_name_no_ext); + /* Silence gcc compiler warning + * (getting so sick of these...) */ + if ((n < 0) || (n >= PATH_MAX_LENGTH)) + n = 0; + if (menu_entries_append_enum(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_DATABASE), MENU_ENUM_LABEL_CONTENT_INFO_DATABASE, @@ -2870,10 +2896,15 @@ static unsigned menu_displaylist_parse_content_information( tmp[0] = '\0'; - snprintf(tmp, sizeof(tmp), + n = snprintf(tmp, sizeof(tmp), "%s: %02u:%02u:%02u", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_RUNTIME), runtime_hours, runtime_minutes, runtime_seconds); + /* Silence gcc compiler warning + * (getting so sick of these...) */ + if ((n < 0) || (n >= PATH_MAX_LENGTH)) + n = 0; + if (menu_entries_append_enum(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_RUNTIME), MENU_ENUM_LABEL_CONTENT_INFO_RUNTIME, @@ -2887,12 +2918,17 @@ static unsigned menu_displaylist_parse_content_information( tmp[0] = '\0'; - snprintf(tmp, sizeof(tmp), + n = snprintf(tmp, sizeof(tmp), "%s: %04u/%02u/%02u - %02u:%02u:%02u", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_LAST_PLAYED), last_played_year, last_played_month, last_played_day, last_played_hour, last_played_minute, last_played_second); + /* Silence gcc compiler warning + * (getting so sick of these...) */ + if ((n < 0) || (n >= PATH_MAX_LENGTH)) + n = 0; + if (menu_entries_append_enum(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_LAST_PLAYED), MENU_ENUM_LABEL_CONTENT_INFO_LAST_PLAYED, @@ -3546,6 +3582,59 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct } } break; + case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE: + { + core_info_list_t *core_info_list = NULL; + playlist_t *playlist = playlist_get_cached(); + + /* Get core list */ + core_info_get_list(&core_info_list); + + if (core_info_list && playlist) + { + const char *current_core_name = playlist_get_default_core_name(playlist); + core_info_t *core_info = NULL; + size_t i; + + /* Sort cores alphabetically */ + core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME); + + /* Add N/A entry */ + if (menu_entries_append_enum(list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), + "", + MENU_ENUM_LABEL_NO_ITEMS, + MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE, + 0, 0)) + count++; + + if (string_is_empty(current_core_name) || + string_is_equal(current_core_name, file_path_str(FILE_PATH_DETECT))) + menu_entries_set_checked(list, 0, true); + + /* Loop through cores */ + for (i = 0; i < core_info_list->count; i++) + { + core_info = NULL; + core_info = core_info_get(core_info_list, i); + + if (core_info) + { + if (menu_entries_append_enum(list, + core_info->display_name, + "", + MENU_ENUM_LABEL_NO_ITEMS, + MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE, + i + 1, 0)) + count++; + + if (string_is_equal(current_core_name, core_info->display_name)) + menu_entries_set_checked(list, i + 1, true); + } + } + } + } + break; case DISPLAYLIST_PERFCOUNTERS_CORE: case DISPLAYLIST_PERFCOUNTERS_FRONTEND: { @@ -5949,9 +6038,43 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, } } - menu_displaylist_parse_playlist_associations(info); + if (menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LIST), + msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST), + MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST, + MENU_SETTING_ACTION, 0, 0)) + count++; + info->need_push = true; break; + + case DISPLAYLIST_PLAYLIST_MANAGER_LIST: + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); + count = menu_displaylist_parse_playlist_manager_list(info); + + if (count == 0) + menu_entries_append_enum(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); + + info->need_push = true; + + break; + case DISPLAYLIST_PLAYLIST_MANAGER_SETTINGS: + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); + + if (!menu_displaylist_parse_playlist_manager_settings(menu, info, info->path)) + menu_entries_append_enum(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); + + info->need_push = true; + + break; case DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); { @@ -6010,6 +6133,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, case DISPLAYLIST_OPTIONS_CHEATS: case DISPLAYLIST_NETWORK_INFO: case DISPLAYLIST_DROPDOWN_LIST_RESOLUTION: + case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE: case DISPLAYLIST_PERFCOUNTERS_CORE: case DISPLAYLIST_PERFCOUNTERS_FRONTEND: case DISPLAYLIST_MENU_SETTINGS_LIST: @@ -6029,6 +6153,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, FILE_TYPE_NONE, 0, 0); break; case DISPLAYLIST_DROPDOWN_LIST_RESOLUTION: + case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE: menu_entries_append_enum(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), diff --git a/menu/menu_displaylist.h b/menu/menu_displaylist.h index 7781d43b32..387aed66c0 100644 --- a/menu/menu_displaylist.h +++ b/menu/menu_displaylist.h @@ -60,6 +60,7 @@ enum menu_displaylist_ctl_state DISPLAYLIST_DROPDOWN_LIST, DISPLAYLIST_DROPDOWN_LIST_SPECIAL, DISPLAYLIST_DROPDOWN_LIST_RESOLUTION, + DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE, DISPLAYLIST_INFO, DISPLAYLIST_HELP, DISPLAYLIST_HELP_SCREEN_LIST, @@ -167,6 +168,8 @@ enum menu_displaylist_ctl_state DISPLAYLIST_MIDI_SETTINGS_LIST, DISPLAYLIST_RECORDING_SETTINGS_LIST, DISPLAYLIST_PLAYLIST_SETTINGS_LIST, + DISPLAYLIST_PLAYLIST_MANAGER_LIST, + DISPLAYLIST_PLAYLIST_MANAGER_SETTINGS, DISPLAYLIST_ACCOUNTS_CHEEVOS_LIST, DISPLAYLIST_ACCOUNTS_YOUTUBE_LIST, DISPLAYLIST_ACCOUNTS_TWITCH_LIST, diff --git a/menu/menu_driver.h b/menu/menu_driver.h index e60322e123..cbd2261858 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -53,7 +53,6 @@ RETRO_BEGIN_DECLS #define MENU_SETTINGS_CHEEVOS_NONE 0xffff #define MENU_SETTINGS_CORE_OPTION_CREATE 0x05000 #define MENU_SETTINGS_CORE_OPTION_START 0x10000 -#define MENU_SETTINGS_PLAYLIST_ASSOCIATION_START 0x20000 #define MENU_SETTINGS_CHEEVOS_START 0x40000 #define MENU_SETTINGS_NETPLAY_ROOMS_START 0x80000 @@ -87,6 +86,7 @@ enum menu_settings_type MENU_PLAYLISTS_TAB, MENU_SETTING_DROPDOWN_ITEM, MENU_SETTING_DROPDOWN_ITEM_RESOLUTION, + MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE, MENU_SETTING_DROPDOWN_SETTING_CORE_OPTIONS_ITEM, MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM, MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM, @@ -120,6 +120,7 @@ enum menu_settings_type MENU_SETTING_HORIZONTAL_MENU, MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, + MENU_SETTING_PLAYLIST_MANAGER_DEFAULT_CORE, MENU_WIFI, MENU_ROOM, MENU_ROOM_LAN, diff --git a/msg_hash.h b/msg_hash.h index 31e7cf2b8c..ae32d0191f 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1138,6 +1138,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST, MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_SPECIAL, MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_RESOLUTION, + MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_DEFAULT_CORE, MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_CONFIGURATIONS_LIST, MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST, @@ -1186,6 +1187,8 @@ enum msg_hash_enums MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST, MENU_ENUM_LABEL_DEFERRED_RECORDING_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST, + MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST, + MENU_ENUM_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS, MENU_ENUM_LABEL_DEFERRED_INPUT_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_LATENCY_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_DRIVER_SETTINGS_LIST, @@ -1809,6 +1812,9 @@ enum msg_hash_enums MENU_LABEL(MULTIMEDIA_SETTINGS), MENU_LABEL(PLAYLIST_SETTINGS), + MENU_LABEL(PLAYLIST_MANAGER_LIST), + MENU_LABEL(PLAYLIST_MANAGER_SETTINGS), + MENU_LABEL(PLAYLIST_MANAGER_DEFAULT_CORE), MENU_LABEL(CORE_UPDATER_SETTINGS), MENU_LABEL(LAKKA_SERVICES), MENU_LABEL(SHADER_APPLY_CHANGES), @@ -2457,6 +2463,8 @@ enum msg_hash_enums #define MENU_LABEL_DEFERRED_AUDIO_SETTINGS_LIST 0x5bba25e2U #define MENU_LABEL_DEFERRED_RECORDING_SETTINGS_LIST 0x05548d52U #define MENU_LABEL_DEFERRED_PLAYLIST_SETTINGS_LIST 0x9518e0c7U +#define MENU_LABEL_DEFERRED_PLAYLIST_MANAGER_LIST 0xD7232C4CU +#define MENU_LABEL_DEFERRED_PLAYLIST_MANAGER_SETTINGS 0x16ACEF81U #define MENU_LABEL_DEFERRED_INPUT_SETTINGS_LIST 0x050bec60U #define MENU_LABEL_DEFERRED_USER_BINDS_LIST 0x28c5750eU #define MENU_LABEL_DEFERRED_ACCOUNTS_CHEEVOS_LIST 0x1322324cU @@ -2497,6 +2505,8 @@ enum msg_hash_enums #define MENU_LABEL_SCREEN_RESOLUTION 0x5c9b3a58U +#define MENU_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE 0x86EDE19DU + /* Menu settings */ #define MENU_LABEL_XMB_FONT 0x0ECA56CA2 diff --git a/playlist.c b/playlist.c index 42d65132fa..b1e7c63f5c 100644 --- a/playlist.c +++ b/playlist.c @@ -46,6 +46,8 @@ struct content_playlist size_t cap; char *conf_path; + char *default_core_path; + char *default_core_name; struct playlist_entry *entries; }; @@ -63,6 +65,7 @@ typedef struct unsigned *current_entry_uint_val; struct string_list **current_entry_string_list_val; char *current_meta_string; + char **current_meta_val; char *current_items_string; bool in_items; bool in_subsystem_roms; @@ -1146,6 +1149,19 @@ void playlist_write_file(playlist_t *playlist) playlist->entries[i].crc32 ? playlist->entries[i].crc32 : "", playlist->entries[i].db_name ? playlist->entries[i].db_name : "" ); + + /* Add default core assignment metadata lines + * (we add these at the end of the file to prevent + * breakage if the playlist is loaded with an older + * version of RetroArch */ + if (!string_is_empty(playlist->default_core_path) && + !string_is_empty(playlist->default_core_name)) + { + filestream_printf(file, "default_core_path = \"%s\"\ndefault_core_name = \"%s\"\n", + playlist->default_core_path, + playlist->default_core_name + ); + } } else #endif @@ -1166,15 +1182,49 @@ void playlist_write_file(playlist_t *playlist) JSON_Writer_WriteStartObject(context.writer); JSON_Writer_WriteNewLine(context.writer); + JSON_Writer_WriteSpace(context.writer, 2); JSON_Writer_WriteString(context.writer, "version", STRLEN_CONST("version"), JSON_UTF8); JSON_Writer_WriteColon(context.writer); JSON_Writer_WriteSpace(context.writer, 1); - JSON_Writer_WriteString(context.writer, "1.0", - STRLEN_CONST("1.0"), JSON_UTF8); + JSON_Writer_WriteString(context.writer, "1.1", + STRLEN_CONST("1.1"), JSON_UTF8); JSON_Writer_WriteComma(context.writer); JSON_Writer_WriteNewLine(context.writer); + + JSON_Writer_WriteSpace(context.writer, 2); + JSON_Writer_WriteString(context.writer, "default_core_path", + STRLEN_CONST("default_core_path"), JSON_UTF8); + JSON_Writer_WriteColon(context.writer); + JSON_Writer_WriteSpace(context.writer, 1); + JSON_Writer_WriteString(context.writer, + playlist->default_core_path + ? playlist->default_core_path + : "", + playlist->default_core_path + ? strlen(playlist->default_core_path) + : 0, + JSON_UTF8); + JSON_Writer_WriteComma(context.writer); + JSON_Writer_WriteNewLine(context.writer); + + JSON_Writer_WriteSpace(context.writer, 2); + JSON_Writer_WriteString(context.writer, "default_core_name", + STRLEN_CONST("default_core_name"), JSON_UTF8); + JSON_Writer_WriteColon(context.writer); + JSON_Writer_WriteSpace(context.writer, 1); + JSON_Writer_WriteString(context.writer, + playlist->default_core_name + ? playlist->default_core_name + : "", + playlist->default_core_name + ? strlen(playlist->default_core_name) + : 0, + JSON_UTF8); + JSON_Writer_WriteComma(context.writer); + JSON_Writer_WriteNewLine(context.writer); + JSON_Writer_WriteSpace(context.writer, 2); JSON_Writer_WriteString(context.writer, "items", STRLEN_CONST("items"), JSON_UTF8); @@ -1382,9 +1432,16 @@ void playlist_free(playlist_t *playlist) if (playlist->conf_path != NULL) free(playlist->conf_path); - playlist->conf_path = NULL; + if (playlist->default_core_path != NULL) + free(playlist->default_core_path); + playlist->default_core_path = NULL; + + if (playlist->default_core_name != NULL) + free(playlist->default_core_name); + playlist->default_core_name = NULL; + for (i = 0; i < playlist->size; i++) { struct playlist_entry *entry = &playlist->entries[i]; @@ -1566,18 +1623,24 @@ static JSON_Parser_HandlerResult JSONStringHandler(JSON_Parser parser, char *pVa { if (pCtx->array_depth == 0) { - if (pCtx->current_meta_string && length && !string_is_empty(pValue)) + if (pCtx->current_meta_val && length && !string_is_empty(pValue)) { /* handle any top-level playlist metadata here */ /*RARCH_LOG("found meta: %s = %s\n", pCtx->current_meta_string, pValue);*/ free(pCtx->current_meta_string); pCtx->current_meta_string = NULL; + + if (*pCtx->current_meta_val) + free(*pCtx->current_meta_val); + + *pCtx->current_meta_val = strdup(pValue); } } } pCtx->current_entry_val = NULL; + pCtx->current_meta_val = NULL; return JSON_Parser_Continue; } @@ -1694,12 +1757,27 @@ static JSON_Parser_HandlerResult JSONObjectMemberHandler(JSON_Parser parser, cha { if (pCtx->array_depth == 0) { + if (pCtx->current_meta_val) + { + /* something went wrong */ + RARCH_WARN("JSON parsing failed at line %d.\n", __LINE__); + return JSON_Parser_Abort; + } + if (length) { if (pCtx->current_meta_string) free(pCtx->current_meta_string); - pCtx->current_meta_string = strdup(pValue); + + if (string_is_equal(pValue, "default_core_path")) + pCtx->current_meta_val = &pCtx->playlist->default_core_path; + else if (string_is_equal(pValue, "default_core_name")) + pCtx->current_meta_val = &pCtx->playlist->default_core_name; + else + { + /* ignore unknown members */ + } } } } @@ -1707,6 +1785,27 @@ static JSON_Parser_HandlerResult JSONObjectMemberHandler(JSON_Parser parser, cha return JSON_Parser_Continue; } +static void get_old_format_metadata_value( + char *metadata_line, char *value, size_t len) +{ + char *start = NULL; + char *end = NULL; + + start = strchr(metadata_line, '\"'); + + if (!start) + return; + + start++; + end = strchr(start, '\"'); + + if (!end) + return; + + *end = '\0'; + strlcpy(value, start, len); +} + static bool playlist_read_file( playlist_t *playlist, const char *path) { @@ -1836,10 +1935,84 @@ static bool playlist_read_file( else { char buf[PLAYLIST_ENTRIES][1024] = {{0}}; + char metadata_line[1024]; + char default_core_path[1024]; + char default_core_name[1024]; + char metadata_char; + size_t metadata_counter; for (i = 0; i < PLAYLIST_ENTRIES; i++) buf[i][0] = '\0'; + metadata_line[0] = '\0'; + default_core_path[0] = '\0'; + default_core_name[0] = '\0'; + metadata_char = 0; + metadata_counter = 0; + + /* Attempt to read metadata lines at end of file */ + filestream_seek(file, -1, SEEK_END); + if (filestream_error(file)) + goto end; + + /* > Exclude trailing newline */ + metadata_char = filestream_getc(file); + + while((metadata_char == '\n') || + (metadata_char == '\r')) + { + filestream_seek(file, -2, SEEK_CUR); + if (filestream_error(file)) + goto end; + + metadata_char = filestream_getc(file); + } + + /* Search backwards for the next two newlines */ + while(metadata_counter < 2) + { + filestream_seek(file, -2, SEEK_CUR); + if (filestream_error(file)) + goto end; + + metadata_char = filestream_getc(file); + if (metadata_char == '\n') + metadata_counter++; + } + + /* > Get default_core_path */ + if (!filestream_gets(file, metadata_line, sizeof(metadata_line))) + goto end; + + if (strncmp("default_core_path", + metadata_line, + STRLEN_CONST("default_core_path")) == 0) + get_old_format_metadata_value( + metadata_line, default_core_path, sizeof(default_core_path)); + + /* > Get default_core_name */ + if (!filestream_gets(file, metadata_line, sizeof(metadata_line))) + goto end; + + if (strncmp("default_core_name", + metadata_line, + STRLEN_CONST("default_core_name")) == 0) + get_old_format_metadata_value( + metadata_line, default_core_name, sizeof(default_core_name)); + + /* > Populate playlist fields, if required */ + if (!string_is_empty(default_core_path) && + !string_is_empty(default_core_name)) + { + playlist->default_core_path = strdup(default_core_path); + playlist->default_core_name = strdup(default_core_name); + } + + /* Read playlist entries */ + filestream_seek(file, 0, SEEK_SET); + if (filestream_error(file)) + goto end; + for (playlist->size = 0; playlist->size < playlist->cap; ) { unsigned i; @@ -1932,11 +2105,13 @@ playlist_t *playlist_init(const char *path, size_t size) return NULL; } - playlist->modified = false; - playlist->size = 0; - playlist->cap = size; - playlist->conf_path = strdup(path); - playlist->entries = entries; + playlist->modified = false; + playlist->size = 0; + playlist->cap = size; + playlist->conf_path = strdup(path); + playlist->default_core_name = NULL; + playlist->default_core_path = NULL; + playlist->entries = entries; playlist_read_file(playlist, path); @@ -2108,3 +2283,57 @@ void playlist_get_db_name(playlist_t *playlist, size_t idx, } } } + +char *playlist_get_default_core_path(playlist_t *playlist) +{ + if (!playlist) + return NULL; + return playlist->default_core_path; +} + +char *playlist_get_default_core_name(playlist_t *playlist) +{ + if (!playlist) + return NULL; + return playlist->default_core_name; +} + +void playlist_set_default_core_path(playlist_t *playlist, const char *core_path) +{ + char real_core_path[PATH_MAX_LENGTH]; + + real_core_path[0] = '\0'; + + if (!playlist || string_is_empty(core_path)) + return; + + /* Get 'real' core path */ + strlcpy(real_core_path, core_path, sizeof(real_core_path)); + if (!string_is_equal(real_core_path, file_path_str(FILE_PATH_DETECT))) + path_resolve_realpath(real_core_path, sizeof(real_core_path)); + + if (string_is_empty(real_core_path)) + return; + + if (!string_is_equal(playlist->default_core_path, real_core_path)) + { + if (playlist->default_core_path) + free(playlist->default_core_path); + playlist->default_core_path = strdup(real_core_path); + playlist->modified = true; + } +} + +void playlist_set_default_core_name(playlist_t *playlist, const char *core_name) +{ + if (!playlist || string_is_empty(core_name)) + return; + + if (!string_is_equal(playlist->default_core_name, core_name)) + { + if (playlist->default_core_name) + free(playlist->default_core_name); + playlist->default_core_name = strdup(core_name); + playlist->modified = true; + } +} diff --git a/playlist.h b/playlist.h index ec134f74a3..7a82fd999b 100644 --- a/playlist.h +++ b/playlist.h @@ -190,6 +190,12 @@ void playlist_get_crc32(playlist_t *playlist, size_t idx, void playlist_get_db_name(playlist_t *playlist, size_t idx, const char **db_name); +char *playlist_get_default_core_path(playlist_t *playlist); +char *playlist_get_default_core_name(playlist_t *playlist); + +void playlist_set_default_core_path(playlist_t *playlist, const char *core_path); +void playlist_set_default_core_name(playlist_t *playlist, const char *core_name); + RETRO_END_DECLS #endif diff --git a/ui/drivers/qt/qt_playlist.cpp b/ui/drivers/qt/qt_playlist.cpp index fa9d7cb96b..10de21189b 100644 --- a/ui/drivers/qt/qt_playlist.cpp +++ b/ui/drivers/qt/qt_playlist.cpp @@ -754,27 +754,14 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) QString currentPlaylistPath; QString currentPlaylistFileName; QFile currentPlaylistFile; - QByteArray currentPlaylistFileNameArray; QFileInfo currentPlaylistFileInfo; QMap coreList; core_info_list_t *core_info_list = NULL; - union string_list_elem_attr attr = {0}; - struct string_list *stnames = NULL; - struct string_list *stcores = NULL; unsigned i = 0; int j = 0; - size_t found = 0; - const char *currentPlaylistFileNameData = NULL; - char new_playlist_names[sizeof(settings->arrays.playlist_names) / sizeof(settings->arrays.playlist_names[0])]; - char new_playlist_cores[sizeof(settings->arrays.playlist_cores) / sizeof(settings->arrays.playlist_cores[0])]; bool specialPlaylist = false; bool foundHiddenPlaylist = false; - new_playlist_names[0] = new_playlist_cores[0] = '\0'; - - stnames = string_split(settings->arrays.playlist_names, ";"); - stcores = string_split(settings->arrays.playlist_cores, ";"); - if (selectedItem) { currentPlaylistPath = selectedItem->data(Qt::UserRole).toString(); @@ -783,9 +770,6 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) currentPlaylistFileInfo = QFileInfo(currentPlaylistPath); currentPlaylistFileName = currentPlaylistFileInfo.fileName(); currentPlaylistDirPath = currentPlaylistFileInfo.absoluteDir().absolutePath(); - - currentPlaylistFileNameArray.append(currentPlaylistFileName); - currentPlaylistFileNameData = currentPlaylistFileNameArray.constData(); } menu.reset(new QMenu(this)); @@ -916,34 +900,57 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) selectedAction = menu->exec(cursorPos); if (!selectedAction) - goto end; + return; if (!specialPlaylist && selectedAction->parent() == associateMenu.data()) { - found = string_list_find_elem(stnames, currentPlaylistFileNameData); + core_info_ctx_find_t coreInfo; + playlist_t *cachedPlaylist = playlist_get_cached(); + playlist_t *playlist = NULL; + bool loadPlaylist = true; + QByteArray currentPlaylistPathByteArray = currentPlaylistPath.toUtf8(); + const char *currentPlaylistPathCString = currentPlaylistPathByteArray.data(); + QByteArray corePathByteArray = selectedAction->property("core_path").toString().toUtf8(); + const char *corePath = corePathByteArray.data(); - if (found) - string_list_set(stcores, static_cast(found - 1), selectedAction->property("core_path").toString().toUtf8().constData()); - else + /* Load playlist, if required */ + if (cachedPlaylist) { - string_list_append(stnames, currentPlaylistFileNameData, attr); - string_list_append(stcores, "DETECT", attr); - - found = string_list_find_elem(stnames, currentPlaylistFileNameData); - - if (found) - string_list_set(stcores, static_cast(found - 1), selectedAction->property("core_path").toString().toUtf8().constData()); + if (string_is_equal(currentPlaylistPathCString, playlist_get_conf_path(cachedPlaylist))) + { + playlist = cachedPlaylist; + loadPlaylist = false; + } } - string_list_join_concat(new_playlist_names, - sizeof(new_playlist_names), stnames, ";"); - string_list_join_concat(new_playlist_cores, - sizeof(new_playlist_cores), stcores, ";"); + if (loadPlaylist) + playlist = playlist_init(currentPlaylistPathCString, COLLECTION_SIZE); - strlcpy(settings->arrays.playlist_names, - new_playlist_names, sizeof(settings->arrays.playlist_names)); - strlcpy(settings->arrays.playlist_cores, - new_playlist_cores, sizeof(settings->arrays.playlist_cores)); + if (playlist) + { + /* Get core info */ + coreInfo.inf = NULL; + coreInfo.path = corePath; + + if (core_info_find(&coreInfo, corePath)) + { + /* Set new core association */ + playlist_set_default_core_path(playlist, coreInfo.inf->path); + playlist_set_default_core_name(playlist, coreInfo.inf->display_name); + } + else + { + playlist_set_default_core_path(playlist, file_path_str(FILE_PATH_DETECT)); + playlist_set_default_core_name(playlist, file_path_str(FILE_PATH_DETECT)); + } + + /* Write changes to disk */ + playlist_write_file(playlist); + + /* Free playlist, if required */ + if (loadPlaylist) + playlist_free(playlist); + } } else if (selectedItem && selectedAction == deletePlaylistAction.data()) { @@ -1044,12 +1051,6 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) } setCoreActions(); - -end: - if (stnames) - string_list_free(stnames); - if (stcores) - string_list_free(stcores); } void MainWindow::deferReloadPlaylists() @@ -1309,50 +1310,57 @@ void MainWindow::deleteCurrentPlaylistItem() reloadPlaylists(); } -QVector > MainWindow::getPlaylistDefaultCores() +QString MainWindow::getPlaylistDefaultCore(QString dbName) { - unsigned i = 0; - settings_t *settings = config_get_ptr(); - struct string_list *playlists = string_split( - settings->arrays.playlist_names, ";"); - struct string_list *cores = string_split( - settings->arrays.playlist_cores, ";"); - QVector > coreList; + settings_t *settings = config_get_ptr(); + QByteArray dbNameByteArray = dbName.toUtf8(); + const char *dbNameCString = dbNameByteArray.data(); + playlist_t *cachedPlaylist = playlist_get_cached(); + playlist_t *playlist = NULL; + bool loadPlaylist = true; + QString corePath = QString(); + char playlistPath[PATH_MAX_LENGTH]; - if (!playlists || !cores) + playlistPath[0] = '\0'; + + if (!settings || string_is_empty(dbNameCString)) + return corePath; + + /* Get playlist path */ + fill_pathname_join( + playlistPath, + settings->paths.directory_playlist, dbNameCString, + sizeof(playlistPath)); + strlcat(playlistPath, file_path_str(FILE_PATH_LPL_EXTENSION), sizeof(playlistPath)); + + /* Load playlist, if required */ + if (cachedPlaylist) { - RARCH_WARN("[Qt]: Could not parse one of playlist_names or playlist_cores\n"); - goto finish; - } - else if (playlists->size != cores->size) - { - RARCH_WARN("[Qt]: playlist_names array size differs from playlist_cores\n"); - goto finish; + if (string_is_equal(playlistPath, playlist_get_conf_path(cachedPlaylist))) + { + playlist = cachedPlaylist; + loadPlaylist = false; + } } - if (playlists->size == 0) - goto finish; + if (loadPlaylist) + playlist = playlist_init(playlistPath, COLLECTION_SIZE); - for (i = 0; i < playlists->size; i++) + if (playlist) { - const char *playlist = playlists->elems[i].data; - const char *core = cores->elems[i].data; - QHash hash; + const char *defaultCorePath = playlist_get_default_core_path(playlist); - hash["playlist_filename"] = playlist; - hash["playlist_filename"].remove(file_path_str(FILE_PATH_LPL_EXTENSION)); - hash["core_path"] = core; + /* Get default core path */ + if (!string_is_empty(defaultCorePath) && + !string_is_equal(defaultCorePath, file_path_str(FILE_PATH_DETECT))) + corePath = QString::fromUtf8(defaultCorePath); - coreList.append(hash); + /* Free playlist, if required */ + if (loadPlaylist) + playlist_free(playlist); } -finish: - if (playlists) - string_list_free(playlists); - if (cores) - string_list_free(cores); - - return coreList; + return corePath; } void MainWindow::getPlaylistFiles() diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index 349eb06977..86cbd116fa 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -1806,26 +1806,15 @@ QHash MainWindow::getSelectedCore() break; case CORE_SELECTION_PLAYLIST_DEFAULT: { - QVector > cores; - int i = 0; + QString defaultCorePath; if (contentHash.isEmpty() || contentHash["db_name"].isEmpty()) break; - cores = getPlaylistDefaultCores(); + defaultCorePath = getPlaylistDefaultCore(contentHash["db_name"]); - for (i = 0; i < cores.count(); i++) - { - if (cores[i]["playlist_filename"] == contentHash["db_name"]) - { - if (cores[i]["core_path"].isEmpty()) - break; - - coreHash["core_path"] = cores[i]["core_path"]; - - break; - } - } + if (!defaultCorePath.isEmpty()) + coreHash["core_path"] = defaultCorePath; break; } @@ -1923,18 +1912,13 @@ void MainWindow::loadContent(const QHash &contentHash) break; case CORE_SELECTION_PLAYLIST_DEFAULT: { - QVector > cores = getPlaylistDefaultCores(); - int i = 0; + QString defaultCorePath = getPlaylistDefaultCore(contentHash["db_name"]); - for (i = 0; i < cores.count(); i++) + if (!defaultCorePath.isEmpty()) { - if (cores[i]["playlist_filename"] == contentHash["db_name"]) - { - corePathArray = cores[i]["core_path"].toUtf8(); - contentPathArray = contentHash["path"].toUtf8(); - contentLabelArray = contentHash["label_noext"].toUtf8(); - break; - } + corePathArray = defaultCorePath.toUtf8(); + contentPathArray = contentHash["path"].toUtf8(); + contentLabelArray = contentHash["label_noext"].toUtf8(); } break; @@ -2097,14 +2081,15 @@ void MainWindow::setCoreActions() if (!currentPlaylistFileName.isEmpty()) { - QVector > defaultCores = getPlaylistDefaultCores(); - int i = 0; + QString defaultCorePath = getPlaylistDefaultCore(currentPlaylistFileName); - if (defaultCores.count() > 0) + if (!defaultCorePath.isEmpty()) { QString currentPlaylistItemDataString; - bool allPlaylists = false; - int row = 0; + bool allPlaylists = false; + int row = 0; + core_info_list_t *coreInfoList = NULL; + unsigned j = 0; if (currentPlaylistItem) { @@ -2126,54 +2111,40 @@ void MainWindow::setCoreActions() continue; } - for (i = 0; i < defaultCores.count(); i++) + core_info_get_list(&coreInfoList); + + if (coreInfoList) { - QString playlist = defaultCores.at(i)["playlist_filename"]; - QString core = defaultCores.at(i)["core_path"]; - - playlist.remove(file_path_str(FILE_PATH_LPL_EXTENSION)); - - if (currentPlaylistFileName == playlist) + for (j = 0; j < coreInfoList->count; j++) { - core_info_list_t *coreInfoList = NULL; - unsigned j = 0; + const core_info_t *info = &coreInfoList->list[j]; - core_info_get_list(&coreInfoList); - - if (coreInfoList) + if (defaultCorePath == info->path) { - for (j = 0; j < coreInfoList->count; j++) + if (m_launchWithComboBox->findText(info->core_name) == -1) { - const core_info_t *info = &coreInfoList->list[j]; + int i = 0; + bool found_existing = false; - if (core == info->path) + for (i = 0; i < m_launchWithComboBox->count(); i++) { - if (m_launchWithComboBox->findText(info->core_name) == -1) + QVariantMap map = m_launchWithComboBox->itemData(i, Qt::UserRole).toMap(); + + if (map.value("core_path").toString() == info->path || map.value("core_name").toString() == info->core_name) { - int i = 0; - bool found_existing = false; - - for (i = 0; i < m_launchWithComboBox->count(); i++) - { - QVariantMap map = m_launchWithComboBox->itemData(i, Qt::UserRole).toMap(); - - if (map.value("core_path").toString() == info->path || map.value("core_name").toString() == info->core_name) - { - found_existing = true; - break; - } - } - - if (!found_existing) - { - QVariantMap comboBoxMap; - comboBoxMap["core_name"] = info->core_name; - comboBoxMap["core_path"] = info->path; - comboBoxMap["core_selection"] = CORE_SELECTION_PLAYLIST_DEFAULT; - m_launchWithComboBox->addItem(info->core_name, QVariant::fromValue(comboBoxMap)); - } + found_existing = true; + break; } } + + if (!found_existing) + { + QVariantMap comboBoxMap; + comboBoxMap["core_name"] = info->core_name; + comboBoxMap["core_path"] = info->path; + comboBoxMap["core_selection"] = CORE_SELECTION_PLAYLIST_DEFAULT; + m_launchWithComboBox->addItem(info->core_name, QVariant::fromValue(comboBoxMap)); + } } } } diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index 05a84b5db1..80447c5324 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -363,7 +363,7 @@ public: QToolButton* runPushButton(); QToolButton* stopPushButton(); QTabWidget* browserAndPlaylistTabWidget(); - QVector > getPlaylistDefaultCores(); + QString getPlaylistDefaultCore(QString dbName); ViewOptionsDialog* viewOptionsDialog(); QSettings* settings(); QVector > getCoreInfo();