mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-16 01:03:16 -05:00
Merge pull request #628 from chme/artwork
[jsonapi] Artwork url for non library items and streams
This commit is contained in:
commit
357d346fce
@ -1724,6 +1724,7 @@ curl --include \
|
|||||||
| data_kind | string | Data type of this track: `file`, `url`, `spotify`, `pipe` |
|
| data_kind | string | Data type of this track: `file`, `url`, `spotify`, `pipe` |
|
||||||
| path | string | Path |
|
| path | string | Path |
|
||||||
| uri | string | Resource identifier |
|
| uri | string | Resource identifier |
|
||||||
|
| artwork_url | string | *(optional)* [Artwork url](#artwork-urls) |
|
||||||
|
|
||||||
|
|
||||||
### `playlist` object
|
### `playlist` object
|
||||||
@ -1748,6 +1749,7 @@ curl --include \
|
|||||||
| track_count | integer | Number of tracks |
|
| track_count | integer | Number of tracks |
|
||||||
| length_ms | integer | Total length of tracks in milliseconds |
|
| length_ms | integer | Total length of tracks in milliseconds |
|
||||||
| uri | string | Resource identifier |
|
| uri | string | Resource identifier |
|
||||||
|
| artwork_url | string | *(optional)* [Artwork url](#artwork-urls) |
|
||||||
|
|
||||||
|
|
||||||
### `album` object
|
### `album` object
|
||||||
@ -1762,6 +1764,7 @@ curl --include \
|
|||||||
| track_count | integer | Number of tracks |
|
| track_count | integer | Number of tracks |
|
||||||
| length_ms | integer | Total length of tracks in milliseconds |
|
| length_ms | integer | Total length of tracks in milliseconds |
|
||||||
| uri | string | Resource identifier |
|
| uri | string | Resource identifier |
|
||||||
|
| artwork_url | string | *(optional)* [Artwork url](#artwork-urls) |
|
||||||
|
|
||||||
|
|
||||||
### `track` object
|
### `track` object
|
||||||
@ -1792,6 +1795,7 @@ curl --include \
|
|||||||
| data_kind | string | Data type of this track: `file`, `stream`, `spotify`, `pipe` |
|
| data_kind | string | Data type of this track: `file`, `stream`, `spotify`, `pipe` |
|
||||||
| path | string | Path |
|
| path | string | Path |
|
||||||
| uri | string | Resource identifier |
|
| uri | string | Resource identifier |
|
||||||
|
| artwork_url | string | *(optional)* [Artwork url](#artwork-urls) |
|
||||||
|
|
||||||
|
|
||||||
### `paging` object
|
### `paging` object
|
||||||
@ -1810,3 +1814,13 @@ curl --include \
|
|||||||
| --------------- | -------- | ----------------------------------------- |
|
| --------------- | -------- | ----------------------------------------- |
|
||||||
| name | string | Name of genre |
|
| name | string | Name of genre |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Artwork urls
|
||||||
|
|
||||||
|
Artwork urls in `queue item`, `artist`, `album` and `track` objects can be either relative urls or absolute urls to the artwork image.
|
||||||
|
Absolute artwork urls are pointing to external artwork images (e. g. for radio streams that provide artwork metadata), while relative artwork urls are served from forked-daapd.
|
||||||
|
|
||||||
|
It is possible to add the query parameters `maxwidth` and/or `maxheight` to relative artwork urls, in order to get a smaller image (forked-daapd only scales down never up).
|
||||||
|
|
||||||
|
Note that even if a relative artwork url attribute is present, it is not guaranteed to exist.
|
@ -5,6 +5,9 @@
|
|||||||
#define ART_FMT_PNG 1
|
#define ART_FMT_PNG 1
|
||||||
#define ART_FMT_JPEG 2
|
#define ART_FMT_JPEG 2
|
||||||
|
|
||||||
|
#define ART_DEFAULT_HEIGHT 600
|
||||||
|
#define ART_DEFAULT_WIDTH 600
|
||||||
|
|
||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
6
src/db.c
6
src/db.c
@ -4665,13 +4665,13 @@ queue_add_item(struct db_queue_item *item, int pos, int shuffle_pos, int queue_v
|
|||||||
"pos, shuffle_pos, path, virtual_path, title, " \
|
"pos, shuffle_pos, path, virtual_path, title, " \
|
||||||
"artist, album_artist, album, genre, songalbumid, " \
|
"artist, album_artist, album, genre, songalbumid, " \
|
||||||
"time_modified, artist_sort, album_sort, album_artist_sort, year, " \
|
"time_modified, artist_sort, album_sort, album_artist_sort, year, " \
|
||||||
"track, disc, queue_version)" \
|
"track, disc, artwork_url, queue_version)" \
|
||||||
"VALUES" \
|
"VALUES" \
|
||||||
"(NULL, %d, %d, %d, %d, " \
|
"(NULL, %d, %d, %d, %d, " \
|
||||||
"%d, %d, %Q, %Q, %Q, " \
|
"%d, %d, %Q, %Q, %Q, " \
|
||||||
"%Q, %Q, %Q, %Q, %" PRIi64 ", " \
|
"%Q, %Q, %Q, %Q, %" PRIi64 ", " \
|
||||||
"%d, %Q, %Q, %Q, %d, " \
|
"%d, %Q, %Q, %Q, %d, " \
|
||||||
"%d, %d, %d);"
|
"%d, %d, %Q, %d);"
|
||||||
|
|
||||||
char *query;
|
char *query;
|
||||||
int ret;
|
int ret;
|
||||||
@ -4681,7 +4681,7 @@ queue_add_item(struct db_queue_item *item, int pos, int shuffle_pos, int queue_v
|
|||||||
pos, shuffle_pos, item->path, item->virtual_path, item->title,
|
pos, shuffle_pos, item->path, item->virtual_path, item->title,
|
||||||
item->artist, item->album_artist, item->album, item->genre, item->songalbumid,
|
item->artist, item->album_artist, item->album, item->genre, item->songalbumid,
|
||||||
item->time_modified, item->artist_sort, item->album_sort, item->album_artist_sort, item->year,
|
item->time_modified, item->artist_sort, item->album_sort, item->album_artist_sort, item->year,
|
||||||
item->track, item->disc, queue_version);
|
item->track, item->disc, item->artwork_url, queue_version);
|
||||||
ret = db_query_run(query, 1, 0);
|
ret = db_query_run(query, 1, 0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -639,7 +639,7 @@ metadata_packet_get(struct http_icy_metadata *metadata, AVFormatContext *fmtctx)
|
|||||||
else
|
else
|
||||||
metadata->title = strdup(metadata->title);
|
metadata->title = strdup(metadata->title);
|
||||||
}
|
}
|
||||||
else if ((strncmp(icy_token, "StreamUrl", strlen("StreamUrl")) == 0) && !metadata->artwork_url)
|
else if ((strncmp(icy_token, "StreamUrl", strlen("StreamUrl")) == 0) && !metadata->artwork_url && strlen(ptr) > 0)
|
||||||
{
|
{
|
||||||
metadata->artwork_url = strdup(ptr);
|
metadata->artwork_url = strdup(ptr);
|
||||||
}
|
}
|
||||||
|
@ -1525,6 +1525,7 @@ queue_item_to_json(struct db_queue_item *queue_item, char shuffle)
|
|||||||
else
|
else
|
||||||
json_object_object_add(item, "position", json_object_new_int(queue_item->pos));
|
json_object_object_add(item, "position", json_object_new_int(queue_item->pos));
|
||||||
|
|
||||||
|
if (queue_item->file_id > 0 && queue_item->file_id != DB_MEDIA_FILE_NON_PERSISTENT_ID)
|
||||||
json_object_object_add(item, "track_id", json_object_new_int(queue_item->file_id));
|
json_object_object_add(item, "track_id", json_object_new_int(queue_item->file_id));
|
||||||
|
|
||||||
safe_json_add_string(item, "title", queue_item->title);
|
safe_json_add_string(item, "title", queue_item->title);
|
||||||
@ -1546,21 +1547,27 @@ queue_item_to_json(struct db_queue_item *queue_item, char shuffle)
|
|||||||
|
|
||||||
safe_json_add_string(item, "path", queue_item->path);
|
safe_json_add_string(item, "path", queue_item->path);
|
||||||
|
|
||||||
if (queue_item->file_id > 0)
|
if (queue_item->file_id > 0 && queue_item->file_id != DB_MEDIA_FILE_NON_PERSISTENT_ID)
|
||||||
{
|
{
|
||||||
ret = snprintf(uri, sizeof(uri), "%s:%s:%d", "library", "track", queue_item->file_id);
|
ret = snprintf(uri, sizeof(uri), "%s:%s:%d", "library", "track", queue_item->file_id);
|
||||||
if (ret < sizeof(uri))
|
if (ret < sizeof(uri))
|
||||||
json_object_object_add(item, "uri", json_object_new_string(uri));
|
json_object_object_add(item, "uri", json_object_new_string(uri));
|
||||||
|
|
||||||
ret = snprintf(artwork_url, sizeof(artwork_url), "/artwork/item/%d", queue_item->file_id);
|
|
||||||
if (ret < sizeof(artwork_url))
|
|
||||||
json_object_object_add(item, "artwork_url", json_object_new_string(artwork_url));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
safe_json_add_string(item, "uri", queue_item->path);
|
safe_json_add_string(item, "uri", queue_item->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queue_item->artwork_url)
|
||||||
|
{
|
||||||
safe_json_add_string(item, "artwork_url", queue_item->artwork_url);
|
safe_json_add_string(item, "artwork_url", queue_item->artwork_url);
|
||||||
}
|
}
|
||||||
|
else if (queue_item->file_id > 0 && queue_item->file_id != DB_MEDIA_FILE_NON_PERSISTENT_ID)
|
||||||
|
{
|
||||||
|
ret = snprintf(artwork_url, sizeof(artwork_url), "/artwork/item/%d", queue_item->file_id);
|
||||||
|
if (ret < sizeof(artwork_url))
|
||||||
|
json_object_object_add(item, "artwork_url", json_object_new_string(artwork_url));
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
@ -4702,7 +4702,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
format = artwork_get_item(evbuffer, itemid, 600, 600);
|
format = artwork_get_item(evbuffer, itemid, ART_DEFAULT_WIDTH, ART_DEFAULT_HEIGHT);
|
||||||
if (format < 0)
|
if (format < 0)
|
||||||
{
|
{
|
||||||
httpd_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
httpd_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
||||||
|
@ -894,7 +894,7 @@ raop_metadata_prepare(int id)
|
|||||||
goto skip_artwork;
|
goto skip_artwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = artwork_get_item(rmd->artwork, queue_item->file_id, 600, 600);
|
ret = artwork_get_item(rmd->artwork, queue_item->file_id, ART_DEFAULT_WIDTH, ART_DEFAULT_HEIGHT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_INFO, L_RAOP, "Failed to retrieve artwork for file id %d; no artwork will be sent\n", id);
|
DPRINTF(E_INFO, L_RAOP, "Failed to retrieve artwork for file id %d; no artwork will be sent\n", id);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "artwork.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
@ -53,6 +54,7 @@ struct spotify_album
|
|||||||
const char *release_date_precision;
|
const char *release_date_precision;
|
||||||
int release_year;
|
int release_year;
|
||||||
const char *uri;
|
const char *uri;
|
||||||
|
const char *artwork_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct spotify_track
|
struct spotify_track
|
||||||
@ -71,6 +73,7 @@ struct spotify_track
|
|||||||
const char *name;
|
const char *name;
|
||||||
int track_number;
|
int track_number;
|
||||||
const char *uri;
|
const char *uri;
|
||||||
|
const char *artwork_url;
|
||||||
|
|
||||||
bool is_playable;
|
bool is_playable;
|
||||||
const char *restrictions;
|
const char *restrictions;
|
||||||
@ -577,6 +580,44 @@ request_pagingobject_endpoint(const char *href, paging_item_cb item_cb, paging_r
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_album_image(json_object *jsonalbum)
|
||||||
|
{
|
||||||
|
json_object *jsonimages;
|
||||||
|
json_object *jsonimage;
|
||||||
|
int image_count;
|
||||||
|
int index;
|
||||||
|
const char *artwork_url;
|
||||||
|
int width;
|
||||||
|
int temp;
|
||||||
|
|
||||||
|
artwork_url = NULL;
|
||||||
|
temp = 0;
|
||||||
|
width = 0;
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(jsonalbum, "images", &jsonimages))
|
||||||
|
{
|
||||||
|
// Find image closest to ART_DEFAULT_WIDTH
|
||||||
|
image_count = json_object_array_length(jsonimages);
|
||||||
|
for (index = 0; index < image_count; index++)
|
||||||
|
{
|
||||||
|
jsonimage = json_object_array_get_idx(jsonimages, index);
|
||||||
|
if (jsonimage)
|
||||||
|
{
|
||||||
|
temp = jparse_int_from_obj(jsonimage, "width");
|
||||||
|
|
||||||
|
if (temp > width && temp < ART_DEFAULT_WIDTH)
|
||||||
|
{
|
||||||
|
artwork_url = jparse_str_from_obj(jsonimage, "url");
|
||||||
|
width = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return artwork_url;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_metadata_track(json_object *jsontrack, struct spotify_track *track)
|
parse_metadata_track(json_object *jsontrack, struct spotify_track *track)
|
||||||
{
|
{
|
||||||
@ -591,6 +632,8 @@ parse_metadata_track(json_object *jsontrack, struct spotify_track *track)
|
|||||||
track->album = jparse_str_from_obj(jsonalbum, "name");
|
track->album = jparse_str_from_obj(jsonalbum, "name");
|
||||||
if (json_object_object_get_ex(jsonalbum, "artists", &jsonartists))
|
if (json_object_object_get_ex(jsonalbum, "artists", &jsonartists))
|
||||||
track->album_artist = jparse_str_from_array(jsonartists, 0, "name");
|
track->album_artist = jparse_str_from_array(jsonartists, 0, "name");
|
||||||
|
|
||||||
|
track->artwork_url = get_album_image(jsonalbum);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json_object_object_get_ex(jsontrack, "artists", &jsonartists))
|
if (json_object_object_get_ex(jsontrack, "artists", &jsonartists))
|
||||||
@ -658,6 +701,8 @@ parse_metadata_album(json_object *jsonalbum, struct spotify_album *album)
|
|||||||
album->release_date_precision = jparse_str_from_obj(jsonalbum, "release_date_precision");
|
album->release_date_precision = jparse_str_from_obj(jsonalbum, "release_date_precision");
|
||||||
album->release_year = get_year_from_date(album->release_date);
|
album->release_year = get_year_from_date(album->release_date);
|
||||||
|
|
||||||
|
album->artwork_url = get_album_image(jsonalbum);
|
||||||
|
|
||||||
// TODO Genre is an array of strings ('genres'), but it is always empty (https://github.com/spotify/web-api/issues/157)
|
// TODO Genre is an array of strings ('genres'), but it is always empty (https://github.com/spotify/web-api/issues/157)
|
||||||
//album->genre = jparse_str_from_obj(jsonalbum, "genre");
|
//album->genre = jparse_str_from_obj(jsonalbum, "genre");
|
||||||
}
|
}
|
||||||
@ -976,11 +1021,13 @@ map_track_to_queueitem(struct db_queue_item *item, const struct spotify_track *t
|
|||||||
{
|
{
|
||||||
item->album_artist = safe_strdup(album->artist);
|
item->album_artist = safe_strdup(album->artist);
|
||||||
item->album = safe_strdup(album->name);
|
item->album = safe_strdup(album->name);
|
||||||
|
item->artwork_url = safe_strdup(album->artwork_url);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
item->album_artist = safe_strdup(track->album_artist);
|
item->album_artist = safe_strdup(track->album_artist);
|
||||||
item->album = safe_strdup(track->album);
|
item->album = safe_strdup(track->album);
|
||||||
|
item->artwork_url = safe_strdup(track->artwork_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
item->disc = track->disc_number;
|
item->disc = track->disc_number;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user