From 0b571765d3f711eaab0a94add4f555ea9874bd3a Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Sat, 13 Jul 2013 12:31:01 +0200 Subject: [PATCH 1/2] Artwork file names made configurable --- forked-daapd.conf | 4 ++++ src/artwork.c | 23 ++++++++++++++--------- src/conffile.c | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/forked-daapd.conf b/forked-daapd.conf index f747f54b..ac422153 100644 --- a/forked-daapd.conf +++ b/forked-daapd.conf @@ -29,6 +29,10 @@ library { # Matches anywhere in the path (not a regexp, though) # compilations = { "/compilations/" } + # Artwork file names (without file type extension) + # forked-daapd will look for jpg and png files with these base names +# artwork_basenames = { "artwork", "cover" } + # Should iTunes metadata override ours? # itunes_overrides = true diff --git a/src/artwork.c b/src/artwork.c index 22382eb7..7eacd07b 100644 --- a/src/artwork.c +++ b/src/artwork.c @@ -37,17 +37,14 @@ #include "db.h" #include "logger.h" +#include "conffile.h" + #if LIBAVFORMAT_VERSION_MAJOR >= 53 # include "avio_evbuffer.h" #endif #include "artwork.h" -static const char *cover_basename[] = - { - "artwork", "cover", "folder", - }; - static const char *cover_extension[] = { "png", "jpg", @@ -674,6 +671,8 @@ artwork_get_dir_image(char *path, int isdir, int max_w, int max_h, int format, s int j; int len; int ret; + cfg_t *lib; + int nbasenames; ret = snprintf(artwork, sizeof(artwork), "%s", path); if ((ret < 0) || (ret >= sizeof(artwork))) @@ -692,14 +691,20 @@ artwork_get_dir_image(char *path, int isdir, int max_w, int max_h, int format, s len = strlen(artwork); - for (i = 0; i < (sizeof(cover_basename) / sizeof(cover_basename[0])); i++) + lib = cfg_getsec(cfg, "library"); + nbasenames = cfg_size(lib, "artwork_basenames"); + + if (nbasenames == 0) + return -1; + + for (i = 0; i < nbasenames; i++) { for (j = 0; j < (sizeof(cover_extension) / sizeof(cover_extension[0])); j++) { - ret = snprintf(artwork + len, sizeof(artwork) - len, "/%s.%s", cover_basename[i], cover_extension[j]); + ret = snprintf(artwork + len, sizeof(artwork) - len, "/%s.%s", cfg_getnstr(lib, "artwork_basenames", i), cover_extension[j]); if ((ret < 0) || (ret >= sizeof(artwork) - len)) { - DPRINTF(E_INFO, L_ART, "Artwork path exceeds PATH_MAX (%s.%s)\n", cover_basename[i], cover_extension[j]); + DPRINTF(E_INFO, L_ART, "Artwork path exceeds PATH_MAX (%s.%s)\n", cfg_getnstr(lib, "artwork_basenames", i), cover_extension[j]); continue; } @@ -717,7 +722,7 @@ artwork_get_dir_image(char *path, int isdir, int max_w, int max_h, int format, s break; } - if (i == (sizeof(cover_basename) / sizeof(cover_basename[0]))) + if (i == nbasenames) return -1; return artwork_get(artwork, max_w, max_h, format, evbuf); diff --git a/src/conffile.c b/src/conffile.c index 823e0d74..fdf127d0 100644 --- a/src/conffile.c +++ b/src/conffile.c @@ -61,6 +61,7 @@ static cfg_opt_t sec_library[] = CFG_STR("password", NULL, CFGF_NONE), CFG_STR_LIST("directories", NULL, CFGF_NONE), CFG_STR_LIST("compilations", NULL, CFGF_NONE), + CFG_STR_LIST("artwork_basenames", "{artwork,cover}", CFGF_NONE), CFG_BOOL("itunes_overrides", cfg_false, CFGF_NONE), CFG_STR_LIST("no_transcode", NULL, CFGF_NONE), CFG_STR_LIST("force_transcode", NULL, CFGF_NONE), From 48b7cd9a05396e13bbc1f5a7e9a6f44e87866da5 Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Sun, 14 Jul 2013 20:54:23 +0200 Subject: [PATCH 2/2] Adds looking for artwork named [directory name].{png,jpg} --- README | 7 ++++++ src/artwork.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/README b/README index a6f39a35..cae37b11 100644 --- a/README +++ b/README @@ -223,15 +223,22 @@ As for the naming convention, it is quite simple; consider your foo.mp3 song, residing at /bar/foo.mp3: - if /bar/foo.{png,jpg} exists, this will be used as the artwork for this file; - failing that, if /bar/{artwork,cover}.{png,jpg} exists, it will be used. + - failing that, if /bar/bar.{png,jpg} exists, it will be used For "groups" (same album name and album artist), the situation is a bit different: - if a file {artwork,cover}.{png,jpg} is found in one of the directories containing files that are part of the group, it is used as the artwork. The first file found is used, ordering is not guaranteed; + - failing that, if [directory name].{png,jpg} is found in one of the + directories containing files that are part of the group, it is used as the + artwork. The first file found is used, ordering is not guaranteed; - failing that, individual files are examined and the first artwork found is used. Here again, ordering is not guaranteed. +{artwork,cover} are the default, you can add other base names in the +configuration file. + You can use symlinks for the artwork files; the artwork is not scanned/indexed in any way in the database and there is no caching on forked-daapd's side. diff --git a/src/artwork.c b/src/artwork.c index 7eacd07b..faa3826e 100644 --- a/src/artwork.c +++ b/src/artwork.c @@ -47,7 +47,7 @@ static const char *cover_extension[] = { - "png", "jpg", + "jpg", "png", }; @@ -728,6 +728,64 @@ artwork_get_dir_image(char *path, int isdir, int max_w, int max_h, int format, s return artwork_get(artwork, max_w, max_h, format, evbuf); } +static int +artwork_get_parentdir_image(char *path, int isdir, int max_w, int max_h, int format, struct evbuffer *evbuf) +{ + char artwork[PATH_MAX]; + char parentdir[PATH_MAX]; + char *ptr; + int len; + int i; + int ret; + + ret = snprintf(artwork, sizeof(artwork), "%s", path); + if ((ret < 0) || (ret >= sizeof(artwork))) + { + DPRINTF(E_INFO, L_ART, "Artwork path exceeds PATH_MAX\n"); + + return -1; + } + + if (!isdir) + { + ptr = strrchr(artwork, '/'); + if (ptr) + *ptr = '\0'; + } + + ptr = strrchr(artwork, '/'); + if ((!ptr) || (strlen(ptr) <= 1)) + return -1; + strcpy(parentdir, ptr + 1); + + len = strlen(artwork); + + for (i = 0; i < (sizeof(cover_extension) / sizeof(cover_extension[0])); i++) + { + ret = snprintf(artwork + len, sizeof(artwork) - len, "/%s.%s", parentdir, cover_extension[i]); + if ((ret < 0) || (ret >= sizeof(artwork) - len)) + { + DPRINTF(E_INFO, L_ART, "Artwork path exceeds PATH_MAX (%s.%s)\n", parentdir, cover_extension[i]); + + continue; + } + + DPRINTF(E_DBG, L_ART, "Trying parent directory artwork file %s\n", artwork); + + ret = access(artwork, F_OK); + if (ret < 0) + continue; + + break; + } + + if (i == (sizeof(cover_extension) / sizeof(cover_extension[0]))) + return -1; + + return artwork_get(artwork, max_w, max_h, format, evbuf); +} + + int artwork_get_item_filename(char *filename, int max_w, int max_h, int format, struct evbuffer *evbuf) @@ -746,6 +804,11 @@ artwork_get_item_filename(char *filename, int max_w, int max_h, int format, stru if (ret > 0) return ret; + /* Look for parentdir(filename).{png,jpg} */ + ret = artwork_get_parentdir_image(filename, 0, max_w, max_h, format, evbuf); + if (ret > 0) + return ret; + return -1; } @@ -800,6 +863,8 @@ artwork_get_group(int id, int max_w, int max_h, int format, struct evbuffer *evb while ((got_art < 0) && ((ret = db_query_fetch_string(&qp, &dir)) == 0) && (dir)) { got_art = artwork_get_dir_image(dir, 1, max_w, max_h, format, evbuf); + if (got_art < 0) + got_art = artwork_get_parentdir_image(dir, 1, max_w, max_h, format, evbuf); } db_query_end(&qp);