From f657780a42cb7246b7a5b18450f40a03cd789c45 Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Sat, 16 Dec 2023 00:11:54 +0100 Subject: [PATCH] [scan] Fix issue where albums get split Regression from PR #1655. This reverts the metadata search to the method used before the PR, so that search is done in the order set by the metadata maps. This means the songalbumid is set by the tag with the highest precedence, not just the first one found. Closes #1696 --- src/library/filescanner_ffmpeg.c | 82 ++++++++++++++------------------ 1 file changed, 36 insertions(+), 46 deletions(-) diff --git a/src/library/filescanner_ffmpeg.c b/src/library/filescanner_ffmpeg.c index 4f2722ff92..4d92dc91be 100644 --- a/src/library/filescanner_ffmpeg.c +++ b/src/library/filescanner_ffmpeg.c @@ -49,6 +49,7 @@ struct metadata_map { int as_int; size_t offset; int (*handler_function)(struct media_file_info *, const char *); + int flags; }; // Used for passing errors to DPRINTF (can't count on av_err2str being present) @@ -196,7 +197,7 @@ static const struct metadata_map md_map_generic[] = { "artist-sort", 0, mfi_offsetof(artist_sort), NULL }, { "album-sort", 0, mfi_offsetof(album_sort), NULL }, { "compilation", 1, mfi_offsetof(compilation), NULL }, - { "lyrics", 0, mfi_offsetof(lyrics), NULL }, + { "lyrics", 0, mfi_offsetof(lyrics), NULL, AV_DICT_IGNORE_SUFFIX }, // ALAC sort tags { "sort_name", 0, mfi_offsetof(title_sort), NULL }, @@ -288,65 +289,56 @@ static const struct metadata_map md_map_id3[] = { NULL, 0, 0, NULL } }; - static int -extract_metadata_from_kv(struct media_file_info *mfi, const char *key, const char *value, const struct metadata_map *md_map) +extract_metadata_from_dict(struct media_file_info *mfi, AVDictionary *md, const struct metadata_map *md_map) { + AVDictionaryEntry *mdt; char **strval; uint32_t *intval; + int mdcount = 0; int i; - if ((value == NULL) || (strlen(value) == 0)) - return 0; - - if (strncasecmp(key, "lyrics-", sizeof("lyrics-") - 1) == 0) - key = "lyrics"; - - for (i = 0; md_map[i].key != NULL; i++) +#if 0 + /* Dump all the metadata reported by ffmpeg */ + while ((mdt = av_dict_iterate(md, mdt))) { - if (strcasecmp(key, md_map[i].key) == 0) - break; + DPRINTF(E_DBG, L_SCAN, " -> %s = %s\n", mdt->key, mdt->value); } +#endif - if (md_map[i].key == NULL) - return 0; // Not found in map - - if (md_map[i].handler_function) - return md_map[i].handler_function(mfi, value); - - if (!md_map[i].as_int) + for (i = 0; md_map[i].key != NULL; i++) { - strval = (char **) ((char *) mfi + md_map[i].offset); + mdt = av_dict_get(md, md_map[i].key, NULL, md_map[i].flags); + if (!mdt || !mdt->value || strlen(mdt->value) == 0) + continue; - if (*strval != NULL) - return 0; + if (md_map[i].handler_function) + { + mdcount += md_map[i].handler_function(mfi, mdt->value); + continue; + } - *strval = strdup(value); - } - else - { - intval = (uint32_t *) ((char *) mfi + md_map[i].offset); + if (!md_map[i].as_int) + { + strval = (char **) ((char *) mfi + md_map[i].offset); - if (*intval != 0) - return 0; + if (*strval != NULL) + continue; - if (safe_atou32(value, intval) < 0) - return 0; - } + *strval = strdup(mdt->value); + } + else + { + intval = (uint32_t *) ((char *) mfi + md_map[i].offset); - return 1; -} + if (*intval != 0) + continue; -static int -extract_metadata_from_dict(struct media_file_info *mfi, AVDictionary *md, const struct metadata_map *md_map) -{ - const AVDictionaryEntry *mdt = NULL; - int mdcount = 0; + if (safe_atou32(mdt->value, intval) < 0) + continue; + } - while ((mdt = av_dict_iterate(md, mdt))) - { -// DPRINTF(E_DBG, L_SCAN, " -> %s = %s\n", mdt->key, mdt->value); - mdcount += extract_metadata_from_kv(mfi, mdt->key, mdt->value, md_map); + mdcount++; } return mdcount; @@ -355,11 +347,9 @@ extract_metadata_from_dict(struct media_file_info *mfi, AVDictionary *md, const static int extract_metadata(struct media_file_info *mfi, AVFormatContext *ctx, AVStream *audio_stream, AVStream *video_stream, const struct metadata_map *md_map) { - int mdcount; + int mdcount = 0; int ret; - mdcount = 0; - if (ctx->metadata) { ret = extract_metadata_from_dict(mfi, ctx->metadata, md_map);