[artwork] Add function to get artwork for non-library queue items

Adds artwork_get_by_queue_item_id() and a source handler for getting artwork
from queue_item->artwork_url.
This commit is contained in:
ejurgensen 2025-10-25 23:06:30 +02:00
parent bf598153f3
commit 921d4446d6
2 changed files with 164 additions and 32 deletions

View File

@ -113,6 +113,8 @@ struct artwork_ctx {
uint32_t media_kind;
// Input data for group handlers
int64_t persistentid;
// Input data for queue item handlers
struct db_queue_item *queue_item;
// Not to be used by handler - query for item or group
struct query_params qp;
@ -210,6 +212,8 @@ static int source_item_ownpl_get(struct artwork_ctx *ctx);
static int source_item_spotifywebapi_search_get(struct artwork_ctx *ctx);
static int source_item_discogs_get(struct artwork_ctx *ctx);
static int source_item_coverartarchive_get(struct artwork_ctx *ctx);
/* Forward - queue item handlers */
static int source_queue_item_artwork_url_get(struct artwork_ctx *ctx);
/* List of sources that can provide artwork for a group (i.e. usually an album
* identified by a persistentid). The source handlers will be called in the
@ -353,6 +357,24 @@ static struct artwork_source artwork_item_source[] =
}
};
/* List of sources that can provide artwork for a queue item. The source
* handlers will be called in the order of this list. Must be terminated by a
* NULL struct.
*/
static struct artwork_source artwork_queue_item_source[] =
{
{
.name = "artwork url",
.handler = source_queue_item_artwork_url_get,
.cache = NEVER,
},
{
.name = NULL,
.handler = NULL,
.cache = 0,
}
};
/* Forward - parsers of online source responses */
static enum parse_result response_jparse_spotify(char **artwork_url, json_object *response, int max_w, int max_h);
static enum parse_result response_jparse_discogs(char **artwork_url, json_object *response, int max_w, int max_h);
@ -1607,41 +1629,25 @@ source_item_own_get(struct artwork_ctx *ctx)
return artwork_get(ctx->evbuf, path, NULL, false, ctx->data_kind, ctx->req_params);
}
/*
* Downloads the artwork from the location pointed to by queue_item->artwork_url
*/
static int
source_item_artwork_url_get(struct artwork_ctx *ctx)
{
struct db_queue_item *queue_item;
const char *proto_http = "http:";
const char *proto_https = "https:";
bool is_http;
bool is_https;
int ret;
DPRINTF(E_SPAM, L_ART, "Trying artwork url for %s\n", ctx->dbmfi->path);
queue_item = db_queue_fetch_byfileid(ctx->id);
if (!queue_item || !queue_item->artwork_url)
goto notfound;
is_http = (strncmp(queue_item->artwork_url, proto_http, strlen(proto_http)) == 0);
is_https = (strncmp(queue_item->artwork_url, proto_https, strlen(proto_https)) == 0);
if (!is_http && !is_https)
goto notfound;
ret = artwork_get_byurl(ctx->evbuf, queue_item->artwork_url, ctx->req_params);
snprintf(ctx->path, sizeof(ctx->path), "%s", queue_item->artwork_url);
free_queue_item(queue_item, 0);
if (ctx->queue_item)
{
ret = source_queue_item_artwork_url_get(ctx);
}
else
{
ctx->queue_item = db_queue_fetch_byfileid(ctx->id);
ret = source_queue_item_artwork_url_get(ctx);
free_queue_item(ctx->queue_item, 0);
}
return ret;
notfound:
free_queue_item(queue_item, 0);
return ART_E_NONE;
}
/*
@ -1852,6 +1858,41 @@ source_item_ownpl_get(struct artwork_ctx *ctx)
return format;
}
/*
* Downloads artwork from ctx->queue_item->artwork_url
*/
static int
source_queue_item_artwork_url_get(struct artwork_ctx *ctx)
{
const char *proto_http = "http:";
const char *proto_https = "https:";
const char *artwork_url;
bool is_http;
bool is_https;
int ret;
if (!ctx->queue_item || !ctx->queue_item->artwork_url)
goto notfound;
DPRINTF(E_SPAM, L_ART, "Trying artwork url for %s\n", ctx->queue_item->path);
artwork_url = ctx->queue_item->artwork_url;
is_http = (strncmp(artwork_url, proto_http, strlen(proto_http)) == 0);
is_https = (strncmp(artwork_url, proto_https, strlen(proto_https)) == 0);
if (!is_http && !is_https)
goto notfound;
ret = artwork_get_byurl(ctx->evbuf, artwork_url, ctx->req_params);
snprintf(ctx->path, sizeof(ctx->path), "%s", artwork_url);
return ret;
notfound:
return ART_E_NONE;
}
/* --------------------------- SOURCE PROCESSING --------------------------- */
@ -2003,13 +2044,52 @@ process_group(struct artwork_ctx *ctx)
return process_items(ctx, 0);
}
static int
process_queue_item(struct artwork_ctx *ctx)
{
const char *source_name;
int i;
int ret;
for (i = 0; artwork_queue_item_source[i].handler; i++)
{
// If just one handler says we should not cache a negative result then we obey that
if ((artwork_queue_item_source[i].cache & ON_FAILURE) == 0)
ctx->cache = NEVER;
source_name = artwork_queue_item_source[i].name;
DPRINTF(E_SPAM, L_ART, "Checking queue item source '%s'\n", source_name);
ret = artwork_queue_item_source[i].handler(ctx);
if (ret > 0)
{
DPRINTF(E_DBG, L_ART, "Artwork for queue item '%s' found in source '%s'\n", ctx->queue_item->title, source_name);
ctx->cache = artwork_queue_item_source[i].cache;
return ret;
}
else if (ret == ART_E_ABORT)
{
DPRINTF(E_DBG, L_ART, "Source '%s' stopped search for artwork for queue item '%s'\n", source_name, ctx->queue_item->title);
ctx->cache = NEVER;
}
else if (ret == ART_E_ERROR)
{
DPRINTF(E_LOG, L_ART, "Source '%s' returned an error for queue item '%s'\n", source_name, ctx->queue_item->title);
ctx->cache = NEVER;
}
}
return -1;
}
/* ------------------------------ ARTWORK API ------------------------------ */
int
artwork_get_item(struct evbuffer *evbuf, int id, int max_w, int max_h, int format)
{
struct artwork_ctx ctx;
struct artwork_ctx ctx = { 0 };
char filter[32];
int ret;
@ -2018,8 +2098,6 @@ artwork_get_item(struct evbuffer *evbuf, int id, int max_w, int max_h, int forma
if (id == DB_MEDIA_FILE_NON_PERSISTENT_ID)
return -1;
memset(&ctx, 0, sizeof(struct artwork_ctx));
ctx.qp.type = Q_ITEMS;
ctx.qp.filter = filter;
ctx.evbuf = evbuf;
@ -2070,13 +2148,11 @@ artwork_get_item(struct evbuffer *evbuf, int id, int max_w, int max_h, int forma
int
artwork_get_group(struct evbuffer *evbuf, int id, int max_w, int max_h, int format)
{
struct artwork_ctx ctx;
struct artwork_ctx ctx = { 0 };
int ret;
DPRINTF(E_DBG, L_ART, "Artwork request for group %d (max_w=%d, max_h=%d)\n", id, max_w, max_h);
memset(&ctx, 0, sizeof(struct artwork_ctx));
/* Get the persistent id for the given group id */
ret = db_group_persistentid_byid(id, &ctx.persistentid);
if (ret < 0)
@ -2111,6 +2187,48 @@ artwork_get_group(struct evbuffer *evbuf, int id, int max_w, int max_h, int form
return -1;
}
int
artwork_get_by_queue_item_id(struct evbuffer *evbuf, int item_id, int max_w, int max_h, int format)
{
struct artwork_ctx ctx = { 0 };
struct db_queue_item *queue_item;
int ret;
DPRINTF(E_DBG, L_ART, "Artwork request for queue item %d (max_w=%d, max_h=%d)\n", item_id, max_w, max_h);
queue_item = db_queue_fetch_byitemid(item_id);
if (!queue_item)
return -1;
if (queue_item->file_id != DB_MEDIA_FILE_NON_PERSISTENT_ID)
{
ret = artwork_get_item(evbuf, queue_item->file_id, max_w, max_h, format);
free_queue_item(queue_item, 0);
return ret;
}
ctx.queue_item = queue_item;
ctx.evbuf = evbuf;
ctx.req_params.max_w = max_w;
ctx.req_params.max_h = max_h;
ctx.req_params.format = format;
ctx.cache = ON_FAILURE;
ret = process_queue_item(&ctx);
if (ret > 0)
{
// No caching of queue item artwork implemented as of yet
free_queue_item(queue_item, 0);
return ret;
}
DPRINTF(E_DBG, L_ART, "No artwork found for queue item %d\n", item_id);
free_queue_item(queue_item, 0);
return -1;
}
/* Checks if the file is an artwork file */
bool
artwork_file_is_artwork(const char *filename)

View File

@ -38,6 +38,20 @@ artwork_get_item(struct evbuffer *evbuf, int id, int max_w, int max_h, int forma
int
artwork_get_group(struct evbuffer *evbuf, int id, int max_w, int max_h, int format);
/*
* Get the artwork image for a queue item. If the queue item is in the library,
* this will return the same as artwork_get_by_file_id
*
* @out evbuf Event buffer that will contain the (scaled) image
* @in item_id The queue item id
* @in max_w Requested maximum image width (may not be obeyed)
* @in max_h Requested maximum image height (may not be obeyed)
* @in format Requested format (may not be obeyed), 0 for default
* @return ART_FMT_* on success, -1 on error or no artwork found
*/
int
artwork_get_by_queue_item_id(struct evbuffer *evbuf, int item_id, int max_w, int max_h, int format);
/*
* Checks if the file is an artwork file (based on user config)
*