RetroArch/gfx/gfx_thumbnail_path.c
Eric Warmenhoven 79e43e2bd4
Fix many warnings (#16180)
Also change iOS/tvOS to use system zlib instead of compiling it in
2024-01-31 09:15:14 -08:00

831 lines
28 KiB
C

/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (gfx_thumbnail_path.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <string/stdstring.h>
#include <file/file_path.h>
#include <lists/file_list.h>
#include "../configuration.h"
#include "../msg_hash.h"
#include "../paths.h"
#include "../file_path_special.h"
#include "gfx_thumbnail_path.h"
/* Fills content_img field of path_data using existing
* content_label field (for internal use only) */
static void gfx_thumbnail_fill_content_img(char *s, size_t len, const char *src, bool shorten)
{
const char* cut = " (";
char *scrub_char_ptr = NULL;
/* Copy source label string */
size_t _len = strlcpy(s, src, len);
int bracketpos = -1;
/* Shortening logic: up to first space + bracket */
if (shorten) {
bracketpos = string_find_index_substring_string(src, cut);
if (bracketpos > 0)
_len = bracketpos;
/* Explicit zero if short name is same as standard name - saves some queries later. */
else
{
s[0] = '\0';
return;
}
}
/* Scrub characters that are not cross-platform and/or violate the
* No-Intro filename standard:
* https://datomatic.no-intro.org/stuff/The%20Official%20No-Intro%20Convention%20(20071030).pdf
* Replace these characters in the entry name with underscores */
while ((scrub_char_ptr = strpbrk(s, "&*/:`\"<>?\\|")))
*scrub_char_ptr = '_';
/* Add PNG extension */
strlcpy(s + _len, ".png", len - _len);
}
/* Returns currently set thumbnail 'type' (Named_Snaps,
* Named_Titles, Named_Boxarts) for specified thumbnail
* identifier (right, left) */
static const char *gfx_thumbnail_get_type(
settings_t *settings,
gfx_thumbnail_path_data_t *path_data,
enum gfx_thumbnail_id thumbnail_id)
{
if (path_data)
{
unsigned type = 0;
unsigned menu_left_thumbnails = settings->uints.menu_left_thumbnails;
unsigned gfx_thumbnails = settings->uints.gfx_thumbnails;
switch (thumbnail_id)
{
case GFX_THUMBNAIL_RIGHT:
if (path_data->playlist_right_mode != PLAYLIST_THUMBNAIL_MODE_DEFAULT)
type = (unsigned)path_data->playlist_right_mode - 1;
else
type = gfx_thumbnails;
break;
case GFX_THUMBNAIL_LEFT:
if (path_data->playlist_left_mode != PLAYLIST_THUMBNAIL_MODE_DEFAULT)
type = (unsigned)path_data->playlist_left_mode - 1;
else
type = menu_left_thumbnails;
break;
default:
goto end;
}
switch (type)
{
case 1:
return "Named_Snaps";
case 2:
return "Named_Titles";
case 3:
return "Named_Boxarts";
case 0:
default:
break;
}
}
end:
return msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF);
}
/* Resets thumbnail path data
* (blanks all internal string containers) */
void gfx_thumbnail_path_reset(gfx_thumbnail_path_data_t *path_data)
{
if (!path_data)
return;
path_data->system[0] = '\0';
path_data->content_path[0] = '\0';
path_data->content_label[0] = '\0';
path_data->content_core_name[0] = '\0';
path_data->content_db_name[0] = '\0';
path_data->content_img[0] = '\0';
path_data->content_img_full[0] = '\0';
path_data->content_img_short[0] = '\0';
path_data->right_path[0] = '\0';
path_data->left_path[0] = '\0';
path_data->playlist_right_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_left_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
}
/* Initialisation */
/* Creates new thumbnail path data container.
* Returns handle to new gfx_thumbnail_path_data_t object.
* on success, otherwise NULL.
* Note: Returned object must be free()d */
gfx_thumbnail_path_data_t *gfx_thumbnail_path_init(void)
{
gfx_thumbnail_path_data_t *path_data = (gfx_thumbnail_path_data_t*)
malloc(sizeof(*path_data));
if (!path_data)
return NULL;
gfx_thumbnail_path_reset(path_data);
return path_data;
}
/* Utility Functions */
/* Returns true if specified thumbnail is enabled
* (i.e. if 'type' is not equal to MENU_ENUM_LABEL_VALUE_OFF) */
bool gfx_thumbnail_is_enabled(gfx_thumbnail_path_data_t *path_data, enum gfx_thumbnail_id thumbnail_id)
{
if (path_data)
{
settings_t *settings = config_get_ptr();
unsigned gfx_thumbnails = settings->uints.gfx_thumbnails;
unsigned menu_left_thumbnails = settings->uints.menu_left_thumbnails;
switch (thumbnail_id)
{
case GFX_THUMBNAIL_RIGHT:
if (path_data->playlist_right_mode != PLAYLIST_THUMBNAIL_MODE_DEFAULT)
return path_data->playlist_right_mode != PLAYLIST_THUMBNAIL_MODE_OFF;
return gfx_thumbnails != 0;
case GFX_THUMBNAIL_LEFT:
if (path_data->playlist_left_mode != PLAYLIST_THUMBNAIL_MODE_DEFAULT)
return path_data->playlist_left_mode != PLAYLIST_THUMBNAIL_MODE_OFF;
return menu_left_thumbnails != 0;
default:
break;
}
}
return false;
}
/* Setters */
/* Sets current 'system' (default database name).
* Returns true if 'system' is valid.
* If playlist is provided, extracts system-specific
* thumbnail assignment metadata (required for accurate
* usage of gfx_thumbnail_is_enabled())
* > Used as a fallback when individual content lacks an
* associated database name */
bool gfx_thumbnail_set_system(gfx_thumbnail_path_data_t *path_data,
const char *system, playlist_t *playlist)
{
if (!path_data)
return false;
/* When system is updated, must regenerate right/left
* thumbnail paths */
path_data->right_path[0] = '\0';
path_data->left_path[0] = '\0';
/* 'Reset' path_data system string */
path_data->system[0] = '\0';
/* Must also reset playlist thumbnail display modes */
path_data->playlist_right_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_left_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
if (string_is_empty(system))
return false;
/* Hack: There is only one MAME thumbnail repo,
* so filter any input starting with 'MAME...' */
if (strncmp(system, "MAME", 4) == 0)
strlcpy(path_data->system, "MAME", sizeof(path_data->system));
else
strlcpy(path_data->system, system, sizeof(path_data->system));
/* Addendum: Now that we have per-playlist thumbnail display
* modes, we must extract them here - otherwise
* gfx_thumbnail_is_enabled() will go out of sync */
if (playlist)
{
const char *playlist_path = playlist_get_conf_path(playlist);
/* Note: This is not considered an error
* (just means that input playlist is ignored) */
if (!string_is_empty(playlist_path))
{
const char *playlist_file = path_basename_nocompression(playlist_path);
/* Note: This is not considered an error
* (just means that input playlist is ignored) */
if (!string_is_empty(playlist_file))
{
/* Check for history/favourites playlists */
bool playlist_valid =
(string_is_equal(system, "history")
&& string_is_equal(playlist_file,
FILE_PATH_CONTENT_HISTORY))
|| (string_is_equal(system, "favorites")
&& string_is_equal(playlist_file,
FILE_PATH_CONTENT_FAVORITES));
if (!playlist_valid)
{
/* This means we have to work a little harder
* i.e. check whether the cached playlist file
* matches the database name */
char *playlist_name = NULL;
char tmp[PATH_MAX_LENGTH];
strlcpy(tmp, playlist_file, sizeof(tmp));
playlist_name = path_remove_extension(tmp);
playlist_valid = string_is_equal(playlist_name, system);
}
/* If we have a valid playlist, extract thumbnail modes */
if (playlist_valid)
{
path_data->playlist_right_mode =
playlist_get_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_RIGHT);
path_data->playlist_left_mode =
playlist_get_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_LEFT);
}
}
}
}
return true;
}
/* Sets current thumbnail content according to the specified label.
* Returns true if content is valid */
bool gfx_thumbnail_set_content(gfx_thumbnail_path_data_t *path_data, const char *label)
{
if (!path_data)
return false;
/* When content is updated, must regenerate right/left
* thumbnail paths */
path_data->right_path[0] = '\0';
path_data->left_path[0] = '\0';
/* 'Reset' path_data content strings */
path_data->content_path[0] = '\0';
path_data->content_label[0] = '\0';
path_data->content_core_name[0] = '\0';
path_data->content_db_name[0] = '\0';
path_data->content_img[0] = '\0';
path_data->content_img_full[0] = '\0';
path_data->content_img_short[0] = '\0';
/* Must also reset playlist thumbnail display modes */
path_data->playlist_right_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_left_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_index = 0;
if (string_is_empty(label))
return false;
/* Cache content label */
strlcpy(path_data->content_label, label, sizeof(path_data->content_label));
/* Determine content image name */
gfx_thumbnail_fill_content_img(path_data->content_img,
sizeof(path_data->content_img), path_data->content_label, false);
gfx_thumbnail_fill_content_img(path_data->content_img_short,
sizeof(path_data->content_img_short), path_data->content_label, true);
/* Have to set content path to *something*...
* Just use label value (it doesn't matter) */
strlcpy(path_data->content_path, label, sizeof(path_data->content_path));
/* Redundant error check... */
return !string_is_empty(path_data->content_img);
}
/* Sets current thumbnail content to the specified image.
* Returns true if content is valid */
bool gfx_thumbnail_set_content_image(
gfx_thumbnail_path_data_t *path_data,
const char *img_dir, const char *img_name)
{
char *content_img_no_ext = NULL;
if (!path_data)
return false;
/* When content is updated, must regenerate right/left
* thumbnail paths */
path_data->right_path[0] = '\0';
path_data->left_path[0] = '\0';
/* 'Reset' path_data content strings */
path_data->content_path[0] = '\0';
path_data->content_label[0] = '\0';
path_data->content_core_name[0] = '\0';
path_data->content_db_name[0] = '\0';
path_data->content_img[0] = '\0';
path_data->content_img_full[0] = '\0';
path_data->content_img_short[0] = '\0';
/* Must also reset playlist thumbnail display modes */
path_data->playlist_right_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_left_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_index = 0;
if (string_is_empty(img_dir) || string_is_empty(img_name))
return false;
if (path_is_media_type(img_name) != RARCH_CONTENT_IMAGE)
return false;
/* Cache content image name */
strlcpy(path_data->content_img,
img_name, sizeof(path_data->content_img));
/* Get image label */
content_img_no_ext = path_remove_extension(path_data->content_img);
if (!string_is_empty(content_img_no_ext))
strlcpy(path_data->content_label,
content_img_no_ext, sizeof(path_data->content_label));
else
strlcpy(path_data->content_label,
path_data->content_img, sizeof(path_data->content_label));
/* Set file path */
fill_pathname_join_special(path_data->content_path,
img_dir, img_name, sizeof(path_data->content_path));
/* Set core name to "imageviewer" */
strlcpy(
path_data->content_core_name,
"imageviewer", sizeof(path_data->content_core_name));
/* Set database name (arbitrarily) to "_images_"
* (required for compatibility with gfx_thumbnail_update_path(),
* but not actually used...) */
strlcpy(path_data->content_db_name,
"_images_", sizeof(path_data->content_db_name));
/* Redundant error check */
return !string_is_empty(path_data->content_path);
}
/* Sets current thumbnail content to the specified playlist entry.
* Returns true if content is valid.
* > Note: It is always best to use playlists when setting
* thumbnail content, since there is no guarantee that the
* corresponding menu entry label will contain a useful
* identifier (it may be 'tainted', e.g. with the current
* core name). 'Real' labels should be extracted from source */
bool gfx_thumbnail_set_content_playlist(
gfx_thumbnail_path_data_t *path_data, playlist_t *playlist, size_t idx)
{
const char *content_path = NULL;
const char *content_label = NULL;
const char *core_name = NULL;
const char *db_name = NULL;
const struct playlist_entry *entry = NULL;
if (!path_data)
return false;
/* When content is updated, must regenerate right/left
* thumbnail paths */
path_data->right_path[0] = '\0';
path_data->left_path[0] = '\0';
/* 'Reset' path_data content strings */
path_data->content_path[0] = '\0';
path_data->content_label[0] = '\0';
path_data->content_core_name[0] = '\0';
path_data->content_db_name[0] = '\0';
path_data->content_img[0] = '\0';
path_data->content_img_full[0] = '\0';
path_data->content_img_short[0] = '\0';
/* Must also reset playlist thumbnail display modes */
path_data->playlist_right_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_left_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_index = 0;
if (!playlist)
return false;
if (idx >= playlist_get_size(playlist))
return false;
/* Read playlist values */
playlist_get_index(playlist, idx, &entry);
if (!entry)
return false;
content_path = entry->path;
content_label = entry->label;
core_name = entry->core_name;
db_name = entry->db_name;
/* Content without a path is invalid by definition */
if (string_is_empty(content_path))
return false;
/* Cache content path
* (This is required for imageviewer, history and favourites content) */
strlcpy(path_data->content_path,
content_path, sizeof(path_data->content_path));
/* Cache core name
* (This is required for imageviewer content) */
if (!string_is_empty(core_name))
strlcpy(path_data->content_core_name,
core_name, sizeof(path_data->content_core_name));
/* Get content label */
if (!string_is_empty(content_label))
strlcpy(path_data->content_label,
content_label, sizeof(path_data->content_label));
else
fill_pathname(path_data->content_label,
path_basename(content_path),
"", sizeof(path_data->content_label));
/* Determine content image name */
{
char* content_name_no_ext = NULL;
char tmp_buf[PATH_MAX_LENGTH];
/* Remove rom file extension
* > path_remove_extension() requires a char * (not const)
* so have to use a temporary buffer... */
const char* base_name = path_basename(path_data->content_path);
strlcpy(tmp_buf, base_name, sizeof(tmp_buf));
content_name_no_ext = path_remove_extension(tmp_buf);
if (!content_name_no_ext)
content_name_no_ext = tmp_buf;
gfx_thumbnail_fill_content_img(path_data->content_img_full,
sizeof(path_data->content_img_full), content_name_no_ext,false);
gfx_thumbnail_fill_content_img(path_data->content_img,
sizeof(path_data->content_img), path_data->content_label,false);
/* Explicit zero if full name is same as standard name - saves some queries later. */
if(strcmp(path_data->content_img, path_data->content_img_full) == 0)
{
path_data->content_img_full[0] = '\0';
}
gfx_thumbnail_fill_content_img(path_data->content_img_short,
sizeof(path_data->content_img_short), path_data->content_label,true);
}
/* Store playlist index */
path_data->playlist_index = idx;
/* Redundant error check... */
if (string_is_empty(path_data->content_img))
return false;
/* Thumbnail image name is done -> now check if
* per-content database name is defined */
if (string_is_empty(db_name))
playlist_get_db_name(playlist, idx, &db_name);
if (!string_is_empty(db_name))
{
/* Hack: There is only one MAME thumbnail repo,
* so filter any input starting with 'MAME...' */
if (strncmp(db_name, "MAME", 4) == 0)
{
path_data->content_db_name[0] = path_data->content_db_name[2] = 'M';
path_data->content_db_name[1] = 'A';
path_data->content_db_name[3] = 'E';
path_data->content_db_name[4] = '\0';
}
else
{
char *db_name_no_ext = NULL;
char tmp_buf[PATH_MAX_LENGTH];
const char* pos = strchr(db_name, '|');
if (pos && (size_t) (pos - db_name)+1 < sizeof(tmp_buf)) {
/* If db_name comes from core info, and there are multiple
* databases mentioned separated by |, use only first one */
strlcpy(tmp_buf, db_name, (size_t) (pos - db_name)+1);
}
else {
/* Remove .lpl extension
* > path_remove_extension() requires a char * (not const)
* so have to use a temporary buffer... */
strlcpy(tmp_buf, db_name, sizeof(tmp_buf));
}
db_name_no_ext = path_remove_extension(tmp_buf);
if (!string_is_empty(db_name_no_ext))
strlcpy(path_data->content_db_name,
db_name_no_ext, sizeof(path_data->content_db_name));
else
strlcpy(path_data->content_db_name,
tmp_buf, sizeof(path_data->content_db_name));
}
}
/* Playlist entry is valid -> it is now 'safe' to
* extract any remaining playlist metadata
* (i.e. thumbnail display modes) */
path_data->playlist_right_mode =
playlist_get_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_RIGHT);
path_data->playlist_left_mode =
playlist_get_thumbnail_mode(playlist, PLAYLIST_THUMBNAIL_LEFT);
return true;
}
/* Updaters */
/* Updates path for specified thumbnail identifier (right, left).
* Must be called after:
* - gfx_thumbnail_set_system()
* - gfx_thumbnail_set_content*()
* ...and before:
* - gfx_thumbnail_get_path()
* Returns true if generated path is valid */
bool gfx_thumbnail_update_path(
gfx_thumbnail_path_data_t *path_data,
enum gfx_thumbnail_id thumbnail_id)
{
char content_dir[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
const char *system_name = NULL;
char *thumbnail_path = NULL;
const char *dir_thumbnails = NULL;
if (!path_data)
return false;
/* Determine which path we are updating... */
switch (thumbnail_id)
{
case GFX_THUMBNAIL_RIGHT:
thumbnail_path = path_data->right_path;
break;
case GFX_THUMBNAIL_LEFT:
thumbnail_path = path_data->left_path;
break;
default:
return false;
}
content_dir[0] = '\0';
if (settings)
dir_thumbnails = settings->paths.directory_thumbnails;
/* Sundry error checking */
if (string_is_empty(dir_thumbnails))
return false;
if (!gfx_thumbnail_is_enabled(path_data, thumbnail_id))
return false;
/* Generate new path */
/* > Check path_data for empty strings */
if ( string_is_empty(path_data->content_path)
|| string_is_empty(path_data->content_img)
|| ( string_is_empty(path_data->system)
&& string_is_empty(path_data->content_db_name)))
return false;
/* > Get current system */
if (string_is_empty(path_data->content_db_name))
{
/* If this is a content history or favorites playlist
* then the current 'path_data->system' string is
* meaningless. In this case, we fall back to the
* content directory name */
if ( string_is_equal(path_data->system, "history")
|| string_is_equal(path_data->system, "favorites"))
{
if (!gfx_thumbnail_get_content_dir(
path_data, content_dir, sizeof(content_dir)))
return false;
system_name = content_dir;
}
else
system_name = path_data->system;
}
else
system_name = path_data->content_db_name;
/* > Special case: thumbnail for imageviewer content
* is the image file itself */
if ( string_is_equal(system_name, "images_history")
|| string_is_equal(path_data->content_core_name, "imageviewer"))
{
/* imageviewer content is identical for left and right thumbnails */
if (path_is_media_type(path_data->content_path) == RARCH_CONTENT_IMAGE)
strlcpy(thumbnail_path,
path_data->content_path, PATH_MAX_LENGTH * sizeof(char));
}
else
{
char tmp_buf[PATH_MAX_LENGTH];
const char *type = gfx_thumbnail_get_type(settings,
path_data, thumbnail_id);
/* > Normal content: assemble path */
/* >> Base + system name */
fill_pathname_join_special(thumbnail_path, dir_thumbnails,
system_name, PATH_MAX_LENGTH * sizeof(char));
/* >> Add type */
fill_pathname_join_special(tmp_buf, thumbnail_path, type, sizeof(tmp_buf));
thumbnail_path[0] = '\0';
/* >> Add content image - first try with full file name */
if(path_data->content_img_full[0] != '\0') {
fill_pathname_join_special(thumbnail_path, tmp_buf,
path_data->content_img_full, PATH_MAX_LENGTH * sizeof(char));
}
/* >> Add content image - second try with label (database name) */
if(!path_is_valid(thumbnail_path) && path_data->content_img[0] != '\0')
{
thumbnail_path[0] = '\0';
fill_pathname_join_special(thumbnail_path, tmp_buf,
path_data->content_img, PATH_MAX_LENGTH * sizeof(char));
}
/* >> Add content image - third try with shortened name (title only) */
if(!path_is_valid(thumbnail_path) && path_data->content_img_short[0] != '\0')
{
thumbnail_path[0] = '\0';
fill_pathname_join_special(thumbnail_path, tmp_buf,
path_data->content_img_short, PATH_MAX_LENGTH * sizeof(char));
}
/* This logic is valid for locally stored thumbnails. For optional downloads,
* gfx_thumbnail_get_img_name() is used */
}
/* Final error check - is cached path empty? */
return !string_is_empty(thumbnail_path);
}
/* Getters */
/* Fetches the current thumbnail file path of the
* specified thumbnail 'type'.
* Returns true if path is valid. */
bool gfx_thumbnail_get_path(
gfx_thumbnail_path_data_t *path_data,
enum gfx_thumbnail_id thumbnail_id,
const char **path)
{
char *thumbnail_path = NULL;
if (!path_data || !path)
return false;
switch (thumbnail_id)
{
case GFX_THUMBNAIL_RIGHT:
if (!string_is_empty(path_data->right_path))
{
thumbnail_path = path_data->right_path;
*path = thumbnail_path;
return true;
}
break;
case GFX_THUMBNAIL_LEFT:
if (!string_is_empty(path_data->left_path))
{
thumbnail_path = path_data->left_path;
*path = thumbnail_path;
return true;
}
break;
default:
break;
}
return false;
}
/* Fetches current 'system' (default database name).
* Returns true if 'system' is valid. */
bool gfx_thumbnail_get_system(
gfx_thumbnail_path_data_t *path_data, const char **system)
{
if (!path_data || !system)
return false;
if (string_is_empty(path_data->system))
return false;
*system = path_data->system;
return true;
}
/* Fetches current thumbnail label.
* Returns true if label is valid. */
bool gfx_thumbnail_get_label(
gfx_thumbnail_path_data_t *path_data, const char **label)
{
if (!path_data || !label)
return false;
if (string_is_empty(path_data->content_label))
return false;
*label = path_data->content_label;
return true;
}
/* Fetches current thumbnail core name.
* Returns true if core name is valid. */
bool gfx_thumbnail_get_core_name(
gfx_thumbnail_path_data_t *path_data, const char **core_name)
{
if (!path_data || !core_name)
return false;
if (string_is_empty(path_data->content_core_name))
return false;
*core_name = path_data->content_core_name;
return true;
}
/* Fetches current thumbnail image name according to name flag
* (name is the same for all thumbnail types).
* Returns true if image name is valid. */
bool gfx_thumbnail_get_img_name(
gfx_thumbnail_path_data_t *path_data, const char **img_name,
enum playlist_thumbnail_name_flags name_flags)
{
if (!path_data || !img_name || name_flags == PLAYLIST_THUMBNAIL_FLAG_NONE)
return false;
if (name_flags & PLAYLIST_THUMBNAIL_FLAG_SHORT_NAME) {
if (string_is_empty(path_data->content_img_short))
return false;
*img_name = path_data->content_img_short;
}
else if (name_flags & PLAYLIST_THUMBNAIL_FLAG_STD_NAME) {
if (string_is_empty(path_data->content_img))
return false;
*img_name = path_data->content_img;
}
else if (name_flags & PLAYLIST_THUMBNAIL_FLAG_FULL_NAME) {
if (string_is_empty(path_data->content_img_full))
return false;
*img_name = path_data->content_img_full;
}
else
return false;
return true;
}
/* Fetches current content directory.
* Returns true if content directory is valid. */
bool gfx_thumbnail_get_content_dir(
gfx_thumbnail_path_data_t *path_data, char *content_dir, size_t len)
{
size_t path_length;
char tmp_buf[PATH_MAX_LENGTH];
const char *last_slash = NULL;
if (!path_data || string_is_empty(path_data->content_path))
return false;
if (!(last_slash = find_last_slash(path_data->content_path)))
return false;
path_length = last_slash + 1 - path_data->content_path;
if (!((path_length > 1) && (path_length < PATH_MAX_LENGTH)))
return false;
strlcpy(tmp_buf, path_data->content_path, path_length * sizeof(char));
strlcpy(content_dir, path_basename_nocompression(tmp_buf), len);
return !string_is_empty(content_dir);
}