Enhanced playlist search functionality

This commit is contained in:
jdgleaver 2020-07-31 15:13:43 +01:00
parent c522f97e0f
commit 776301883c
15 changed files with 567 additions and 103 deletions

View File

@ -482,17 +482,16 @@ void gfx_thumbnail_process_stream(
if (thumbnail->delay_timer > p_gfx_thumb->stream_delay)
{
/* Sanity check */
if (!path_data || !playlist)
return;
/* Update thumbnail content */
if (!gfx_thumbnail_set_content_playlist(path_data, playlist, idx))
if (!path_data ||
!playlist ||
!gfx_thumbnail_set_content_playlist(path_data, playlist, idx))
{
/* Content is invalid
* > Reset thumbnail and set missing status */
gfx_thumbnail_reset(thumbnail);
thumbnail->status = GFX_THUMBNAIL_STATUS_MISSING;
thumbnail->alpha = 1.0f;
return;
}
@ -576,12 +575,10 @@ void gfx_thumbnail_process_streams(
/* Check if one or more thumbnails should be requested */
if (request_right || request_left)
{
/* Sanity check */
if (!path_data || !playlist)
return;
/* Update thumbnail content */
if (!gfx_thumbnail_set_content_playlist(path_data, playlist, idx))
if (!path_data ||
!playlist ||
!gfx_thumbnail_set_content_playlist(path_data, playlist, idx))
{
/* Content is invalid
* > Reset thumbnail and set missing status */
@ -589,12 +586,14 @@ void gfx_thumbnail_process_streams(
{
gfx_thumbnail_reset(right_thumbnail);
right_thumbnail->status = GFX_THUMBNAIL_STATUS_MISSING;
right_thumbnail->alpha = 1.0f;
}
if (request_left)
{
gfx_thumbnail_reset(left_thumbnail);
left_thumbnail->status = GFX_THUMBNAIL_STATUS_MISSING;
left_thumbnail->alpha = 1.0f;
}
return;

View File

@ -33,19 +33,61 @@ int action_cancel_pop_default(const char *path,
const char *label, unsigned type, size_t idx)
{
size_t new_selection_ptr;
const char *menu_label = NULL;
const char *menu_label = NULL;
unsigned menu_type = MENU_SETTINGS_NONE;
bool menu_has_label = false;
struct string_list *menu_search_terms = menu_driver_search_get_terms();
#ifdef HAVE_AUDIOMIXER
settings_t *settings = config_get_ptr();
bool audio_enable_menu = settings->bools.audio_enable_menu;
bool audio_enable_menu_cancel = settings->bools.audio_enable_menu_cancel;
settings_t *settings = config_get_ptr();
bool audio_enable_menu = settings->bools.audio_enable_menu;
bool audio_enable_menu_cancel = settings->bools.audio_enable_menu_cancel;
if (audio_enable_menu && audio_enable_menu_cancel)
audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_CANCEL);
#endif
menu_entries_get_last_stack(NULL, &menu_label, NULL, NULL, NULL);
menu_entries_get_last_stack(NULL, &menu_label, &menu_type, NULL, NULL);
menu_has_label = !string_is_empty(menu_label);
if (!string_is_empty(menu_label))
/* Check whether search terms have been set */
if (menu_search_terms)
{
bool is_playlist = false;
/* Check whether this is a playlist */
is_playlist = (menu_type == MENU_SETTING_HORIZONTAL_MENU) ||
(menu_type == MENU_HISTORY_TAB) ||
(menu_type == MENU_FAVORITES_TAB) ||
(menu_type == MENU_IMAGES_TAB) ||
(menu_type == MENU_MUSIC_TAB) ||
(menu_type == MENU_VIDEO_TAB) ||
(menu_type == FILE_TYPE_PLAYLIST_COLLECTION);
if (!is_playlist && menu_has_label)
is_playlist = string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY)) ||
string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST)) ||
string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST)) ||
string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MUSIC_LIST)) ||
string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST));
/* Remove last search term */
if (is_playlist && menu_driver_search_pop())
{
bool refresh = false;
/* Reset navigation pointer */
menu_navigation_set_selection(0);
menu_driver_navigation_set(false);
/* Refresh menu */
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
return 0;
}
}
if (menu_has_label)
{
if (
string_is_equal(menu_label,

View File

@ -25,6 +25,15 @@ static int deferred_push_content_list(void *data, void *userdata,
const char *label, unsigned type)
{
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
/* Must clear any existing menu search terms
* when switching 'tabs', since doing so
* bypasses standard backwards navigation
* (i.e. 'cancel' actions would normally
* pop the search stack - this will not
* happen if we jump to a new list directly) */
menu_driver_search_clear();
menu_navigation_set_selection(0);
return action_refresh_default((file_list_t*)data, selection_buf);
}

View File

@ -760,7 +760,7 @@ int generic_action_ok_displaylist_push(const char *path,
info_label = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS);
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS;
info.directory_ptr = idx;
menu->rpl_entry_selection_ptr = (unsigned)idx;
menu->rpl_entry_selection_ptr = (unsigned)entry_idx;
dl_type = DISPLAYLIST_GENERIC;
break;
case ACTION_OK_DL_AUDIO_DSP_PLUGIN:

View File

@ -1211,8 +1211,10 @@ static int action_bind_sublabel_playlist_entry(
const char *label, const char *path,
char *s, size_t len)
{
size_t list_size = menu_entries_get_size();
playlist_t *playlist = NULL;
const struct playlist_entry *entry = NULL;
size_t playlist_index = i;
#ifdef HAVE_OZONE
const char *menu_ident = menu_driver_ident();
#endif
@ -1239,17 +1241,24 @@ static int action_bind_sublabel_playlist_entry(
return 0;
#endif
/* Get playlist index corresponding
* to the current entry */
if (!list || (i >= list_size))
return 0;
playlist_index = list->list[i].entry_idx;
/* Get current playlist */
playlist = playlist_get_cached();
if (!playlist)
return 0;
if (i >= playlist_get_size(playlist))
if (playlist_index >= playlist_get_size(playlist))
return 0;
/* Read playlist entry */
playlist_get_index(playlist, i, &entry);
playlist_get_index(playlist, playlist_index, &entry);
/* Only add sublabel if a core is currently assigned
* > Both core name and core path must be valid */
@ -1286,7 +1295,7 @@ static int action_bind_sublabel_playlist_entry(
/* Check whether runtime info should be loaded from log file */
if (entry->runtime_status == PLAYLIST_RUNTIME_UNKNOWN)
runtime_update_playlist(
playlist, i,
playlist, playlist_index,
directory_runtime_log,
directory_playlist,
(playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE),

View File

@ -74,6 +74,23 @@
return 1; \
}
static void action_get_title_fill_playlist_default(
char *s, enum msg_hash_enums lbl, size_t len)
{
/* Copy playlist name */
strlcpy(s, msg_hash_to_str(lbl), len);
/* Add current search terms */
menu_driver_search_append_terms_string(s, len);
}
#define DEFAULT_TITLE_PLAYLIST_MACRO(func_name, lbl) \
static int (func_name)(const char *path, const char *label, unsigned menu_type, char *s, size_t len) \
{ \
action_get_title_fill_playlist_default(s, lbl, len); \
return 0; \
}
static int action_get_title_action_generic(
const char *path, const char *label,
unsigned menu_type, char *s, size_t len)
@ -328,6 +345,9 @@ static int action_get_title_deferred_playlist_list(const char *path, const char
else
strlcpy(s, playlist_file, len);
/* Add current search terms */
menu_driver_search_append_terms_string(s, len);
return 0;
}
@ -491,7 +511,6 @@ DEFAULT_TITLE_MACRO(action_get_core_manager_list, MENU_ENUM_LABEL_
DEFAULT_TITLE_MACRO(action_get_add_content_list, MENU_ENUM_LABEL_VALUE_ADD_CONTENT_LIST)
DEFAULT_TITLE_MACRO(action_get_configurations_list, MENU_ENUM_LABEL_VALUE_CONFIGURATIONS_LIST)
DEFAULT_TITLE_MACRO(action_get_core_options_list, MENU_ENUM_LABEL_VALUE_CORE_OPTIONS)
DEFAULT_TITLE_MACRO(action_get_load_recent_list, MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_HISTORY)
DEFAULT_TITLE_MACRO(action_get_quick_menu_list, MENU_ENUM_LABEL_VALUE_CONTENT_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_input_remapping_options_list, MENU_ENUM_LABEL_VALUE_CORE_INPUT_REMAPPING_OPTIONS)
DEFAULT_TITLE_MACRO(action_get_shader_options_list, MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS)
@ -575,10 +594,6 @@ DEFAULT_TITLE_MACRO(action_get_network_information_list, MENU_ENUM_LABEL_
DEFAULT_TITLE_MACRO(action_get_settings_list, MENU_ENUM_LABEL_VALUE_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_title_information_list, MENU_ENUM_LABEL_VALUE_INFORMATION_LIST)
DEFAULT_TITLE_MACRO(action_get_title_information, MENU_ENUM_LABEL_VALUE_INFORMATION)
DEFAULT_TITLE_MACRO(action_get_title_goto_favorites, MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES)
DEFAULT_TITLE_MACRO(action_get_title_goto_image, MENU_ENUM_LABEL_VALUE_GOTO_IMAGES)
DEFAULT_TITLE_MACRO(action_get_title_goto_music, MENU_ENUM_LABEL_VALUE_GOTO_MUSIC)
DEFAULT_TITLE_MACRO(action_get_title_goto_video, MENU_ENUM_LABEL_VALUE_GOTO_VIDEO)
DEFAULT_TITLE_MACRO(action_get_title_collection, MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB)
DEFAULT_TITLE_MACRO(action_get_title_deferred_core_list, MENU_ENUM_LABEL_VALUE_SUPPORTED_CORES)
DEFAULT_TITLE_MACRO(action_get_title_dropdown_resolution_item, MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION)
@ -656,6 +671,12 @@ DEFAULT_TITLE_MACRO(action_get_title_switch_gpu_profile, MENU_ENUM_LABE
DEFAULT_TITLE_MACRO(action_get_title_switch_backlight_control, MENU_ENUM_LABEL_VALUE_SWITCH_BACKLIGHT_CONTROL)
#endif
DEFAULT_TITLE_PLAYLIST_MACRO(action_get_title_deferred_history_list, MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_HISTORY)
DEFAULT_TITLE_PLAYLIST_MACRO(action_get_title_deferred_favorites_list, MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES)
DEFAULT_TITLE_PLAYLIST_MACRO(action_get_title_deferred_images_list, MENU_ENUM_LABEL_VALUE_GOTO_IMAGES)
DEFAULT_TITLE_PLAYLIST_MACRO(action_get_title_deferred_music_list, MENU_ENUM_LABEL_VALUE_GOTO_MUSIC)
DEFAULT_TITLE_PLAYLIST_MACRO(action_get_title_deferred_video_list, MENU_ENUM_LABEL_VALUE_GOTO_VIDEO)
static int action_get_title_generic(char *s, size_t len, const char *path,
const char *text)
{
@ -733,28 +754,36 @@ static int action_get_title_group_settings(const char *path, const char *label,
{
enum msg_hash_enums type;
enum msg_hash_enums val;
bool is_playlist_tab;
} title_info_list_t;
/* Note: MENU_ENUM_LABEL_HORIZONTAL_MENU *is* a playlist
* tab, but its actual title is set elsewhere - so treat
* it as a generic top-level item */
title_info_list_t info_list[] = {
{MENU_ENUM_LABEL_MAIN_MENU, MENU_ENUM_LABEL_VALUE_MAIN_MENU} ,
{MENU_ENUM_LABEL_HISTORY_TAB, MENU_ENUM_LABEL_VALUE_HISTORY_TAB} ,
{MENU_ENUM_LABEL_FAVORITES_TAB, MENU_ENUM_LABEL_VALUE_FAVORITES_TAB} ,
{MENU_ENUM_LABEL_IMAGES_TAB, MENU_ENUM_LABEL_VALUE_IMAGES_TAB } ,
{MENU_ENUM_LABEL_MUSIC_TAB, MENU_ENUM_LABEL_VALUE_MUSIC_TAB } ,
{MENU_ENUM_LABEL_VIDEO_TAB, MENU_ENUM_LABEL_VALUE_VIDEO_TAB } ,
{MENU_ENUM_LABEL_SETTINGS_TAB, MENU_ENUM_LABEL_VALUE_SETTINGS_TAB } ,
{MENU_ENUM_LABEL_PLAYLISTS_TAB, MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB} ,
{MENU_ENUM_LABEL_ADD_TAB, MENU_ENUM_LABEL_VALUE_ADD_TAB } ,
{MENU_ENUM_LABEL_EXPLORE_TAB, MENU_ENUM_LABEL_VALUE_EXPLORE_TAB } ,
{MENU_ENUM_LABEL_NETPLAY_TAB, MENU_ENUM_LABEL_VALUE_NETPLAY_TAB } ,
{MENU_ENUM_LABEL_HORIZONTAL_MENU, MENU_ENUM_LABEL_VALUE_HORIZONTAL_MENU },
{MENU_ENUM_LABEL_MAIN_MENU, MENU_ENUM_LABEL_VALUE_MAIN_MENU, false },
{MENU_ENUM_LABEL_HISTORY_TAB, MENU_ENUM_LABEL_VALUE_HISTORY_TAB, true },
{MENU_ENUM_LABEL_FAVORITES_TAB, MENU_ENUM_LABEL_VALUE_FAVORITES_TAB, true },
{MENU_ENUM_LABEL_IMAGES_TAB, MENU_ENUM_LABEL_VALUE_IMAGES_TAB, true },
{MENU_ENUM_LABEL_MUSIC_TAB, MENU_ENUM_LABEL_VALUE_MUSIC_TAB, true },
{MENU_ENUM_LABEL_VIDEO_TAB, MENU_ENUM_LABEL_VALUE_VIDEO_TAB, true },
{MENU_ENUM_LABEL_SETTINGS_TAB, MENU_ENUM_LABEL_VALUE_SETTINGS_TAB, false },
{MENU_ENUM_LABEL_PLAYLISTS_TAB, MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB, false },
{MENU_ENUM_LABEL_ADD_TAB, MENU_ENUM_LABEL_VALUE_ADD_TAB, false },
{MENU_ENUM_LABEL_EXPLORE_TAB, MENU_ENUM_LABEL_VALUE_EXPLORE_TAB, false },
{MENU_ENUM_LABEL_NETPLAY_TAB, MENU_ENUM_LABEL_VALUE_NETPLAY_TAB, false },
{MENU_ENUM_LABEL_HORIZONTAL_MENU, MENU_ENUM_LABEL_VALUE_HORIZONTAL_MENU, false },
};
for (i = 0; i < ARRAY_SIZE(info_list); i++)
{
if (string_is_equal(label, msg_hash_to_str(info_list[i].type)))
{
strlcpy(s, msg_hash_to_str(info_list[i].val), len);
if (info_list[i].is_playlist_tab)
action_get_title_fill_playlist_default(
s, info_list[i].val, len);
else
strlcpy(s, msg_hash_to_str(info_list[i].val), len);
return 0;
}
}
@ -858,10 +887,11 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_DEFERRED_MIDI_SETTINGS_LIST, action_get_midi_settings_list},
{MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_LIST, action_get_download_core_content_list},
{MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_SUBDIR_LIST, action_get_download_core_content_list},
{MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST, action_get_title_goto_favorites},
{MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST, action_get_title_goto_image},
{MENU_ENUM_LABEL_DEFERRED_MUSIC_LIST, action_get_title_goto_music},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST, action_get_title_goto_video},
{MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY, action_get_title_deferred_history_list},
{MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST, action_get_title_deferred_favorites_list},
{MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST, action_get_title_deferred_images_list},
{MENU_ENUM_LABEL_DEFERRED_MUSIC_LIST, action_get_title_deferred_music_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST, action_get_title_deferred_video_list},
{MENU_ENUM_LABEL_DEFERRED_DRIVER_SETTINGS_LIST, action_get_driver_settings_list},
{MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST, action_get_audio_settings_list},
{MENU_ENUM_LABEL_DEFERRED_AUDIO_RESAMPLER_SETTINGS_LIST, action_get_audio_resampler_settings_list},
@ -1002,8 +1032,6 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
action_get_add_content_list},
{MENU_ENUM_LABEL_CORE_OPTIONS,
action_get_core_options_list},
{MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY,
action_get_load_recent_list},
{MENU_ENUM_LABEL_CONTENT_SETTINGS,
action_get_quick_menu_list},
{MENU_ENUM_LABEL_CORE_INPUT_REMAPPING_OPTIONS,
@ -1305,7 +1333,7 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
BIND_ACTION_GET_TITLE(cbs, action_get_core_options_list);
break;
case MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY:
BIND_ACTION_GET_TITLE(cbs, action_get_load_recent_list);
BIND_ACTION_GET_TITLE(cbs, action_get_title_deferred_history_list);
break;
case MENU_ENUM_LABEL_CONTENT_SETTINGS:
BIND_ACTION_GET_TITLE(cbs, action_get_quick_menu_list);

View File

@ -2756,7 +2756,7 @@ static INLINE void materialui_kill_scroll_animation(
static bool materialui_render_process_entry_default(
materialui_handle_t* mui,
materialui_node_t *node,
size_t entry_idx, size_t selection,
size_t entry_idx, size_t selection, size_t playlist_idx,
bool first_entry_found, bool last_entry_found,
unsigned thumbnail_upscale_threshold,
bool network_on_demand_thumbnails)
@ -2775,7 +2775,7 @@ static bool materialui_render_process_entry_default(
static bool materialui_render_process_entry_playlist_thumb_list(
materialui_handle_t* mui,
materialui_node_t *node,
size_t entry_idx, size_t selection,
size_t entry_idx, size_t selection, size_t playlist_idx,
bool first_entry_found, bool last_entry_found,
unsigned thumbnail_upscale_threshold,
bool network_on_demand_thumbnails)
@ -2786,15 +2786,15 @@ static bool materialui_render_process_entry_playlist_thumb_list(
* and free thumbnails for all off-screen entries */
if (mui->secondary_thumbnail_enabled)
gfx_thumbnail_process_streams(
mui->thumbnail_path_data, mui->playlist, entry_idx,
&node->thumbnails.primary, &node->thumbnails.secondary,
on_screen,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
mui->thumbnail_path_data, mui->playlist, playlist_idx,
&node->thumbnails.primary, &node->thumbnails.secondary,
on_screen,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
else
gfx_thumbnail_process_stream(
mui->thumbnail_path_data, GFX_THUMBNAIL_RIGHT,
mui->playlist, entry_idx, &node->thumbnails.primary,
mui->playlist, playlist_idx, &node->thumbnails.primary,
on_screen,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
@ -2810,7 +2810,7 @@ static bool materialui_render_process_entry_playlist_thumb_list(
static bool materialui_render_process_entry_playlist_dual_icon(
materialui_handle_t* mui,
materialui_node_t *node,
size_t entry_idx, size_t selection,
size_t entry_idx, size_t selection, size_t playlist_idx,
bool first_entry_found, bool last_entry_found,
unsigned thumbnail_upscale_threshold,
bool network_on_demand_thumbnails)
@ -2822,11 +2822,11 @@ static bool materialui_render_process_entry_playlist_dual_icon(
* > Note that secondary thumbnail is force
* enabled in dual icon mode */
gfx_thumbnail_process_streams(
mui->thumbnail_path_data, mui->playlist, entry_idx,
&node->thumbnails.primary, &node->thumbnails.secondary,
on_screen,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
mui->thumbnail_path_data, mui->playlist, playlist_idx,
&node->thumbnails.primary, &node->thumbnails.secondary,
on_screen,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
/* Always return true - every entry must
* be processed */
@ -2839,7 +2839,7 @@ static bool materialui_render_process_entry_playlist_dual_icon(
static bool materialui_render_process_entry_playlist_desktop(
materialui_handle_t* mui,
materialui_node_t *node,
size_t entry_idx, size_t selection,
size_t entry_idx, size_t selection, size_t playlist_idx,
bool first_entry_found, bool last_entry_found,
unsigned thumbnail_upscale_threshold,
bool network_on_demand_thumbnails)
@ -2862,11 +2862,11 @@ static bool materialui_render_process_entry_playlist_desktop(
* > Note that secondary thumbnail is force
* enabled */
gfx_thumbnail_process_streams(
mui->thumbnail_path_data, mui->playlist, entry_idx,
&node->thumbnails.primary, &node->thumbnails.secondary,
is_on_screen,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
mui->thumbnail_path_data, mui->playlist, playlist_idx,
&node->thumbnails.primary, &node->thumbnails.secondary,
is_on_screen,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
/* If this is *not* the currently selected
* entry, then our work is done */
@ -2929,7 +2929,7 @@ static bool materialui_render_process_entry_playlist_desktop(
int n;
/* Read playlist entry */
playlist_get_index(mui->playlist, selection, &entry);
playlist_get_index(mui->playlist, playlist_idx, &entry);
/* Sanity check */
if (!entry)
@ -2956,7 +2956,7 @@ static bool materialui_render_process_entry_playlist_desktop(
{
if (entry->runtime_status == PLAYLIST_RUNTIME_UNKNOWN)
runtime_update_playlist(
mui->playlist, selection,
mui->playlist, playlist_idx,
directory_runtime_log,
directory_playlist,
(runtime_type == PLAYLIST_RUNTIME_PER_CORE),
@ -3024,7 +3024,7 @@ static bool materialui_render_process_entry_playlist_desktop(
static bool (*materialui_render_process_entry)(
materialui_handle_t* mui,
materialui_node_t *node,
size_t entry_idx, size_t selection,
size_t entry_idx, size_t selection, size_t playlist_idx,
bool first_entry_found, bool last_entry_found,
unsigned thumbnail_upscale_threshold,
bool network_on_demand_thumbnails) = materialui_render_process_entry_default;
@ -3285,6 +3285,7 @@ static void materialui_render(void *data,
* for the current entry */
if (!materialui_render_process_entry(
mui, node, i, selection,
list->list[i].entry_idx,
first_entry_found, last_entry_found,
thumbnail_upscale_threshold,
network_on_demand_thumbnails))
@ -7658,11 +7659,22 @@ static void materialui_populate_entries(
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD));
}
/* If this is a playlist, then cache it */
/* If this is a *valid* playlist, then cache it
* Note: Empty playlists have a 'no entries available'
* message as the first item - thus a playlist is
* valid if the first item is of the correct
* FILE_TYPE_RPL_ENTRY type */
mui->playlist = NULL;
if (mui->is_playlist)
mui->playlist = playlist_get_cached();
else
mui->playlist = NULL;
{
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
size_t list_size = menu_entries_get_size();
if (list &&
(list_size > 0) &&
(list->list[0].type == FILE_TYPE_RPL_ENTRY))
mui->playlist = playlist_get_cached();
}
/* Update navigation bar tabs
* > Note: We do this regardless of whether

View File

@ -151,6 +151,8 @@ static void *ozone_init(void **userdata, bool video_is_threaded)
ozone->show_thumbnail_bar = false;
ozone->dimensions.sidebar_width = 0.0f;
ozone->num_search_terms_old = 0;
ozone->thumbnail_path_data = gfx_thumbnail_path_init();
if (!ozone->thumbnail_path_data)
goto error;
@ -2009,9 +2011,24 @@ static void ozone_set_thumbnail_content(void *data, const char *s)
/* Playlist content */
if (string_is_empty(s))
{
size_t selection = menu_navigation_get_selection();
size_t selection = menu_navigation_get_selection();
size_t list_size = menu_entries_get_size();
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
bool playlist_valid = false;
size_t playlist_index = selection;
/* Get playlist index corresponding
* to the selected entry */
if (list &&
(selection < list_size) &&
(list->list[selection].type == FILE_TYPE_RPL_ENTRY))
{
playlist_valid = true;
playlist_index = list->list[selection].entry_idx;
}
gfx_thumbnail_set_content_playlist(ozone->thumbnail_path_data,
playlist_get_cached(), selection);
playlist_valid ? playlist_get_cached() : NULL, playlist_index);
}
}
else if (ozone->is_db_manager_list)
@ -2525,7 +2542,13 @@ static void ozone_set_header(ozone_handle_t *ozone)
ozone_node_t *node = (ozone_node_t*) file_list_get_userdata_at_offset(ozone->horizontal_list, ozone->categories_selection_ptr - ozone->system_tab_end-1);
if (node && node->console_name)
{
strlcpy(ozone->title, node->console_name, sizeof(ozone->title));
/* Add current search terms */
menu_driver_search_append_terms_string(
ozone->title, sizeof(ozone->title));
}
}
}
@ -2605,6 +2628,56 @@ static void ozone_populate_entries(void *data, const char *path, const char *lab
{
menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
ozone_selection_changed(ozone, false);
/* Handle playlist searches
* (Ozone is a fickle beast...) */
if (ozone->is_playlist)
{
struct string_list *menu_search_terms =
menu_driver_search_get_terms();
size_t num_search_terms =
menu_search_terms ? menu_search_terms->size : 0;
if (ozone->num_search_terms_old != num_search_terms)
{
/* Refresh thumbnails */
ozone_unload_thumbnail_textures(ozone);
if (gfx_thumbnail_is_enabled(ozone->thumbnail_path_data, GFX_THUMBNAIL_RIGHT) ||
gfx_thumbnail_is_enabled(ozone->thumbnail_path_data, GFX_THUMBNAIL_LEFT))
{
ozone_set_thumbnail_content(ozone, "");
ozone_update_thumbnail_image(ozone);
}
/* If we are currently inside an empty
* playlist, return to the sidebar */
if (!ozone->cursor_in_sidebar)
{
size_t list_size = menu_entries_get_size();
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
uintptr_t animation_tag = (uintptr_t)&ozone->animations.cursor_alpha;
bool goto_sidebar = false;
if (!list || (list->size < 1))
goto_sidebar = true;
if (!goto_sidebar &&
(list->list[0].type != FILE_TYPE_RPL_ENTRY))
goto_sidebar = true;
if (goto_sidebar)
{
gfx_animation_kill_by_tag(&animation_tag);
ozone->empty_playlist = true;
ozone_go_to_sidebar(ozone, animation_tag);
}
}
ozone->num_search_terms_old = num_search_terms;
}
}
return;
}
@ -3329,6 +3402,7 @@ static enum menu_action ozone_parse_menu_entry_action(
break;
case MENU_ACTION_LEFT:
ozone->cursor_mode = false;
if (ozone->cursor_in_sidebar)
{
new_action = MENU_ACTION_ACCESSIBILITY_SPEAK_TITLE;
@ -3365,6 +3439,18 @@ static enum menu_action ozone_parse_menu_entry_action(
break;
case MENU_ACTION_CANCEL:
ozone->cursor_mode = false;
/* If this is a playlist, handle 'backing out'
* of a search, if required */
if (ozone->is_playlist)
{
struct string_list *menu_search_terms = menu_driver_search_get_terms();
if (menu_search_terms &&
(menu_search_terms->size > 0))
break;
}
if (ozone->cursor_in_sidebar)
{
/* Go back to main menu tab */
@ -3573,7 +3659,22 @@ void ozone_update_content_metadata(ozone_handle_t *ozone)
if (ozone->is_playlist && playlist)
{
const char *core_label = NULL;
const char *core_label = NULL;
const struct playlist_entry *entry = NULL;
size_t list_size = menu_entries_get_size();
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
bool playlist_valid = false;
size_t playlist_index = selection;
/* Get playlist index corresponding
* to the selected entry */
if (list &&
(selection < list_size) &&
(list->list[selection].type == FILE_TYPE_RPL_ENTRY))
{
playlist_valid = true;
playlist_index = list->list[selection].entry_idx;
}
/* Fill core name */
if (!core_name || string_is_equal(core_name, "DETECT"))
@ -3597,15 +3698,15 @@ void ozone_update_content_metadata(ozone_handle_t *ozone)
ozone->selection_core_name_lines = 1;
/* Fill play time if applicable */
if (content_runtime_log || content_runtime_log_aggr)
if (playlist_valid &&
(content_runtime_log || content_runtime_log_aggr))
playlist_get_index(playlist, playlist_index, &entry);
if (entry)
{
const struct playlist_entry *entry = NULL;
playlist_get_index(playlist, selection, &entry);
if (entry->runtime_status == PLAYLIST_RUNTIME_UNKNOWN)
runtime_update_playlist(
playlist, selection,
playlist, playlist_index,
directory_runtime_log,
directory_playlist,
(runtime_type == PLAYLIST_RUNTIME_PER_CORE),

View File

@ -209,6 +209,7 @@ struct ozone_handle
bool is_playlist;
bool is_playlist_old;
size_t num_search_terms_old;
bool empty_playlist;

View File

@ -4959,13 +4959,29 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load)
rgui->entry_has_thumbnail = false;
rgui->entry_has_left_thumbnail = false;
rgui->thumbnail_load_pending = false;
/* Update thumbnail content/path */
if ((rgui->show_fs_thumbnail || rgui_inline_thumbnails)
&& rgui->is_playlist)
{
size_t selection = menu_navigation_get_selection();
size_t list_size = menu_entries_get_size();
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
bool playlist_valid = false;
size_t playlist_index = selection;
/* Get playlist index corresponding
* to the selected entry */
if (list &&
(selection < list_size) &&
(list->list[selection].type == FILE_TYPE_RPL_ENTRY))
{
playlist_valid = true;
playlist_index = list->list[selection].entry_idx;
}
if (gfx_thumbnail_set_content_playlist(rgui->thumbnail_path_data,
playlist_get_cached(), menu_navigation_get_selection()))
playlist_valid ? playlist_get_cached() : NULL, playlist_index))
{
if (gfx_thumbnail_is_enabled(rgui->thumbnail_path_data, GFX_THUMBNAIL_RIGHT))
has_thumbnail = gfx_thumbnail_update_path(rgui->thumbnail_path_data, GFX_THUMBNAIL_RIGHT);
@ -4976,7 +4992,7 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load)
has_thumbnail;
}
}
/* Check whether thumbnails should be loaded */
if (has_thumbnail)
{

View File

@ -1226,9 +1226,24 @@ static void xmb_set_thumbnail_content(void *data, const char *s)
/* Playlist content */
if (string_is_empty(s))
{
size_t selection = menu_navigation_get_selection();
size_t selection = menu_navigation_get_selection();
size_t list_size = menu_entries_get_size();
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
bool playlist_valid = false;
size_t playlist_index = selection;
/* Get playlist index corresponding
* to the selected entry */
if (list &&
(selection < list_size) &&
(list->list[selection].type == FILE_TYPE_RPL_ENTRY))
{
playlist_valid = true;
playlist_index = list->list[selection].entry_idx;
}
gfx_thumbnail_set_content_playlist(xmb->thumbnail_path_data,
playlist_get_cached(), selection);
playlist_valid ? playlist_get_cached() : NULL, playlist_index);
xmb->fullscreen_thumbnails_available = true;
}
}
@ -1262,7 +1277,6 @@ static void xmb_set_thumbnail_content(void *data, const char *s)
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
xmb_node_t *node = (xmb_node_t*)file_list_get_userdata_at_offset(selection_buf, selection);
if (node)
{
menu_entry_init(&entry);
@ -1831,6 +1845,7 @@ static void xmb_set_title(xmb_handle_t *xmb)
else
{
const char *path = NULL;
menu_entries_get_at_offset(
xmb->horizontal_list,
xmb->categories_selection_ptr - (xmb->system_tab_end + 1),
@ -1841,6 +1856,10 @@ static void xmb_set_title(xmb_handle_t *xmb)
fill_pathname_base_noext(
xmb->title_name, path, sizeof(xmb->title_name));
/* Add current search terms */
menu_driver_search_append_terms_string(
xmb->title_name, sizeof(xmb->title_name));
}
}
@ -2399,6 +2418,8 @@ static void xmb_populate_entries(void *data,
xmb->is_quick_menu = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_SETTINGS));
xmb_set_title(xmb);
if (menu_driver_ctl(RARCH_MENU_CTL_IS_PREVENT_POPULATE, NULL))
{
xmb_selection_pointer_changed(xmb, false);
@ -2406,8 +2427,6 @@ static void xmb_populate_entries(void *data,
return;
}
xmb_set_title(xmb);
if (xmb->categories_selection_ptr != xmb->categories_active_idx_old)
xmb_list_switch(xmb);
else

View File

@ -1394,11 +1394,13 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
settings_t *settings = config_get_ptr();
bool show_inline_core_name = false;
const char *menu_driver = menu_driver_ident();
struct string_list *search_terms = menu_driver_search_get_terms();
unsigned pl_show_inline_core_name = settings->uints.playlist_show_inline_core_name;
bool pl_show_sublabels = settings->bools.playlist_show_sublabels;
void (*sanitization)(char*);
label_spacer[0] = '\0';
info->count = 0;
if (list_size == 0)
goto error;
@ -1482,7 +1484,9 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
for (i = 0; i < list_size; i++)
{
char menu_entry_label[PATH_MAX_LENGTH];
const struct playlist_entry *entry = NULL;
const struct playlist_entry *entry = NULL;
const char *entry_path = NULL;
bool entry_valid = true;
menu_entry_label[0] = '\0';
@ -1516,8 +1520,7 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
}
}
menu_entries_append_enum(info->list, menu_entry_label, entry->path,
MENU_ENUM_LABEL_PLAYLIST_ENTRY, FILE_TYPE_RPL_ENTRY, 0, i);
entry_path = entry->path;
}
else
{
@ -1532,13 +1535,38 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
else if (!string_is_empty(entry->core_name))
strlcpy(menu_entry_label, entry->core_name, sizeof(menu_entry_label));
menu_entries_append_enum(info->list, menu_entry_label, path_playlist,
MENU_ENUM_LABEL_PLAYLIST_ENTRY, FILE_TYPE_RPL_ENTRY, 0, i);
entry_path = path_playlist;
}
info->count++;
/* Check whether entry matches search terms,
* if required */
if (search_terms)
{
size_t j;
for (j = 0; j < search_terms->size; j++)
{
const char *search_term = search_terms->elems[j].data;
if (!string_is_empty(search_term) &&
!strcasestr(menu_entry_label, search_term))
{
entry_valid = false;
break;
}
}
}
/* Add menu entry */
if (entry_valid && menu_entries_append_enum(info->list,
menu_entry_label, entry_path,
MENU_ENUM_LABEL_PLAYLIST_ENTRY, FILE_TYPE_RPL_ENTRY, 0, i))
info->count++;
}
if (info->count < 1)
goto error;
return 0;
error:

View File

@ -28,6 +28,7 @@
#include <retro_common_api.h>
#include <formats/image.h>
#include <queues/task_queue.h>
#include <lists/string_list.h>
#include "menu_defines.h"
#include "menu_input.h"
@ -330,6 +331,12 @@ typedef struct
{
unsigned unsigned_var;
} scratchpad;
/* Holds a list of search terms that may be
* used to filter the currently displayed
* menu list */
struct string_list *search_terms;
const menu_ctx_driver_t *driver_ctx;
void *userdata;
} menu_handle_t;
@ -478,6 +485,14 @@ void menu_display_handle_wallpaper_upload(retro_task_t *task,
void menu_explore_free(void);
#endif
bool menu_driver_search_push(const char *search_term);
bool menu_driver_search_pop(void);
void menu_driver_search_clear(void);
struct string_list *menu_driver_search_get_terms(void);
/* Convenience function: Appends list of current
* search terms to specified string */
void menu_driver_search_append_terms_string(char *s, size_t len);
menu_handle_t *menu_driver_get_ptr(void);
enum action_iterate_type

View File

@ -379,7 +379,7 @@ void playlist_get_index(playlist_t *playlist,
size_t idx,
const struct playlist_entry **entry)
{
if (!playlist || !entry)
if (!playlist || !entry || (idx >= playlist->size))
return;
*entry = &playlist->entries[idx];

View File

@ -7279,6 +7279,139 @@ static void menu_driver_list_free(
}
}
bool menu_driver_search_push(const char *search_term)
{
struct rarch_state *p_rarch = &rarch_st;
menu_handle_t *menu = p_rarch->menu_driver_data;
union string_list_elem_attr attr;
if (!menu || string_is_empty(search_term))
return false;
/* Initialise list, if required */
if (!menu->search_terms)
{
menu->search_terms = string_list_new();
if (!menu->search_terms)
return false;
}
/* Check whether search term already exists */
if (string_list_find_elem(menu->search_terms, search_term))
return false;
/* Add search term */
attr.i = 0;
if (!string_list_append(menu->search_terms,
search_term, attr))
return false;
return true;
}
bool menu_driver_search_pop(void)
{
struct rarch_state *p_rarch = &rarch_st;
menu_handle_t *menu = p_rarch->menu_driver_data;
union string_list_elem_attr attr = {0};
size_t element_index;
if (!menu || !menu->search_terms)
return false;
/* If we have a 'broken' list, free it
* (this cannot actually happen, but if
* we didn't free the list in this case
* then menu navigation could get 'stuck') */
if ((menu->search_terms->size < 1) ||
!menu->search_terms->elems)
goto free_list;
/* Get index of last element in the list */
element_index = menu->search_terms->size - 1;
/* If this is the only element, free the
* entire list */
if (element_index == 0)
goto free_list;
/* Otherwise, 'reset' the element... */
if (menu->search_terms->elems[element_index].data)
{
free(menu->search_terms->elems[element_index].data);
menu->search_terms->elems[element_index].data = NULL;
}
if (menu->search_terms->elems[element_index].userdata)
{
free(menu->search_terms->elems[element_index].userdata);
menu->search_terms->elems[element_index].userdata = NULL;
}
menu->search_terms->elems[element_index].attr = attr;
/* ...and decrement the list size */
menu->search_terms->size--;
return true;
free_list:
string_list_free(menu->search_terms);
menu->search_terms = NULL;
return true;
}
void menu_driver_search_clear(void)
{
struct rarch_state *p_rarch = &rarch_st;
menu_handle_t *menu = p_rarch->menu_driver_data;
if (!menu)
return;
if (menu->search_terms)
string_list_free(menu->search_terms);
menu->search_terms = NULL;
}
struct string_list *menu_driver_search_get_terms(void)
{
struct rarch_state *p_rarch = &rarch_st;
menu_handle_t *menu = p_rarch->menu_driver_data;
if (!menu)
return NULL;
return menu->search_terms;
}
/* Convenience function: Appends list of current
* search terms to specified string */
void menu_driver_search_append_terms_string(char *s, size_t len)
{
struct rarch_state *p_rarch = &rarch_st;
menu_handle_t *menu = p_rarch->menu_driver_data;
if (menu &&
menu->search_terms &&
(menu->search_terms->size > 0) &&
s)
{
char search_str[512];
search_str[0] = '\0';
string_list_join_concat(search_str, sizeof(search_str),
menu->search_terms, " > ");
strlcat(s, " > ", len);
strlcat(s, search_str, len);
}
}
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
{
struct rarch_state *p_rarch = &rarch_st;
@ -7400,6 +7533,8 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
free(p_rarch->menu_driver_data->core_buf);
p_rarch->menu_driver_data->core_buf = NULL;
menu_driver_search_clear();
menu_st->entries.need_refresh = false;
menu_st->entries.nonblocking_refresh = false;
menu_st->entries.begin = 0;
@ -11892,18 +12027,68 @@ bool gfx_widgets_ready(void)
static void menu_input_search_cb(void *userdata, const char *str)
{
size_t idx = 0;
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
const char *label = NULL;
unsigned type = MENU_SETTINGS_NONE;
bool is_playlist = false;
if (!selection_buf)
return;
if (string_is_empty(str))
goto end;
if (str && *str && file_list_search(selection_buf, str, &idx))
/* Determine whether we are currently
* viewing a playlist */
menu_entries_get_last_stack(NULL,
&label, &type,
NULL, NULL);
is_playlist = (type == MENU_SETTING_HORIZONTAL_MENU) ||
(type == MENU_HISTORY_TAB) ||
(type == MENU_FAVORITES_TAB) ||
(type == MENU_IMAGES_TAB) ||
(type == MENU_MUSIC_TAB) ||
(type == MENU_VIDEO_TAB) ||
(type == FILE_TYPE_PLAYLIST_COLLECTION);
if (!is_playlist && !string_is_empty(label))
is_playlist = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MUSIC_LIST)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST));
if (is_playlist)
{
menu_navigation_set_selection(idx);
menu_driver_navigation_set(true);
/* Add search term */
if (menu_driver_search_push(str))
{
bool refresh = false;
/* Reset navigation pointer */
menu_navigation_set_selection(0);
menu_driver_navigation_set(false);
/* Refresh menu */
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
}
}
/* Perform a regular search: jump to the
* first matching entry */
else
{
size_t idx = 0;
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
if (!selection_buf)
goto end;
if (file_list_search(selection_buf, str, &idx))
{
menu_navigation_set_selection(idx);
menu_driver_navigation_set(true);
}
}
end:
menu_input_dialog_end();
}