From 7252b3e509fdcdb5dc34b8fe9fef0cc8a9e08177 Mon Sep 17 00:00:00 2001 From: chme Date: Thu, 6 Sep 2018 21:16:27 +0200 Subject: [PATCH] [db] Add support to add items to the queue at specified position --- src/db.c | 119 ++++++++++++++++++++------------------------ src/db.h | 6 +-- src/httpd_dacp.c | 6 +-- src/httpd_jsonapi.c | 8 +-- src/mpd.c | 25 +++++----- src/player.c | 2 +- 6 files changed, 77 insertions(+), 89 deletions(-) diff --git a/src/db.c b/src/db.c index 54b9dfcd..4804a145 100644 --- a/src/db.c +++ b/src/db.c @@ -4612,7 +4612,7 @@ queue_add_file(struct db_media_file_info *dbmfi, int pos, int shuffle_pos, int q query = sqlite3_mprintf(Q_TMPL, dbmfi->id, dbmfi->song_length, dbmfi->data_kind, dbmfi->media_kind, - pos, pos, dbmfi->path, dbmfi->virtual_path, dbmfi->title, + pos, shuffle_pos, dbmfi->path, dbmfi->virtual_path, dbmfi->title, dbmfi->artist, dbmfi->album_artist, dbmfi->album, dbmfi->genre, dbmfi->songalbumid, dbmfi->time_modified, dbmfi->artist_sort, dbmfi->album_sort, dbmfi->album_artist_sort, dbmfi->year, dbmfi->track, dbmfi->disc, queue_version); @@ -4710,66 +4710,18 @@ db_queue_update_item(struct db_queue_item *qi) int db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id) { - int queue_version; - struct db_media_file_info dbmfi; - char *query; - int shuffle_pos; int pos; int ret; - queue_version = queue_transaction_begin(); - // Position of the first new item pos = db_queue_get_pos(item_id, 0); if (pos < 0) { - ret = -1; - goto end_transaction; + return -1; } pos++; - // Shuffle position of the first new item - shuffle_pos = db_queue_get_count(); - if (shuffle_pos < 0) - { - ret = -1; - goto end_transaction; - } - - // Start query for new items from files table - ret = db_query_start(qp); - if (ret < 0) - goto end_transaction; - - DPRINTF(E_DBG, L_DB, "Player queue query returned %d items\n", qp->results); - - // Update pos for all items after the item with item_id - query = sqlite3_mprintf("UPDATE queue SET pos = pos + %d, queue_version = %d WHERE pos > %d;", qp->results, queue_version, (pos - 1)); - ret = db_query_run(query, 1, 0); - if (ret < 0) - goto end_transaction; - - // Iterate over new items from files table and insert into queue - while (((ret = db_query_fetch_file(qp, &dbmfi)) == 0) && (dbmfi.id)) - { - ret = queue_add_file(&dbmfi, pos, shuffle_pos, queue_version); - - if (ret < 0) - { - DPRINTF(E_LOG, L_DB, "Failed to add song with id %s (%s) to queue\n", dbmfi.id, dbmfi.title); - break; - } - - DPRINTF(E_DBG, L_DB, "Added song with id %s (%s) to queue\n", dbmfi.id, dbmfi.title); - shuffle_pos++; - pos++; - } - - db_query_end(qp); - - end_transaction: - queue_transaction_end(ret, queue_version); - + ret = db_queue_add_by_query(qp, 0, 0, pos, NULL, NULL); return ret; } @@ -4825,21 +4777,30 @@ db_queue_add_item(struct db_queue_add_info *queue_add_info, struct db_queue_item * @param qp Query parameters for the files table * @param reshuffle If 1 queue will be reshuffled after adding new items * @param item_id The base item id, all items after this will be reshuffled - * @return Item id of the last inserted item on success, -1 on failure + * @param position The position in the queue for the new queue item, -1 to add at end of queue + * @param count If not NULL returns the number of items added to the queue + * @param new_item_id If not NULL return the queue item id of the first new queue item + * @return 0 on success, -1 on failure */ int -db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id) +db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id) { struct db_media_file_info dbmfi; + char *query; int queue_version; + int queue_count; int pos; - int new_item_id = 0; // Quell compiler warning about uninitialized use of new_item_id int ret; + if (new_item_id) + *new_item_id = 0; + if (count) + *count = 0; + queue_version = queue_transaction_begin(); - pos = db_queue_get_count(); - if (pos < 0) + queue_count = db_queue_get_count(); + if (queue_count < 0) { ret = -1; goto end_transaction; @@ -4858,9 +4819,24 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id) return 0; } + if (position < 0 || position > queue_count) + { + pos = queue_count; + } + else + { + pos = position; + + // Update pos for all items from the given position (make room for the new items in the queue) + query = sqlite3_mprintf("UPDATE queue SET pos = pos + %d, queue_version = %d WHERE pos >= %d;", qp->results, queue_version, pos); + ret = db_query_run(query, 1, 0); + if (ret < 0) + goto end_transaction; + } + while (((ret = db_query_fetch_file(qp, &dbmfi)) == 0) && (dbmfi.id)) { - ret = queue_add_file(&dbmfi, pos, pos, queue_version); + ret = queue_add_file(&dbmfi, pos, queue_count, queue_version); if (ret < 0) { @@ -4869,7 +4845,14 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id) } DPRINTF(E_DBG, L_DB, "Added song id %s (%s) to queue\n", dbmfi.id, dbmfi.title); + + if (new_item_id && *new_item_id == 0) + *new_item_id = (int) sqlite3_last_insert_rowid(hdl); + if (count) + (*count)++; + pos++; + queue_count++; } db_query_end(qp); @@ -4877,8 +4860,6 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id) if (ret < 0) goto end_transaction; - new_item_id = (int) sqlite3_last_insert_rowid(hdl); - // Reshuffle after adding new items if (reshuffle) { @@ -4888,7 +4869,7 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id) end_transaction: queue_transaction_end(ret, queue_version); - return (ret == 0) ? new_item_id : ret; + return ret; } /* @@ -4897,10 +4878,13 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id) * @param plid Id of the stored playlist * @param reshuffle If 1 queue will be reshuffled after adding new items * @param item_id The base item id, all items after this will be reshuffled - * @return Item id of the last inserted item on success, -1 on failure + * @param position The position in the queue for the new queue item, -1 to add at end of queue + * @param count If not NULL returns the number of items added to the queue + * @param new_item_id If not NULL return the queue item id of the first new queue item + * @return 0 on success, -1 on failure */ int -db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id) +db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id) { struct query_params qp; int ret; @@ -4910,7 +4894,7 @@ db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id) qp.id = plid; qp.type = Q_PLITEMS; - ret = db_queue_add_by_query(&qp, reshuffle, item_id); + ret = db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id); return ret; } @@ -4921,10 +4905,13 @@ db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id) * @param id Id of the file * @param reshuffle If 1 queue will be reshuffled after adding new items * @param item_id The base item id, all items after this will be reshuffled - * @return Item id of the last inserted item on success, -1 on failure + * @param position The position in the queue for the new queue item, -1 to add at end of queue + * @param count If not NULL returns the number of items added to the queue + * @param new_item_id If not NULL return the queue item id of the first new queue item + * @return 0 on success, -1 on failure */ int -db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id) +db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id) { struct query_params qp; char buf[124]; @@ -4936,7 +4923,7 @@ db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id) snprintf(buf, sizeof(buf), "f.id = %" PRIu32, id); qp.filter = buf; - ret = db_queue_add_by_query(&qp, reshuffle, item_id); + ret = db_queue_add_by_query(&qp, reshuffle, item_id, position, count, new_item_id); return ret; } diff --git a/src/db.h b/src/db.h index b4248f09..b4a9d778 100644 --- a/src/db.h +++ b/src/db.h @@ -778,13 +778,13 @@ int db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id); int -db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id); +db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id); int -db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id); +db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id, int position, int *count, int *new_item_id); int -db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id); +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); diff --git a/src/httpd_dacp.c b/src/httpd_dacp.c index b09a1dea..e38dfed8 100644 --- a/src/httpd_dacp.c +++ b/src/httpd_dacp.c @@ -414,7 +414,7 @@ dacp_queueitem_add(const char *query, const char *queuefilter, const char *sort, if (mode == 3) ret = db_queue_add_by_queryafteritemid(&qp, status.item_id); else - ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id); + ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id, -1, NULL, NULL); if (qp.filter) free(qp.filter); @@ -1446,9 +1446,9 @@ dacp_reply_playspec(struct httpd_request *hreq) db_queue_clear(0); if (plid > 0) - ret = db_queue_add_by_playlistid(plid, status.shuffle, status.item_id); + ret = db_queue_add_by_playlistid(plid, status.shuffle, status.item_id, -1, NULL, NULL); else if (id > 0) - ret = db_queue_add_by_fileid(id, status.shuffle, status.item_id); + ret = db_queue_add_by_fileid(id, status.shuffle, status.item_id, -1, NULL, NULL); if (ret < 0) { diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index f94bee15..3c683cfa 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -1559,7 +1559,7 @@ queue_tracks_add_artist(const char *id) player_get_status(&status); - ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id); + ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, -1, NULL, NULL); free(query_params.filter); @@ -1582,7 +1582,7 @@ queue_tracks_add_album(const char *id) player_get_status(&status); - ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id); + ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, -1, NULL, NULL); free(query_params.filter); @@ -1605,7 +1605,7 @@ queue_tracks_add_track(const char *id) player_get_status(&status); - ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id); + ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, -1, NULL, NULL); free(query_params.filter); @@ -1629,7 +1629,7 @@ queue_tracks_add_playlist(const char *id) player_get_status(&status); - ret = db_queue_add_by_playlistid(playlist_id, status.shuffle, status.item_id); + ret = db_queue_add_by_playlistid(playlist_id, status.shuffle, status.item_id, -1, NULL, NULL); return ret; } diff --git a/src/mpd.c b/src/mpd.c index 7d3370d8..e009751d 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -1641,12 +1641,14 @@ mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, s * @return The queue item id of the last inserted item or -1 on failure */ static int -mpd_queue_add(char *path, bool exact_match) +mpd_queue_add(char *path, bool exact_match, int position) { struct query_params qp; struct player_status status; + int new_item_id; int ret; + new_item_id = 0; memset(&qp, 0, sizeof(struct query_params)); qp.type = Q_ITEMS; @@ -1666,9 +1668,13 @@ mpd_queue_add(char *path, bool exact_match) player_get_status(&status); - ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id); + ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id, position, NULL, &new_item_id); free(qp.filter); + + if (ret == 0) + return new_item_id; + return ret; } @@ -1682,7 +1688,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, st { int ret; - ret = mpd_queue_add(argv[1], false); + ret = mpd_queue_add(argv[1], false, -1); if (ret < 0) { @@ -1726,7 +1732,7 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, } } - ret = mpd_queue_add(argv[1], true); + ret = mpd_queue_add(argv[1], true, to_pos); if (ret == 0) { @@ -1745,11 +1751,6 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, return ACK_ERROR_UNKNOWN; } - if (to_pos >= 0) - { - db_queue_move_byitemid(ret, to_pos, 0); - } - evbuffer_add_printf(evbuf, "Id: %d\n", ret); // mpd_queue_add returns the item_id of the last inserted queue item @@ -2463,7 +2464,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, s player_get_status(&status); - ret = db_queue_add_by_playlistid(pli->id, status.shuffle, status.item_id); + ret = db_queue_add_by_playlistid(pli->id, status.shuffle, status.item_id, -1, NULL, NULL); free_pli(pli, 0); if (ret < 0) { @@ -2687,7 +2688,7 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg player_get_status(&status); - ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id); + ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id, -1, NULL, NULL); free(qp.filter); if (ret < 0) { @@ -3175,7 +3176,7 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm player_get_status(&status); - ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id); + ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id, -1, NULL, NULL); free(qp.filter); if (ret < 0) { diff --git a/src/player.c b/src/player.c index 1fb0f017..9d2443d1 100644 --- a/src/player.c +++ b/src/player.c @@ -2111,7 +2111,7 @@ playback_start_id(void *arg, int *retval) { db_queue_clear(0); - ret = db_queue_add_by_fileid(cmdarg->id, 0, 0); + ret = db_queue_add_by_fileid(cmdarg->id, 0, 0, -1, NULL, NULL); if (ret < 0) return COMMAND_END;