[pipe/artwork] Support for artwork via Shairport metadata pipes

This implementation uses the cache for storage. Might change that to use a
tmpfile instead.
This commit is contained in:
ejurgensen 2019-09-09 21:39:25 +02:00
parent 2e149273e5
commit 69fafd873d
2 changed files with 68 additions and 1 deletions

View File

@ -138,6 +138,7 @@ static int source_item_cache_get(struct artwork_ctx *ctx);
static int source_item_embedded_get(struct artwork_ctx *ctx);
static int source_item_own_get(struct artwork_ctx *ctx);
static int source_item_stream_get(struct artwork_ctx *ctx);
static int source_item_pipe_get(struct artwork_ctx *ctx);
static int source_item_spotify_get(struct artwork_ctx *ctx);
static int source_item_spotifywebapi_get(struct artwork_ctx *ctx);
static int source_item_ownpl_get(struct artwork_ctx *ctx);
@ -196,6 +197,12 @@ static struct artwork_source artwork_item_source[] =
.data_kinds = (1 << DATA_KIND_HTTP),
.cache = NEVER,
},
{
.name = "pipe",
.handler = source_item_pipe_get,
.data_kinds = (1 << DATA_KIND_PIPE),
.cache = NEVER,
},
{
.name = "Spotify",
.handler = source_item_spotify_get,
@ -836,6 +843,26 @@ source_item_stream_get(struct artwork_ctx *ctx)
return ret;
}
/*
* If we are playing a pipe and there is also a metadata pipe, then
* input/pipe.c may have saved the incoming artwork via cache_artwork_stash()
*
*/
static int
source_item_pipe_get(struct artwork_ctx *ctx)
{
int ret;
int format;
DPRINTF(E_SPAM, L_ART, "Trying pipe metadata from %s.metadata\n", ctx->dbmfi->path);
ret = cache_artwork_read(ctx->evbuf, "pipe://metadata", &format);
if (ret < 0)
return ART_E_NONE;
return format;
}
#ifdef HAVE_SPOTIFY_H
static int
source_item_spotify_get(struct artwork_ctx *ctx)

View File

@ -62,6 +62,8 @@
#include "conffile.h"
#include "listener.h"
#include "player.h"
#include "artwork.h"
#include "cache.h"
#include "worker.h"
#include "commands.h"
#include "mxml-compat.h"
@ -72,6 +74,8 @@
#define PIPE_READ_MAX 65536
// Max number of bytes to buffer from metadata pipes
#define PIPE_METADATA_BUFLEN_MAX 262144
// Ignore pictures with larger size than this
#define PIPE_PICTURE_SIZE_MAX 262144
enum pipetype
{
@ -353,6 +357,34 @@ handle_volume(const char *volume)
DPRINTF(E_LOG, L_PLAYER, "Shairport airplay volume out of range (-144.0, [-30.0 - 0.0]): %.2f\n", airplay_volume);
}
static void
handle_picture(struct input_metadata *m, uint8_t *data, int data_len)
{
struct evbuffer *evbuf;
int format;
if (data_len < 2 || data_len > PIPE_PICTURE_SIZE_MAX)
goto error;
if (data[0] == 0xff && data[1] == 0xd8)
format = ART_FMT_JPEG;
else if (data[0] == 0x89 && data[1] == 0x50)
format = ART_FMT_PNG;
else
goto error;
CHECK_NULL(L_PLAYER, evbuf = evbuffer_new());
evbuffer_add(evbuf, data, data_len);
cache_artwork_stash(evbuf, "pipe://metadata", format);
evbuffer_free(evbuf);
return;
error:
DPRINTF(E_LOG, L_PLAYER, "Unsupported picture size (%d) or format from Shairport metadata pipe\n", data_len);
cache_artwork_stash(NULL, NULL, 0); // Clear the artwork stash
}
// returns 1 on metadata found, 0 on nothing, -1 on error
static int
handle_item(struct input_metadata *m, const char *item)
@ -366,6 +398,7 @@ handle_item(struct input_metadata *m, const char *item)
char **dstptr;
char *progress;
char *volume;
char *picture;
uint8_t *data;
int data_len;
int ret;
@ -412,6 +445,8 @@ handle_item(struct input_metadata *m, const char *item)
dstptr = &progress;
else if (code == dmapval("pvol"))
dstptr = &volume;
else if (code == dmapval("PICT"))
dstptr = &picture;
else
goto out_nothing;
@ -429,7 +464,7 @@ handle_item(struct input_metadata *m, const char *item)
goto out_error;
}
DPRINTF(E_DBG, L_PLAYER, "Read Shairport metadata (type=%8x, code=%8x, len=%d): '%s'\n", type, code, data_len, (char *)data);
DPRINTF(E_DBG, L_PLAYER, "Read Shairport metadata (type=%8x, code=%8x, len=%d)\n", type, code, data_len);
if (dstptr == &progress)
{
@ -443,6 +478,11 @@ handle_item(struct input_metadata *m, const char *item)
handle_volume(volume);
free(data);
}
else if (dstptr == &picture)
{
handle_picture(m, data, data_len);
free(data);
}
else
{
free(*dstptr); // If m->x is already set, free it