diff --git a/config.def.h b/config.def.h index 71efaaea98..dddd8f7cb4 100644 --- a/config.def.h +++ b/config.def.h @@ -704,6 +704,9 @@ static const uint16_t network_remote_base_port = 55400; /* Number of entries that will be kept in content history playlist file. */ static const unsigned default_content_history_size = 100; +/* Sort all playlists (apart from histories) alphabetically */ +static const bool playlist_sort_alphabetical = true; + /* File format to use when writing playlists to disk */ static const bool playlist_use_old_format = false; diff --git a/configuration.c b/configuration.c index f60752c548..ade4d92802 100644 --- a/configuration.c +++ b/configuration.c @@ -1576,6 +1576,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("playlist_use_old_format", &settings->bools.playlist_use_old_format, true, playlist_use_old_format, false); SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, content_runtime_log, false); + SETTING_BOOL("playlist_sort_alphabetical", &settings->bools.playlist_sort_alphabetical, true, playlist_sort_alphabetical, false); + *size = count; return tmp; diff --git a/configuration.h b/configuration.h index ed6561798b..49748cc0c5 100644 --- a/configuration.h +++ b/configuration.h @@ -310,6 +310,7 @@ typedef struct settings bool content_runtime_log; bool playlist_show_core_name; + bool playlist_sort_alphabetical; } bools; struct diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index e8f942cae2..7df240bfaf 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1785,3 +1785,5 @@ MSG_HASH(MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG, "content_runtime_log") MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME, "playlist_show_core_name") +MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL, + "playlist_sort_alphabetical") diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index dde3743fb1..6944256020 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -8238,6 +8238,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_CORE_NAME, "Labels each playlist entry with the currently associated core (if any)." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_PLAYLIST_SORT_ALPHABETICAL, + "Sort playlists alphabetically" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PLAYLIST_SORT_ALPHABETICAL, + "Sorts content playlists in alphabetical order. Note that 'history' playlists of recently used games, images, music and videos are excluded." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_SOUNDS, "Menu Sounds" diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 8fa16d7a7f..b22202fba5 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -521,6 +521,7 @@ default_sublabel_macro(action_bind_sublabel_menu_rgui_internal_upscale_level, default_sublabel_macro(action_bind_sublabel_menu_ticker_type, MENU_ENUM_SUBLABEL_MENU_TICKER_TYPE) default_sublabel_macro(action_bind_sublabel_menu_ticker_speed, MENU_ENUM_SUBLABEL_MENU_TICKER_SPEED) default_sublabel_macro(action_bind_sublabel_playlist_show_core_name, MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_CORE_NAME) +default_sublabel_macro(action_bind_sublabel_playlist_sort_alphabetical, MENU_ENUM_SUBLABEL_PLAYLIST_SORT_ALPHABETICAL) static int action_bind_sublabel_systeminfo_controller_entry( file_list_t *list, @@ -2268,6 +2269,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_show_core_name); break; + case MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_sort_alphabetical); + break; default: case MSG_UNKNOWN: return -1; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index dd7d325de3..192693b122 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -1350,10 +1350,11 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info, if (core_name) strlcpy(fill_buf, core_name, path_size); - /* Note: this function is never called when using RGUI, - * but if it ever were then we must ensure that thumbnail + /* Note: this condition is never met when using RGUI, + * since 'is_history' is always set to 'true'. + * But if it ever were then we must ensure that thumbnail * updates are omitted (since this functionality is - * handled elsewhere) */ + * handled elsewhere). */ if (!is_history && i == selection && !string_is_empty(label) && !string_is_equal(settings->arrays.menu_driver, "rgui")) { char *content_basename = strdup(label); @@ -2547,7 +2548,8 @@ static void menu_displaylist_set_new_playlist( static int menu_displaylist_parse_horizontal_list( menu_handle_t *menu, - menu_displaylist_info_t *info) + menu_displaylist_info_t *info, + bool sort) { menu_ctx_list_t list_info; menu_ctx_list_t list_horiz_info; @@ -2582,6 +2584,8 @@ static int menu_displaylist_parse_horizontal_list( fill_pathname_base_noext(lpl_basename, item->path, sizeof(lpl_basename)); menu_driver_set_thumbnail_system(lpl_basename, sizeof(lpl_basename)); + + /* Note: Redundant, since this function is never used for history lists... */ if (string_is_equal(lpl_basename, "content_history")) is_historylist = true; @@ -2597,7 +2601,12 @@ static int menu_displaylist_parse_horizontal_list( if (playlist) { - playlist_qsort(playlist); + /* Note: If this function were used for history lists, then history + * lists would be sorted alphabetically. This is incorrect behaviour. + * Fortunately it never happens... */ + if (sort) + playlist_qsort(playlist); + menu_displaylist_parse_playlist(info, playlist, msg_hash_to_str(MENU_ENUM_LABEL_COLLECTION), is_historylist); @@ -4126,6 +4135,7 @@ static void menu_displaylist_parse_playlist_generic( menu_displaylist_info_t *info, const char *playlist_name, const char *playlist_path, + bool sort, int *ret) { playlist_t *playlist = NULL; @@ -4135,8 +4145,13 @@ static void menu_displaylist_parse_playlist_generic( playlist = playlist_get_cached(); if (playlist) + { + if (sort) + playlist_qsort(playlist); + *ret = menu_displaylist_parse_playlist(info, playlist, playlist_name, true); + } } #ifdef HAVE_NETWORKING @@ -4759,6 +4774,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist #endif break; case DISPLAYLIST_PLAYLIST_COLLECTION: + /* Note: This would appear to be legacy code. Cannot find + * a single instance where this case is met... */ menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); if (string_is_equal(info->path, file_path_str(FILE_PATH_CONTENT_HISTORY))) { @@ -4796,7 +4813,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist if (playlist) { - playlist_qsort(playlist); + if (settings->bools.playlist_sort_alphabetical) + playlist_qsort(playlist); ret = menu_displaylist_parse_playlist(info, playlist, path_playlist, false); @@ -4804,7 +4822,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist if (ret == 0) { - info->need_sort = true; + info->need_sort = settings->bools.playlist_sort_alphabetical; info->need_refresh = true; info->need_push = true; } @@ -4820,6 +4838,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist menu, info, "history", settings->paths.path_content_history, + false, &ret); else { @@ -4836,31 +4855,33 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist info->need_push = true; break; case DISPLAYLIST_FAVORITES: - info->count = 0; - { settings_t *settings = config_get_ptr(); + info->count = 0; + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); menu_displaylist_parse_playlist_generic(menu, info, "favorites", settings->paths.path_content_favorites, + settings->bools.playlist_sort_alphabetical, &ret); - } - if (info->count == 0) - { - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_FAVORITES_AVAILABLE), - msg_hash_to_str(MENU_ENUM_LABEL_NO_FAVORITES_AVAILABLE), - MENU_ENUM_LABEL_NO_FAVORITES_AVAILABLE, - MENU_INFO_MESSAGE, 0, 0); - info->need_push_no_playlist_entries = false; - ret = 0; - } + if (info->count == 0) + { + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_FAVORITES_AVAILABLE), + msg_hash_to_str(MENU_ENUM_LABEL_NO_FAVORITES_AVAILABLE), + MENU_ENUM_LABEL_NO_FAVORITES_AVAILABLE, + MENU_INFO_MESSAGE, 0, 0); + info->need_push_no_playlist_entries = false; + ret = 0; + } - ret = 0; - info->need_refresh = true; - info->need_push = true; + ret = 0; + info->need_sort = settings->bools.playlist_sort_alphabetical; + info->need_refresh = true; + info->need_push = true; + } break; case DISPLAYLIST_MUSIC_HISTORY: { @@ -4871,6 +4892,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist menu_displaylist_parse_playlist_generic(menu, info, "music_history", settings->paths.path_content_music_history, + false, &ret); if (info->count == 0) @@ -4902,6 +4924,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist menu_displaylist_parse_playlist_generic(menu, info, "video_history", settings->paths.path_content_video_history, + false, &ret); count++; } @@ -5264,28 +5287,38 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist info->need_push = true; break; case DISPLAYLIST_PLAYLIST_SETTINGS_LIST: - menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - ret = menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_HISTORY_LIST_ENABLE, - PARSE_ONLY_BOOL, false); - ret = menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_CONTENT_HISTORY_SIZE, - PARSE_ONLY_UINT, false); - ret = menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_PLAYLIST_ENTRY_RENAME, - PARSE_ONLY_BOOL, false); - ret = menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_PLAYLIST_ENTRY_REMOVE, - PARSE_ONLY_BOOL, false); - ret = menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT, - PARSE_ONLY_BOOL, false); - ret = menu_displaylist_parse_settings_enum(menu, info, - MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME, - PARSE_ONLY_BOOL, false); + { + settings_t *settings = config_get_ptr(); - menu_displaylist_parse_playlist_associations(info); - info->need_push = true; + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_HISTORY_LIST_ENABLE, + PARSE_ONLY_BOOL, false); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CONTENT_HISTORY_SIZE, + PARSE_ONLY_UINT, false); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_PLAYLIST_ENTRY_RENAME, + PARSE_ONLY_BOOL, false); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_PLAYLIST_ENTRY_REMOVE, + PARSE_ONLY_BOOL, false); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL, + PARSE_ONLY_BOOL, false); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT, + PARSE_ONLY_BOOL, false); + if (string_is_equal(settings->arrays.menu_driver, "rgui")) + { + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME, + PARSE_ONLY_BOOL, false); + } + + menu_displaylist_parse_playlist_associations(info); + info->need_push = true; + } break; case DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -7182,12 +7215,16 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist info->need_push = true; break; case DISPLAYLIST_HORIZONTAL: - menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); - ret = menu_displaylist_parse_horizontal_list(menu, info); + { + settings_t *settings = config_get_ptr(); - info->need_sort = true; - info->need_refresh = true; - info->need_push = true; + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); + ret = menu_displaylist_parse_horizontal_list(menu, info, settings->bools.playlist_sort_alphabetical); + + info->need_sort = settings->bools.playlist_sort_alphabetical; + info->need_refresh = true; + info->need_push = true; + } break; case DISPLAYLIST_HORIZONTAL_CONTENT_ACTIONS: menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); @@ -8054,16 +8091,22 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist use_filebrowser = true; break; case DISPLAYLIST_PLAYLIST: - menu_displaylist_parse_playlist_generic(menu, info, - path_basename(info->path), - info->path, - &ret); - ret = 0; - - if (ret == 0) { - info->need_refresh = true; - info->need_push = true; + settings_t *settings = config_get_ptr(); + + menu_displaylist_parse_playlist_generic(menu, info, + path_basename(info->path), + info->path, + settings->bools.playlist_sort_alphabetical, + &ret); + ret = 0; /* Why do we do this...? */ + + if (ret == 0) + { + info->need_sort = settings->bools.playlist_sort_alphabetical; + info->need_refresh = true; + info->need_push = true; + } } break; case DISPLAYLIST_IMAGES_HISTORY: @@ -8076,6 +8119,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist menu_displaylist_parse_playlist_generic(menu, info, "images_history", settings->paths.path_content_image_history, + false, &ret); count++; } diff --git a/menu/menu_setting.c b/menu/menu_setting.c index bdb8f5b46d..cbb3132f81 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -9761,6 +9761,22 @@ static bool setting_append_list( general_read_handler, SD_FLAG_NONE); + CONFIG_BOOL( + list, list_info, + &settings->bools.playlist_sort_alphabetical, + MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL, + MENU_ENUM_LABEL_VALUE_PLAYLIST_SORT_ALPHABETICAL, + playlist_sort_alphabetical, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + CONFIG_BOOL( list, list_info, &settings->bools.playlist_use_old_format, diff --git a/msg_hash.h b/msg_hash.h index f8b2dfa45f..0956888179 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2273,6 +2273,7 @@ enum msg_hash_enums MENU_LABEL(CONTENT_RUNTIME_LOG), MENU_LABEL(PLAYLIST_SHOW_CORE_NAME), + MENU_LABEL(PLAYLIST_SORT_ALPHABETICAL), MSG_LAST };