Add playlist-based thumbnail downloader

This commit is contained in:
jdgleaver 2019-05-14 16:24:24 +01:00
parent 7ea74548b1
commit 154957505c
18 changed files with 698 additions and 8 deletions

View File

@ -1682,7 +1682,8 @@ ifeq ($(HAVE_NETWORKING), 1)
tasks/task_netplay_lan_scan.o \
tasks/task_netplay_nat_traversal.o \
tasks/task_wifi.o \
tasks/task_netplay_find_content.o
tasks/task_netplay_find_content.o \
tasks/task_pl_thumbnail_download.o
ifeq ($(HAVE_SSL), 1)
OBJ += $(LIBRETRO_COMM_DIR)/net/net_socket_ssl.o

View File

@ -57,6 +57,7 @@ enum file_path_enum
FILE_PATH_CHEATS_ZIP,
FILE_PATH_LAKKA_URL,
FILE_PATH_CORE_THUMBNAILS_URL,
FILE_PATH_CORE_THUMBNAILPACKS_URL,
FILE_PATH_INDEX_DIRS_URL,
FILE_PATH_NETPLAY_ROOM_LIST_URL,
FILE_PATH_INDEX_URL,

View File

@ -165,6 +165,9 @@ const char *file_path_str(enum file_path_enum enum_idx)
str = "registry.lpl";
break;
case FILE_PATH_CORE_THUMBNAILS_URL:
str = "http://thumbnails.libretro.com";
break;
case FILE_PATH_CORE_THUMBNAILPACKS_URL:
str = "http://thumbnailpacks.libretro.com";
break;
case FILE_PATH_LAKKA_URL:

View File

@ -1201,6 +1201,9 @@ DATA RUNLOOP
#include "../tasks/task_database.c"
#include "../tasks/task_database_cue.c"
#endif
#ifdef HAVE_NETWORKING
#include "../tasks/task_pl_thumbnail_download.c"
#endif
/*============================================================
SCREENSHOTS

View File

@ -387,6 +387,8 @@ MSG_HASH(MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST,
"deferred_saving_settings_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST,
"deferred_thumbnails_updater_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST,
"deferred_pl_thumbnails_updater_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST,
"deferred_updater_settings_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_USER_BINDS_LIST,
@ -1155,6 +1157,8 @@ MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_DIRECTORY,
"thumbnails_directory")
MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST,
"thumbnails_updater_list")
MSG_HASH(MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST,
"pl_thumbnails_updater_list")
MSG_HASH(MENU_ENUM_LABEL_TIMEDATE_ENABLE,
"menu_timedate_enable")
MSG_HASH(MENU_ENUM_LABEL_TIMEDATE_STYLE,

View File

@ -3134,6 +3134,18 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST,
"Thumbnails Updater"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_THUMBNAILS_UPDATER_LIST,
"Download complete thumbnail package for selected system."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST,
"Playlist Thumbnails Updater"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_PL_THUMBNAILS_UPDATER_LIST,
"Download individual thumbnails for each entry of selected playlist."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_BOXARTS,
"Boxarts"

View File

@ -188,6 +188,7 @@ generic_deferred_push(deferred_push_rgui_theme_preset, DISPLAYLIST_
#ifdef HAVE_NETWORKING
generic_deferred_push(deferred_push_thumbnails_updater_list, DISPLAYLIST_THUMBNAILS_UPDATER)
generic_deferred_push(deferred_push_pl_thumbnails_updater_list, DISPLAYLIST_PL_THUMBNAILS_UPDATER)
generic_deferred_push(deferred_push_core_updater_list, DISPLAYLIST_CORES_UPDATER)
generic_deferred_push(deferred_push_core_content_list, DISPLAYLIST_CORE_CONTENT)
generic_deferred_push(deferred_push_core_content_dirs_list, DISPLAYLIST_CORE_CONTENT_DIRS)
@ -977,6 +978,11 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
{
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_thumbnails_updater_list);
}
else if (strstr(label,
msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST)))
{
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_pl_thumbnails_updater_list);
}
else if (strstr(label,
msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_LIST)))
{
@ -1091,6 +1097,11 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
case MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST:
#ifdef HAVE_NETWORKING
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_thumbnails_updater_list);
#endif
break;
case MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST:
#ifdef HAVE_NETWORKING
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_pl_thumbnails_updater_list);
#endif
break;
case MENU_ENUM_LABEL_DEFERRED_LAKKA_LIST:

View File

@ -771,6 +771,15 @@ int generic_action_ok_displaylist_push(const char *path,
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST;
dl_type = DISPLAYLIST_PENDING_CLEAR;
break;
case ACTION_OK_DL_PL_THUMBNAILS_UPDATER_LIST:
info.type = type;
info.directory_ptr = idx;
info_path = path;
info_label = msg_hash_to_str(
MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST);
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST;
dl_type = DISPLAYLIST_PENDING_CLEAR;
break;
case ACTION_OK_DL_CORE_CONTENT_DIRS_SUBDIR_LIST:
fill_pathname_join_delim(tmp, path, label, ';',
sizeof(tmp));
@ -3412,7 +3421,7 @@ static int generic_action_ok_network(const char *path,
break;
case MENU_ENUM_LABEL_CB_THUMBNAILS_UPDATER_LIST:
fill_pathname_join(url_path,
file_path_str(FILE_PATH_CORE_THUMBNAILS_URL),
file_path_str(FILE_PATH_CORE_THUMBNAILPACKS_URL),
file_path_str(FILE_PATH_INDEX_URL), sizeof(url_path));
url_label = msg_hash_to_str(enum_idx);
type_id2 = ACTION_OK_DL_THUMBNAILS_UPDATER_LIST;
@ -3567,6 +3576,8 @@ void cb_generic_download(retro_task_t *task,
dir_path = buf;
break;
}
case MENU_ENUM_LABEL_CB_SINGLE_THUMBNAIL:
break;
default:
RARCH_WARN("Unknown transfer type '%s' bailing out.\n",
msg_hash_to_str(transf->enum_idx));
@ -3576,8 +3587,18 @@ void cb_generic_download(retro_task_t *task,
if (!string_is_empty(dir_path))
fill_pathname_join(output_path, dir_path,
transf->path, sizeof(output_path));
else if (transf->enum_idx == MENU_ENUM_LABEL_CB_SINGLE_THUMBNAIL)
{
/* In this particular case we have the whole path
* already built from the task */
strlcpy(output_path, transf->path, sizeof(output_path));
}
/* Make sure the directory exists */
/* Make sure the directory exists
* This function is horrible. It mutates the original path
* so after operating we'll have to set the path to the intended
* location again...
*/
path_basedir_wrapper(output_path);
if (!path_mkdir(output_path))
@ -3589,14 +3610,20 @@ void cb_generic_download(retro_task_t *task,
if (!string_is_empty(dir_path))
fill_pathname_join(output_path, dir_path,
transf->path, sizeof(output_path));
else if (transf->enum_idx == MENU_ENUM_LABEL_CB_SINGLE_THUMBNAIL)
{
/* In this particular case we have the whole path
* already built from the task */
strlcpy(output_path, transf->path, sizeof(output_path));
}
#ifdef HAVE_COMPRESSION
if (path_is_compressed_file(output_path))
{
if (task_check_decompress(output_path))
{
err = msg_hash_to_str(MSG_DECOMPRESSION_ALREADY_IN_PROGRESS);
goto finish;
err = msg_hash_to_str(MSG_DECOMPRESSION_ALREADY_IN_PROGRESS);
goto finish;
}
}
#endif
@ -3622,8 +3649,8 @@ void cb_generic_download(retro_task_t *task,
msg_hash_calculate(msg_hash_to_str(transf->enum_idx)),
frontend_userdata))
{
err = msg_hash_to_str(MSG_DECOMPRESSION_FAILED);
goto finish;
err = msg_hash_to_str(MSG_DECOMPRESSION_FAILED);
goto finish;
}
}
#else
@ -3731,7 +3758,7 @@ static int action_ok_download_generic(const char *path,
path = file_path_str(FILE_PATH_SHADERS_CG_ZIP);
break;
case MENU_ENUM_LABEL_CB_CORE_THUMBNAILS_DOWNLOAD:
strlcpy(s, file_path_str(FILE_PATH_CORE_THUMBNAILS_URL), sizeof(s));
strlcpy(s, file_path_str(FILE_PATH_CORE_THUMBNAILPACKS_URL), sizeof(s));
break;
default:
strlcpy(s, settings->paths.network_buildbot_url, sizeof(s));
@ -4294,6 +4321,7 @@ default_action_ok_func(action_ok_push_accounts_youtube_list, ACTION_OK_DL_ACCOUN
default_action_ok_func(action_ok_push_accounts_twitch_list, ACTION_OK_DL_ACCOUNTS_TWITCH_LIST)
default_action_ok_func(action_ok_open_archive, ACTION_OK_DL_OPEN_ARCHIVE)
default_action_ok_func(action_ok_rgui_menu_theme_preset, ACTION_OK_DL_RGUI_MENU_THEME_PRESET)
default_action_ok_func(action_ok_pl_thumbnails_updater_list, ACTION_OK_DL_PL_THUMBNAILS_UPDATER_LIST)
static int action_ok_open_uwp_permission_settings(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
@ -5337,6 +5365,33 @@ static int action_ok_core_delete(const char *path,
return 0;
}
static int action_ok_pl_content_thumbnails(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
#ifdef HAVE_NETWORKING
settings_t *settings = config_get_ptr();
char playlist_path[PATH_MAX_LENGTH];
playlist_path[0] = '\0';
if (!settings)
return -1;
if (string_is_empty(settings->paths.directory_playlist))
return -1;
fill_pathname_join(
playlist_path,
settings->paths.directory_playlist, label,
sizeof(playlist_path));
task_push_pl_thumbnail_download(path, playlist_path);
return 0;
#else
return -1;
#endif
}
static int is_rdb_entry(enum msg_hash_enums enum_idx)
{
switch (enum_idx)
@ -5635,6 +5690,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_OK(cbs, action_ok_thumbnails_updater_list);
break;
case MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_OK(cbs, action_ok_pl_thumbnails_updater_list);
break;
case MENU_ENUM_LABEL_UPDATE_LAKKA:
BIND_ACTION_OK(cbs, action_ok_lakka_list);
break;
@ -6324,6 +6382,9 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
case FILE_TYPE_DOWNLOAD_THUMBNAIL_CONTENT:
BIND_ACTION_OK(cbs, action_ok_core_content_thumbnails);
break;
case FILE_TYPE_DOWNLOAD_PL_THUMBNAIL_CONTENT:
BIND_ACTION_OK(cbs, action_ok_pl_content_thumbnails);
break;
case FILE_TYPE_DOWNLOAD_CORE:
BIND_ACTION_OK(cbs, action_ok_core_updater_download);
break;

View File

@ -568,6 +568,8 @@ default_sublabel_macro(action_bind_sublabel_playlist_sort_alphabetical,
default_sublabel_macro(action_bind_sublabel_playlist_fuzzy_archive_match, MENU_ENUM_SUBLABEL_PLAYLIST_FUZZY_ARCHIVE_MATCH)
default_sublabel_macro(action_bind_sublabel_menu_rgui_full_width_layout, MENU_ENUM_SUBLABEL_MENU_RGUI_FULL_WIDTH_LAYOUT)
default_sublabel_macro(action_bind_sublabel_menu_rgui_extended_ascii, MENU_ENUM_SUBLABEL_MENU_RGUI_EXTENDED_ASCII)
default_sublabel_macro(action_bind_sublabel_thumbnails_updater_list, MENU_ENUM_SUBLABEL_THUMBNAILS_UPDATER_LIST)
default_sublabel_macro(action_bind_sublabel_pl_thumbnails_updater_list, MENU_ENUM_SUBLABEL_PL_THUMBNAILS_UPDATER_LIST)
default_sublabel_macro(action_bind_sublabel_help_send_debug_info, MENU_ENUM_SUBLABEL_HELP_SEND_DEBUG_INFO)
static int action_bind_sublabel_systeminfo_controller_entry(
@ -2533,6 +2535,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_MENU_RGUI_EXTENDED_ASCII:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_extended_ascii);
break;
case MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_thumbnails_updater_list);
break;
case MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_pl_thumbnails_updater_list);
break;
case MENU_ENUM_LABEL_HELP_SEND_DEBUG_INFO:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_help_send_debug_info);
break;

View File

@ -110,6 +110,7 @@ default_title_macro(action_get_sideload_core_list, MENU_ENUM_LABEL_
default_title_macro(action_get_online_updater_list, MENU_ENUM_LABEL_VALUE_ONLINE_UPDATER)
default_title_macro(action_get_netplay_list, MENU_ENUM_LABEL_VALUE_NETPLAY)
default_title_macro(action_get_online_thumbnails_updater_list, MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST)
default_title_macro(action_get_online_pl_thumbnails_updater_list, MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST)
default_title_macro(action_get_core_updater_list, MENU_ENUM_LABEL_VALUE_CORE_UPDATER_LIST)
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)
@ -773,6 +774,9 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_GET_TITLE(cbs, action_get_online_thumbnails_updater_list);
break;
case MENU_ENUM_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_GET_TITLE(cbs, action_get_online_pl_thumbnails_updater_list);
break;
case MENU_ENUM_LABEL_DEFERRED_CORE_UPDATER_LIST:
BIND_ACTION_GET_TITLE(cbs, action_get_core_updater_list);
break;
@ -1118,6 +1122,9 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
case MENU_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_GET_TITLE(cbs, action_get_online_thumbnails_updater_list);
break;
case MENU_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST:
BIND_ACTION_GET_TITLE(cbs, action_get_online_pl_thumbnails_updater_list);
break;
case MENU_LABEL_DEFERRED_CORE_UPDATER_LIST:
BIND_ACTION_GET_TITLE(cbs, action_get_core_updater_list);
break;

View File

@ -115,6 +115,7 @@ enum
ACTION_OK_DL_CURSOR_MANAGER_LIST,
ACTION_OK_DL_CORE_UPDATER_LIST,
ACTION_OK_DL_THUMBNAILS_UPDATER_LIST,
ACTION_OK_DL_PL_THUMBNAILS_UPDATER_LIST,
ACTION_OK_DL_BROWSE_URL_LIST,
ACTION_OK_DL_CORE_CONTENT_LIST,
ACTION_OK_DL_CORE_CONTENT_DIRS_LIST,

View File

@ -2562,6 +2562,56 @@ static void menu_displaylist_parse_playlist_associations(
string_list_free(str_list);
}
static unsigned menu_displaylist_parse_pl_thumbnail_download_list(
menu_displaylist_info_t *info)
{
settings_t *settings = config_get_ptr();
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;
dir_list_sort(str_list, true);
for (i = 0; i < str_list->size; i++)
{
char path_base[PATH_MAX_LENGTH];
const char *path =
path_basename(str_list->elems[i].data);
path_base[0] = '\0';
if (string_is_empty(path))
continue;
strlcpy(path_base, path, sizeof(path_base));
path_remove_extension(path_base);
menu_entries_append_enum(info->list,
path_base,
path,
MENU_ENUM_LABEL_PLAYLIST_ENTRY,
FILE_TYPE_DOWNLOAD_PL_THUMBNAIL_CONTENT,
0, 0);
count++;
}
}
/* Not necessary to check for NULL here */
string_list_free(str_list);
return count;
}
static bool menu_displaylist_push_internal(
const char *label,
menu_displaylist_ctx_entry_t *entry,
@ -4919,6 +4969,23 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
(int)menu->core_len, FILE_TYPE_DOWNLOAD_THUMBNAIL_CONTENT,
true, false);
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;
info->need_refresh = true;
info->need_clear = true;
#endif
break;
case DISPLAYLIST_PL_THUMBNAILS_UPDATER:
#ifdef HAVE_NETWORKING
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
count = menu_displaylist_parse_pl_thumbnail_download_list(info);
if (count == 0)
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
@ -6208,6 +6275,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST,
MENU_SETTING_ACTION, 0, 0))
count++;
if (menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST),
msg_hash_to_str(MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST),
MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST,
MENU_SETTING_ACTION, 0, 0))
count++;
if (menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT),
msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS),
@ -6235,6 +6308,13 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
MENU_SETTING_ACTION, 0, 0))
count++;
if (menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST),
msg_hash_to_str(MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST),
MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST,
MENU_SETTING_ACTION, 0, 0))
count++;
if (menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT),
msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS),

View File

@ -88,6 +88,7 @@ enum menu_displaylist_ctl_state
DISPLAYLIST_CORES_COLLECTION_SUPPORTED,
DISPLAYLIST_CORES_UPDATER,
DISPLAYLIST_THUMBNAILS_UPDATER,
DISPLAYLIST_PL_THUMBNAILS_UPDATER,
DISPLAYLIST_LAKKA,
DISPLAYLIST_CORES_DETECTED,
DISPLAYLIST_CORE_OPTIONS,

View File

@ -87,6 +87,34 @@ void menu_thumbnail_path_reset(menu_thumbnail_path_data_t *path_data)
/* Utility Functions */
/* Fetches the thumbnail subdirectory (Named_Snaps,
* Named_Titles, Named_Boxarts) corresponding to the
* specified 'type index' (1, 2, 3).
* Returns true if 'type index' is valid */
bool menu_thumbnail_get_sub_directory(unsigned type_idx, const char **sub_directory)
{
if (!sub_directory)
return false;
switch (type_idx)
{
case 1:
*sub_directory = "Named_Snaps";
return true;
case 2:
*sub_directory = "Named_Titles";
return true;
case 3:
*sub_directory = "Named_Boxarts";
return true;
case 0:
default:
break;
}
return false;
}
/* Returns currently set thumbnail 'type' (Named_Snaps,
* Named_Titles, Named_Boxarts) for specified thumbnail
* identifier (right, left) */
@ -569,6 +597,42 @@ bool menu_thumbnail_get_path(menu_thumbnail_path_data_t *path_data, enum menu_th
return true;
}
/* Fetches current 'system' (default database name).
* Returns true if 'system' is valid. */
bool menu_thumbnail_get_system(menu_thumbnail_path_data_t *path_data, const char **system)
{
if (!path_data)
return false;
if (!system)
return false;
if (string_is_empty(path_data->system))
return false;
*system = path_data->system;
return true;
}
/* Fetches current content path.
* Returns true if content path is valid. */
bool menu_thumbnail_get_content_path(menu_thumbnail_path_data_t *path_data, const char **content_path)
{
if (!path_data)
return false;
if (!content_path)
return false;
if (string_is_empty(path_data->content_path))
return false;
*content_path = path_data->content_path;
return true;
}
/* Fetches current thumbnail label.
* Returns true if label is valid. */
bool menu_thumbnail_get_label(menu_thumbnail_path_data_t *path_data, const char **label)
@ -604,3 +668,40 @@ bool menu_thumbnail_get_core_name(menu_thumbnail_path_data_t *path_data, const c
return true;
}
/* Fetches current database name.
* Returns true if database name is valid. */
bool menu_thumbnail_get_db_name(menu_thumbnail_path_data_t *path_data, const char **db_name)
{
if (!path_data)
return false;
if (!db_name)
return false;
if (string_is_empty(path_data->content_db_name))
return false;
*db_name = path_data->content_db_name;
return true;
}
/* Fetches current thumbnail image name
* (name is the same for all thumbnail types).
* Returns true if image name is valid. */
bool menu_thumbnail_get_img_name(menu_thumbnail_path_data_t *path_data, const char **img_name)
{
if (!path_data)
return false;
if (!img_name)
return false;
if (string_is_empty(path_data->content_img))
return false;
*img_name = path_data->content_img;
return true;
}

View File

@ -64,6 +64,12 @@ void menu_thumbnail_path_reset(menu_thumbnail_path_data_t *path_data);
/* Utility Functions */
/* Fetches the thumbnail subdirectory (Named_Snaps,
* Named_Titles, Named_Boxarts) corresponding to the
* specified 'type index' (1, 2, 3).
* Returns true if 'type index' is valid */
bool menu_thumbnail_get_sub_directory(unsigned type_idx, const char **sub_directory);
/* Returns currently set thumbnail 'type' (Named_Snaps,
* Named_Titles, Named_Boxarts) for specified thumbnail
* identifier (right, left) */
@ -116,6 +122,14 @@ bool menu_thumbnail_update_path(menu_thumbnail_path_data_t *path_data, enum menu
* Returns true if path is valid. */
bool menu_thumbnail_get_path(menu_thumbnail_path_data_t *path_data, enum menu_thumbnail_id thumbnail_id, const char **path);
/* Fetches current 'system' (default database name).
* Returns true if 'system' is valid. */
bool menu_thumbnail_get_system(menu_thumbnail_path_data_t *path_data, const char **system);
/* Fetches current content path.
* Returns true if content path is valid. */
bool menu_thumbnail_get_content_path(menu_thumbnail_path_data_t *path_data, const char **content_path);
/* Fetches current thumbnail label.
* Returns true if label is valid. */
bool menu_thumbnail_get_label(menu_thumbnail_path_data_t *path_data, const char **label);
@ -124,6 +138,15 @@ bool menu_thumbnail_get_label(menu_thumbnail_path_data_t *path_data, const char
* Returns true if core name is valid. */
bool menu_thumbnail_get_core_name(menu_thumbnail_path_data_t *path_data, const char **core_name);
/* Fetches current database name.
* Returns true if database name is valid. */
bool menu_thumbnail_get_db_name(menu_thumbnail_path_data_t *path_data, const char **db_name);
/* Fetches current thumbnail image name
* (name is the same for all thumbnail types).
* Returns true if image name is valid. */
bool menu_thumbnail_get_img_name(menu_thumbnail_path_data_t *path_data, const char **img_name);
RETRO_END_DECLS
#endif

View File

@ -147,6 +147,10 @@ enum msg_file_type
FILE_TYPE_GONG,
/* Note: New entries must be added at the end, otherwise
* menu_cbs_init_bind_get_string_representation_compare_type() breaks... */
FILE_TYPE_DOWNLOAD_PL_THUMBNAIL_CONTENT,
FILE_TYPE_LAST
};
@ -1056,6 +1060,7 @@ enum msg_hash_enums
MENU_LABEL(QUICK_MENU_VIEWS_SETTINGS),
MENU_LABEL(MENU_SETTINGS),
MENU_LABEL(THUMBNAILS_UPDATER_LIST),
MENU_LABEL(PL_THUMBNAILS_UPDATER_LIST),
MENU_LABEL(USER_INTERFACE_SETTINGS),
MENU_LABEL(POWER_MANAGEMENT_SETTINGS),
MENU_LABEL(RETRO_ACHIEVEMENTS_SETTINGS),
@ -1170,6 +1175,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_DEFERRED_CORE_LIST,
MENU_ENUM_LABEL_DEFERRED_CORE_UPDATER_LIST,
MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST,
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_INPUT_SETTINGS_LIST,
@ -2068,6 +2074,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_CB_MENU_LEFT_THUMBNAIL,
MENU_ENUM_LABEL_CB_MENU_SAVESTATE_THUMBNAIL,
MENU_ENUM_LABEL_CB_MENU_WALLPAPER,
MENU_ENUM_LABEL_CB_PL_THUMBNAILS_DOWNLOAD,
MENU_ENUM_LABEL_CB_THUMBNAILS_UPDATER_DOWNLOAD,
MENU_ENUM_LABEL_CB_THUMBNAILS_UPDATER_LIST,
MENU_ENUM_LABEL_CB_UPDATE_ASSETS,
@ -2080,6 +2087,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_CB_UPDATE_SHADERS_GLSL,
MENU_ENUM_LABEL_CB_UPDATE_SHADERS_SLANG,
MENU_ENUM_LABEL_CB_DISCORD_AVATAR,
MENU_ENUM_LABEL_CB_SINGLE_THUMBNAIL,
/* Sublabels */
MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY,
@ -2392,6 +2400,7 @@ enum msg_hash_enums
/* Deferred */
#define MENU_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST 0x364dfa2bU
#define MENU_LABEL_DEFERRED_PL_THUMBNAILS_UPDATER_LIST 0x428E8466U
#define MENU_LABEL_DEFERRED_VIDEO_FILTER 0x966ad201U
#define MENU_LABEL_DEFERRED_CORE_LIST_SET 0xa6d5fdb4U
#define MENU_LABEL_DEFERRED_DATABASE_MANAGER_LIST 0x7c0b704fU

View File

@ -0,0 +1,362 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2014-2017 - Jean-André Santoni
* Copyright (C) 2016-2019 - Brad Parker
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <string/stdstring.h>
#include <file/file_path.h>
#include <streams/file_stream.h>
#include <net/net_http.h>
#include "tasks_internal.h"
#include "task_file_transfer.h"
#include "../configuration.h"
#include "../file_path_special.h"
#include "../playlist.h"
#include "../menu/menu_thumbnail_path.h"
#include "../menu/menu_cbs.h"
#ifndef COLLECTION_SIZE
#define COLLECTION_SIZE 99999
#endif
enum pl_thumb_status
{
PL_THUMB_BEGIN = 0,
PL_THUMB_ITERATE_ENTRY,
PL_THUMB_ITERATE_TYPE,
PL_THUMB_END
};
typedef struct pl_thumb_handle
{
char *system;
char *playlist_path;
playlist_t *playlist;
menu_thumbnail_path_data_t *thumbnail_path_data;
retro_task_t *http_task;
size_t list_size;
size_t list_index;
unsigned type_idx;
enum pl_thumb_status status;
} pl_thumb_handle_t;
/* Fetches local and remote paths for current thumbnail
* of current type */
static bool get_thumbnail_paths(
pl_thumb_handle_t *pl_thumb,
char *path, size_t path_size,
char *url, size_t url_size)
{
settings_t *settings = config_get_ptr();
const char *system = NULL;
const char *db_name = NULL;
const char *img_name = NULL;
const char *sub_dir = NULL;
const char *system_name = NULL;
char raw_url[2048];
char tmp_buf[PATH_MAX_LENGTH];
raw_url[0] = '\0';
tmp_buf[0] = '\0';
/* Sanity check */
if (!pl_thumb || !settings)
return false;
if (!pl_thumb->thumbnail_path_data)
return false;
if (string_is_empty(settings->paths.directory_thumbnails))
return false;
/* Extract required strings */
menu_thumbnail_get_system(pl_thumb->thumbnail_path_data, &system);
menu_thumbnail_get_db_name(pl_thumb->thumbnail_path_data, &db_name);
if (!menu_thumbnail_get_img_name(pl_thumb->thumbnail_path_data, &img_name))
return false;
if (!menu_thumbnail_get_sub_directory(pl_thumb->type_idx, &sub_dir))
return false;
/* Dermine system name */
system_name = string_is_empty(db_name) ? system : db_name;
if (string_is_empty(system_name))
return false;
/* Generate local path */
fill_pathname_join(path, settings->paths.directory_thumbnails,
system_name, path_size);
fill_pathname_join(tmp_buf, path, sub_dir, sizeof(tmp_buf));
fill_pathname_join(path, tmp_buf, img_name, path_size);
if (string_is_empty(path))
return false;
/* Generate remote path */
strlcpy(raw_url, file_path_str(FILE_PATH_CORE_THUMBNAILS_URL), sizeof(raw_url));
strlcat(raw_url, "/", sizeof(raw_url));
strlcat(raw_url, system_name, sizeof(raw_url));
strlcat(raw_url, "/", sizeof(raw_url));
strlcat(raw_url, sub_dir, sizeof(raw_url));
strlcat(raw_url, "/", sizeof(raw_url));
strlcat(raw_url, img_name, sizeof(raw_url));
if (string_is_empty(raw_url))
return false;
net_http_urlencode_full(url, raw_url, url_size);
if (string_is_empty(url))
return false;
return true;
}
/* Download thumbnail of the current type for the current
* playlist entry */
static void download_pl_thumbnail(pl_thumb_handle_t *pl_thumb)
{
char path[PATH_MAX_LENGTH];
char url[2048];
path[0] = '\0';
url[0] = '\0';
/* Sanity check */
if (!pl_thumb)
return;
/* Check if paths are valid */
if (get_thumbnail_paths(pl_thumb, path, sizeof(path), url, sizeof(url)))
{
/* Only download missing thumbnails */
if (!filestream_exists(path))
{
file_transfer_t *transf = (file_transfer_t*)calloc(1, sizeof(file_transfer_t));
if (!transf)
return; /* If this happens then everything is broken anyway... */
/* Initialise file transfer */
transf->enum_idx = MENU_ENUM_LABEL_CB_SINGLE_THUMBNAIL;
strlcpy(transf->path, path, sizeof(transf->path));
/* Note: We don't actually care if this fails since that
* just means the file is missing from the server, so it's
* not something we can handle here... */
pl_thumb->http_task = task_push_http_transfer(url, true, NULL, cb_generic_download, transf);
}
}
}
static void task_pl_thumbnail_download_handler(retro_task_t *task)
{
pl_thumb_handle_t *pl_thumb = NULL;
if (!task)
goto task_finished;
pl_thumb = (pl_thumb_handle_t*)task->state;
if (!pl_thumb)
goto task_finished;
if (task_get_cancelled(task))
goto task_finished;
switch (pl_thumb->status)
{
case PL_THUMB_BEGIN:
{
/* Load playlist */
if (!filestream_exists(pl_thumb->playlist_path))
goto task_finished;
pl_thumb->playlist = playlist_init(pl_thumb->playlist_path, COLLECTION_SIZE);
if (!pl_thumb->playlist)
goto task_finished;
pl_thumb->list_size = playlist_size(pl_thumb->playlist);
if (pl_thumb->list_size < 1)
goto task_finished;
/* Initialise thumbnail path data */
pl_thumb->thumbnail_path_data = menu_thumbnail_path_init();
if (!pl_thumb->thumbnail_path_data)
goto task_finished;
if (!menu_thumbnail_set_system(pl_thumb->thumbnail_path_data, pl_thumb->system))
goto task_finished;
/* All good - can start iterating */
pl_thumb->status = PL_THUMB_ITERATE_ENTRY;
}
break;
case PL_THUMB_ITERATE_ENTRY:
{
/* Set current thumbnail content */
if (menu_thumbnail_set_content_playlist(
pl_thumb->thumbnail_path_data, pl_thumb->playlist, pl_thumb->list_index))
{
const char *label = NULL;
/* Update progress display */
task_free_title(task);
if (menu_thumbnail_get_label(pl_thumb->thumbnail_path_data, &label))
task_set_title(task, strdup(label));
else
task_set_title(task, strdup(""));
task_set_progress(task, (pl_thumb->list_index * 100) / pl_thumb->list_size);
/* Start iterating over thumbnail type */
pl_thumb->type_idx = 1;
pl_thumb->status = PL_THUMB_ITERATE_TYPE;
}
}
break;
case PL_THUMB_ITERATE_TYPE:
{
/* Ensure that we only enqueue one transfer
* at a time... */
if (pl_thumb->http_task)
{
if (task_get_finished(pl_thumb->http_task))
pl_thumb->http_task = NULL;
else
break;
}
/* Download current thumbnail */
download_pl_thumbnail(pl_thumb);
/* Increment thumbnail type */
pl_thumb->type_idx++;
if (pl_thumb->type_idx > 3)
{
/* Time to move on to the next entry */
pl_thumb->list_index++;
if (pl_thumb->list_index < pl_thumb->list_size)
pl_thumb->status = PL_THUMB_ITERATE_ENTRY;
else
pl_thumb->status = PL_THUMB_END;
}
}
break;
case PL_THUMB_END:
default:
task_set_progress(task, 100);
goto task_finished;
break;
}
return;
task_finished:
if (task)
task_set_finished(task, true);
if (pl_thumb)
{
if (!string_is_empty(pl_thumb->system))
{
free(pl_thumb->system);
pl_thumb->system = NULL;
}
if (!string_is_empty(pl_thumb->playlist_path))
{
free(pl_thumb->playlist_path);
pl_thumb->playlist_path = NULL;
}
if (pl_thumb->playlist)
{
playlist_free(pl_thumb->playlist);
pl_thumb->playlist = NULL;
}
if (pl_thumb->thumbnail_path_data)
{
free(pl_thumb->thumbnail_path_data);
pl_thumb->thumbnail_path_data = NULL;
}
free(pl_thumb);
pl_thumb = NULL;
}
}
bool task_push_pl_thumbnail_download(
const char *system, const char *playlist_path)
{
retro_task_t *task = task_init();
pl_thumb_handle_t *pl_thumb = (pl_thumb_handle_t*)calloc(1, sizeof(pl_thumb_handle_t));
/* Sanity check */
if (!task || !pl_thumb || string_is_empty(system) || string_is_empty(playlist_path))
goto error;
if (string_is_equal(system, "history") ||
string_is_equal(system, "favorites") ||
string_is_equal(system, "images_history"))
goto error;
/* Configure task */
task->handler = task_pl_thumbnail_download_handler;
task->state = pl_thumb;
task->title = strdup(system);
task->alternative_look = true;
task->progress = 0;
/* Configure handle */
pl_thumb->system = strdup(system);
pl_thumb->playlist_path = strdup(playlist_path);
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->status = PL_THUMB_BEGIN;
task_queue_push(task);
return true;
error:
if (task)
{
free(task);
task = NULL;
}
if (pl_thumb)
{
free(pl_thumb);
pl_thumb = NULL;
}
return false;
}

View File

@ -56,6 +56,8 @@ bool task_push_netplay_lan_scan_rooms(retro_task_callback_t cb);
bool task_push_netplay_nat_traversal(void *nat_traversal_state, uint16_t port);
bool task_push_pl_thumbnail_download(const char *system, const char *playlist_path);
#endif
bool task_push_image_load(const char *fullpath,