[jsonapi] Add support for updating queue_item metadata (closes #1153)

This commit also changes db.c's sort_tag_create to always recreate sort tags,
so that they match source tags, should they have changed. Unclear to me why
the previous solution didn't do that, so will probably regret this change when
it dawns on me.
This commit is contained in:
ejurgensen 2021-01-20 22:39:34 +01:00
parent 275d66b6ad
commit aaffa4a83f
3 changed files with 72 additions and 35 deletions

View File

@ -529,7 +529,7 @@ curl -X PUT "http://localhost:3689/api/outputs/0/toggle"
| GET | [/api/queue](#list-queue-items) | Get a list of queue items | | GET | [/api/queue](#list-queue-items) | Get a list of queue items |
| PUT | [/api/queue/clear](#clearing-the-queue) | Remove all items from the queue | | PUT | [/api/queue/clear](#clearing-the-queue) | Remove all items from the queue |
| POST | [/api/queue/items/add](#adding-items-to-the-queue) | Add items to the queue | | POST | [/api/queue/items/add](#adding-items-to-the-queue) | Add items to the queue |
| PUT | [/api/queue/items/{id}](#moving-a-queue-item) | Move a queue item in the queue | | PUT | [/api/queue/items/{id}](#updating-a-queue-item) | Updating a queue item in the queue |
| DELETE | [/api/queue/items/{id}](#removing-a-queue-item) | Remove a queue item form the queue | | DELETE | [/api/queue/items/{id}](#removing-a-queue-item) | Remove a queue item form the queue |
@ -690,9 +690,9 @@ curl -X POST "http://localhost:3689/api/queue/items/add?limit=10&clear=true&play
} }
``` ```
### Moving a queue item ### Updating a queue item
Move a queue item in the current queue Update or move a queue item in the current queue
**Endpoint** **Endpoint**
@ -711,6 +711,13 @@ PUT /api/queue/items/{id}
| Parameter | Value | | Parameter | Value |
| --------------- | ----------------------------------------------------------- | | --------------- | ----------------------------------------------------------- |
| new_position | The new position for the queue item in the current queue. | | new_position | The new position for the queue item in the current queue. |
| title | New track title |
| album | New album title |
| artist | New artist |
| album_artist | New album artist |
| composer | New composer |
| genre | New genre |
| artwork_url | New URL to track artwork |
**Response** **Response**
@ -722,6 +729,9 @@ On success returns the HTTP `204 No Content` success status response code.
curl -X PUT "http://localhost:3689/api/queue/items/3?new_position=0" curl -X PUT "http://localhost:3689/api/queue/items/3?new_position=0"
``` ```
```shell
curl -X PUT "http://localhost:3689/api/queue/items/3?title=Awesome%20title&artwork_url=http%3A%2F%2Fgyfgafguf.dk%2Fimages%2Fpige3.jpg"
```
### Removing a queue item ### Removing a queue item

View File

@ -760,14 +760,7 @@ sort_tag_create(char **sort_tag, const char *src_tag)
/* Note: include terminating NUL in string length for u8_normalize */ /* Note: include terminating NUL in string length for u8_normalize */
if (*sort_tag) free(*sort_tag);
{
DPRINTF(E_DBG, L_DB, "Existing sort tag will be normalized: %s\n", *sort_tag);
o_ptr = u8_normalize(UNINORM_NFD, (uint8_t *)*sort_tag, strlen(*sort_tag) + 1, NULL, &len);
free(*sort_tag);
*sort_tag = (char *)o_ptr;
return;
}
if (!src_tag || ((len = strlen(src_tag)) == 0)) if (!src_tag || ((len = strlen(src_tag)) == 0))
{ {
@ -4774,7 +4767,7 @@ db_queue_update_item(struct db_queue_item *qi)
"file_id = %d, song_length = %d, data_kind = %d, media_kind = %d, " \ "file_id = %d, song_length = %d, data_kind = %d, media_kind = %d, " \
"pos = %d, shuffle_pos = %d, path = '%q', virtual_path = %Q, " \ "pos = %d, shuffle_pos = %d, path = '%q', virtual_path = %Q, " \
"title = %Q, artist = %Q, album_artist = %Q, album = %Q, " \ "title = %Q, artist = %Q, album_artist = %Q, album = %Q, " \
"composer = %Q," \ "composer = %Q, " \
"genre = %Q, time_modified = %d, " \ "genre = %Q, time_modified = %d, " \
"songalbumid = %" PRIi64 ", songartistid = %" PRIi64 ", " \ "songalbumid = %" PRIi64 ", songartistid = %" PRIi64 ", " \
"artist_sort = %Q, album_sort = %Q, album_artist_sort = %Q, " \ "artist_sort = %Q, album_sort = %Q, album_artist_sort = %Q, " \
@ -4786,6 +4779,8 @@ db_queue_update_item(struct db_queue_item *qi)
char *query; char *query;
int ret; int ret;
fixup_tags_queue_item(qi);
queue_version = queue_transaction_begin(); queue_version = queue_transaction_begin();
query = sqlite3_mprintf(Q_TMPL, query = sqlite3_mprintf(Q_TMPL,

View File

@ -2533,33 +2533,15 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
} }
static int static int
jsonapi_reply_queue_tracks_move(struct httpd_request *hreq) update_pos(uint32_t item_id, const char *new)
{ {
uint32_t item_id;
uint32_t new_position; uint32_t new_position;
const char *param;
struct player_status status; struct player_status status;
int ret; int ret;
ret = safe_atou32(hreq->uri_parsed->path_parts[3], &item_id); if (safe_atou32(new, &new_position) < 0)
if (ret < 0)
{ {
DPRINTF(E_LOG, L_WEB, "No valid item id given '%s'\n", hreq->uri_parsed->path); DPRINTF(E_LOG, L_WEB, "No valid item new_position '%s'\n", new);
return HTTP_BADREQUEST;
}
param = evhttp_find_header(hreq->query, "new_position");
if (!param)
{
DPRINTF(E_LOG, L_WEB, "Missing parameter 'new_position'\n");
return HTTP_BADREQUEST;
}
if (safe_atou32(param, &new_position) < 0)
{
DPRINTF(E_LOG, L_WEB, "No valid item new_position '%s'\n", param);
return HTTP_BADREQUEST; return HTTP_BADREQUEST;
} }
@ -2568,10 +2550,60 @@ jsonapi_reply_queue_tracks_move(struct httpd_request *hreq)
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_WEB, "Moving item '%d' to new position %d failed\n", item_id, new_position); DPRINTF(E_LOG, L_WEB, "Moving item '%d' to new position %d failed\n", item_id, new_position);
return HTTP_INTERNAL; return HTTP_INTERNAL;
} }
return HTTP_OK;
}
static inline void
update_str(char **str, const char *new)
{
free(*str);
*str = strdup(new);
}
static int
jsonapi_reply_queue_tracks_update(struct httpd_request *hreq)
{
struct db_queue_item *queue_item;
uint32_t item_id;
const char *param;
bool is_changed;
int ret;
ret = safe_atou32(hreq->uri_parsed->path_parts[3], &item_id);
if (ret < 0 || !(queue_item = db_queue_fetch_byitemid(item_id)))
{
DPRINTF(E_LOG, L_WEB, "No valid item id given '%s'\n", hreq->uri_parsed->path);
return HTTP_BADREQUEST;
}
ret = HTTP_OK;
is_changed = false;
if ((param = evhttp_find_header(hreq->query, "new_position")))
ret = update_pos(item_id, param);
if ((param = evhttp_find_header(hreq->query, "title")) && (is_changed = true))
update_str(&queue_item->title, param);
if ((param = evhttp_find_header(hreq->query, "album")) && (is_changed = true))
update_str(&queue_item->album, param);
if ((param = evhttp_find_header(hreq->query, "artist")) && (is_changed = true))
update_str(&queue_item->artist, param);
if ((param = evhttp_find_header(hreq->query, "album_artist")) && (is_changed = true))
update_str(&queue_item->album_artist, param);
if ((param = evhttp_find_header(hreq->query, "composer")) && (is_changed = true))
update_str(&queue_item->composer, param);
if ((param = evhttp_find_header(hreq->query, "genre")) && (is_changed = true))
update_str(&queue_item->genre, param);
if ((param = evhttp_find_header(hreq->query, "artwork_url")) && (is_changed = true))
update_str(&queue_item->artwork_url, param);
if (ret != HTTP_OK)
return ret;
if (is_changed)
db_queue_update_item(queue_item);
return HTTP_NOCONTENT; return HTTP_NOCONTENT;
} }
@ -4345,7 +4377,7 @@ static struct httpd_uri_map adm_handlers[] =
{ EVHTTP_REQ_GET, "^/api/queue$", jsonapi_reply_queue }, { EVHTTP_REQ_GET, "^/api/queue$", jsonapi_reply_queue },
{ EVHTTP_REQ_PUT, "^/api/queue/clear$", jsonapi_reply_queue_clear }, { EVHTTP_REQ_PUT, "^/api/queue/clear$", jsonapi_reply_queue_clear },
{ EVHTTP_REQ_POST, "^/api/queue/items/add$", jsonapi_reply_queue_tracks_add }, { EVHTTP_REQ_POST, "^/api/queue/items/add$", jsonapi_reply_queue_tracks_add },
{ EVHTTP_REQ_PUT, "^/api/queue/items/[[:digit:]]+$", jsonapi_reply_queue_tracks_move }, { EVHTTP_REQ_PUT, "^/api/queue/items/[[:digit:]]+$", jsonapi_reply_queue_tracks_update },
{ EVHTTP_REQ_DELETE, "^/api/queue/items/[[:digit:]]+$", jsonapi_reply_queue_tracks_delete }, { EVHTTP_REQ_DELETE, "^/api/queue/items/[[:digit:]]+$", jsonapi_reply_queue_tracks_delete },
{ EVHTTP_REQ_POST, "^/api/queue/save$", jsonapi_reply_queue_save}, { EVHTTP_REQ_POST, "^/api/queue/save$", jsonapi_reply_queue_save},