From 20aff2a05aabfe1423b89682f44859e957080a77 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Fri, 24 May 2019 12:02:02 +0100 Subject: [PATCH] Add optional 'on demand' thumbnail downloads --- config.def.h | 3 + configuration.c | 1 + configuration.h | 1 + intl/msg_hash_lbl.h | 2 + intl/msg_hash_us.h | 8 ++ menu/cbs/menu_cbs_ok.c | 6 +- menu/cbs/menu_cbs_sublabel.c | 4 + menu/drivers/ozone/ozone.c | 38 ++++++ menu/drivers/rgui.c | 42 +++++- menu/drivers/xmb.c | 43 +++++- menu/menu_displaylist.c | 5 + menu/menu_setting.c | 14 ++ msg_hash.h | 1 + tasks/task_pl_thumbnail_download.c | 201 +++++++++++++++++++++++++---- tasks/tasks_internal.h | 7 +- 15 files changed, 335 insertions(+), 41 deletions(-) diff --git a/config.def.h b/config.def.h index 18e8235a03..49d47b36c2 100644 --- a/config.def.h +++ b/config.def.h @@ -730,6 +730,9 @@ static const uint16_t network_cmd_port = 55355; static const bool stdin_cmd_enable = false; static const uint16_t network_remote_base_port = 55400; + +static const bool network_on_demand_thumbnails = false; + /* Number of entries that will be kept in content history playlist file. */ static const unsigned default_content_history_size = 100; diff --git a/configuration.c b/configuration.c index 82e4b142d6..4657a53dba 100644 --- a/configuration.c +++ b/configuration.c @@ -1380,6 +1380,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("netplay_request_device_p14", &settings->bools.netplay_request_devices[13], true, false, false); SETTING_BOOL("netplay_request_device_p15", &settings->bools.netplay_request_devices[14], true, false, false); SETTING_BOOL("netplay_request_device_p16", &settings->bools.netplay_request_devices[15], true, false, false); + SETTING_BOOL("network_on_demand_thumbnails", &settings->bools.network_on_demand_thumbnails, true, network_on_demand_thumbnails, false); #endif SETTING_BOOL("input_descriptor_label_show", &settings->bools.input_descriptor_label_show, true, input_descriptor_label_show, false); SETTING_BOOL("input_descriptor_hide_unbound", &settings->bools.input_descriptor_hide_unbound, true, input_descriptor_hide_unbound, false); diff --git a/configuration.h b/configuration.h index 9eeea244fa..49fe5db4f8 100644 --- a/configuration.h +++ b/configuration.h @@ -231,6 +231,7 @@ typedef struct settings /* Network */ bool network_buildbot_auto_extract_archive; + bool network_on_demand_thumbnails; /* UI */ bool ui_menubar_enable; diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 8769c39007..abde58a036 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -771,6 +771,8 @@ MSG_HASH(MENU_ENUM_LABEL_NETWORK_REMOTE_USER_1_ENABLE, "network_remote_user_1_enable") MSG_HASH(MENU_ENUM_LABEL_NETWORK_REMOTE_USER_LAST_ENABLE, "network_remote_user_last_enable") +MSG_HASH(MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS, + "network_on_demand_thumbnails") MSG_HASH(MENU_ENUM_LABEL_NETWORK_SETTINGS, "network_settings") MSG_HASH(MENU_ENUM_LABEL_NO_ACHIEVEMENTS_TO_DISPLAY, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 734347c80b..0c674fa76c 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1920,6 +1920,14 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_NETWORK_REMOTE_PORT, "Network Remote Base Port" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_NETWORK_ON_DEMAND_THUMBNAILS, + "On-Demand Thumbnail Downloads" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETWORK_ON_DEMAND_THUMBNAILS, + "Automatically download missing thumbnail images while browsing playlists. Has a severe performance impact." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETWORK_SETTINGS, "Network" diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index c9142c31c8..ead73e314b 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -5397,7 +5397,6 @@ static int action_ok_pl_entry_content_thumbnails(const char *path, char system[PATH_MAX_LENGTH]; menu_handle_t *menu = NULL; playlist_t *playlist = playlist_get_cached(); - settings_t *settings = config_get_ptr(); system[0] = '\0'; @@ -5410,8 +5409,9 @@ static int action_ok_pl_entry_content_thumbnails(const char *path, menu_driver_get_thumbnail_system(system, sizeof(system)); task_push_pl_entry_thumbnail_download(system, - settings->paths.directory_thumbnails, - playlist, menu->rpl_entry_selection_ptr); + playlist, menu->rpl_entry_selection_ptr, + true, false); + return 0; } #endif diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index d2ae08066a..3b9f89febf 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -129,6 +129,7 @@ default_sublabel_macro(action_bind_sublabel_midi_settings_list, MENU_ 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_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) default_sublabel_macro(action_bind_sublabel_recording_settings_list, MENU_ENUM_SUBLABEL_RECORDING_SETTINGS) default_sublabel_macro(action_bind_sublabel_frame_throttle_settings_list, MENU_ENUM_SUBLABEL_FRAME_THROTTLE_SETTINGS) @@ -2382,6 +2383,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_NETWORK_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_network_settings_list); break; + case MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_network_on_demand_thumbnails); + break; case MENU_ENUM_LABEL_USER_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_user_settings_list); break; diff --git a/menu/drivers/ozone/ozone.c b/menu/drivers/ozone/ozone.c index 05dd797197..ed24fae482 100644 --- a/menu/drivers/ozone/ozone.c +++ b/menu/drivers/ozone/ozone.c @@ -398,6 +398,13 @@ static void ozone_update_thumbnail_image(void *data) const char *left_thumbnail_path = NULL; bool supports_rgba = video_driver_supports_rgba(); + /* Have to wrap `thumbnails_missing` like this to silence + * brain dead `set but not used` warnings when networking + * is disabled... */ +#ifdef HAVE_NETWORKING + bool thumbnails_missing = false; +#endif + if (!ozone) return; @@ -408,7 +415,12 @@ static void ozone_update_thumbnail_image(void *data) supports_rgba, menu_display_handle_thumbnail_upload, NULL); else + { video_driver_texture_unload(&ozone->thumbnail); +#ifdef HAVE_NETWORKING + thumbnails_missing = true; +#endif + } } else video_driver_texture_unload(&ozone->thumbnail); @@ -420,10 +432,36 @@ static void ozone_update_thumbnail_image(void *data) supports_rgba, menu_display_handle_left_thumbnail_upload, NULL); else + { video_driver_texture_unload(&ozone->left_thumbnail); +#ifdef HAVE_NETWORKING + thumbnails_missing = true; +#endif + } } else video_driver_texture_unload(&ozone->left_thumbnail); + +#ifdef HAVE_NETWORKING + /* On demand thumbnail downloads */ + if (thumbnails_missing) + { + settings_t *settings = config_get_ptr(); + + if (!settings) + return; + + if (settings->bools.network_on_demand_thumbnails) + { + const char *system = NULL; + + if (menu_thumbnail_get_system(ozone->thumbnail_path_data, &system)) + task_push_pl_entry_thumbnail_download(system, + playlist_get_cached(), menu_navigation_get_selection(), + false, true); + } + } +#endif } static void ozone_refresh_thumbnail_image(void *data) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index cb6bf96083..bbd51ed6c7 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -1588,7 +1588,12 @@ static void process_wallpaper(rgui_t *rgui, struct texture_image *image) rgui->force_redraw = true; } -static bool request_thumbnail(thumbnail_t *thumbnail, enum menu_thumbnail_id thumbnail_id, uint32_t *queue_size, const char *path) +static bool request_thumbnail( + thumbnail_t *thumbnail, + enum menu_thumbnail_id thumbnail_id, + uint32_t *queue_size, + const char *path, + bool *file_missing) { /* Do nothing if current thumbnail path hasn't changed */ if (!string_is_empty(path) && !string_is_empty(thumbnail->path)) @@ -1619,8 +1624,10 @@ static bool request_thumbnail(thumbnail_t *thumbnail, enum menu_thumbnail_id thu return true; } } + else + *file_missing = true; } - + return false; } @@ -4157,10 +4164,11 @@ static void rgui_get_thumbnail_system(void *userdata, char *s, size_t len) strlcpy(s, system, len); } -static void rgui_load_current_thumbnails(rgui_t *rgui) +static void rgui_load_current_thumbnails(rgui_t *rgui, bool download_missing) { const char *thumbnail_path = NULL; const char *left_thumbnail_path = NULL; + bool thumbnails_missing = false; /* Right (or fullscreen) thumbnail */ if (menu_thumbnail_get_path(rgui->thumbnail_path_data, @@ -4168,7 +4176,10 @@ static void rgui_load_current_thumbnails(rgui_t *rgui) { rgui->entry_has_thumbnail = request_thumbnail( rgui->show_fs_thumbnail ? &fs_thumbnail : &mini_thumbnail, - MENU_THUMBNAIL_RIGHT, &rgui->thumbnail_queue_size, thumbnail_path); + MENU_THUMBNAIL_RIGHT, + &rgui->thumbnail_queue_size, + thumbnail_path, + &thumbnails_missing); } /* Left thumbnail @@ -4180,7 +4191,11 @@ static void rgui_load_current_thumbnails(rgui_t *rgui) MENU_THUMBNAIL_LEFT, &left_thumbnail_path)) { rgui->entry_has_left_thumbnail = request_thumbnail( - &mini_left_thumbnail, MENU_THUMBNAIL_LEFT, &rgui->left_thumbnail_queue_size, left_thumbnail_path); + &mini_left_thumbnail, + MENU_THUMBNAIL_LEFT, + &rgui->left_thumbnail_queue_size, + left_thumbnail_path, + &thumbnails_missing); } } @@ -4190,6 +4205,19 @@ static void rgui_load_current_thumbnails(rgui_t *rgui) /* Force a redraw (so 'entry_has_thumbnail' values are * applied immediately) */ rgui->force_redraw = true; + +#ifdef HAVE_NETWORKING + /* On demand thumbnail downloads */ + if (thumbnails_missing && download_missing) + { + const char *system = NULL; + + if (menu_thumbnail_get_system(rgui->thumbnail_path_data, &system)) + task_push_pl_entry_thumbnail_download(system, + playlist_get_cached(), menu_navigation_get_selection(), + false, true); + } +#endif } static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load) @@ -4224,7 +4252,7 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load) { /* Check whether thumbnails should be loaded immediately */ if ((settings->uints.menu_rgui_thumbnail_delay == 0) || force_load) - rgui_load_current_thumbnails(rgui); + rgui_load_current_thumbnails(rgui, settings->bools.network_on_demand_thumbnails); else { /* Schedule a delayed load */ @@ -4613,7 +4641,7 @@ static void rgui_frame(void *data, video_frame_info_t *video_info) * fullscreen thumbnail view is incredibly jarring...) */ if ((cpu_features_get_time_usec() - rgui->thumbnail_load_trigger_time) >= (settings->uints.menu_rgui_thumbnail_delay * 1000 * (rgui->show_fs_thumbnail ? 1.5f : 1.0f))) - rgui_load_current_thumbnails(rgui); + rgui_load_current_thumbnails(rgui, settings->bools.network_on_demand_thumbnails); } } diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 2b52ef1735..35befde564 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -1009,6 +1009,14 @@ static void xmb_update_thumbnail_image(void *data) xmb_handle_t *xmb = (xmb_handle_t*)data; const char *right_thumbnail_path = NULL; const char *left_thumbnail_path = NULL; + bool supports_rgba = video_driver_supports_rgba(); + + /* Have to wrap `thumbnails_missing` like this to silence + * brain dead `set but not used` warnings when networking + * is disabled... */ +#ifdef HAVE_NETWORKING + bool thumbnails_missing = false; +#endif if (!xmb) return; @@ -1017,10 +1025,15 @@ static void xmb_update_thumbnail_image(void *data) { if (filestream_exists(right_thumbnail_path)) task_push_image_load(right_thumbnail_path, - video_driver_supports_rgba(), + supports_rgba, menu_display_handle_thumbnail_upload, NULL); else + { video_driver_texture_unload(&xmb->thumbnail); +#ifdef HAVE_NETWORKING + thumbnails_missing = true; +#endif + } } else video_driver_texture_unload(&xmb->thumbnail); @@ -1029,13 +1042,39 @@ static void xmb_update_thumbnail_image(void *data) { if (filestream_exists(left_thumbnail_path)) task_push_image_load(left_thumbnail_path, - video_driver_supports_rgba(), + supports_rgba, menu_display_handle_left_thumbnail_upload, NULL); else + { video_driver_texture_unload(&xmb->left_thumbnail); +#ifdef HAVE_NETWORKING + thumbnails_missing = true; +#endif + } } else video_driver_texture_unload(&xmb->left_thumbnail); + +#ifdef HAVE_NETWORKING + /* On demand thumbnail downloads */ + if (thumbnails_missing) + { + settings_t *settings = config_get_ptr(); + + if (!settings) + return; + + if (settings->bools.network_on_demand_thumbnails) + { + const char *system = NULL; + + if (menu_thumbnail_get_system(xmb->thumbnail_path_data, &system)) + task_push_pl_entry_thumbnail_download(system, + playlist_get_cached(), menu_navigation_get_selection(), + false, true); + } + } +#endif } static unsigned xmb_get_system_tab(xmb_handle_t *xmb, unsigned i) diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 804ed4bd81..281f372dc8 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -3388,6 +3388,11 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct PARSE_ONLY_BOOL, false) != -1) count++; + if (menu_displaylist_parse_settings_enum(list, + MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS, + PARSE_ONLY_BOOL, false) != -1) + count++; + if (menu_displaylist_parse_settings_enum(list, MENU_ENUM_LABEL_UPDATER_SETTINGS, PARSE_ACTION, false) != -1) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index ced79304b1..9298e67320 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -13699,6 +13699,20 @@ static bool setting_append_list( general_read_handler, SD_FLAG_ADVANCED); #endif + CONFIG_BOOL( + list, list_info, + &settings->bools.network_on_demand_thumbnails, + MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS, + MENU_ENUM_LABEL_VALUE_NETWORK_ON_DEMAND_THUMBNAILS, + network_on_demand_thumbnails, + 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); #endif } END_SUB_GROUP(list, list_info, parent_group); diff --git a/msg_hash.h b/msg_hash.h index 11764c8be9..39925c6af2 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1660,6 +1660,7 @@ enum msg_hash_enums MENU_LABEL(STDIN_CMD_ENABLE), MENU_LABEL(NETWORK_REMOTE_ENABLE), MENU_LABEL(NETWORK_REMOTE_PORT), + MENU_LABEL(NETWORK_ON_DEMAND_THUMBNAILS), MENU_ENUM_LABEL_NETWORK_REMOTE_USER_1_ENABLE, diff --git a/tasks/task_pl_thumbnail_download.c b/tasks/task_pl_thumbnail_download.c index 84bdce31a9..ecf24e2538 100644 --- a/tasks/task_pl_thumbnail_download.c +++ b/tasks/task_pl_thumbnail_download.c @@ -28,6 +28,7 @@ #include "tasks_internal.h" #include "task_file_transfer.h" +#include "../configuration.h" #include "../file_path_special.h" #include "../playlist.h" @@ -62,9 +63,18 @@ typedef struct pl_thumb_handle size_t list_size; size_t list_index; unsigned type_idx; + bool overwrite; + bool right_thumbnail_exists; + bool left_thumbnail_exists; enum pl_thumb_status status; } pl_thumb_handle_t; +typedef struct pl_entry_id +{ + playlist_t *playlist; + size_t idx; +} pl_entry_id_t; + /*********************/ /* Utility Functions */ /*********************/ @@ -159,7 +169,7 @@ static bool get_thumbnail_paths( /* Download thumbnail of the current type for the current * playlist entry */ -static void download_pl_thumbnail(pl_thumb_handle_t *pl_thumb, bool overwrite) +static void download_pl_thumbnail(pl_thumb_handle_t *pl_thumb) { char path[PATH_MAX_LENGTH]; char url[2048]; @@ -171,7 +181,7 @@ static void download_pl_thumbnail(pl_thumb_handle_t *pl_thumb, bool overwrite) if (get_thumbnail_paths(pl_thumb, path, sizeof(path), url, sizeof(url))) { /* Only download missing thumbnails */ - if (!filestream_exists(path) || overwrite) + if (!filestream_exists(path) || pl_thumb->overwrite) { file_transfer_t *transf = (file_transfer_t*)calloc(1, sizeof(file_transfer_t)); if (!transf) @@ -228,17 +238,6 @@ static void free_pl_thumb_handle(pl_thumb_handle_t *pl_thumb, bool free_playlist pl_thumb = NULL; } -/* Callback: Refresh menu thumbnail display once - * download is complete */ -static void cb_task_pl_thumbnail_refresh_menu( - retro_task_t *task, void *task_data, - void *user_data, const char *err) -{ -#if defined(RARCH_INTERNAL) && defined(HAVE_MENU) - menu_driver_ctl(RARCH_MENU_CTL_REFRESH_THUMBNAIL_IMAGE, NULL); -#endif -} - /*******************************/ /* Playlist Thumbnail Download */ /*******************************/ @@ -345,7 +344,7 @@ static void task_pl_thumbnail_download_handler(retro_task_t *task) /* Download current thumbnail */ if (pl_thumb) - download_pl_thumbnail(pl_thumb, false); + download_pl_thumbnail(pl_thumb); /* Increment thumbnail type */ pl_thumb->type_idx++; @@ -368,18 +367,40 @@ task_finished: free_pl_thumb_handle(pl_thumb, true); } +static bool task_pl_thumbnail_finder(retro_task_t *task, void *user_data) +{ + pl_thumb_handle_t *pl_thumb = NULL; + + if (!task || !user_data) + return false; + + if (task->handler != task_pl_thumbnail_download_handler) + return false; + + pl_thumb = (pl_thumb_handle_t*)task->state; + if (!pl_thumb) + return false; + + return string_is_equal((const char*)user_data, pl_thumb->playlist_path); +} + bool task_push_pl_thumbnail_download( const char *system, const char *playlist_path) { + task_finder_data_t find_data; + settings_t *settings = config_get_ptr(); retro_task_t *task = task_init(); pl_thumb_handle_t *pl_thumb = (pl_thumb_handle_t*)calloc(1, sizeof(pl_thumb_handle_t)); const char *playlist_file = path_basename(playlist_path); /* Sanity check */ - if (!task || !pl_thumb || - string_is_empty(system) || + if (!settings || !task || !pl_thumb) + goto error; + + if (string_is_empty(system) || string_is_empty(playlist_path) || - string_is_empty(playlist_file)) + string_is_empty(playlist_file) || + string_is_empty(settings->paths.directory_thumbnails)) goto error; /* Only parse supported playlist types */ @@ -393,6 +414,14 @@ bool task_push_pl_thumbnail_download( string_is_equal(system, "images_history")) goto error; + /* Concurrent download of thumbnails for the same + * playlist is not allowed */ + find_data.func = task_pl_thumbnail_finder; + find_data.userdata = (void*)playlist_path; + + if (task_queue_find(&find_data)) + goto error; + /* Configure task */ task->handler = task_pl_thumbnail_download_handler; task->state = pl_thumb; @@ -403,12 +432,14 @@ bool task_push_pl_thumbnail_download( /* Configure handle */ pl_thumb->system = strdup(system); pl_thumb->playlist_path = strdup(playlist_path); + pl_thumb->dir_thumbnails = strdup(settings->paths.directory_thumbnails); pl_thumb->playlist = NULL; pl_thumb->thumbnail_path_data = NULL; pl_thumb->http_task = NULL; pl_thumb->list_size = 0; pl_thumb->list_index = 0; pl_thumb->type_idx = 1; + pl_thumb->overwrite = false; pl_thumb->status = PL_THUMB_BEGIN; task_queue_push(task); @@ -436,15 +467,62 @@ error: /* Playlist Entry Thumbnail Download */ /*************************************/ +static void cb_task_pl_entry_thumbnail_refresh_menu( + retro_task_t *task, void *task_data, + void *user_data, const char *err) +{ +#if defined(RARCH_INTERNAL) && defined(HAVE_MENU) + + pl_thumb_handle_t *pl_thumb = NULL; + const char *thumbnail_path = NULL; + const char *left_thumbnail_path = NULL; + bool do_refresh = false; + + if (!task) + return; + + pl_thumb = (pl_thumb_handle_t*)task->state; + + /* Only refresh if left/right thumbnails did not exist + * when the task began, but do exist now + * (with the caveat that we must also refresh if existing + * files have been overwritten) */ + + if (!pl_thumb->right_thumbnail_exists || pl_thumb->overwrite) + if (menu_thumbnail_update_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_RIGHT)) + if (menu_thumbnail_get_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_RIGHT, &thumbnail_path)) + do_refresh = filestream_exists(thumbnail_path); + + if (!do_refresh) + if (!pl_thumb->left_thumbnail_exists || pl_thumb->overwrite) + if (menu_thumbnail_update_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_LEFT)) + if (menu_thumbnail_get_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_LEFT, &left_thumbnail_path)) + do_refresh = filestream_exists(left_thumbnail_path); + + if (do_refresh) + menu_driver_ctl(RARCH_MENU_CTL_REFRESH_THUMBNAIL_IMAGE, NULL); + +#endif +} + +static void task_pl_entry_thumbnail_free(retro_task_t *task) +{ + pl_thumb_handle_t *pl_thumb = NULL; + + if (!task) + return; + + pl_thumb = (pl_thumb_handle_t*)task->state; + + free_pl_thumb_handle(pl_thumb, false); +} + static void task_pl_entry_thumbnail_download_handler(retro_task_t *task) { pl_thumb_handle_t *pl_thumb = NULL; if (!task) - { - free_pl_thumb_handle(pl_thumb, false); return; - } pl_thumb = (pl_thumb_handle_t*)task->state; @@ -458,7 +536,9 @@ static void task_pl_entry_thumbnail_download_handler(retro_task_t *task) { case PL_THUMB_BEGIN: { - const char *label = NULL; + const char *label = NULL; + const char *right_thumbnail_path = NULL; + const char *left_thumbnail_path = NULL; /* Initialise thumbnail path data */ pl_thumb->thumbnail_path_data = menu_thumbnail_path_init(); @@ -473,6 +553,18 @@ static void task_pl_entry_thumbnail_download_handler(retro_task_t *task) pl_thumb->thumbnail_path_data, pl_thumb->playlist, pl_thumb->list_index)) goto task_finished; + /* Check whether current right/left thumbnails + * already exist (required for menu refresh callback) */ + pl_thumb->right_thumbnail_exists = false; + if (menu_thumbnail_update_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_RIGHT)) + if (menu_thumbnail_get_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_RIGHT, &right_thumbnail_path)) + pl_thumb->right_thumbnail_exists = filestream_exists(right_thumbnail_path); + + pl_thumb->left_thumbnail_exists = false; + if (menu_thumbnail_update_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_LEFT)) + if (menu_thumbnail_get_path(pl_thumb->thumbnail_path_data, MENU_THUMBNAIL_LEFT, &left_thumbnail_path)) + pl_thumb->left_thumbnail_exists = filestream_exists(left_thumbnail_path); + /* Set task title */ task_free_title(task); if (menu_thumbnail_get_label(pl_thumb->thumbnail_path_data, &label)) @@ -509,7 +601,7 @@ static void task_pl_entry_thumbnail_download_handler(retro_task_t *task) /* Download current thumbnail */ if (pl_thumb) - download_pl_thumbnail(pl_thumb, true); + download_pl_thumbnail(pl_thumb); /* Increment thumbnail type */ pl_thumb->type_idx++; @@ -528,20 +620,50 @@ task_finished: if (task) task_set_finished(task, true); +} + +static bool task_pl_entry_thumbnail_finder(retro_task_t *task, void *user_data) +{ + pl_entry_id_t *entry_id = NULL; + pl_thumb_handle_t *pl_thumb = NULL; - free_pl_thumb_handle(pl_thumb, false); + if (!task || !user_data) + return false; + + if (task->handler != task_pl_entry_thumbnail_download_handler) + return false; + + entry_id = (pl_entry_id_t*)user_data; + if (!entry_id) + return false; + + pl_thumb = (pl_thumb_handle_t*)task->state; + if (!pl_thumb) + return false; + + return (entry_id->idx == pl_thumb->list_index) && + string_is_equal(playlist_get_conf_path(entry_id->playlist), + playlist_get_conf_path(pl_thumb->playlist)); } bool task_push_pl_entry_thumbnail_download( const char *system, - const char *dir_thumbnails, - playlist_t *playlist, unsigned idx) + playlist_t *playlist, + unsigned idx, + bool overwrite, + bool mute) { + task_finder_data_t find_data; + settings_t *settings = config_get_ptr(); retro_task_t *task = task_init(); pl_thumb_handle_t *pl_thumb = (pl_thumb_handle_t*)calloc(1, sizeof(pl_thumb_handle_t)); + pl_entry_id_t *entry_id = (pl_entry_id_t*)calloc(1, sizeof(pl_entry_id_t)); /* Sanity check */ - if (!task || !pl_thumb || !playlist || string_is_empty(system)) + if (!settings || !task || !pl_thumb || !playlist || !entry_id) + goto error; + + if (string_is_empty(system) || string_is_empty(settings->paths.directory_thumbnails)) goto error; if (idx >= playlist_size(playlist)) @@ -553,25 +675,42 @@ bool task_push_pl_entry_thumbnail_download( string_is_equal(system, "video_history")) goto error; + /* Concurrent download of thumbnails for the same + * playlist entry is not allowed */ + entry_id->playlist = playlist; + entry_id->idx = idx; + + find_data.func = task_pl_entry_thumbnail_finder; + find_data.userdata = (void*)entry_id; + + if (task_queue_find(&find_data)) + goto error; + + free(entry_id); + entry_id = NULL; + /* Configure task */ task->handler = task_pl_entry_thumbnail_download_handler; task->state = pl_thumb; task->title = strdup(system); task->alternative_look = true; + task->mute = mute; task->progress = 0; - task->callback = cb_task_pl_thumbnail_refresh_menu; + task->callback = cb_task_pl_entry_thumbnail_refresh_menu; + task->cleanup = task_pl_entry_thumbnail_free; /* Configure handle */ pl_thumb->system = strdup(system); pl_thumb->playlist_path = NULL; + pl_thumb->dir_thumbnails = strdup(settings->paths.directory_thumbnails); pl_thumb->playlist = playlist; pl_thumb->thumbnail_path_data = NULL; pl_thumb->http_task = NULL; pl_thumb->list_size = playlist_size(playlist); pl_thumb->list_index = idx; pl_thumb->type_idx = 1; + pl_thumb->overwrite = overwrite; pl_thumb->status = PL_THUMB_BEGIN; - pl_thumb->dir_thumbnails = strdup(dir_thumbnails); task_queue_push(task); @@ -591,5 +730,11 @@ error: pl_thumb = NULL; } + if (entry_id) + { + free(entry_id); + entry_id = NULL; + } + return false; } diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index d59ee3767a..e68d7fe219 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -63,7 +63,12 @@ bool task_push_netplay_nat_traversal(void *nat_traversal_state, uint16_t port); #ifdef HAVE_MENU bool task_push_pl_thumbnail_download(const char *system, const char *playlist_path); -bool task_push_pl_entry_thumbnail_download(const char *system, const char *dir_thumbnails, playlist_t *playlist, unsigned idx); +bool task_push_pl_entry_thumbnail_download( + const char *system, + playlist_t *playlist, + unsigned idx, + bool overwrite, + bool mute); #endif #endif