mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-14 08:15:02 -05:00
Merge pull request #454 from chme/queue
Unique queue item ids and proper implementation of mpd commands 'plchanges' and 'plchangesposid'
This commit is contained in:
commit
55e4350b18
476
src/db.c
476
src/db.c
@ -4028,51 +4028,70 @@ db_speaker_clear_all(void)
|
||||
/* Queue */
|
||||
|
||||
/*
|
||||
* Increments the version of the queue in the admin table and notifies listener of LISTENER_QUEUE
|
||||
* about the change.
|
||||
*
|
||||
* This function must be called after successfully modifying the queue table in order to send
|
||||
* notification messages to the clients (e. g. dacp or mpd clients).
|
||||
* Start a new transaction for modifying the queue. Returns the new queue version for the following changes.
|
||||
* After finishing all queue modifications 'queue_transaction_end' needs to be called.
|
||||
*/
|
||||
static void
|
||||
queue_inc_version_and_notify()
|
||||
static int
|
||||
queue_transaction_begin()
|
||||
{
|
||||
int queue_version;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
|
||||
queue_version = db_admin_getint(DB_ADMIN_QUEUE_VERSION);
|
||||
queue_version++;
|
||||
|
||||
return queue_version;
|
||||
}
|
||||
|
||||
/*
|
||||
* If retval == 0, updates the version of the queue in the admin table, commits the transaction
|
||||
* and notifies listener of LISTENER_QUEUE about the changes.
|
||||
* If retval < 0, rollsback the transaction.
|
||||
*
|
||||
* This function must be called after modifying the queue.
|
||||
*
|
||||
* @param retval 'retval' == 0, if modifying the queue was successful or 'retval' < 0 if an error occurred
|
||||
* @param queue_version The new queue version, for the pending modifications
|
||||
*/
|
||||
static void
|
||||
queue_transaction_end(int retval, int queue_version)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
ret = db_admin_setint(DB_ADMIN_QUEUE_VERSION, queue_version);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Error incrementing queue version. Could not update version in admin table: %d\n", queue_version);
|
||||
db_transaction_rollback();
|
||||
return;
|
||||
}
|
||||
goto error;
|
||||
|
||||
db_transaction_end();
|
||||
|
||||
listener_notify(LISTENER_QUEUE);
|
||||
return;
|
||||
|
||||
error:
|
||||
db_transaction_rollback();
|
||||
}
|
||||
|
||||
static int
|
||||
queue_add_file(struct db_media_file_info *dbmfi, int pos, int shuffle_pos)
|
||||
queue_reshuffle(uint32_t item_id, int queue_version);
|
||||
|
||||
static int
|
||||
queue_add_file(struct db_media_file_info *dbmfi, int pos, int shuffle_pos, int queue_version)
|
||||
{
|
||||
#define Q_TMPL "INSERT INTO queue " \
|
||||
"(id, file_id, song_length, data_kind, media_kind, " \
|
||||
"pos, shuffle_pos, path, virtual_path, title, " \
|
||||
"artist, album_artist, album, genre, songalbumid, " \
|
||||
"time_modified, artist_sort, album_sort, album_artist_sort, year, " \
|
||||
"track, disc)" \
|
||||
"track, disc, queue_version)" \
|
||||
"VALUES" \
|
||||
"(NULL, %s, %s, %s, %s, " \
|
||||
"%d, %d, %Q, %Q, %Q, " \
|
||||
"%Q, %Q, %Q, %Q, %s, " \
|
||||
"%s, %Q, %Q, %Q, %s, " \
|
||||
"%s, %s);"
|
||||
"%s, %s, %d);"
|
||||
|
||||
char *query;
|
||||
int ret;
|
||||
@ -4082,7 +4101,7 @@ queue_add_file(struct db_media_file_info *dbmfi, int pos, int shuffle_pos)
|
||||
pos, 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);
|
||||
dbmfi->track, dbmfi->disc, queue_version);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
|
||||
return ret;
|
||||
@ -4099,24 +4118,29 @@ db_queue_update_item(struct db_queue_item *qi)
|
||||
"title = %Q, artist = %Q, album_artist = %Q, album = %Q, " \
|
||||
"genre = %Q, songalbumid = %" PRIi64 ", time_modified = %d, " \
|
||||
"artist_sort = %Q, album_sort = %Q, album_artist_sort = %Q, " \
|
||||
"year = %d, track = %d, disc = %d, artwork_url = %Q " \
|
||||
"year = %d, track = %d, disc = %d, artwork_url = %Q, " \
|
||||
"queue_version = %d " \
|
||||
"WHERE id = %d;"
|
||||
|
||||
int queue_version;
|
||||
char *query;
|
||||
int ret;
|
||||
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
query = sqlite3_mprintf(Q_TMPL,
|
||||
qi->file_id, qi->song_length, qi->data_kind, qi->media_kind,
|
||||
qi->pos, qi->shuffle_pos, qi->path, qi->virtual_path,
|
||||
qi->title, qi->artist, qi->album_artist, qi->album,
|
||||
qi->genre, qi->songalbumid, qi->time_modified,
|
||||
qi->artist_sort, qi->album_sort, qi->album_artist_sort,
|
||||
qi->year, qi->track, qi->disc, qi->artwork_url,
|
||||
qi->year, qi->track, qi->disc, qi->artwork_url, queue_version,
|
||||
qi->id);
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
|
||||
/* MPD changes playlist version when metadata changes */
|
||||
queue_inc_version_and_notify();
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return ret;
|
||||
#undef Q_TMPL
|
||||
@ -4140,21 +4164,21 @@ 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;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
// Position of the first new item
|
||||
pos = db_queue_get_pos(item_id, 0);
|
||||
if (pos < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not fetch queue item for item-id %d\n", item_id);
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto end_transaction;
|
||||
}
|
||||
pos++;
|
||||
|
||||
@ -4162,35 +4186,27 @@ db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id)
|
||||
shuffle_pos = db_queue_get_count();
|
||||
if (shuffle_pos < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not get count from queue\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto end_transaction;
|
||||
}
|
||||
|
||||
// Start query for new items from files table
|
||||
ret = db_query_start(qp);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not start query\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
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 WHERE pos > %d;", qp->results, (pos - 1));
|
||||
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)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
ret = queue_add_file(&dbmfi, pos, shuffle_pos, queue_version);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -4205,18 +4221,10 @@ db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id)
|
||||
|
||||
db_query_end(qp);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching results\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
db_transaction_end();
|
||||
|
||||
queue_inc_version_and_notify();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4237,39 +4245,36 @@ int
|
||||
db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id)
|
||||
{
|
||||
struct db_media_file_info dbmfi;
|
||||
int queue_version;
|
||||
int pos;
|
||||
int new_item_id;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
pos = db_queue_get_count();
|
||||
if (pos < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not get count from queue\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto end_transaction;
|
||||
}
|
||||
|
||||
ret = db_query_start(qp);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not start query\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Player queue query returned %d items\n", qp->results);
|
||||
|
||||
if (qp->results == 0)
|
||||
{
|
||||
db_query_end(qp);
|
||||
db_transaction_end();
|
||||
return 0;
|
||||
ret = -1;
|
||||
goto end_transaction;
|
||||
}
|
||||
|
||||
while (((ret = db_query_fetch_file(qp, &dbmfi)) == 0) && (dbmfi.id))
|
||||
{
|
||||
ret = queue_add_file(&dbmfi, pos, pos);
|
||||
ret = queue_add_file(&dbmfi, pos, pos, queue_version);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -4284,27 +4289,20 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id)
|
||||
db_query_end(qp);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching results\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
ret = (int) sqlite3_last_insert_rowid(hdl);
|
||||
|
||||
db_transaction_end();
|
||||
new_item_id = (int) sqlite3_last_insert_rowid(hdl);
|
||||
|
||||
// Reshuffle after adding new items
|
||||
if (reshuffle)
|
||||
{
|
||||
db_queue_reshuffle(item_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
queue_inc_version_and_notify();
|
||||
ret = queue_reshuffle(item_id, queue_version);
|
||||
}
|
||||
|
||||
return ret;
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return (ret == 0) ? new_item_id : ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4365,26 +4363,27 @@ db_queue_add_item(struct db_queue_item *queue_item, char reshuffle, uint32_t ite
|
||||
"pos, shuffle_pos, path, virtual_path, title, " \
|
||||
"artist, album_artist, album, genre, songalbumid, " \
|
||||
"time_modified, artist_sort, album_sort, album_artist_sort, year, " \
|
||||
"track, disc)" \
|
||||
"track, disc, queue_version)" \
|
||||
"VALUES" \
|
||||
"(NULL, %d, %d, %d, %d, " \
|
||||
"%d, %d, %Q, %Q, %Q, " \
|
||||
"%Q, %Q, %Q, %Q, %d, " \
|
||||
"%d, %Q, %Q, %Q, %d, " \
|
||||
"%d, %d);"
|
||||
"%d, %d, %d);"
|
||||
|
||||
int queue_version;
|
||||
char *query;
|
||||
int pos;
|
||||
int new_item_id;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
pos = db_queue_get_count();
|
||||
if (pos < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not get count from queue\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto end_transaction;
|
||||
}
|
||||
|
||||
query = sqlite3_mprintf(Q_TMPL,
|
||||
@ -4392,29 +4391,23 @@ db_queue_add_item(struct db_queue_item *queue_item, char reshuffle, uint32_t ite
|
||||
pos, pos, queue_item->path, queue_item->virtual_path, queue_item->title,
|
||||
queue_item->artist, queue_item->album_artist, queue_item->album, queue_item->genre, queue_item->songalbumid,
|
||||
queue_item->time_modified, queue_item->artist_sort, queue_item->album_sort, queue_item->album_artist_sort, queue_item->year,
|
||||
queue_item->track, queue_item->disc);
|
||||
queue_item->track, queue_item->disc, queue_version);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Error adding queue item\n");
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
ret = (int) sqlite3_last_insert_rowid(hdl);
|
||||
|
||||
db_transaction_end();
|
||||
new_item_id = (int) sqlite3_last_insert_rowid(hdl);
|
||||
|
||||
// Reshuffle after adding new items
|
||||
if (reshuffle)
|
||||
{
|
||||
db_queue_reshuffle(item_id);
|
||||
ret = queue_reshuffle(item_id, queue_version);
|
||||
}
|
||||
else
|
||||
{
|
||||
queue_inc_version_and_notify();
|
||||
}
|
||||
return ret;
|
||||
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return (ret == 0) ? new_item_id : ret;
|
||||
|
||||
#undef Q_TMPL
|
||||
}
|
||||
@ -4850,9 +4843,9 @@ db_queue_fetch_prev(uint32_t item_id, char shuffle)
|
||||
}
|
||||
|
||||
static int
|
||||
queue_fix_pos(enum sort_type sort)
|
||||
queue_fix_pos(enum sort_type sort, int queue_version)
|
||||
{
|
||||
#define Q_TMPL "UPDATE queue SET %q = %d WHERE id = %d;"
|
||||
#define Q_TMPL "UPDATE queue SET %q = %d, queue_version = %d WHERE id = %d and %q <> %d;"
|
||||
|
||||
struct query_params qp;
|
||||
struct db_queue_item queue_item;
|
||||
@ -4875,9 +4868,9 @@ queue_fix_pos(enum sort_type sort)
|
||||
if (queue_item.pos != pos)
|
||||
{
|
||||
if (sort == S_SHUFFLE_POS)
|
||||
query = sqlite3_mprintf(Q_TMPL, "shuffle_pos", pos, queue_item.id);
|
||||
query = sqlite3_mprintf(Q_TMPL, "shuffle_pos", pos, queue_version, queue_item.id, "shuffle_pos", pos);
|
||||
else
|
||||
query = sqlite3_mprintf(Q_TMPL, "pos", pos, queue_item.id);
|
||||
query = sqlite3_mprintf(Q_TMPL, "pos", pos, queue_version, queue_item.id, "pos", pos);
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
@ -4897,7 +4890,7 @@ queue_fix_pos(enum sort_type sort)
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove files that are disabled or non existant in the library and repair ordering of
|
||||
* Remove files that are disabled or non existent in the library and repair ordering of
|
||||
* the queue (shuffle and normal)
|
||||
*/
|
||||
int
|
||||
@ -4905,17 +4898,15 @@ db_queue_cleanup()
|
||||
{
|
||||
#define Q_TMPL "DELETE FROM queue WHERE NOT file_id IN (SELECT id from files WHERE disabled = 0);"
|
||||
|
||||
int queue_version;
|
||||
int deleted;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
ret = db_query_run(Q_TMPL, 0, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
deleted = sqlite3_changes(hdl);
|
||||
if (deleted <= 0)
|
||||
@ -4926,25 +4917,17 @@ db_queue_cleanup()
|
||||
}
|
||||
|
||||
// Update position of normal queue
|
||||
ret = queue_fix_pos(S_POS);
|
||||
ret = queue_fix_pos(S_POS, queue_version);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
// Update position of shuffle queue
|
||||
ret = queue_fix_pos(S_SHUFFLE_POS);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
ret = queue_fix_pos(S_SHUFFLE_POS, queue_version);
|
||||
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
#undef Q_TMPL
|
||||
}
|
||||
@ -4957,39 +4940,28 @@ db_queue_cleanup()
|
||||
int
|
||||
db_queue_clear(uint32_t keep_item_id)
|
||||
{
|
||||
int queue_version;
|
||||
char *query;
|
||||
int ret;
|
||||
|
||||
query = sqlite3_mprintf("DELETE FROM queue where id <> %d;", keep_item_id);
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
db_transaction_begin();
|
||||
query = sqlite3_mprintf("DELETE FROM queue where id <> %d;", keep_item_id);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret == 0 && keep_item_id)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (keep_item_id)
|
||||
{
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = 0 AND shuffle_pos = 0 where id = %d;", keep_item_id);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = 0, shuffle_pos = 0, queue_version = %d where id = %d;", queue_version, keep_item_id);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return ret;
|
||||
}
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
queue_delete_item(struct db_queue_item *queue_item)
|
||||
queue_delete_item(struct db_queue_item *queue_item, int queue_version)
|
||||
{
|
||||
char *query;
|
||||
int ret;
|
||||
@ -5003,7 +4975,7 @@ queue_delete_item(struct db_queue_item *queue_item)
|
||||
}
|
||||
|
||||
// Update pos for all items after the item with given item_id
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1 WHERE pos > %d;", queue_item->pos);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1, queue_version = %d WHERE pos > %d;", queue_version, queue_item->pos);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -5011,7 +4983,7 @@ queue_delete_item(struct db_queue_item *queue_item)
|
||||
}
|
||||
|
||||
// Update shuffle_pos for all items after the item with given item_id
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos - 1 WHERE shuffle_pos > %d;", queue_item->shuffle_pos);
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos - 1, queue_version = %d WHERE shuffle_pos > %d;", queue_version, queue_item->shuffle_pos);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -5024,18 +4996,16 @@ queue_delete_item(struct db_queue_item *queue_item)
|
||||
int
|
||||
db_queue_delete_byitemid(uint32_t item_id)
|
||||
{
|
||||
int queue_version;
|
||||
struct db_queue_item queue_item;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
ret = queue_fetch_byitemid(item_id, &queue_item, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
if (queue_item.id == 0)
|
||||
{
|
||||
@ -5043,17 +5013,10 @@ db_queue_delete_byitemid(uint32_t item_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = queue_delete_item(&queue_item);
|
||||
ret = queue_delete_item(&queue_item, queue_version);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
}
|
||||
else
|
||||
{
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
}
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -5061,38 +5024,28 @@ db_queue_delete_byitemid(uint32_t item_id)
|
||||
int
|
||||
db_queue_delete_bypos(uint32_t pos, int count)
|
||||
{
|
||||
int queue_version;
|
||||
char *query;
|
||||
int to_pos;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
// Remove item with the given item_id
|
||||
to_pos = pos + count;
|
||||
query = sqlite3_mprintf("DELETE FROM queue where pos >= %d AND pos < %d;", pos, to_pos);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
ret = queue_fix_pos(S_POS);
|
||||
ret = queue_fix_pos(S_POS, queue_version);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
ret = queue_fix_pos(S_SHUFFLE_POS);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
ret = queue_fix_pos(S_SHUFFLE_POS, queue_version);
|
||||
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -5100,35 +5053,27 @@ db_queue_delete_bypos(uint32_t pos, int count)
|
||||
int
|
||||
db_queue_delete_byposrelativetoitem(uint32_t pos, uint32_t item_id, char shuffle)
|
||||
{
|
||||
int queue_version;
|
||||
struct db_queue_item queue_item;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
ret = queue_fetch_byposrelativetoitem(pos, item_id, shuffle, &queue_item, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
else if (queue_item.id == 0)
|
||||
goto end_transaction;
|
||||
|
||||
if (queue_item.id == 0)
|
||||
{
|
||||
// No item found
|
||||
db_transaction_end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = queue_delete_item(&queue_item);
|
||||
ret = queue_delete_item(&queue_item, queue_version);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
}
|
||||
else
|
||||
{
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
}
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -5144,18 +5089,19 @@ db_queue_delete_byposrelativetoitem(uint32_t pos, uint32_t item_id, char shuffle
|
||||
int
|
||||
db_queue_move_byitemid(uint32_t item_id, int pos_to, char shuffle)
|
||||
{
|
||||
int queue_version;
|
||||
char *query;
|
||||
int pos_from;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
// Find item with the given item_id
|
||||
pos_from = db_queue_get_pos(item_id, shuffle);
|
||||
if (pos_from < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto end_transaction;
|
||||
}
|
||||
|
||||
// Update pos for all items after the item with given item_id
|
||||
@ -5166,10 +5112,7 @@ db_queue_move_byitemid(uint32_t item_id, int pos_to, char shuffle)
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
// Update pos for all items from the given pos_to
|
||||
if (shuffle)
|
||||
@ -5179,10 +5122,7 @@ db_queue_move_byitemid(uint32_t item_id, int pos_to, char shuffle)
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
// Update item with the given item_id
|
||||
if (shuffle)
|
||||
@ -5191,16 +5131,11 @@ db_queue_move_byitemid(uint32_t item_id, int pos_to, char shuffle)
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = %d where id = %d;", pos_to, item_id);
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5213,19 +5148,17 @@ db_queue_move_byitemid(uint32_t item_id, int pos_to, char shuffle)
|
||||
int
|
||||
db_queue_move_bypos(int pos_from, int pos_to)
|
||||
{
|
||||
int queue_version;
|
||||
struct db_queue_item queue_item;
|
||||
char *query;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
// Find item to move
|
||||
ret = queue_fetch_bypos(pos_from, 0, &queue_item, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
if (queue_item.id == 0)
|
||||
{
|
||||
@ -5234,36 +5167,25 @@ db_queue_move_bypos(int pos_from, int pos_to)
|
||||
}
|
||||
|
||||
// Update pos for all items after the item with given position
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1 WHERE pos > %d;", queue_item.pos);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1, queue_version = %d WHERE pos > %d;", queue_version, queue_item.pos);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
// Update pos for all items from the given pos_to
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos + 1 WHERE pos >= %d;", pos_to);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos + 1, queue_version = %d WHERE pos >= %d;", queue_version, pos_to);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
// Update item with the given item_id
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = %d where id = %d;", pos_to, queue_item.id);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = %d, queue_version = %d where id = %d;", pos_to, queue_version, queue_item.id);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5278,23 +5200,21 @@ db_queue_move_bypos(int pos_from, int pos_to)
|
||||
int
|
||||
db_queue_move_byposrelativetoitem(uint32_t from_pos, uint32_t to_offset, uint32_t item_id, char shuffle)
|
||||
{
|
||||
int queue_version;
|
||||
struct db_queue_item queue_item;
|
||||
char *query;
|
||||
int pos_move_from;
|
||||
int pos_move_to;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Move by pos: from %d offset %d relative to item (%d)\n", from_pos, to_offset, item_id);
|
||||
|
||||
// Find item with the given item_id
|
||||
ret = queue_fetch_byitemid(item_id, &queue_item, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Move by pos: base item (id=%d, pos=%d, file-id=%d)\n", queue_item.id, queue_item.pos, queue_item.file_id);
|
||||
|
||||
@ -5329,10 +5249,7 @@ db_queue_move_byposrelativetoitem(uint32_t from_pos, uint32_t to_offset, uint32_
|
||||
// Find item to move
|
||||
ret = queue_fetch_bypos(pos_move_from, shuffle, &queue_item, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Move by pos: move item (id=%d, pos=%d, file-id=%d)\n", queue_item.id, queue_item.pos, queue_item.file_id);
|
||||
|
||||
@ -5344,47 +5261,36 @@ db_queue_move_byposrelativetoitem(uint32_t from_pos, uint32_t to_offset, uint32_
|
||||
|
||||
// Update pos for all items after the item with given position
|
||||
if (shuffle)
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos - 1 WHERE shuffle_pos > %d;", queue_item.shuffle_pos);
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos - 1, queue_version = %d WHERE shuffle_pos > %d;", queue_version, queue_item.shuffle_pos);
|
||||
else
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1 WHERE pos > %d;", queue_item.pos);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1, queue_version = %d WHERE pos > %d;", queue_version, queue_item.pos);
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
// Update pos for all items from the given pos_to
|
||||
if (shuffle)
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos + 1 WHERE shuffle_pos >= %d;", pos_move_to);
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos + 1, queue_version = %d WHERE shuffle_pos >= %d;", queue_version, pos_move_to);
|
||||
else
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos + 1 WHERE pos >= %d;", pos_move_to);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos + 1, queue_version = %d WHERE pos >= %d;", queue_version, pos_move_to);
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
goto end_transaction;
|
||||
|
||||
// Update item with the given item_id
|
||||
if (shuffle)
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = %d where id = %d;", pos_move_to, queue_item.id);
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = %d, queue_version = %d where id = %d;", pos_move_to, queue_version, queue_item.id);
|
||||
else
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = %d where id = %d;", pos_move_to, queue_item.id);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = %d, queue_version = %d where id = %d;", pos_move_to, queue_version, queue_item.id);
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
end_transaction:
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5396,8 +5302,8 @@ db_queue_move_byposrelativetoitem(uint32_t from_pos, uint32_t to_offset, uint32_
|
||||
* @param item_id The base item, after this item the queue is reshuffled
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
db_queue_reshuffle(uint32_t item_id)
|
||||
static int
|
||||
queue_reshuffle(uint32_t item_id, int queue_version)
|
||||
{
|
||||
char *query;
|
||||
int pos;
|
||||
@ -5409,15 +5315,13 @@ db_queue_reshuffle(uint32_t item_id)
|
||||
struct query_params qp;
|
||||
int ret;
|
||||
|
||||
db_transaction_begin();
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Reshuffle queue after item with item-id: %d\n", item_id);
|
||||
|
||||
// Reset the shuffled order
|
||||
ret = db_query_run("UPDATE queue SET shuffle_pos = pos;", 0, 0);
|
||||
// Reset the shuffled order and mark all items as changed
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = pos, queue_version = %d;", queue_version);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -5427,7 +5331,6 @@ db_queue_reshuffle(uint32_t item_id)
|
||||
pos = db_queue_get_pos(item_id, 0);
|
||||
if (pos < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -5455,7 +5358,6 @@ db_queue_reshuffle(uint32_t item_id)
|
||||
if (ret < 0)
|
||||
{
|
||||
sqlite3_free(qp.filter);
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -5478,16 +5380,36 @@ db_queue_reshuffle(uint32_t item_id)
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
db_transaction_rollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
db_transaction_end();
|
||||
queue_inc_version_and_notify();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reshuffles the shuffle queue
|
||||
*
|
||||
* If the given item_id is 0, the whole shuffle queue is reshuffled, otherwise the
|
||||
* queue is reshuffled after the item with the given id (excluding this item).
|
||||
*
|
||||
* @param item_id The base item, after this item the queue is reshuffled
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
db_queue_reshuffle(uint32_t item_id)
|
||||
{
|
||||
int queue_version;
|
||||
int ret;
|
||||
|
||||
queue_version = queue_transaction_begin();
|
||||
|
||||
ret = queue_reshuffle(item_id, queue_version);
|
||||
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
db_queue_get_count()
|
||||
{
|
||||
|
2
src/db.h
2
src/db.h
@ -428,6 +428,8 @@ struct db_queue_item
|
||||
uint32_t disc;
|
||||
|
||||
char *artwork_url;
|
||||
|
||||
uint32_t queue_version;
|
||||
};
|
||||
|
||||
char *
|
||||
|
@ -162,7 +162,7 @@
|
||||
|
||||
#define T_QUEUE \
|
||||
"CREATE TABLE IF NOT EXISTS queue (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT," \
|
||||
" file_id INTEGER NOT NULL," \
|
||||
" pos INTEGER NOT NULL," \
|
||||
" shuffle_pos INTEGER NOT NULL," \
|
||||
@ -184,7 +184,8 @@
|
||||
" year INTEGER DEFAULT 0," \
|
||||
" track INTEGER DEFAULT 0," \
|
||||
" disc INTEGER DEFAULT 0," \
|
||||
" artwork_url VARCHAR(4096) DEFAULT NULL" \
|
||||
" artwork_url VARCHAR(4096) DEFAULT NULL," \
|
||||
" queue_version INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define TRG_GROUPS_INSERT_FILES \
|
||||
|
@ -26,7 +26,7 @@
|
||||
* is a major upgrade. In other words minor version upgrades permit downgrading
|
||||
* forked-daapd after the database was upgraded. */
|
||||
#define SCHEMA_VERSION_MAJOR 19
|
||||
#define SCHEMA_VERSION_MINOR 05
|
||||
#define SCHEMA_VERSION_MINOR 06
|
||||
|
||||
int
|
||||
db_init_indices(sqlite3 *hdl);
|
||||
|
@ -1574,6 +1574,58 @@ static const struct db_upgrade_query db_upgrade_v1905_queries[] =
|
||||
};
|
||||
|
||||
|
||||
/* Upgrade from schema v19.05 to v20.00 */
|
||||
|
||||
#define U_V1906_DROP_TABLE_QUEUE \
|
||||
"DROP TABLE queue;"
|
||||
|
||||
#define U_V1906_CREATE_TABLE_QUEUE \
|
||||
"CREATE TABLE IF NOT EXISTS queue (" \
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT," \
|
||||
" file_id INTEGER NOT NULL," \
|
||||
" pos INTEGER NOT NULL," \
|
||||
" shuffle_pos INTEGER NOT NULL," \
|
||||
" data_kind INTEGER NOT NULL," \
|
||||
" media_kind INTEGER NOT NULL," \
|
||||
" song_length INTEGER NOT NULL," \
|
||||
" path VARCHAR(4096) NOT NULL," \
|
||||
" virtual_path VARCHAR(4096) NOT NULL," \
|
||||
" title VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" artist VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album_artist VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" album VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" genre VARCHAR(255) DEFAULT NULL COLLATE DAAP," \
|
||||
" songalbumid INTEGER NOT NULL," \
|
||||
" time_modified INTEGER DEFAULT 0," \
|
||||
" artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album_artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" year INTEGER DEFAULT 0," \
|
||||
" track INTEGER DEFAULT 0," \
|
||||
" disc INTEGER DEFAULT 0," \
|
||||
" artwork_url VARCHAR(4096) DEFAULT NULL," \
|
||||
" queue_version INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define U_V1906_UPDATE_HTTP_VIRTUAL_PATH \
|
||||
"UPDATE files SET virtual_path = '/' || path WHERE data_kind = 1;"
|
||||
|
||||
#define U_V1906_SCVER_MAJOR \
|
||||
"UPDATE admin SET value = '19' WHERE key = 'schema_version_major';"
|
||||
#define U_V1906_SCVER_MINOR \
|
||||
"UPDATE admin SET value = '06' WHERE key = 'schema_version_minor';"
|
||||
|
||||
static const struct db_upgrade_query db_upgrade_V1906_queries[] =
|
||||
{
|
||||
{ U_V1906_DROP_TABLE_QUEUE, "drop queue table" },
|
||||
{ U_V1906_CREATE_TABLE_QUEUE, "create queue table" },
|
||||
{ U_V1906_UPDATE_HTTP_VIRTUAL_PATH, "update virtual path for http streams" },
|
||||
|
||||
{ U_V1906_SCVER_MAJOR, "set schema_version_major to 19" },
|
||||
{ U_V1906_SCVER_MINOR, "set schema_version_minor to 06" },
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
db_upgrade(sqlite3 *hdl, int db_ver)
|
||||
{
|
||||
@ -1719,6 +1771,13 @@ db_upgrade(sqlite3 *hdl, int db_ver)
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 1905:
|
||||
ret = db_generic_upgrade(hdl, db_upgrade_V1906_queries, sizeof(db_upgrade_V1906_queries) / sizeof(db_upgrade_V1906_queries[0]));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
92
src/mpd.c
92
src/mpd.c
@ -1882,6 +1882,52 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
plchanges_build_queryparams(struct query_params *query_params, int argc, char **argv, char **errmsg)
|
||||
{
|
||||
uint32_t version;
|
||||
int start_pos;
|
||||
int end_pos;
|
||||
int ret;
|
||||
|
||||
memset(query_params, 0, sizeof(struct query_params));
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
*errmsg = safe_asprintf("Missing argument for command 'plchanges'");
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
ret = safe_atou32(argv[1], &version);
|
||||
if (ret < 0)
|
||||
{
|
||||
*errmsg = safe_asprintf("Argument doesn't convert to integer: '%s'", argv[1]);
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
start_pos = 0;
|
||||
end_pos = 0;
|
||||
if (argc > 2)
|
||||
{
|
||||
ret = mpd_pars_range_arg(argv[2], &start_pos, &end_pos);
|
||||
if (ret < 0)
|
||||
{
|
||||
*errmsg = safe_asprintf("Argument doesn't convert to integer or range: '%s'", argv[2]);
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
|
||||
if (start_pos < 0)
|
||||
DPRINTF(E_DBG, L_MPD, "Command 'playlistinfo' called with pos < 0 (arg = '%s'), ignore arguments and return whole queue\n", argv[1]);
|
||||
}
|
||||
|
||||
if (start_pos < 0 || end_pos <= 0)
|
||||
query_params->filter = db_mprintf("(queue_version > %d)", version);
|
||||
else
|
||||
query_params->filter = db_mprintf("(queue_version > %d AND pos >= %d AND pos < %d)", version, start_pos, end_pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Command handler function for 'plchanges'
|
||||
* Lists all changed songs in the queue since the given playlist version in argv[1].
|
||||
@ -1893,34 +1939,34 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
||||
struct db_queue_item queue_item;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* forked-daapd does not keep track of changes in the queue based on the playlist version,
|
||||
* therefor plchanges returns all songs in the queue as changed ignoring the given version.
|
||||
*/
|
||||
memset(&query_params, 0, sizeof(struct query_params));
|
||||
ret = plchanges_build_queryparams(&query_params, argc, argv, errmsg);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = db_queue_enum_start(&query_params);
|
||||
if (ret < 0)
|
||||
{
|
||||
*errmsg = safe_asprintf("Failed to start queue enum for command plchanges");
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
goto error;
|
||||
|
||||
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
|
||||
{
|
||||
ret = mpd_add_db_queue_item(evbuf, &queue_item);
|
||||
if (ret < 0)
|
||||
{
|
||||
*errmsg = safe_asprintf("Error adding media info for file with id: %d", queue_item.file_id);
|
||||
|
||||
db_queue_enum_end(&query_params);
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
DPRINTF(E_LOG, L_MPD, "Error adding media info for file with id: %d", queue_item.file_id);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
db_queue_enum_end(&query_params);
|
||||
free_query_params(&query_params, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
db_queue_enum_end(&query_params);
|
||||
free_query_params(&query_params, 1);
|
||||
*errmsg = safe_asprintf("Failed to start queue enum for command plchanges");
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1934,18 +1980,13 @@ mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char *
|
||||
struct db_queue_item queue_item;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* forked-daapd does not keep track of changes in the queue based on the playlist version,
|
||||
* therefor plchangesposid returns all songs in the queue as changed ignoring the given version.
|
||||
*/
|
||||
memset(&query_params, 0, sizeof(struct query_params));
|
||||
ret = plchanges_build_queryparams(&query_params, argc, argv, errmsg);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = db_queue_enum_start(&query_params);
|
||||
if (ret < 0)
|
||||
{
|
||||
*errmsg = safe_asprintf("Failed to start queue enum for command plchangesposid");
|
||||
return ACK_ERROR_ARG;
|
||||
}
|
||||
goto error;
|
||||
|
||||
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
|
||||
{
|
||||
@ -1957,8 +1998,15 @@ mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char *
|
||||
}
|
||||
|
||||
db_queue_enum_end(&query_params);
|
||||
free_query_params(&query_params, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
db_queue_enum_end(&query_params);
|
||||
free_query_params(&query_params, 1);
|
||||
*errmsg = safe_asprintf("Failed to start queue enum for command plchangesposid");
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
42
src/player.c
42
src/player.c
@ -385,26 +385,30 @@ metadata_update_cb(void *arg)
|
||||
goto out_free_metadata;
|
||||
}
|
||||
|
||||
// Since we won't be using the metadata struct values for anything else than
|
||||
// this we just swap pointers
|
||||
if (metadata->artist)
|
||||
swap_pointers(&queue_item->artist, &metadata->artist);
|
||||
if (metadata->title)
|
||||
swap_pointers(&queue_item->title, &metadata->title);
|
||||
if (metadata->album)
|
||||
swap_pointers(&queue_item->album, &metadata->album);
|
||||
if (metadata->genre)
|
||||
swap_pointers(&queue_item->genre, &metadata->genre);
|
||||
if (metadata->artwork_url)
|
||||
swap_pointers(&queue_item->artwork_url, &metadata->artwork_url);
|
||||
if (metadata->song_length)
|
||||
queue_item->song_length = metadata->song_length;
|
||||
|
||||
ret = db_queue_update_item(queue_item);
|
||||
if (ret < 0)
|
||||
// Update queue item if metadata changed
|
||||
if (metadata->artist || metadata->title || metadata->album || metadata->genre || metadata->artwork_url || metadata->song_length)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Database error while updating queue with new metadata\n");
|
||||
goto out_free_queueitem;
|
||||
// Since we won't be using the metadata struct values for anything else than
|
||||
// this we just swap pointers
|
||||
if (metadata->artist)
|
||||
swap_pointers(&queue_item->artist, &metadata->artist);
|
||||
if (metadata->title)
|
||||
swap_pointers(&queue_item->title, &metadata->title);
|
||||
if (metadata->album)
|
||||
swap_pointers(&queue_item->album, &metadata->album);
|
||||
if (metadata->genre)
|
||||
swap_pointers(&queue_item->genre, &metadata->genre);
|
||||
if (metadata->artwork_url)
|
||||
swap_pointers(&queue_item->artwork_url, &metadata->artwork_url);
|
||||
if (metadata->song_length)
|
||||
queue_item->song_length = metadata->song_length;
|
||||
|
||||
ret = db_queue_update_item(queue_item);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Database error while updating queue with new metadata\n");
|
||||
goto out_free_queueitem;
|
||||
}
|
||||
}
|
||||
|
||||
o_metadata = outputs_metadata_prepare(metadata->item_id);
|
||||
|
Loading…
Reference in New Issue
Block a user