Skip to content

Commit

Permalink
Flexible thumbnail matching (#16040)
Browse files Browse the repository at this point in the history
Add logic to handle 3 possible thumbnail names, in following order:
- most exact name derived from content file (same name, with .png extension)
- usual name derived from playlist (usually coming from database)
- shortened name up to first bracket, chopping off region/publisher etc. info

For local file system, names are checked always.
For thumbnail downloads, names are checked each time the item comes up
in the playlist, meaning that it may take going back and forth 3 times
for a thumbnail to appear. However, as a positive change, failed thumbnail
downloads are not repeated for the same playlist, which was not the case
earlier.
  • Loading branch information
zoltanvb authored Dec 27, 2023
1 parent 824a0f8 commit 3ce56c5
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 29 deletions.
16 changes: 12 additions & 4 deletions gfx/gfx_thumbnail.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,12 @@ void gfx_thumbnail_request(
const char *system = NULL;
const char *img_name = NULL;
static char last_img_name[PATH_MAX_LENGTH] = {0};

enum playlist_thumbnail_name_flags next_flag;
if (!playlist)
goto end;

/* Get current image name */
if (!gfx_thumbnail_get_img_name(path_data, &img_name))
/* Validate entry */
if (!gfx_thumbnail_get_img_name(path_data, &img_name, PLAYLIST_THUMBNAIL_FLAG_STD_NAME))
goto end;

/* Only trigger a thumbnail download if image
Expand All @@ -321,7 +321,15 @@ void gfx_thumbnail_request(
if (!gfx_thumbnail_get_system(path_data, &system))
goto end;

/* Trigger thumbnail download */
/* Apply flexible thumbnail naming: ROM file name - database name - short name */
next_flag = playlist_get_next_thumbnail_name_flag(playlist,idx);
if (next_flag == PLAYLIST_THUMBNAIL_FLAG_NONE)
goto end;

/* Trigger thumbnail download *
* Note: download will grab all 3 possible thumbnails, no matter
* what left/right thumbnails are set at the moment */
playlist_update_thumbnail_name_flag(playlist, idx, next_flag);
task_push_pl_entry_thumbnail_download(
system, playlist, (unsigned)idx,
false, true);
Expand Down
83 changes: 63 additions & 20 deletions gfx/gfx_thumbnail_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,23 @@

/* 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)
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 > 2)
_len = bracketpos;
}
/* Scrub characters that are not cross-platform and/or violate the
* No-Intro filename standard:
* http://datomatic.no-intro.org/stuff/The%20Official%20No-Intro%20Convention%20(20071030).zip
* 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 = '_';
Expand Down Expand Up @@ -289,7 +298,9 @@ bool gfx_thumbnail_set_content(gfx_thumbnail_path_data_t *path_data, const char

/* Determine content image name */
gfx_thumbnail_fill_content_img(path_data->content_img,
sizeof(path_data->content_img), path_data->content_label);
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) */
Expand Down Expand Up @@ -444,8 +455,6 @@ bool gfx_thumbnail_set_content_playlist(
"", sizeof(path_data->content_label));

/* Determine content image name */
if (settings->bools.playlist_use_filename ||
playlist_thumbnail_match_with_filename(playlist))
{
char* content_name_no_ext = NULL;
char tmp_buf[PATH_MAX_LENGTH];
Expand All @@ -457,13 +466,12 @@ bool gfx_thumbnail_set_content_playlist(
strlcpy(tmp_buf, base_name, sizeof(tmp_buf));
content_name_no_ext = path_remove_extension(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), content_name_no_ext);
}
else
{
gfx_thumbnail_fill_content_img(path_data->content_img,
sizeof(path_data->content_img), path_data->content_label);
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);
}

/* Store playlist index */
Expand Down Expand Up @@ -620,10 +628,28 @@ bool gfx_thumbnail_update_path(
/* >> Add type */
fill_pathname_join_special(tmp_buf, thumbnail_path, type, sizeof(tmp_buf));

/* >> Add content image */
thumbnail_path[0] = '\0';
fill_pathname_join_special(thumbnail_path, tmp_buf,
path_data->content_img, PATH_MAX_LENGTH * sizeof(char));
/* >> 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? */
Expand Down Expand Up @@ -715,18 +741,35 @@ bool gfx_thumbnail_get_core_name(
return true;
}

/* Fetches current thumbnail image name
/* 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)
gfx_thumbnail_path_data_t *path_data, const char **img_name,
enum playlist_thumbnail_name_flags name_flags)
{
if (!path_data || !img_name)
return false;
if (string_is_empty(path_data->content_img))
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;
*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;
}
Expand Down
4 changes: 3 additions & 1 deletion gfx/gfx_thumbnail_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ struct gfx_thumbnail_path_data
size_t playlist_index;
char content_path[PATH_MAX_LENGTH];
char content_img[PATH_MAX_LENGTH];
char content_img_short[PATH_MAX_LENGTH];
char content_img_full[PATH_MAX_LENGTH];
char right_path[PATH_MAX_LENGTH];
char left_path[PATH_MAX_LENGTH];
char content_label[256];
Expand Down Expand Up @@ -147,7 +149,7 @@ bool gfx_thumbnail_get_core_name(gfx_thumbnail_path_data_t *path_data, const cha
/* Fetches current thumbnail image name
* (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);
bool gfx_thumbnail_get_img_name(gfx_thumbnail_path_data_t *path_data, const char **img_name, enum playlist_thumbnail_name_flags name_flags);

/* Fetches current content directory.
* Returns true if content directory is valid. */
Expand Down
42 changes: 42 additions & 0 deletions playlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,48 @@ bool playlist_push_runtime(playlist_t *playlist,
return false;
}

void playlist_update_thumbnail_name_flag(playlist_t *playlist, size_t idx,
enum playlist_thumbnail_name_flags thumbnail_flags)
{
struct playlist_entry *entry = NULL;

if (!playlist || idx >= RBUF_LEN(playlist->entries))
return;

entry = &playlist->entries[idx];
entry->thumbnail_flags |= thumbnail_flags;
}

enum playlist_thumbnail_name_flags playlist_get_curr_thumbnail_name_flag(playlist_t *playlist, size_t idx)
{
struct playlist_entry *entry = NULL;

if (!playlist || idx >= RBUF_LEN(playlist->entries))
return PLAYLIST_THUMBNAIL_FLAG_NONE;

entry = &playlist->entries[idx];
return entry->thumbnail_flags;
}


enum playlist_thumbnail_name_flags playlist_get_next_thumbnail_name_flag(playlist_t *playlist, size_t idx)
{
struct playlist_entry *entry = NULL;

if (!playlist || idx >= RBUF_LEN(playlist->entries))
return PLAYLIST_THUMBNAIL_FLAG_NONE;
entry = &playlist->entries[idx];

if (entry->thumbnail_flags & PLAYLIST_THUMBNAIL_FLAG_SHORT_NAME)
return PLAYLIST_THUMBNAIL_FLAG_NONE;
if (entry->thumbnail_flags & PLAYLIST_THUMBNAIL_FLAG_STD_NAME)
return PLAYLIST_THUMBNAIL_FLAG_SHORT_NAME;
if (entry->thumbnail_flags & PLAYLIST_THUMBNAIL_FLAG_FULL_NAME)
return PLAYLIST_THUMBNAIL_FLAG_STD_NAME;
return PLAYLIST_THUMBNAIL_FLAG_FULL_NAME;
}


/**
* playlist_resolve_path:
* @mode : PLAYLIST_LOAD or PLAYLIST_SAVE
Expand Down
15 changes: 15 additions & 0 deletions playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ enum playlist_thumbnail_id
PLAYLIST_THUMBNAIL_LEFT
};

enum playlist_thumbnail_name_flags
{
PLAYLIST_THUMBNAIL_FLAG_INVALID = 0,
PLAYLIST_THUMBNAIL_FLAG_FULL_NAME = (1 << 0),
PLAYLIST_THUMBNAIL_FLAG_STD_NAME = (1 << 1),
PLAYLIST_THUMBNAIL_FLAG_SHORT_NAME = (1 << 2),
PLAYLIST_THUMBNAIL_FLAG_NONE = (1 << 3)
};

typedef struct content_playlist playlist_t;

/* Holds all parameters required to uniquely
Expand Down Expand Up @@ -129,6 +138,7 @@ struct playlist_entry
unsigned last_played_minute;
unsigned last_played_second;
enum playlist_runtime_status runtime_status;
enum playlist_thumbnail_name_flags thumbnail_flags;
};

/* Holds all configuration parameters required
Expand Down Expand Up @@ -291,6 +301,11 @@ void playlist_update_runtime(playlist_t *playlist, size_t idx,
const struct playlist_entry *update_entry,
bool register_update);

void playlist_update_thumbnail_name_flag(playlist_t *playlist, size_t idx,
enum playlist_thumbnail_name_flags thumbnail_flags);
enum playlist_thumbnail_name_flags playlist_get_next_thumbnail_name_flag(playlist_t *playlist, size_t idx);
enum playlist_thumbnail_name_flags playlist_get_curr_thumbnail_name_flag(playlist_t *playlist, size_t idx);

void playlist_get_index_by_path(playlist_t *playlist,
const char *search_path,
const struct playlist_entry **entry);
Expand Down
15 changes: 11 additions & 4 deletions tasks/task_pl_thumbnail_download.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ typedef struct pl_thumb_handle
unsigned type_idx;

enum pl_thumb_status status;

enum playlist_thumbnail_name_flags name_flags;

uint8_t flags;
} pl_thumb_handle_t;

Expand Down Expand Up @@ -155,7 +156,7 @@ static bool get_thumbnail_paths(
/* Extract required strings */
gfx_thumbnail_get_system( pl_thumb->thumbnail_path_data, &system);
gfx_thumbnail_get_db_name(pl_thumb->thumbnail_path_data, &db_name);
if (!gfx_thumbnail_get_img_name(pl_thumb->thumbnail_path_data, &img_name))
if (!gfx_thumbnail_get_img_name(pl_thumb->thumbnail_path_data, &img_name, pl_thumb->name_flags))
return false;
if (!gfx_thumbnail_get_sub_directory(pl_thumb->type_idx, &sub_dir))
return false;
Expand Down Expand Up @@ -816,7 +817,8 @@ bool task_push_pl_entry_thumbnail_download(
gfx_thumbnail_path_data_t *
thumbnail_path_data = NULL;
const char *dir_thumbnails = NULL;

enum playlist_thumbnail_name_flags curr_flag = PLAYLIST_THUMBNAIL_FLAG_INVALID;

/* Sanity check */
if (!settings || !task || !pl_thumb || !playlist || !entry_id)
goto error;
Expand Down Expand Up @@ -871,7 +873,11 @@ bool task_push_pl_entry_thumbnail_download(
if (!gfx_thumbnail_set_content_playlist(
thumbnail_path_data, playlist, idx))
goto error;


curr_flag = playlist_get_curr_thumbnail_name_flag(playlist,idx);
if (curr_flag == PLAYLIST_THUMBNAIL_FLAG_NONE)
goto error;

/* Configure handle
* > Note: playlist_config is unused by this task */
pl_thumb->system = NULL;
Expand All @@ -883,6 +889,7 @@ bool task_push_pl_entry_thumbnail_download(
pl_thumb->list_size = playlist_size(playlist);
pl_thumb->list_index = idx;
pl_thumb->type_idx = 1;
pl_thumb->name_flags = curr_flag;
pl_thumb->status = PL_THUMB_BEGIN;

if (overwrite)
Expand Down

0 comments on commit 3ce56c5

Please sign in to comment.