[db] Add support to add items to the queue at specified position

This commit is contained in:
chme 2018-09-06 21:16:27 +02:00
parent 197fc6402e
commit 7252b3e509
6 changed files with 77 additions and 89 deletions

119
src/db.c
View File

@ -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, query = sqlite3_mprintf(Q_TMPL,
dbmfi->id, dbmfi->song_length, dbmfi->data_kind, dbmfi->media_kind, 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->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->time_modified, dbmfi->artist_sort, dbmfi->album_sort, dbmfi->album_artist_sort, dbmfi->year,
dbmfi->track, dbmfi->disc, queue_version); dbmfi->track, dbmfi->disc, queue_version);
@ -4710,66 +4710,18 @@ db_queue_update_item(struct db_queue_item *qi)
int int
db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id) 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 pos;
int ret; int ret;
queue_version = queue_transaction_begin();
// Position of the first new item // Position of the first new item
pos = db_queue_get_pos(item_id, 0); pos = db_queue_get_pos(item_id, 0);
if (pos < 0) if (pos < 0)
{ {
ret = -1; return -1;
goto end_transaction;
} }
pos++; pos++;
// Shuffle position of the first new item ret = db_queue_add_by_query(qp, 0, 0, pos, NULL, NULL);
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);
return ret; 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 qp Query parameters for the files table
* @param reshuffle If 1 queue will be reshuffled after adding new items * @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 * @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 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; struct db_media_file_info dbmfi;
char *query;
int queue_version; int queue_version;
int queue_count;
int pos; int pos;
int new_item_id = 0; // Quell compiler warning about uninitialized use of new_item_id
int ret; int ret;
if (new_item_id)
*new_item_id = 0;
if (count)
*count = 0;
queue_version = queue_transaction_begin(); queue_version = queue_transaction_begin();
pos = db_queue_get_count(); queue_count = db_queue_get_count();
if (pos < 0) if (queue_count < 0)
{ {
ret = -1; ret = -1;
goto end_transaction; goto end_transaction;
@ -4858,9 +4819,24 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id)
return 0; 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)) 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) 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); 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++; pos++;
queue_count++;
} }
db_query_end(qp); 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) if (ret < 0)
goto end_transaction; goto end_transaction;
new_item_id = (int) sqlite3_last_insert_rowid(hdl);
// Reshuffle after adding new items // Reshuffle after adding new items
if (reshuffle) if (reshuffle)
{ {
@ -4888,7 +4869,7 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id)
end_transaction: end_transaction:
queue_transaction_end(ret, queue_version); 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 plid Id of the stored playlist
* @param reshuffle If 1 queue will be reshuffled after adding new items * @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 * @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 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; struct query_params qp;
int ret; int ret;
@ -4910,7 +4894,7 @@ db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id)
qp.id = plid; qp.id = plid;
qp.type = Q_PLITEMS; 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; 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 id Id of the file
* @param reshuffle If 1 queue will be reshuffled after adding new items * @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 * @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 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; struct query_params qp;
char buf[124]; 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); snprintf(buf, sizeof(buf), "f.id = %" PRIu32, id);
qp.filter = buf; 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; return ret;
} }

View File

@ -778,13 +778,13 @@ int
db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id); db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id);
int 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 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 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 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);

View File

@ -414,7 +414,7 @@ dacp_queueitem_add(const char *query, const char *queuefilter, const char *sort,
if (mode == 3) if (mode == 3)
ret = db_queue_add_by_queryafteritemid(&qp, status.item_id); ret = db_queue_add_by_queryafteritemid(&qp, status.item_id);
else 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) if (qp.filter)
free(qp.filter); free(qp.filter);
@ -1446,9 +1446,9 @@ dacp_reply_playspec(struct httpd_request *hreq)
db_queue_clear(0); db_queue_clear(0);
if (plid > 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) 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) if (ret < 0)
{ {

View File

@ -1559,7 +1559,7 @@ queue_tracks_add_artist(const char *id)
player_get_status(&status); 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); free(query_params.filter);
@ -1582,7 +1582,7 @@ queue_tracks_add_album(const char *id)
player_get_status(&status); 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); free(query_params.filter);
@ -1605,7 +1605,7 @@ queue_tracks_add_track(const char *id)
player_get_status(&status); 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); free(query_params.filter);
@ -1629,7 +1629,7 @@ queue_tracks_add_playlist(const char *id)
player_get_status(&status); 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; return ret;
} }

View File

@ -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 * @return The queue item id of the last inserted item or -1 on failure
*/ */
static int 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 query_params qp;
struct player_status status; struct player_status status;
int new_item_id;
int ret; int ret;
new_item_id = 0;
memset(&qp, 0, sizeof(struct query_params)); memset(&qp, 0, sizeof(struct query_params));
qp.type = Q_ITEMS; qp.type = Q_ITEMS;
@ -1666,9 +1668,13 @@ mpd_queue_add(char *path, bool exact_match)
player_get_status(&status); 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); free(qp.filter);
if (ret == 0)
return new_item_id;
return ret; return ret;
} }
@ -1682,7 +1688,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, st
{ {
int ret; int ret;
ret = mpd_queue_add(argv[1], false); ret = mpd_queue_add(argv[1], false, -1);
if (ret < 0) 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) if (ret == 0)
{ {
@ -1745,11 +1751,6 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg,
return ACK_ERROR_UNKNOWN; return ACK_ERROR_UNKNOWN;
} }
if (to_pos >= 0)
{
db_queue_move_byitemid(ret, to_pos, 0);
}
evbuffer_add_printf(evbuf, evbuffer_add_printf(evbuf,
"Id: %d\n", "Id: %d\n",
ret); // mpd_queue_add returns the item_id of the last inserted queue item 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); 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); free_pli(pli, 0);
if (ret < 0) if (ret < 0)
{ {
@ -2687,7 +2688,7 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
player_get_status(&status); 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); free(qp.filter);
if (ret < 0) if (ret < 0)
{ {
@ -3175,7 +3176,7 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
player_get_status(&status); 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); free(qp.filter);
if (ret < 0) if (ret < 0)
{ {

View File

@ -2111,7 +2111,7 @@ playback_start_id(void *arg, int *retval)
{ {
db_queue_clear(0); 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) if (ret < 0)
return COMMAND_END; return COMMAND_END;