diff --git a/README_JSON_API.md b/README_JSON_API.md index eef5920a..27ace19e 100644 --- a/README_JSON_API.md +++ b/README_JSON_API.md @@ -37,7 +37,7 @@ JSON-Object model: **Endpoint** -``` +```http GET /api/player ``` @@ -57,11 +57,11 @@ GET /api/player **Example** -``` +```shell curl -X GET "http://localhost:3689/api/player" ``` -``` +```json { "state": "pause", "repeat": "off", @@ -81,15 +81,15 @@ Start or resume, pause, stop playback. **Endpoint** -``` +```http PUT /api/player/play ``` -``` +```http PUT /api/player/pause ``` -``` +```http PUT /api/player/stop ``` @@ -99,15 +99,15 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/player/play" ``` -``` +```shell curl -X PUT "http://localhost:3689/api/player/pause" ``` -``` +```shell curl -X PUT "http://localhost:3689/api/player/stop" ``` @@ -118,11 +118,11 @@ Skip forward or backward **Endpoint** -``` +```http PUT /api/player/next ``` -``` +```http PUT /api/player/prev ``` @@ -132,11 +132,11 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/player/next" ``` -``` +```shell curl -X PUT "http://localhost:3689/api/player/prev" ``` @@ -147,7 +147,7 @@ Enable or disable shuffle mode **Endpoint** -``` +```http PUT /api/player/shuffle ``` @@ -164,7 +164,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/player/shuffle?state=true" ``` @@ -175,7 +175,7 @@ Enable or disable consume mode **Endpoint** -``` +```http PUT /api/player/consume ``` @@ -192,7 +192,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/player/consume?state=true" ``` @@ -203,7 +203,7 @@ Change repeat mode **Endpoint** -``` +```http PUT /api/player/repeat ``` @@ -220,7 +220,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/player/repeat?state=all" ``` @@ -231,7 +231,7 @@ Change master volume or volume of a specific output. **Endpoint** -``` +```http PUT /api/player/volume ``` @@ -249,11 +249,11 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/player/volume?volume=50" ``` -``` +```shell curl -X PUT "http://localhost:3689/api/player/volume?volume=50&output_id=0" ``` @@ -264,7 +264,7 @@ Seek to a position in the currently playing track. **Endpoint** -``` +```http PUT /api/player/seek ``` @@ -281,7 +281,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/player/seek?position_ms=2000" ``` @@ -302,7 +302,7 @@ curl -X PUT "http://localhost:3689/api/player/seek?position_ms=2000" **Endpoint** -``` +```http GET /api/outputs ``` @@ -328,11 +328,11 @@ GET /api/outputs **Example** -``` +```shell curl -X GET "http://localhost:3689/api/outputs" ``` -``` +```json { "outputs": [ { @@ -376,7 +376,7 @@ with the given ids and disables the remaining outputs. **Endpoint** -``` +```http PUT /api/outputs/set ``` @@ -392,7 +392,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/outputs/set" --data "{\"outputs\":[\"198018693182577\",\"0\"]}" ``` @@ -403,7 +403,7 @@ Get an output **Endpoint** -``` +```http GET /api/outputs/{id} ``` @@ -419,11 +419,11 @@ On success returns the HTTP `200 OK` success status response code. With the resp **Example** -``` +```shell curl -X GET "http://localhost:3689/api/outputs/0" ``` -``` +```json { "id": "0", "name": "Computer", @@ -442,7 +442,7 @@ Enable or disable an output and change its volume. **Endpoint** -``` +```http PUT /api/outputs/{id} ``` @@ -465,7 +465,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/outputs/0" --data "{\"selected\":true, \"volume\": 50}" ``` @@ -489,7 +489,7 @@ Lists the items in the current queue **Endpoint** -``` +```http GET /api/queue ``` @@ -511,11 +511,11 @@ GET /api/queue **Example** -``` +```shell curl -X GET "http://localhost:3689/api/queue" ``` -``` +```json { "version": 833, "count": 20, @@ -553,7 +553,7 @@ Remove all items form the current queue **Endpoint** -``` +```http PUT /api/queue/clear ``` @@ -563,7 +563,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/queue/clear" ``` @@ -574,7 +574,7 @@ Add tracks, playlists artists or albums to the current queue **Endpoint** -``` +```http POST /api/queue/items/add ``` @@ -583,6 +583,7 @@ POST /api/queue/items/add | Parameter | Value | | --------------- | ----------------------------------------------------------- | | uris | Comma seperated list of resource identifiers (`track`, `playlist`, `artist` or `album` object `uri`) | +| position | *(Optional)* If a position is given, new items are inserted starting from this position into the queue. | **Response** @@ -590,7 +591,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X POST "http://localhost:3689/api/queue/items/add?uris=library:playlist:68,library:artist:2932599850102967727" ``` @@ -601,7 +602,7 @@ Move a queue item in the current queue **Endpoint** -``` +```http PUT /api/queue/items/{id} ``` @@ -623,7 +624,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/queue/items/3?new_position=0" ``` @@ -634,7 +635,7 @@ Remove a queue item from the current queue **Endpoint** -``` +```http DELETE /api/queue/items/{id} ``` @@ -650,7 +651,7 @@ On success returns the HTTP `204 No Content` success status response code. **Example** -``` +```shell curl -X PUT "http://localhost:3689/api/queue/items/2" ``` @@ -680,7 +681,7 @@ Lists the playlists in your library **Endpoint** -``` +```http GET /api/library/playlists ``` @@ -703,11 +704,11 @@ GET /api/library/playlists **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/playlists" ``` -``` +```json { "items": [ { @@ -732,7 +733,7 @@ Get a specific playlists in your library **Endpoint** -``` +```http GET /api/library/playlists/{id} ``` @@ -749,11 +750,11 @@ On success returns the HTTP `200 OK` success status response code. With the resp **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/playlists/1" ``` -``` +```json { "id": 1, "name": "radio", @@ -770,7 +771,7 @@ Lists the tracks in a playlists **Endpoint** -``` +```http GET /api/library/playlists/{id}/tracks ``` @@ -799,11 +800,11 @@ GET /api/library/playlists/{id}/tracks **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/playlists/1/tracks" ``` -``` +```json { "items": [ { @@ -843,7 +844,7 @@ Lists the artists in your library **Endpoint** -``` +```http GET /api/library/artists ``` @@ -866,11 +867,11 @@ GET /api/library/artists **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/artists" ``` -``` +```json { "items": [ { @@ -897,7 +898,7 @@ Get a specific artist in your library **Endpoint** -``` +```http GET /api/library/artists/{id} ``` @@ -914,11 +915,11 @@ On success returns the HTTP `200 OK` success status response code. With the resp **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/artists/3815427709949443149" ``` -``` +```json { "id": "3815427709949443149", "name": "ABAY", @@ -937,7 +938,7 @@ Lists the albums of an artist **Endpoint** -``` +```http GET /api/library/artists/{id}/albums ``` @@ -966,11 +967,11 @@ GET /api/library/artists/{id}/albums **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/artists/32561671101664759/albums" ``` -``` +```json { "items": [ { @@ -998,7 +999,7 @@ Lists the albums in your library **Endpoint** -``` +```http GET /api/library/albums ``` @@ -1021,11 +1022,11 @@ GET /api/library/albums **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/albums" ``` -``` +```json { "items": [ { @@ -1053,7 +1054,7 @@ Get a specific album in your library **Endpoint** -``` +```http GET /api/library/albums/{id} ``` @@ -1070,11 +1071,11 @@ On success returns the HTTP `200 OK` success status response code. With the resp **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/albums/8009851123233197743" ``` -``` +```json { "id": "8009851123233197743", "name": "Add Violence", @@ -1094,7 +1095,7 @@ Lists the tracks in an album **Endpoint** -``` +```http GET /api/library/albums/{id}/tracks ``` @@ -1123,11 +1124,11 @@ GET /api/library/albums/{id}/tracks **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/albums/1/tracks" ``` -``` +```json { "items": [ { @@ -1166,7 +1167,7 @@ Get list of genres **Endpoint** -``` +```http GET /api/library/genres ``` **Response** @@ -1181,11 +1182,11 @@ GET /api/library/genres **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/genres" ``` -``` +```json { "items": [ { @@ -1217,7 +1218,7 @@ Lists the albums in a genre **Endpoint** -``` +```http GET api/search?type=albums&expression=genre+is+\"{genre name}\"" ``` @@ -1241,14 +1242,14 @@ GET api/search?type=albums&expression=genre+is+\"{genre name}\"" **Example** -``` +```shell curl -X GET "http://localhost:3689/api/search?type=albums&expression=genre+is+\"Pop\"" curl -X GET "http://localhost:3689/api/search?type=albums&expression=genre+is+\"Rock%2FPop\"" # Rock/Pop curl -X GET "http://localhost:3689/api/search?type=albums&expression=genre+is+\"Drum%20%26%20Bass\"" # Drum & Bass curl -X GET "http://localhost:3689/api/search?type=albums&expression=genre+is+\"%2790s%20Alternative\"" # '90 Alternative ``` -``` +```json { "albums": { "items": [ @@ -1296,7 +1297,7 @@ Get information about the number of tracks, artists and albums and the total pla **Endpoint** -``` +```http GET /api/library/count ``` @@ -1318,11 +1319,11 @@ GET /api/library/count **Example** -``` +```shell curl -X GET "http://localhost:3689/api/library/count?expression=data_kind+is+file" ``` -``` +```json { "tracks": 6811, "artists": 355, @@ -1348,7 +1349,7 @@ Search for playlists, artists, albums, tracks, genres that include the given que **Endpoint** -``` +```http GET /api/search ``` @@ -1376,11 +1377,11 @@ GET /api/search Search for all tracks, artists, albums and playlists that contain "the" in their title and return the first two results for each type: -``` +```shell curl -X GET "http://localhost:3689/api/search?type=tracks,artists,albums,playlists&query=the&offset=0&limit=2" ``` -``` +```json { "tracks": { "items": [ @@ -1491,7 +1492,7 @@ Search for artists, albums, tracks by a smart playlist query expression (see [RE **Endpoint** -``` +```http GET /api/search ``` @@ -1517,7 +1518,7 @@ GET /api/search Search for music tracks ordered descending by the time added to the library and limit result to 2 items: -``` +```shell curl -X GET "http://localhost:3689/api/search?type=tracks&expression=media_kind+is+music+order+by+time_added+desc&offset=0&limit=2" ``` @@ -1534,7 +1535,7 @@ curl -X GET "http://localhost:3689/api/search?type=tracks&expression=media_kind+ **Endpoint** -``` +```http GET /api/config ``` @@ -1549,11 +1550,11 @@ GET /api/config **Example** -``` +```shell curl -X GET "http://localhost:3689/api/config" ``` -``` +```json { "websocket_port": 3688, "version": "25.0", @@ -1597,7 +1598,7 @@ will send a message each time one of the events occurred. **Example** -``` +```shell curl --include \ --no-buffer \ --header "Connection: Upgrade" \ @@ -1611,7 +1612,7 @@ curl --include \ --data "{ \"notify\": [ \"player\" ] }" ``` -``` +```json { "notify": [ "player" diff --git a/src/db.c b/src/db.c index 608765d1..433f8294 100644 --- a/src/db.c +++ b/src/db.c @@ -4678,7 +4678,7 @@ queue_add_item(struct db_queue_item *item, int pos, int shuffle_pos, int queue_v query = sqlite3_mprintf(Q_TMPL, item->file_id, item->song_length, item->data_kind, item->media_kind, - pos, 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->time_modified, item->artist_sort, item->album_sort, item->album_artist_sort, item->year, item->track, item->disc, queue_version); @@ -4760,28 +4760,48 @@ db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id) } int -db_queue_add_start(struct db_queue_add_info *queue_add_info) +db_queue_add_start(struct db_queue_add_info *queue_add_info, int pos) { + int queue_count; int ret = 0; memset(queue_add_info, 0, sizeof(struct db_queue_add_info)); queue_add_info->queue_version = queue_transaction_begin(); - queue_add_info->pos = db_queue_get_count(); - if (queue_add_info->pos < 0) + queue_count = db_queue_get_count(); + if (queue_count < 0) { ret = -1; queue_transaction_end(ret, queue_add_info->queue_version); return ret; } - return 0; + queue_add_info->pos = queue_count; + queue_add_info->shuffle_pos = queue_count; + + if (pos >= 0 && pos < queue_count) + queue_add_info->pos = pos; + + queue_add_info->start_pos = queue_add_info->pos; + + return 0; } -void +int db_queue_add_end(struct db_queue_add_info *queue_add_info, int ret) { + char *query; + + // Update pos for all items from the given position + if (ret == 0) + { + query = sqlite3_mprintf("UPDATE queue SET pos = pos + %d, queue_version = %d WHERE pos >= %d AND queue_version < %d;", + queue_add_info->count, queue_add_info->queue_version, queue_add_info->start_pos, queue_add_info->queue_version); + ret = db_query_run(query, 1, 0); + } + queue_transaction_end(ret, queue_add_info->queue_version); + return ret; } int @@ -4790,9 +4810,16 @@ db_queue_add_item(struct db_queue_add_info *queue_add_info, struct db_queue_item int ret; fixup_tags_queue_item(item); - ret = queue_add_item(item, queue_add_info->pos, queue_add_info->pos, queue_add_info->queue_version); + ret = queue_add_item(item, queue_add_info->pos, queue_add_info->shuffle_pos, queue_add_info->queue_version); if (ret == 0) - queue_add_info->pos++; + { + queue_add_info->pos++; + queue_add_info->shuffle_pos++; + queue_add_info->count++; + + if (queue_add_info->new_item_id == 0) + queue_add_info->new_item_id = (int) sqlite3_last_insert_rowid(hdl); + } return ret; diff --git a/src/db.h b/src/db.h index b4a9d778..906d3f9a 100644 --- a/src/db.h +++ b/src/db.h @@ -474,7 +474,11 @@ struct db_queue_item struct db_queue_add_info { int queue_version; + int start_pos; int pos; + int shuffle_pos; + int count; + int new_item_id; }; char * @@ -787,9 +791,9 @@ int db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id); int -db_queue_add_start(struct db_queue_add_info *queue_add_info); +db_queue_add_start(struct db_queue_add_info *queue_add_info, int pos); -void +int db_queue_add_end(struct db_queue_add_info *queue_add_info, int ret); int diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index d2b598c0..ca3eb84b 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -1566,10 +1566,11 @@ queue_item_to_json(struct db_queue_item *queue_item, char shuffle) } static int -queue_tracks_add_artist(const char *id) +queue_tracks_add_artist(const char *id, int pos) { struct query_params query_params; struct player_status status; + int count = 0; int ret = 0; memset(&query_params, 0, sizeof(struct query_params)); @@ -1581,18 +1582,22 @@ queue_tracks_add_artist(const char *id) player_get_status(&status); - ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, -1, NULL, NULL); + ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, &count, NULL); free(query_params.filter); + if (ret == 0) + return count; + return ret; } static int -queue_tracks_add_album(const char *id) +queue_tracks_add_album(const char *id, int pos) { struct query_params query_params; struct player_status status; + int count = 0; int ret = 0; memset(&query_params, 0, sizeof(struct query_params)); @@ -1604,18 +1609,22 @@ queue_tracks_add_album(const char *id) player_get_status(&status); - ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, -1, NULL, NULL); + ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, &count, NULL); free(query_params.filter); + if (ret == 0) + return count; + return ret; } static int -queue_tracks_add_track(const char *id) +queue_tracks_add_track(const char *id, int pos) { struct query_params query_params; struct player_status status; + int count = 0; int ret = 0; memset(&query_params, 0, sizeof(struct query_params)); @@ -1627,18 +1636,22 @@ queue_tracks_add_track(const char *id) player_get_status(&status); - ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, -1, NULL, NULL); + ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, &count, NULL); free(query_params.filter); + if (ret == 0) + return count; + return ret; } static int -queue_tracks_add_playlist(const char *id) +queue_tracks_add_playlist(const char *id, int pos) { struct player_status status; int playlist_id; + int count = 0; int ret; ret = safe_atoi32(id, &playlist_id); @@ -1651,7 +1664,10 @@ queue_tracks_add_playlist(const char *id) player_get_status(&status); - ret = db_queue_add_by_playlistid(playlist_id, status.shuffle, status.item_id, -1, NULL, NULL); + ret = db_queue_add_by_playlistid(playlist_id, status.shuffle, status.item_id, pos, &count, NULL); + + if (ret == 0) + return count; return ret; } @@ -1663,8 +1679,24 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq) char *uris; char *uri; const char *id; + int pos = -1; + int count = 0; int ret = 0; + + param = evhttp_find_header(hreq->query, "position"); + if (param) + { + if (safe_atoi32(param, &pos) < 0) + { + DPRINTF(E_LOG, L_WEB, "Invalid position parameter '%s'\n", param); + + return HTTP_BADREQUEST; + } + + DPRINTF(E_DBG, L_WEB, "Add tracks starting at position '%d\n", pos); + } + param = evhttp_find_header(hreq->query, "uris"); if (!param) { @@ -1678,35 +1710,41 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq) do { + count = 0; + if (strncmp(uri, "library:artist:", strlen("library:artist:")) == 0) { id = uri + (strlen("library:artist:")); - queue_tracks_add_artist(id); + count = queue_tracks_add_artist(id, pos); } else if (strncmp(uri, "library:album:", strlen("library:album:")) == 0) { id = uri + (strlen("library:album:")); - queue_tracks_add_album(id); + count = queue_tracks_add_album(id, pos); } else if (strncmp(uri, "library:track:", strlen("library:track:")) == 0) { id = uri + (strlen("library:track:")); - queue_tracks_add_track(id); + count = queue_tracks_add_track(id, pos); } else if (strncmp(uri, "library:playlist:", strlen("library:playlist:")) == 0) { id = uri + (strlen("library:playlist:")); - queue_tracks_add_playlist(id); + count = queue_tracks_add_playlist(id, pos); } else { - ret = library_queue_add(uri); + ret = library_queue_add(uri, pos, &count, NULL); if (ret != LIBRARY_OK) { DPRINTF(E_LOG, L_WEB, "Invalid uri '%s'\n", uri); break; } + pos += count; } + + if (pos >= 0) + pos += count; } while ((uri = strtok(NULL, ","))); diff --git a/src/library.c b/src/library.c index 90682297..462f32ae 100644 --- a/src/library.c +++ b/src/library.c @@ -143,7 +143,7 @@ library_add_media(struct media_file_info *mfi) } int -library_queue_add(const char *path) +library_queue_add(const char *path, int position, int *count, int *new_item_id) { int i; int ret; @@ -159,7 +159,7 @@ library_queue_add(const char *path) continue; } - ret = sources[i]->queue_add(path); + ret = sources[i]->queue_add(path, position, count, new_item_id); if (ret == LIBRARY_OK) { diff --git a/src/library.h b/src/library.h index e02446ea..ba20f3d4 100644 --- a/src/library.h +++ b/src/library.h @@ -84,7 +84,7 @@ struct library_source /* * Add item for the given path to the current queue */ - int (*queue_add)(const char *path); + int (*queue_add)(const char *path, int position, int *count, int *new_item_id); }; void @@ -94,7 +94,7 @@ int library_add_playlist_info(const char *path, const char *title, const char *virtual_path, enum pl_type type, int parent_pl_id, int dir_id); int -library_queue_add(const char *path); +library_queue_add(const char *path, int position, int *count, int *new_item_id); void library_rescan(); diff --git a/src/library/filescanner.c b/src/library/filescanner.c index fd36704b..a8a6fb2e 100644 --- a/src/library/filescanner.c +++ b/src/library/filescanner.c @@ -1676,7 +1676,7 @@ map_media_file_to_queue_item(struct db_queue_item *queue_item, struct media_file } static int -queue_add_stream(const char *path) +queue_add_stream(const char *path, int position, int *count, int *new_item_id) { struct media_file_info mfi; struct db_queue_item item; @@ -1690,11 +1690,18 @@ queue_add_stream(const char *path) map_media_file_to_queue_item(&item, &mfi); - ret = db_queue_add_start(&queue_add_info); + ret = db_queue_add_start(&queue_add_info, position); if (ret == 0) { ret = db_queue_add_item(&queue_add_info, &item); - db_queue_add_end(&queue_add_info, ret); + ret = db_queue_add_end(&queue_add_info, ret); + if (ret == 0) + { + if (count) + *count = queue_add_info.count; + if (new_item_id) + *new_item_id = queue_add_info.new_item_id; + } } free_queue_item(&item, 1); @@ -1704,11 +1711,11 @@ queue_add_stream(const char *path) } static int -queue_add(const char *uri) +queue_add(const char *uri, int position, int *count, int *new_item_id) { if (strncasecmp(uri, "http://", strlen("http://")) == 0) { - queue_add_stream(uri); + queue_add_stream(uri, position, count, new_item_id); return LIBRARY_OK; } diff --git a/src/mpd.c b/src/mpd.c index e009751d..7ad9bdcb 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -1699,7 +1699,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, st if (ret == 0) { // Given path is not in the library, check if it is possible to add as a non-library queue item - ret = library_queue_add(argv[1]); + ret = library_queue_add(argv[1], -1, NULL, NULL); if (ret != LIBRARY_OK) { *errmsg = safe_asprintf("Failed to add song '%s' to playlist (unkown path)", argv[1]); @@ -1737,7 +1737,7 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, if (ret == 0) { // Given path is not in the library, directly add it as a new queue item - ret = library_queue_add(argv[1]); + ret = library_queue_add(argv[1], to_pos, NULL, NULL); if (ret != LIBRARY_OK) { *errmsg = safe_asprintf("Failed to add song '%s' to playlist (unkown path)", argv[1]); diff --git a/src/spotify_webapi.c b/src/spotify_webapi.c index 2a734b3a..ff66cb41 100644 --- a/src/spotify_webapi.c +++ b/src/spotify_webapi.c @@ -997,7 +997,7 @@ map_track_to_queueitem(struct db_queue_item *item, const struct spotify_track *t } static int -queue_add_track(const char *uri) +queue_add_track(const char *uri, int position, int *count, int *new_item_id) { json_object *response; struct spotify_track track; @@ -1015,11 +1015,18 @@ queue_add_track(const char *uri) map_track_to_queueitem(&item, &track, NULL); - ret = db_queue_add_start(&queue_add_info); + ret = db_queue_add_start(&queue_add_info, position); if (ret == 0) { ret = db_queue_add_item(&queue_add_info, &item); - db_queue_add_end(&queue_add_info, ret); + ret = db_queue_add_end(&queue_add_info, ret); + if (ret == 0) + { + if (count) + *count = queue_add_info.count; + if (new_item_id) + *new_item_id = queue_add_info.new_item_id; + } } free_queue_item(&item, 1); @@ -1061,7 +1068,7 @@ queue_add_album_tracks(json_object *item, int index, int total, void *arg) } static int -queue_add_album(const char *uri) +queue_add_album(const char *uri, int position, int *count, int *new_item_id) { char *album_endpoint_uri = NULL; char *endpoint_uri = NULL; @@ -1073,7 +1080,7 @@ queue_add_album(const char *uri) json_album = request_endpoint_with_token_refresh(album_endpoint_uri); parse_metadata_album(json_album, ¶m.album); - ret = db_queue_add_start(¶m.queue_add_info); + ret = db_queue_add_start(¶m.queue_add_info, position); if (ret < 0) goto out; @@ -1081,7 +1088,9 @@ queue_add_album(const char *uri) ret = request_pagingobject_endpoint(endpoint_uri, queue_add_album_tracks, NULL, NULL, true, ¶m); - db_queue_add_end(¶m.queue_add_info, ret); + ret = db_queue_add_end(¶m.queue_add_info, ret); + if (ret == 0 && count) + *count = param.queue_add_info.count; out: free(album_endpoint_uri); @@ -1128,13 +1137,13 @@ queue_add_playlist_tracks(json_object *item, int index, int total, void *arg) } static int -queue_add_playlist(const char *uri) +queue_add_playlist(const char *uri, int position, int *count, int *new_item_id) { char *endpoint_uri; struct db_queue_add_info queue_add_info; int ret; - ret = db_queue_add_start(&queue_add_info); + ret = db_queue_add_start(&queue_add_info, position); if (ret < 0) return -1; @@ -1142,7 +1151,9 @@ queue_add_playlist(const char *uri) ret = request_pagingobject_endpoint(endpoint_uri, queue_add_playlist_tracks, NULL, NULL, true, &queue_add_info); - db_queue_add_end(&queue_add_info, ret); + ret = db_queue_add_end(&queue_add_info, ret); + if (ret == 0 && count) + *count = queue_add_info.count; free(endpoint_uri); @@ -1150,21 +1161,21 @@ queue_add_playlist(const char *uri) } static int -queue_add(const char *uri) +queue_add(const char *uri, int position, int *count, int *new_item_id) { if (strncasecmp(uri, "spotify:track:", strlen("spotify:track:")) == 0) { - queue_add_track(uri); + queue_add_track(uri, position, count, new_item_id); return LIBRARY_OK; } else if (strncasecmp(uri, "spotify:album:", strlen("spotify:album:")) == 0) { - queue_add_album(uri); + queue_add_album(uri, position, count, new_item_id); return LIBRARY_OK; } else if (strncasecmp(uri, "spotify:", strlen("spotify:")) == 0) { - queue_add_playlist(uri); + queue_add_playlist(uri, position, count, new_item_id); return LIBRARY_OK; }