[jsonapi] Add PUT /api/library/tracks endpoint (update multiple tracks)

Also fix error in json doc (track->id type)
This commit is contained in:
ejurgensen 2021-10-09 00:49:29 +02:00
parent 41e3733ccc
commit d2ee9f20fb
2 changed files with 128 additions and 3 deletions

View File

@ -791,7 +791,8 @@ curl -X PUT "http://localhost:3689/api/queue/items/2"
| GET | [/api/library/albums/{id}/tracks](#list-album-tracks) | Get list of tracks for an album |
| GET | [/api/library/tracks/{id}](#get-a-track) | Get a track |
| GET | [/api/library/tracks/{id}/playlists](#list-playlists-for-a-track) | Get list of playlists for a track |
| PUT | [/api/library/tracks/{id}](#update-track-properties) | Update track properties |
| PUT | [/api/library/tracks](#update-track-properties) | Update multiple track properties |
| PUT | [/api/library/tracks/{id}](#update-track-properties) | Update single track properties |
| GET | [/api/library/genres](#list-genres) | Get list of genres |
| GET | [/api/library/count](#get-count-of-tracks-artists-and-albums) | Get count of tracks, artists and albums |
| GET | [/api/library/files](#list-local-directories) | Get list of directories in the local library |
@ -1602,7 +1603,30 @@ curl -X GET "http://localhost:3689/api/library/tracks/27/playlists"
### Update track properties
Change properties of a specific track (supported properties are "rating", "play_count" and "usermark")
Change properties of one or more tracks (supported properties are "rating", "play_count" and "usermark")
**Endpoint**
```http
PUT /api/library/tracks
```
**Body parameters**
| Parameter | Type | Value |
| --------------- | -------- | ----------------------- |
| tracks | array | Array of track objects |
**Response**
On success returns the HTTP `204 No Content` success status response code.
**Example**
```shell
curl -X PUT -d '{ "tracks": [ { "id": 1, "rating": 100, "usermark": 4 }, { "id": 2, "usermark": 3 } ] }' "http://localhost:3689/api/library/tracks"
```
**Endpoint**
@ -2536,7 +2560,7 @@ curl --include \
| Key | Type | Value |
| ------------------ | -------- | ----------------------------------------- |
| id | string | Track id |
| id | integer | Track id |
| title | string | Title |
| title_sort | string | Sort title |
| artist | string | Track artist name |

View File

@ -334,6 +334,25 @@ track_to_json(struct db_media_file_info *dbmfi)
return item;
}
// TODO Only partially implemented. A full implementation should use a mapping
// table, which should also be used above in track_to_json(). It should also
// return errors if there are incorrect/mispelled fields, but not sure how to
// walk a json object with json-c.
static int
json_to_track(struct media_file_info *mfi, json_object *json)
{
if (jparse_contains_key(json, "id", json_type_int))
mfi->id = jparse_int_from_obj(json, "id");
if (jparse_contains_key(json, "usermark", json_type_int))
mfi->usermark = jparse_int_from_obj(json, "usermark");
if (jparse_contains_key(json, "rating", json_type_int))
mfi->rating = jparse_int_from_obj(json, "rating");
if (jparse_contains_key(json, "play_count", json_type_int))
mfi->play_count = jparse_int_from_obj(json, "play_count");
return HTTP_OK;
}
static json_object *
playlist_to_json(struct db_playlist_info *dbpli)
{
@ -3293,6 +3312,87 @@ jsonapi_reply_library_tracks_get_byid(struct httpd_request *hreq)
return HTTP_OK;
}
static int
jsonapi_reply_library_tracks_put(struct httpd_request *hreq)
{
struct evbuffer *in_evbuf;
json_object *request = NULL;
json_object *tracks;
json_object *track = NULL;
struct media_file_info *mfi = NULL;
int ret;
int err;
int32_t track_id;
int i;
in_evbuf = evhttp_request_get_input_buffer(hreq->req);
request = jparse_obj_from_evbuffer(in_evbuf);
if (!request)
{
DPRINTF(E_LOG, L_WEB, "Failed to read json tracks request\n");
err = HTTP_BADREQUEST;
goto error;
}
ret = jparse_array_from_obj(request, "tracks", &tracks);
if (ret < 0)
{
DPRINTF(E_LOG, L_WEB, "Failed to parse json tracks request\n");
err = HTTP_BADREQUEST;
goto error;
}
db_transaction_begin();
i = 0;
while ((track = json_object_array_get_idx(tracks, i)))
{
track_id = jparse_int_from_obj(track, "id");
if (track_id == 0)
{
DPRINTF(E_LOG, L_WEB, "Invalid or missing track id in json tracks request\n");
err = HTTP_BADREQUEST;
goto error;
}
mfi = db_file_fetch_byid(track_id);
if (!mfi)
{
DPRINTF(E_LOG, L_WEB, "Unknown track_id %d in json tracks request\n", track_id);
err = HTTP_NOTFOUND;
goto error;
}
ret = json_to_track(mfi, track);
if (ret != HTTP_OK)
{
err = ret;
goto error;
}
ret = library_media_save(mfi);
if (ret < 0)
{
err = HTTP_INTERNAL;
goto error;
}
free_mfi(mfi, 0);
mfi = NULL;
i++;
}
jparse_free(request);
db_transaction_end();
return HTTP_OK;
error:
jparse_free(request);
if (track)
db_transaction_rollback();
free_mfi(mfi, 0);
return err;
}
static int
jsonapi_reply_library_tracks_put_byid(struct httpd_request *hreq)
{
@ -4424,6 +4524,7 @@ static struct httpd_uri_map adm_handlers[] =
{ EVHTTP_REQ_GET, "^/api/library/albums/[[:digit:]]+$", jsonapi_reply_library_album },
{ EVHTTP_REQ_GET, "^/api/library/albums/[[:digit:]]+/tracks$", jsonapi_reply_library_album_tracks },
{ EVHTTP_REQ_PUT, "^/api/library/albums/[[:digit:]]+/tracks$", jsonapi_reply_library_album_tracks_put_byid },
{ EVHTTP_REQ_PUT, "^/api/library/tracks$", jsonapi_reply_library_tracks_put },
{ EVHTTP_REQ_GET, "^/api/library/tracks/[[:digit:]]+$", jsonapi_reply_library_tracks_get_byid },
{ EVHTTP_REQ_PUT, "^/api/library/tracks/[[:digit:]]+$", jsonapi_reply_library_tracks_put_byid },
{ EVHTTP_REQ_GET, "^/api/library/tracks/[[:digit:]]+/playlists$", jsonapi_reply_library_track_playlists },