Merge pull request #75 from couteau/ownartwork (and additional artwork.c overhaul)
This commit is contained in:
commit
a9bc1a21dc
|
@ -91,6 +91,11 @@ library {
|
||||||
# forked-daapd will look for jpg and png files with these base names
|
# forked-daapd will look for jpg and png files with these base names
|
||||||
# artwork_basenames = { "artwork", "cover", "Folder" }
|
# artwork_basenames = { "artwork", "cover", "Folder" }
|
||||||
|
|
||||||
|
# Enable searching for artwork corresponding to each individual media
|
||||||
|
# file instead of only looking for album artwork. This is disabled by
|
||||||
|
# default to reduce cache size.
|
||||||
|
# artwork_individual = false
|
||||||
|
|
||||||
# File types the scanner should ignore
|
# File types the scanner should ignore
|
||||||
# Non-audio files will never be added to the database, but here you
|
# Non-audio files will never be added to the database, but here you
|
||||||
# can prevent the scanner from even probing them. This might improve
|
# can prevent the scanner from even probing them. This might improve
|
||||||
|
|
394
src/artwork.c
394
src/artwork.c
|
@ -58,17 +58,17 @@ static const char *cover_extension[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
artwork_read(char *filename, struct evbuffer *evbuf)
|
artwork_read(char *path, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
uint8_t buf[4096];
|
uint8_t buf[4096];
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int fd;
|
int fd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY);
|
fd = open(path, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_ART, "Could not open artwork file '%s': %s\n", filename, strerror(errno));
|
DPRINTF(E_WARN, L_ART, "Could not open artwork file '%s': %s\n", path, strerror(errno));
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ artwork_read(char *filename, struct evbuffer *evbuf)
|
||||||
ret = fstat(fd, &sb);
|
ret = fstat(fd, &sb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_ART, "Could not stat() artwork file '%s': %s\n", filename, strerror(errno));
|
DPRINTF(E_WARN, L_ART, "Could not stat() artwork file '%s': %s\n", path, strerror(errno));
|
||||||
|
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
@ -621,7 +621,7 @@ artwork_rescale(AVFormatContext *src_ctx, int s, int out_w, int out_h, struct ev
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
artwork_get(char *filename, int max_w, int max_h, struct evbuffer *evbuf)
|
artwork_get(char *path, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
AVFormatContext *src_ctx;
|
AVFormatContext *src_ctx;
|
||||||
int s;
|
int s;
|
||||||
|
@ -635,13 +635,13 @@ artwork_get(char *filename, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
src_ctx = NULL;
|
src_ctx = NULL;
|
||||||
|
|
||||||
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
|
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
|
||||||
ret = avformat_open_input(&src_ctx, filename, NULL, NULL);
|
ret = avformat_open_input(&src_ctx, path, NULL, NULL);
|
||||||
#else
|
#else
|
||||||
ret = av_open_input_file(&src_ctx, filename, NULL, 0, NULL);
|
ret = av_open_input_file(&src_ctx, path, NULL, 0, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_ART, "Cannot open artwork file '%s': %s\n", filename, strerror(AVUNERROR(ret)));
|
DPRINTF(E_WARN, L_ART, "Cannot open artwork file '%s': %s\n", path, strerror(AVUNERROR(ret)));
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -688,7 +688,7 @@ artwork_get(char *filename, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
|
|
||||||
if (s == src_ctx->nb_streams)
|
if (s == src_ctx->nb_streams)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_ART, "Artwork file '%s' not a PNG or JPEG file\n", filename);
|
DPRINTF(E_LOG, L_ART, "Artwork file '%s' not a PNG or JPEG file\n", path);
|
||||||
|
|
||||||
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21)
|
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21)
|
||||||
avformat_close_input(&src_ctx);
|
avformat_close_input(&src_ctx);
|
||||||
|
@ -703,7 +703,7 @@ artwork_get(char *filename, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
/* Fastpath */
|
/* Fastpath */
|
||||||
if (!ret && format_ok)
|
if (!ret && format_ok)
|
||||||
{
|
{
|
||||||
ret = artwork_read(filename, evbuf);
|
ret = artwork_read(path, evbuf);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = format_ok;
|
ret = format_ok;
|
||||||
}
|
}
|
||||||
|
@ -727,7 +727,7 @@ artwork_get(char *filename, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
|
|
||||||
#if LIBAVFORMAT_VERSION_MAJOR >= 55 || (LIBAVFORMAT_VERSION_MAJOR == 54 && LIBAVFORMAT_VERSION_MINOR >= 6)
|
#if LIBAVFORMAT_VERSION_MAJOR >= 55 || (LIBAVFORMAT_VERSION_MAJOR == 54 && LIBAVFORMAT_VERSION_MINOR >= 6)
|
||||||
static int
|
static int
|
||||||
artwork_get_embedded_image(char *filename, int max_w, int max_h, struct evbuffer *evbuf)
|
artwork_get_embedded_image(char *path, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
AVFormatContext *src_ctx;
|
AVFormatContext *src_ctx;
|
||||||
AVStream *src_st;
|
AVStream *src_st;
|
||||||
|
@ -737,14 +737,14 @@ artwork_get_embedded_image(char *filename, int max_w, int max_h, struct evbuffer
|
||||||
int format_ok;
|
int format_ok;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DPRINTF(E_SPAM, L_ART, "Trying embedded artwork in %s\n", filename);
|
DPRINTF(E_SPAM, L_ART, "Trying embedded artwork in %s\n", path);
|
||||||
|
|
||||||
src_ctx = NULL;
|
src_ctx = NULL;
|
||||||
|
|
||||||
ret = avformat_open_input(&src_ctx, filename, NULL, NULL);
|
ret = avformat_open_input(&src_ctx, path, NULL, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_ART, "Cannot open media file '%s': %s\n", filename, strerror(AVUNERROR(ret)));
|
DPRINTF(E_WARN, L_ART, "Cannot open media file '%s': %s\n", path, strerror(AVUNERROR(ret)));
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -786,13 +786,13 @@ artwork_get_embedded_image(char *filename, int max_w, int max_h, struct evbuffer
|
||||||
|
|
||||||
if (s == src_ctx->nb_streams)
|
if (s == src_ctx->nb_streams)
|
||||||
{
|
{
|
||||||
DPRINTF(E_SPAM, L_ART, "Did not find embedded artwork in '%s'\n", filename);
|
DPRINTF(E_SPAM, L_ART, "Did not find embedded artwork in '%s'\n", path);
|
||||||
|
|
||||||
avformat_close_input(&src_ctx);
|
avformat_close_input(&src_ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DPRINTF(E_DBG, L_ART, "Found embedded artwork in '%s'\n", filename);
|
DPRINTF(E_DBG, L_ART, "Found embedded artwork in '%s'\n", path);
|
||||||
|
|
||||||
src_st = src_ctx->streams[s];
|
src_st = src_ctx->streams[s];
|
||||||
|
|
||||||
|
@ -839,10 +839,88 @@ artwork_get_embedded_image(char *filename, int max_w, int max_h, struct evbuffer
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Looks for basename(in_path).{png,jpg}, so if is in_path is /foo/bar.mp3 it
|
||||||
|
* will look for /foo/bar.png and /foo/bar.jpg
|
||||||
|
*
|
||||||
|
* @param in_path path to the item we are getting artwork for
|
||||||
|
* @param max_w maximum image width
|
||||||
|
* @param max_h maximum image height
|
||||||
|
* @param out_path path to artwork, input must be either NULL or char[PATH_MAX]
|
||||||
|
* @param evbuf the event buffer that will contain the (scaled) image
|
||||||
|
* @return ART_FMT_* on success, 0 on nothing found, -1 on error
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
artwork_get_dir_image(char *path, int max_w, int max_h, char *filename, struct evbuffer *evbuf)
|
artwork_get_own_image(char *in_path, int max_w, int max_h, char *out_path, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
char artwork[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
char *ptr;
|
||||||
|
int len;
|
||||||
|
int nextensions;
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = snprintf(path, sizeof(path), "%s", in_path);
|
||||||
|
if ((ret < 0) || (ret >= sizeof(path)))
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_ART, "Artwork path exceeds PATH_MAX (%s)\n", in_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = strrchr(path, '.');
|
||||||
|
if (ptr)
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
len = strlen(path);
|
||||||
|
|
||||||
|
nextensions = sizeof(cover_extension) / sizeof(cover_extension[0]);
|
||||||
|
|
||||||
|
for (i = 0; i < nextensions; i++)
|
||||||
|
{
|
||||||
|
ret = snprintf(path + len, sizeof(path) - len, ".%s", cover_extension[i]);
|
||||||
|
if ((ret < 0) || (ret >= sizeof(path) - len))
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_ART, "Artwork path will exceed PATH_MAX (%s)\n", in_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(E_SPAM, L_ART, "Trying own artwork file %s\n", path);
|
||||||
|
|
||||||
|
ret = access(path, F_OK);
|
||||||
|
if (ret < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == nextensions)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_ART, "Found own artwork file %s\n", path);
|
||||||
|
|
||||||
|
if (out_path)
|
||||||
|
strcpy(out_path, path);
|
||||||
|
|
||||||
|
return artwork_get(path, max_w, max_h, evbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Looks for cover files in a directory, so if dir is /foo/bar and the user has
|
||||||
|
* configured the cover file names "cover" and "artwork" it will look for
|
||||||
|
* /foo/bar/cover.{png,jpg}, /foo/bar/artwork.{png,jpg} and also
|
||||||
|
* /foo/bar/bar.{png,jpg} (so called parentdir artwork)
|
||||||
|
*
|
||||||
|
* @param dir the directory to search
|
||||||
|
* @param max_w maximum image width
|
||||||
|
* @param max_h maximum image height
|
||||||
|
* @param out_path path to artwork, input must be either NULL or char[PATH_MAX]
|
||||||
|
* @param evbuf the event buffer that will contain the (scaled) image
|
||||||
|
* @return ART_FMT_* on success, 0 on nothing found, -1 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
artwork_get_dir_image(char *dir, int max_w, int max_h, char *out_path, struct evbuffer *evbuf)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
char parentdir[PATH_MAX];
|
char parentdir[PATH_MAX];
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
@ -853,21 +931,20 @@ artwork_get_dir_image(char *path, int max_w, int max_h, char *filename, struct e
|
||||||
int nextensions;
|
int nextensions;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
ret = snprintf(artwork, sizeof(artwork), "%s", path);
|
ret = snprintf(path, sizeof(path), "%s", dir);
|
||||||
if ((ret < 0) || (ret >= sizeof(artwork)))
|
if ((ret < 0) || (ret >= sizeof(path)))
|
||||||
{
|
{
|
||||||
DPRINTF(E_INFO, L_ART, "Artwork path exceeds PATH_MAX\n");
|
DPRINTF(E_LOG, L_ART, "Artwork path exceeds PATH_MAX (%s)\n", dir);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(artwork);
|
len = strlen(path);
|
||||||
|
|
||||||
lib = cfg_getsec(cfg, "library");
|
lib = cfg_getsec(cfg, "library");
|
||||||
nbasenames = cfg_size(lib, "artwork_basenames");
|
nbasenames = cfg_size(lib, "artwork_basenames");
|
||||||
|
|
||||||
if (nbasenames == 0)
|
if (nbasenames == 0)
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
nextensions = sizeof(cover_extension) / sizeof(cover_extension[0]);
|
nextensions = sizeof(cover_extension) / sizeof(cover_extension[0]);
|
||||||
|
|
||||||
|
@ -875,17 +952,16 @@ artwork_get_dir_image(char *path, int max_w, int max_h, char *filename, struct e
|
||||||
{
|
{
|
||||||
for (j = 0; j < nextensions; j++)
|
for (j = 0; j < nextensions; j++)
|
||||||
{
|
{
|
||||||
ret = snprintf(artwork + len, sizeof(artwork) - len, "/%s.%s", cfg_getnstr(lib, "artwork_basenames", i), cover_extension[j]);
|
ret = snprintf(path + len, sizeof(path) - len, "/%s.%s", cfg_getnstr(lib, "artwork_basenames", i), cover_extension[j]);
|
||||||
if ((ret < 0) || (ret >= sizeof(artwork) - len))
|
if ((ret < 0) || (ret >= sizeof(path) - len))
|
||||||
{
|
{
|
||||||
DPRINTF(E_INFO, L_ART, "Artwork path exceeds PATH_MAX (%s.%s)\n", cfg_getnstr(lib, "artwork_basenames", i), cover_extension[j]);
|
DPRINTF(E_LOG, L_ART, "Artwork path will exceed PATH_MAX (%s/%s)\n", dir, cfg_getnstr(lib, "artwork_basenames", i));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_SPAM, L_ART, "Trying directory artwork file %s\n", artwork);
|
DPRINTF(E_SPAM, L_ART, "Trying directory artwork file %s\n", path);
|
||||||
|
|
||||||
ret = access(artwork, F_OK);
|
ret = access(path, F_OK);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -901,29 +977,32 @@ artwork_get_dir_image(char *path, int max_w, int max_h, char *filename, struct e
|
||||||
// If the loop for directory artwork did not exit early, look for parent directory artwork
|
// If the loop for directory artwork did not exit early, look for parent directory artwork
|
||||||
if (i == nbasenames)
|
if (i == nbasenames)
|
||||||
{
|
{
|
||||||
ptr = strrchr(artwork, '/');
|
ptr = strrchr(path, '/');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
||||||
ptr = strrchr(artwork, '/');
|
ptr = strrchr(path, '/');
|
||||||
if ((!ptr) || (strlen(ptr) <= 1))
|
if ((!ptr) || (strlen(ptr) <= 1))
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_ART, "Could not find parent dir name (%s)\n", path);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
strcpy(parentdir, ptr + 1);
|
strcpy(parentdir, ptr + 1);
|
||||||
|
|
||||||
len = strlen(artwork);
|
len = strlen(path);
|
||||||
|
|
||||||
for (i = 0; i < nextensions; i++)
|
for (i = 0; i < nextensions; i++)
|
||||||
{
|
{
|
||||||
ret = snprintf(artwork + len, sizeof(artwork) - len, "/%s.%s", parentdir, cover_extension[i]);
|
ret = snprintf(path + len, sizeof(path) - len, "/%s.%s", parentdir, cover_extension[i]);
|
||||||
if ((ret < 0) || (ret >= sizeof(artwork) - len))
|
if ((ret < 0) || (ret >= sizeof(path) - len))
|
||||||
{
|
{
|
||||||
DPRINTF(E_INFO, L_ART, "Artwork path exceeds PATH_MAX (%s.%s)\n", parentdir, cover_extension[i]);
|
DPRINTF(E_LOG, L_ART, "Artwork path will exceed PATH_MAX (%s)\n", parentdir);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_SPAM, L_ART, "Trying parent directory artwork file %s\n", artwork);
|
DPRINTF(E_SPAM, L_ART, "Trying parent directory artwork file %s\n", path);
|
||||||
|
|
||||||
ret = access(artwork, F_OK);
|
ret = access(path, F_OK);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -931,42 +1010,99 @@ artwork_get_dir_image(char *path, int max_w, int max_h, char *filename, struct e
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == nextensions)
|
if (i == nextensions)
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_ART, "Found directory artwork file %s\n", artwork);
|
DPRINTF(E_DBG, L_ART, "Found directory artwork file %s\n", path);
|
||||||
strcpy(filename, artwork);
|
|
||||||
|
|
||||||
return artwork_get(artwork, max_w, max_h, evbuf);
|
if (out_path)
|
||||||
|
strcpy(out_path, path);
|
||||||
|
|
||||||
|
return artwork_get(path, max_w, max_h, evbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given an artwork type (eg embedded, Spotify, own) this function will direct
|
||||||
|
* to the appropriate handler
|
||||||
|
*
|
||||||
|
* @param in_path path to the item we are getting artwork for
|
||||||
|
* @param artwork type of the artwork
|
||||||
|
* @param max_w maximum image width
|
||||||
|
* @param max_h maximum image height
|
||||||
|
* @param out_path path to artwork, input must be either NULL or char[PATH_MAX]
|
||||||
|
* @param evbuf the event buffer that will contain the (scaled) image
|
||||||
|
* @return ART_FMT_* on success, 0 on nothing found, -1 on error
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
artwork_get_item_path(char *path, int artwork, int max_w, int max_h, struct evbuffer *evbuf)
|
artwork_get_item_path(char *in_path, int artwork, int max_w, int max_h, char *out_path, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
if (out_path)
|
||||||
|
strcpy(out_path, in_path);
|
||||||
|
|
||||||
switch (artwork)
|
switch (artwork)
|
||||||
{
|
{
|
||||||
case ARTWORK_NONE:
|
case ARTWORK_NONE:
|
||||||
break;
|
break;
|
||||||
|
case ARTWORK_UNKNOWN:
|
||||||
|
case ARTWORK_OWN:
|
||||||
|
if (cfg_getbool(cfg_getsec(cfg, "library"), "artwork_individual"))
|
||||||
|
ret = artwork_get_own_image(in_path, max_w, max_h, out_path, evbuf);
|
||||||
|
break;
|
||||||
#ifdef HAVE_SPOTIFY_H
|
#ifdef HAVE_SPOTIFY_H
|
||||||
case ARTWORK_SPOTIFY:
|
case ARTWORK_SPOTIFY:
|
||||||
ret = spotify_artwork_get(evbuf, path, max_w, max_h);
|
ret = spotify_artwork_get(evbuf, in_path, max_w, max_h);
|
||||||
(ret < 0) ? (ret = 0) : (ret = ART_FMT_JPEG);
|
(ret < 0) ? (ret = 0) : (ret = ART_FMT_JPEG);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if LIBAVFORMAT_VERSION_MAJOR >= 55 || (LIBAVFORMAT_VERSION_MAJOR == 54 && LIBAVFORMAT_VERSION_MINOR >= 6)
|
#if LIBAVFORMAT_VERSION_MAJOR >= 55 || (LIBAVFORMAT_VERSION_MAJOR == 54 && LIBAVFORMAT_VERSION_MINOR >= 6)
|
||||||
case ARTWORK_EMBEDDED:
|
case ARTWORK_EMBEDDED:
|
||||||
ret = artwork_get_embedded_image(path, max_w, max_h, evbuf);
|
ret = artwork_get_embedded_image(in_path, max_w, max_h, evbuf);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret > 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
else
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the artwork for the given media file and the given maxiumum width/height
|
||||||
|
|
||||||
|
* @param mfi the media file structure for the file whose image should be returned
|
||||||
|
* @param max_w maximum image width
|
||||||
|
* @param max_h maximum image height
|
||||||
|
* @param evbuf the event buffer that will contain the (scaled) image
|
||||||
|
* @return ART_FMT_* on success, 0 on nothing found, -1 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
artwork_get_item_mfi(struct media_file_info *mfi, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
int cached;
|
||||||
|
int format;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_ART, "Looking for artwork for item with id %d\n", mfi->id);
|
||||||
|
|
||||||
|
ret = cache_artwork_get(CACHE_ARTWORK_INDIVIDUAL, mfi->id, max_w, max_h, &cached, &format, evbuf);
|
||||||
|
if ((ret == 0) && cached)
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_ART, "Item %d found in cache with format %d\n", mfi->id, format);
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mfi->data_kind == 0)
|
||||||
|
{
|
||||||
|
format = artwork_get_item_path(mfi->path, mfi->artwork, max_w, max_h, path, evbuf);
|
||||||
|
|
||||||
|
if (format > 0)
|
||||||
|
cache_artwork_add(CACHE_ARTWORK_INDIVIDUAL, mfi->id, max_w, max_h, format, path, evbuf);
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,47 +1116,35 @@ artwork_get_item_path(char *path, int artwork, int max_w, int max_h, struct evbu
|
||||||
* @param max_w maximum image width
|
* @param max_w maximum image width
|
||||||
* @param max_h maximum image height
|
* @param max_h maximum image height
|
||||||
* @param evbuf the event buffer that will contain the (scaled) image
|
* @param evbuf the event buffer that will contain the (scaled) image
|
||||||
|
* @return ART_FMT_* on success, 0 on nothing found, -1 on error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
artwork_get_group_persistentid(int64_t persistentid, int max_w, int max_h, struct evbuffer *evbuf)
|
artwork_get_group_persistentid(int64_t persistentid, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct db_media_file_info dbmfi;
|
struct db_media_file_info dbmfi;
|
||||||
|
char path[PATH_MAX];
|
||||||
char *dir;
|
char *dir;
|
||||||
int got_art;
|
|
||||||
int cached;
|
int cached;
|
||||||
int format;
|
int format;
|
||||||
char filename[PATH_MAX];
|
|
||||||
int ret;
|
int ret;
|
||||||
int artwork;
|
int artwork;
|
||||||
int got_spotifyitem;
|
int got_spotifyitem;
|
||||||
uint32_t data_kind;
|
uint32_t data_kind;
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_ART, "Artwork request for group %" PRIi64 "\n", persistentid);
|
DPRINTF(E_DBG, L_ART, "Looking for artwork for group with persistentid %" PRIi64 "\n", persistentid);
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
format = 0;
|
|
||||||
got_spotifyitem = 0;
|
got_spotifyitem = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First check if the artwork cache has a cached entry for the given persistent id and requested width/height
|
* First check if the artwork cache has a cached entry for the given persistent id and requested width/height
|
||||||
*/
|
*/
|
||||||
ret = cache_artwork_get(persistentid, max_w, max_h, &cached, &format, evbuf);
|
ret = cache_artwork_get(CACHE_ARTWORK_GROUP, persistentid, max_w, max_h, &cached, &format, evbuf);
|
||||||
if (ret == 0 && cached)
|
if ((ret == 0) && cached)
|
||||||
{
|
{
|
||||||
if (format > 0)
|
DPRINTF(E_DBG, L_ART, "Group %" PRIi64 " found in cache with format %d\n", persistentid, format);
|
||||||
{
|
|
||||||
// Artwork found in cache "ret" contains the format of the image
|
|
||||||
DPRINTF(E_DBG, L_ART, "Artwork found in cache for group %" PRIi64 "\n", persistentid);
|
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
else if (format == 0)
|
|
||||||
{
|
|
||||||
// Entry found in cache but there is not artwork available
|
|
||||||
DPRINTF(E_DBG, L_ART, "Artwork found in cache but no image available for group %" PRIi64 "\n", persistentid);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Image is not in the artwork cache. Try directory artwork first */
|
/* Image is not in the artwork cache. Try directory artwork first */
|
||||||
memset(&qp, 0, sizeof(struct query_params));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
|
@ -1037,28 +1161,31 @@ artwork_get_group_persistentid(int64_t persistentid, int max_w, int max_h, struc
|
||||||
goto files_art;
|
goto files_art;
|
||||||
}
|
}
|
||||||
|
|
||||||
got_art = 0;
|
format = 0;
|
||||||
while (!got_art && ((ret = db_query_fetch_string(&qp, &dir)) == 0) && (dir))
|
while (((ret = db_query_fetch_string(&qp, &dir)) == 0) && (dir))
|
||||||
{
|
{
|
||||||
/* If item is an internet stream don't look for artwork */
|
/* The db query may return non-directories (eg if item is an internet stream or Spotify) */
|
||||||
if (strncmp(dir, "http://", strlen("http://")) == 0)
|
if (access(dir, F_OK) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If Spotify item don't look for files artwork */
|
format = artwork_get_dir_image(dir, max_w, max_h, path, evbuf);
|
||||||
if (strncmp(dir, "spotify:", strlen("spotify:")) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
format = artwork_get_dir_image(dir, max_w, max_h, filename, evbuf);
|
if (format > 0)
|
||||||
got_art = (format > 0);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUP_DIRS results\n");
|
|
||||||
else if (got_art > 0)
|
|
||||||
{
|
{
|
||||||
cache_artwork_add(persistentid, max_w, max_h, format, filename, evbuf);
|
DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUP_DIRS results\n");
|
||||||
|
goto files_art;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Found artwork, cache it and return */
|
||||||
|
if (format > 0)
|
||||||
|
{
|
||||||
|
cache_artwork_add(CACHE_ARTWORK_GROUP, persistentid, max_w, max_h, format, path, evbuf);
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,24 +1201,22 @@ artwork_get_group_persistentid(int64_t persistentid, int max_w, int max_h, struc
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_ART, "Could not start Q_GROUP_ITEMS query\n");
|
DPRINTF(E_LOG, L_ART, "Could not start Q_GROUP_ITEMS query\n");
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
got_art = 0;
|
format = 0;
|
||||||
while (!got_art && ((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
|
while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
|
||||||
{
|
{
|
||||||
if ((safe_atoi32(dbmfi.artwork, &artwork) != 0) && (safe_atou32(dbmfi.data_kind, &data_kind) != 0))
|
if ((safe_atoi32(dbmfi.artwork, &artwork) != 0) && (safe_atou32(dbmfi.data_kind, &data_kind) != 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
format = artwork_get_item_path(dbmfi.path, artwork, max_w, max_h, evbuf);
|
format = artwork_get_item_path(dbmfi.path, artwork, max_w, max_h, path, evbuf);
|
||||||
got_art = (format > 0);
|
|
||||||
|
|
||||||
if (artwork == ARTWORK_SPOTIFY)
|
if (artwork == ARTWORK_SPOTIFY)
|
||||||
got_spotifyitem = 1;
|
got_spotifyitem = 1;
|
||||||
|
|
||||||
if (got_art)
|
if (format > 0)
|
||||||
strcpy(filename, dbmfi.path);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
@ -1101,75 +1226,104 @@ artwork_get_group_persistentid(int64_t persistentid, int max_w, int max_h, struc
|
||||||
DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUP_ITEMS results\n");
|
DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUP_ITEMS results\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (format < 0)
|
|
||||||
|
/* Found artwork, cache it and return */
|
||||||
|
if (format > 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_ART, "Error reading artwork\n");
|
cache_artwork_add(CACHE_ARTWORK_GROUP, persistentid, max_w, max_h, format, path, evbuf);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (got_art > 0)
|
|
||||||
{
|
|
||||||
cache_artwork_add(persistentid, max_w, max_h, format, filename, evbuf);
|
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
else if (format < 0)
|
||||||
/* Add cache entry for no artwork available */
|
{
|
||||||
if (!got_spotifyitem)
|
DPRINTF(E_WARN, L_ART, "Error getting artwork for group %" PRIi64 "\n", persistentid);
|
||||||
cache_artwork_add(persistentid, max_w, max_h, 0, "", evbuf);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_ART, "No artwork found for group %" PRIi64 "\n", persistentid);
|
DPRINTF(E_DBG, L_ART, "No artwork found for group %" PRIi64 "\n", persistentid);
|
||||||
|
|
||||||
return -1;
|
/* Add cache entry for no artwork available */
|
||||||
|
if (!got_spotifyitem)
|
||||||
|
cache_artwork_add(CACHE_ARTWORK_GROUP, persistentid, max_w, max_h, 0, "", evbuf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the artwork image for the given item id and the given maximum width/height
|
||||||
|
*
|
||||||
|
* @param id the mfi item id
|
||||||
|
* @param max_w maximum image width
|
||||||
|
* @param max_h maximum image height
|
||||||
|
* @param evbuf the event buffer that will contain the (scaled) image
|
||||||
|
* @return ART_FMT_* on success, -1 on error or no artwork found
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
artwork_get_item(int id, int max_w, int max_h, struct evbuffer *evbuf)
|
artwork_get_item(int id, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
struct media_file_info *mfi;
|
struct media_file_info *mfi;
|
||||||
int ret;
|
int format;
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_ART, "Artwork request for item %d\n", id);
|
|
||||||
|
|
||||||
mfi = db_file_fetch_byid(id);
|
mfi = db_file_fetch_byid(id);
|
||||||
if (!mfi)
|
if (!mfi)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_ART, "Artwork request for item %d, but no such item in database\n", id);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
DPRINTF(E_DBG, L_ART, "Artwork request for item %d (%s)\n", id, mfi->fname);
|
||||||
* Load artwork image for the persistent id
|
|
||||||
*/
|
format = 0;
|
||||||
ret = artwork_get_group_persistentid(mfi->songalbumid, max_w, max_h, evbuf);
|
if (cfg_getbool(cfg_getsec(cfg, "library"), "artwork_individual"))
|
||||||
if (ret < 0)
|
format = artwork_get_item_mfi(mfi, max_w, max_h, evbuf);
|
||||||
DPRINTF(E_DBG, L_ART, "No artwork found for item id %d (%s)\n", id, mfi->fname);
|
|
||||||
|
/* No individual artwork or individual artwork disabled, try group artwork */
|
||||||
|
if (format <= 0)
|
||||||
|
format = artwork_get_group_persistentid(mfi->songalbumid, max_w, max_h, evbuf);
|
||||||
|
|
||||||
free_mfi(mfi, 0);
|
free_mfi(mfi, 0);
|
||||||
|
|
||||||
return ret;
|
if (format <= 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_ART, "No artwork found for item %d\n", id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the artwork image for the given group id and the given maximum width/height
|
||||||
|
*
|
||||||
|
* @param id the group id (not the persistent id)
|
||||||
|
* @param max_w maximum image width
|
||||||
|
* @param max_h maximum image height
|
||||||
|
* @param evbuf the event buffer that will contain the (scaled) image
|
||||||
|
* @return ART_FMT_* on success, -1 on error or no artwork found
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
artwork_get_group(int id, int max_w, int max_h, struct evbuffer *evbuf)
|
artwork_get_group(int id, int max_w, int max_h, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
int64_t persistentid;
|
int64_t persistentid;
|
||||||
int ret;
|
int format;
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_ART, "Artwork request for group %d\n", id);
|
DPRINTF(E_DBG, L_ART, "Artwork request for group %d\n", id);
|
||||||
|
|
||||||
/*
|
/* Get the persistent id for the given group id */
|
||||||
* Get the persistent id for the given group id
|
if (db_group_persistentid_byid(id, &persistentid) < 0)
|
||||||
*/
|
{
|
||||||
ret = db_group_persistentid_byid(id, &persistentid);
|
|
||||||
if (ret < 0) {
|
|
||||||
DPRINTF(E_LOG, L_ART, "Error fetching persistent id for group id %d\n", id);
|
DPRINTF(E_LOG, L_ART, "Error fetching persistent id for group id %d\n", id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Load artwork image for the persistent id */
|
||||||
* Load artwork image for the persistent id
|
format = artwork_get_group_persistentid(persistentid, max_w, max_h, evbuf);
|
||||||
*/
|
if (format <= 0)
|
||||||
ret = artwork_get_group_persistentid(persistentid, max_w, max_h, evbuf);
|
{
|
||||||
if (ret < 0)
|
DPRINTF(E_DBG, L_ART, "No artwork found for group %d\n", id);
|
||||||
DPRINTF(E_DBG, L_ART, "No artwork found for group id %d\n", id);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checks if the file is an artwork file */
|
/* Checks if the file is an artwork file */
|
||||||
|
|
25
src/cache.c
25
src/cache.c
|
@ -38,7 +38,7 @@
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
|
|
||||||
#define CACHE_VERSION 1
|
#define CACHE_VERSION 2
|
||||||
|
|
||||||
/* The DAAP cache will cache raw daap replies for queries added with
|
/* The DAAP cache will cache raw daap replies for queries added with
|
||||||
* cache_add(). Only some query types are supported.
|
* cache_add(). Only some query types are supported.
|
||||||
|
@ -66,6 +66,7 @@ struct cache_command
|
||||||
int msec;
|
int msec;
|
||||||
|
|
||||||
char *path; // artwork path
|
char *path; // artwork path
|
||||||
|
int type; // individual or group artwork
|
||||||
int64_t peristentid;
|
int64_t peristentid;
|
||||||
int max_w;
|
int max_w;
|
||||||
int max_h;
|
int max_h;
|
||||||
|
@ -236,6 +237,7 @@ cache_create_tables(void)
|
||||||
#define T_ARTWORK \
|
#define T_ARTWORK \
|
||||||
"CREATE TABLE IF NOT EXISTS artwork (" \
|
"CREATE TABLE IF NOT EXISTS artwork (" \
|
||||||
" id INTEGER PRIMARY KEY NOT NULL,"\
|
" id INTEGER PRIMARY KEY NOT NULL,"\
|
||||||
|
" type INTEGER NOT NULL DEFAULT 0," \
|
||||||
" persistentid INTEGER NOT NULL," \
|
" persistentid INTEGER NOT NULL," \
|
||||||
" max_w INTEGER NOT NULL," \
|
" max_w INTEGER NOT NULL," \
|
||||||
" max_h INTEGER NOT NULL," \
|
" max_h INTEGER NOT NULL," \
|
||||||
|
@ -245,7 +247,7 @@ cache_create_tables(void)
|
||||||
" data BLOB" \
|
" data BLOB" \
|
||||||
");"
|
");"
|
||||||
#define I_ARTWORK_ID \
|
#define I_ARTWORK_ID \
|
||||||
"CREATE INDEX IF NOT EXISTS idx_persistentidwh ON artwork(persistentid, max_w, max_h);"
|
"CREATE INDEX IF NOT EXISTS idx_persistentidwh ON artwork(type, persistentid, max_w, max_h);"
|
||||||
#define I_ARTWORK_PATH \
|
#define I_ARTWORK_PATH \
|
||||||
"CREATE INDEX IF NOT EXISTS idx_pathtime ON artwork(filepath, db_timestamp);"
|
"CREATE INDEX IF NOT EXISTS idx_pathtime ON artwork(filepath, db_timestamp);"
|
||||||
#define T_ADMIN_CACHE \
|
#define T_ADMIN_CACHE \
|
||||||
|
@ -1055,7 +1057,7 @@ cache_artwork_add_impl(struct cache_command *cmd)
|
||||||
int datalen;
|
int datalen;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
query = "INSERT INTO artwork (id, persistentid, max_w, max_h, format, filepath, db_timestamp, data) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?);";
|
query = "INSERT INTO artwork (id, persistentid, max_w, max_h, format, filepath, db_timestamp, data, type) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?);";
|
||||||
|
|
||||||
ret = sqlite3_prepare_v2(g_db_hdl, query, -1, &stmt, 0);
|
ret = sqlite3_prepare_v2(g_db_hdl, query, -1, &stmt, 0);
|
||||||
if (ret != SQLITE_OK)
|
if (ret != SQLITE_OK)
|
||||||
|
@ -1079,6 +1081,7 @@ cache_artwork_add_impl(struct cache_command *cmd)
|
||||||
sqlite3_bind_text(stmt, 5, cmd->arg.path, -1, SQLITE_STATIC);
|
sqlite3_bind_text(stmt, 5, cmd->arg.path, -1, SQLITE_STATIC);
|
||||||
sqlite3_bind_int(stmt, 6, (uint64_t)time(NULL));
|
sqlite3_bind_int(stmt, 6, (uint64_t)time(NULL));
|
||||||
sqlite3_bind_blob(stmt, 7, data, datalen, SQLITE_STATIC);
|
sqlite3_bind_blob(stmt, 7, data, datalen, SQLITE_STATIC);
|
||||||
|
sqlite3_bind_int(stmt, 8, cmd->arg.type);
|
||||||
|
|
||||||
ret = sqlite3_step(stmt);
|
ret = sqlite3_step(stmt);
|
||||||
if (ret != SQLITE_DONE)
|
if (ret != SQLITE_DONE)
|
||||||
|
@ -1104,7 +1107,8 @@ cache_artwork_add_impl(struct cache_command *cmd)
|
||||||
* If there is a cached entry for the given id and width/height, the parameter cached is set to 1.
|
* If there is a cached entry for the given id and width/height, the parameter cached is set to 1.
|
||||||
* In this case format and data contain the cached values.
|
* In this case format and data contain the cached values.
|
||||||
*
|
*
|
||||||
* @param cmd->arg.persistentid persistent songalbumid or songartistid
|
* @param cmd->arg.type individual or group artwork
|
||||||
|
* @param cmd->arg.persistentid persistent itemid, songalbumid or songartistid
|
||||||
* @param cmd->arg.max_w maximum image width
|
* @param cmd->arg.max_w maximum image width
|
||||||
* @param cmd->arg.max_h maximum image height
|
* @param cmd->arg.max_h maximum image height
|
||||||
* @param cmd->arg.cached set by this function to 0 if no cache entry exists, otherwise 1
|
* @param cmd->arg.cached set by this function to 0 if no cache entry exists, otherwise 1
|
||||||
|
@ -1115,13 +1119,13 @@ cache_artwork_add_impl(struct cache_command *cmd)
|
||||||
static int
|
static int
|
||||||
cache_artwork_get_impl(struct cache_command *cmd)
|
cache_artwork_get_impl(struct cache_command *cmd)
|
||||||
{
|
{
|
||||||
#define Q_TMPL "SELECT a.format, a.data FROM artwork a WHERE a.persistentid = %" PRIi64 " AND a.max_w = %d AND a.max_h = %d;"
|
#define Q_TMPL "SELECT a.format, a.data FROM artwork a WHERE a.type = %d AND a.persistentid = %" PRIi64 " AND a.max_w = %d AND a.max_h = %d;"
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
char *query;
|
char *query;
|
||||||
int datalen;
|
int datalen;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
query = sqlite3_mprintf(Q_TMPL, cmd->arg.peristentid, cmd->arg.max_w, cmd->arg.max_h);
|
query = sqlite3_mprintf(Q_TMPL, cmd->arg.type, cmd->arg.peristentid, cmd->arg.max_w, cmd->arg.max_h);
|
||||||
if (!query)
|
if (!query)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_CACHE, "Out of memory for query string\n");
|
DPRINTF(E_LOG, L_CACHE, "Out of memory for query string\n");
|
||||||
|
@ -1453,7 +1457,8 @@ cache_artwork_purge_cruft(time_t ref)
|
||||||
/*
|
/*
|
||||||
* Adds the given (scaled) artwork image to the artwork cache
|
* Adds the given (scaled) artwork image to the artwork cache
|
||||||
*
|
*
|
||||||
* @param persistentid persistent songalbumid or songartistid
|
* @param type individual or group artwork
|
||||||
|
* @param persistentid persistent itemid, songalbumid or songartistid
|
||||||
* @param max_w maximum image width
|
* @param max_w maximum image width
|
||||||
* @param max_h maximum image height
|
* @param max_h maximum image height
|
||||||
* @param format ART_FMT_PNG for png, ART_FMT_JPEG for jpeg or 0 if no artwork available
|
* @param format ART_FMT_PNG for png, ART_FMT_JPEG for jpeg or 0 if no artwork available
|
||||||
|
@ -1462,7 +1467,7 @@ cache_artwork_purge_cruft(time_t ref)
|
||||||
* @return 0 if successful, -1 if an error occurred
|
* @return 0 if successful, -1 if an error occurred
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cache_artwork_add(int64_t persistentid, int max_w, int max_h, int format, char *filename, struct evbuffer *evbuf)
|
cache_artwork_add(int type, int64_t persistentid, int max_w, int max_h, int format, char *filename, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
struct cache_command cmd;
|
struct cache_command cmd;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1473,6 +1478,7 @@ cache_artwork_add(int64_t persistentid, int max_w, int max_h, int format, char *
|
||||||
command_init(&cmd);
|
command_init(&cmd);
|
||||||
|
|
||||||
cmd.func = cache_artwork_add_impl;
|
cmd.func = cache_artwork_add_impl;
|
||||||
|
cmd.arg.type = type;
|
||||||
cmd.arg.peristentid = persistentid;
|
cmd.arg.peristentid = persistentid;
|
||||||
cmd.arg.max_w = max_w;
|
cmd.arg.max_w = max_w;
|
||||||
cmd.arg.max_h = max_h;
|
cmd.arg.max_h = max_h;
|
||||||
|
@ -1502,7 +1508,7 @@ cache_artwork_add(int64_t persistentid, int max_w, int max_h, int format, char *
|
||||||
* @return 0 if successful, -1 if an error occurred
|
* @return 0 if successful, -1 if an error occurred
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cache_artwork_get(int64_t persistentid, int max_w, int max_h, int *cached, int *format, struct evbuffer *evbuf)
|
cache_artwork_get(int type, int64_t persistentid, int max_w, int max_h, int *cached, int *format, struct evbuffer *evbuf)
|
||||||
{
|
{
|
||||||
struct cache_command cmd;
|
struct cache_command cmd;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1513,6 +1519,7 @@ cache_artwork_get(int64_t persistentid, int max_w, int max_h, int *cached, int *
|
||||||
command_init(&cmd);
|
command_init(&cmd);
|
||||||
|
|
||||||
cmd.func = cache_artwork_get_impl;
|
cmd.func = cache_artwork_get_impl;
|
||||||
|
cmd.arg.type = type;
|
||||||
cmd.arg.peristentid = persistentid;
|
cmd.arg.peristentid = persistentid;
|
||||||
cmd.arg.max_w = max_w;
|
cmd.arg.max_w = max_w;
|
||||||
cmd.arg.max_h = max_h;
|
cmd.arg.max_h = max_h;
|
||||||
|
|
|
@ -27,6 +27,9 @@ cache_daap_threshold(void);
|
||||||
|
|
||||||
/* ---------------------------- Artwork cache API --------------------------- */
|
/* ---------------------------- Artwork cache API --------------------------- */
|
||||||
|
|
||||||
|
#define CACHE_ARTWORK_GROUP 0
|
||||||
|
#define CACHE_ARTWORK_INDIVIDUAL 1
|
||||||
|
|
||||||
int
|
int
|
||||||
cache_artwork_ping(char *path, time_t mtime);
|
cache_artwork_ping(char *path, time_t mtime);
|
||||||
|
|
||||||
|
@ -37,10 +40,10 @@ int
|
||||||
cache_artwork_purge_cruft(time_t ref);
|
cache_artwork_purge_cruft(time_t ref);
|
||||||
|
|
||||||
int
|
int
|
||||||
cache_artwork_add(int64_t persistentid, int max_w, int max_h, int format, char *filename, struct evbuffer *evbuf);
|
cache_artwork_add(int type, int64_t persistentid, int max_w, int max_h, int format, char *filename, struct evbuffer *evbuf);
|
||||||
|
|
||||||
int
|
int
|
||||||
cache_artwork_get(int64_t persistentid, int max_w, int max_h, int *cached, int *format, struct evbuffer *evbuf);
|
cache_artwork_get(int type, int64_t persistentid, int max_w, int max_h, int *cached, int *format, struct evbuffer *evbuf);
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------- Cache API --------------------------- */
|
/* ---------------------------- Cache API --------------------------- */
|
||||||
|
|
|
@ -76,6 +76,7 @@ static cfg_opt_t sec_library[] =
|
||||||
CFG_STR("name_podcasts", "Podcasts", CFGF_NONE),
|
CFG_STR("name_podcasts", "Podcasts", CFGF_NONE),
|
||||||
CFG_STR("name_audiobooks", "Audiobooks", CFGF_NONE),
|
CFG_STR("name_audiobooks", "Audiobooks", CFGF_NONE),
|
||||||
CFG_STR_LIST("artwork_basenames", "{artwork,cover,Folder}", CFGF_NONE),
|
CFG_STR_LIST("artwork_basenames", "{artwork,cover,Folder}", CFGF_NONE),
|
||||||
|
CFG_BOOL("artwork_individual", cfg_false, CFGF_NONE),
|
||||||
CFG_STR_LIST("filetypes_ignore", "{.db,.ini,.db-journal,.pdf}", CFGF_NONE),
|
CFG_STR_LIST("filetypes_ignore", "{.db,.ini,.db-journal,.pdf}", CFGF_NONE),
|
||||||
CFG_BOOL("filescan_disable", cfg_false, CFGF_NONE),
|
CFG_BOOL("filescan_disable", cfg_false, CFGF_NONE),
|
||||||
CFG_BOOL("itunes_overrides", cfg_false, CFGF_NONE),
|
CFG_BOOL("itunes_overrides", cfg_false, CFGF_NONE),
|
||||||
|
|
Loading…
Reference in New Issue