mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-14 08:15:02 -05:00
[db] Refactor queue_item functions
- Use prepared statements - Add qi_mfi_map that defines mapping between mfi, dbmfi and qi - Use qi_cols_map/qi_mfi_map for iteration (avoid duplicating field references) - Stick to "qi" as name for a queue_item in db.c (more similar to mfi/pli/gri) - Some renaming and other minor stuff in db.c's queue code
This commit is contained in:
parent
76c52bba3b
commit
689d1ce3dd
571
src/db.c
571
src/db.c
@ -112,16 +112,26 @@ struct db_statements
|
||||
|
||||
sqlite3_stmt *playlists_insert;
|
||||
sqlite3_stmt *playlists_update;
|
||||
|
||||
sqlite3_stmt *queue_items_insert;
|
||||
sqlite3_stmt *queue_items_update;
|
||||
};
|
||||
|
||||
struct col_type_map {
|
||||
char *name;
|
||||
size_t offset;
|
||||
ssize_t offset;
|
||||
short type;
|
||||
enum fixup_type fixup;
|
||||
short flag;
|
||||
};
|
||||
|
||||
struct qi_mfi_map
|
||||
{
|
||||
ssize_t qi_offset;
|
||||
ssize_t mfi_offset;
|
||||
ssize_t dbmfi_offset;
|
||||
};
|
||||
|
||||
struct fixup_ctx
|
||||
{
|
||||
const struct col_type_map *map;
|
||||
@ -129,7 +139,7 @@ struct fixup_ctx
|
||||
void *data;
|
||||
struct media_file_info *mfi;
|
||||
struct playlist_info *pli;
|
||||
struct db_queue_item *queue_item;
|
||||
struct db_queue_item *qi;
|
||||
};
|
||||
|
||||
struct query_clause {
|
||||
@ -248,11 +258,12 @@ static const struct col_type_map pli_cols_map[] =
|
||||
/* This list must be kept in sync with
|
||||
* - the order of the columns in the queue table
|
||||
* - the type and name of the fields in struct db_queue_item
|
||||
* - with qi_mfi_map
|
||||
*/
|
||||
static const struct col_type_map qi_cols_map[] =
|
||||
{
|
||||
{ "id", qi_offsetof(id), DB_TYPE_INT, DB_FIXUP_STANDARD, DB_FLAG_NO_BIND },
|
||||
{ "file_id", qi_offsetof(id), DB_TYPE_INT },
|
||||
{ "file_id", qi_offsetof(file_id), DB_TYPE_INT },
|
||||
{ "pos", qi_offsetof(pos), DB_TYPE_INT },
|
||||
{ "shuffle_pos", qi_offsetof(shuffle_pos), DB_TYPE_INT },
|
||||
{ "data_kind", qi_offsetof(data_kind), DB_TYPE_INT },
|
||||
@ -405,6 +416,43 @@ static const ssize_t dbgri_cols_map[] =
|
||||
dbgri_offsetof(seek),
|
||||
};
|
||||
|
||||
/* This list must be kept in sync with
|
||||
* - qi_cols_map
|
||||
*/
|
||||
static const struct qi_mfi_map qi_mfi_map[] =
|
||||
{
|
||||
{ qi_offsetof(id), -1, -1 },
|
||||
{ qi_offsetof(file_id), mfi_offsetof(id), dbmfi_offsetof(id) },
|
||||
{ qi_offsetof(pos), -1, -1 },
|
||||
{ qi_offsetof(shuffle_pos), -1, -1 },
|
||||
{ qi_offsetof(data_kind), mfi_offsetof(data_kind), dbmfi_offsetof(data_kind) },
|
||||
{ qi_offsetof(media_kind), mfi_offsetof(media_kind), dbmfi_offsetof(media_kind) },
|
||||
{ qi_offsetof(song_length), mfi_offsetof(song_length), dbmfi_offsetof(song_length) },
|
||||
{ qi_offsetof(path), mfi_offsetof(path), dbmfi_offsetof(path) },
|
||||
{ qi_offsetof(virtual_path), mfi_offsetof(virtual_path), dbmfi_offsetof(virtual_path) },
|
||||
{ qi_offsetof(title), mfi_offsetof(title), dbmfi_offsetof(title) },
|
||||
{ qi_offsetof(artist), mfi_offsetof(artist), dbmfi_offsetof(artist) },
|
||||
{ qi_offsetof(album_artist), mfi_offsetof(album_artist), dbmfi_offsetof(album_artist) },
|
||||
{ qi_offsetof(album), mfi_offsetof(album), dbmfi_offsetof(album) },
|
||||
{ qi_offsetof(genre), mfi_offsetof(genre), dbmfi_offsetof(genre) },
|
||||
{ qi_offsetof(songalbumid), mfi_offsetof(songalbumid), dbmfi_offsetof(songalbumid) },
|
||||
{ qi_offsetof(time_modified), mfi_offsetof(time_modified), dbmfi_offsetof(time_modified) },
|
||||
{ qi_offsetof(artist_sort), mfi_offsetof(artist_sort), dbmfi_offsetof(artist_sort) },
|
||||
{ qi_offsetof(album_sort), mfi_offsetof(album_sort), dbmfi_offsetof(album_sort) },
|
||||
{ qi_offsetof(album_artist_sort), mfi_offsetof(album_artist_sort), dbmfi_offsetof(album_artist_sort) },
|
||||
{ qi_offsetof(year), mfi_offsetof(year), dbmfi_offsetof(year) },
|
||||
{ qi_offsetof(track), mfi_offsetof(track), dbmfi_offsetof(track) },
|
||||
{ qi_offsetof(disc), mfi_offsetof(disc), dbmfi_offsetof(disc) },
|
||||
{ qi_offsetof(artwork_url), -1, -1 },
|
||||
{ qi_offsetof(queue_version), -1, -1 },
|
||||
{ qi_offsetof(composer), mfi_offsetof(composer), dbmfi_offsetof(composer) },
|
||||
{ qi_offsetof(songartistid), mfi_offsetof(songartistid), dbmfi_offsetof(songartistid) },
|
||||
{ qi_offsetof(type), mfi_offsetof(type), dbmfi_offsetof(type) },
|
||||
{ qi_offsetof(bitrate), mfi_offsetof(bitrate), dbmfi_offsetof(bitrate) },
|
||||
{ qi_offsetof(samplerate), mfi_offsetof(samplerate), dbmfi_offsetof(samplerate) },
|
||||
{ qi_offsetof(channels), mfi_offsetof(channels), dbmfi_offsetof(channels) },
|
||||
};
|
||||
|
||||
/* This list must be kept in sync with
|
||||
* - the order of the columns in the inotify table
|
||||
* - the name and type of the fields in struct watch_info
|
||||
@ -719,29 +767,73 @@ free_query_params(struct query_params *qp, int content_only)
|
||||
}
|
||||
|
||||
void
|
||||
free_queue_item(struct db_queue_item *queue_item, int content_only)
|
||||
free_queue_item(struct db_queue_item *qi, int content_only)
|
||||
{
|
||||
if (!queue_item)
|
||||
if (!qi)
|
||||
return;
|
||||
|
||||
free(queue_item->path);
|
||||
free(queue_item->virtual_path);
|
||||
free(queue_item->title);
|
||||
free(queue_item->artist);
|
||||
free(queue_item->album_artist);
|
||||
free(queue_item->composer);
|
||||
free(queue_item->album);
|
||||
free(queue_item->genre);
|
||||
free(queue_item->artist_sort);
|
||||
free(queue_item->album_sort);
|
||||
free(queue_item->album_artist_sort);
|
||||
free(queue_item->artwork_url);
|
||||
free(queue_item->type);
|
||||
free(qi->path);
|
||||
free(qi->virtual_path);
|
||||
free(qi->title);
|
||||
free(qi->artist);
|
||||
free(qi->album_artist);
|
||||
free(qi->composer);
|
||||
free(qi->album);
|
||||
free(qi->genre);
|
||||
free(qi->artist_sort);
|
||||
free(qi->album_sort);
|
||||
free(qi->album_artist_sort);
|
||||
free(qi->artwork_url);
|
||||
free(qi->type);
|
||||
|
||||
if (!content_only)
|
||||
free(queue_item);
|
||||
free(qi);
|
||||
else
|
||||
memset(queue_item, 0, sizeof(struct db_queue_item));
|
||||
memset(qi, 0, sizeof(struct db_queue_item));
|
||||
}
|
||||
|
||||
// Utility function for stepping through mfi/pli/qi structs and setting the
|
||||
// values from some source, which could be another struct. Some examples:
|
||||
// - src is a dbmfi, dst is a qi, dst_type is DB_TYPE_INT, caller wants to own
|
||||
// qi so must_strdup is true, dbmfi has strings so parse_integers is true
|
||||
// - src is a **char, dst is a qi, dst_type is DB_TYPE_STRING, src_offset is 0
|
||||
// because src is not a struct, caller wants to strdup the string so
|
||||
// must_strdup is true
|
||||
static inline void
|
||||
struct_set(void *dst_struct, ssize_t dst_offset, int dst_type, const void *src_struct, ssize_t src_offset, bool must_strdup, bool parse_integers)
|
||||
{
|
||||
char *srcstr;
|
||||
uint32_t srcu32val;
|
||||
int64_t srci64val;
|
||||
char **dstptr;
|
||||
|
||||
srcstr = *(char **)(src_struct + src_offset);
|
||||
|
||||
switch (dst_type)
|
||||
{
|
||||
case DB_TYPE_STRING:
|
||||
dstptr = (char **)(dst_struct + dst_offset);
|
||||
*dstptr = must_strdup ? safe_strdup(srcstr) : srcstr;
|
||||
break;
|
||||
|
||||
case DB_TYPE_INT:
|
||||
if (parse_integers)
|
||||
safe_atou32(srcstr, &srcu32val);
|
||||
else
|
||||
srcu32val = *(uint32_t *)(src_struct + src_offset);
|
||||
|
||||
memcpy(dst_struct + dst_offset, &srcu32val, sizeof(srcu32val));
|
||||
break;
|
||||
|
||||
case DB_TYPE_INT64:
|
||||
if (parse_integers)
|
||||
safe_atoi64(srcstr, &srci64val);
|
||||
else
|
||||
srci64val = *(int64_t *)(src_struct + src_offset);
|
||||
|
||||
memcpy(dst_struct + dst_offset, &srci64val, sizeof(srci64val));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -902,8 +994,8 @@ fixup_defaults(char **tag, enum fixup_type fixup, struct fixup_ctx *ctx)
|
||||
}
|
||||
else if (ctx->pli && ctx->pli->path)
|
||||
*tag = strdup(ctx->pli->path);
|
||||
else if (ctx->queue_item && ctx->queue_item->path)
|
||||
*tag = strdup(ctx->queue_item->path);
|
||||
else if (ctx->qi && ctx->qi->path)
|
||||
*tag = strdup(ctx->qi->path);
|
||||
else
|
||||
*tag = strdup(CFG_NAME_UNKNOWN_TITLE);
|
||||
break;
|
||||
@ -950,8 +1042,8 @@ fixup_defaults(char **tag, enum fixup_type fixup, struct fixup_ctx *ctx)
|
||||
*tag = strdup(ca); // If ca is empty string then the artist will not be shown in artist view
|
||||
else if (ctx->mfi && ctx->mfi->artist)
|
||||
*tag = strdup(ctx->mfi->artist);
|
||||
else if (ctx->queue_item && ctx->queue_item->artist)
|
||||
*tag = strdup(ctx->queue_item->artist);
|
||||
else if (ctx->qi && ctx->qi->artist)
|
||||
*tag = strdup(ctx->qi->artist);
|
||||
else
|
||||
*tag = strdup(CFG_NAME_UNKNOWN_ARTIST);
|
||||
break;
|
||||
@ -970,8 +1062,8 @@ fixup_defaults(char **tag, enum fixup_type fixup, struct fixup_ctx *ctx)
|
||||
ctx->mfi->media_kind = MEDIA_KIND_MUSIC;
|
||||
else if (ctx->pli && !ctx->pli->media_kind)
|
||||
ctx->pli->media_kind = MEDIA_KIND_MUSIC;
|
||||
else if (ctx->queue_item && !ctx->queue_item->media_kind)
|
||||
ctx->queue_item->media_kind = MEDIA_KIND_MUSIC;
|
||||
else if (ctx->qi && !ctx->qi->media_kind)
|
||||
ctx->qi->media_kind = MEDIA_KIND_MUSIC;
|
||||
|
||||
break;
|
||||
|
||||
@ -1022,22 +1114,22 @@ fixup_sort_tags(char **tag, enum fixup_type fixup, struct fixup_ctx *ctx)
|
||||
case DB_FIXUP_ARTIST_SORT:
|
||||
if (ctx->mfi)
|
||||
sort_tag_create(tag, ctx->mfi->artist);
|
||||
else if (ctx->queue_item)
|
||||
sort_tag_create(tag, ctx->queue_item->artist);
|
||||
else if (ctx->qi)
|
||||
sort_tag_create(tag, ctx->qi->artist);
|
||||
break;
|
||||
|
||||
case DB_FIXUP_ALBUM_SORT:
|
||||
if (ctx->mfi)
|
||||
sort_tag_create(tag, ctx->mfi->album);
|
||||
else if (ctx->queue_item)
|
||||
sort_tag_create(tag, ctx->queue_item->album);
|
||||
else if (ctx->qi)
|
||||
sort_tag_create(tag, ctx->qi->album);
|
||||
break;
|
||||
|
||||
case DB_FIXUP_ALBUM_ARTIST_SORT:
|
||||
if (ctx->mfi)
|
||||
sort_tag_create(tag, ctx->mfi->album_artist);
|
||||
else if (ctx->queue_item)
|
||||
sort_tag_create(tag, ctx->queue_item->album_artist);
|
||||
else if (ctx->qi)
|
||||
sort_tag_create(tag, ctx->qi->album_artist);
|
||||
break;
|
||||
|
||||
case DB_FIXUP_COMPOSER_SORT:
|
||||
@ -1103,11 +1195,11 @@ fixup_tags_pli(struct playlist_info *pli)
|
||||
}
|
||||
|
||||
static void
|
||||
fixup_tags_queue_item(struct db_queue_item *queue_item)
|
||||
fixup_tags_qi(struct db_queue_item *qi)
|
||||
{
|
||||
struct fixup_ctx ctx = { 0 };
|
||||
ctx.data = queue_item;
|
||||
ctx.queue_item = queue_item;
|
||||
ctx.data = qi;
|
||||
ctx.qi = qi;
|
||||
ctx.map = qi_cols_map;
|
||||
ctx.map_size = ARRAY_SIZE(qi_cols_map);
|
||||
|
||||
@ -1171,6 +1263,12 @@ bind_pli(sqlite3_stmt *stmt, struct playlist_info *pli)
|
||||
return bind_generic(stmt, pli, pli_cols_map, ARRAY_SIZE(pli_cols_map), pli->id);
|
||||
}
|
||||
|
||||
static int
|
||||
bind_qi(sqlite3_stmt *stmt, struct db_queue_item *qi)
|
||||
{
|
||||
return bind_generic(stmt, qi, qi_cols_map, ARRAY_SIZE(qi_cols_map), qi->id);
|
||||
}
|
||||
|
||||
/* Unlock notification support */
|
||||
static void
|
||||
unlock_notify_cb(void **args, int nargs)
|
||||
@ -4664,7 +4762,7 @@ queue_transaction_begin()
|
||||
*
|
||||
* 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 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
|
||||
@ -4672,7 +4770,7 @@ queue_transaction_end(int retval, int queue_version)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (retval != 0)
|
||||
if (retval < 0)
|
||||
goto error;
|
||||
|
||||
ret = db_admin_setint(DB_ADMIN_QUEUE_VERSION, queue_version);
|
||||
@ -4691,116 +4789,139 @@ static int
|
||||
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)
|
||||
queue_item_add(struct db_queue_item *qi)
|
||||
{
|
||||
#define Q_TMPL "INSERT INTO queue " \
|
||||
"(id, file_id, song_length, data_kind, media_kind, " \
|
||||
"pos, shuffle_pos, path, virtual_path, title, " \
|
||||
"artist, composer, album_artist, album, genre, songalbumid, songartistid," \
|
||||
"time_modified, artist_sort, album_sort, album_artist_sort, year, " \
|
||||
"type, bitrate, samplerate, channels, " \
|
||||
"track, disc, queue_version)" \
|
||||
"VALUES" \
|
||||
"(NULL, %s, %s, %s, %s, " \
|
||||
"%d, %d, %Q, %Q, %Q, " \
|
||||
"%Q, %Q, %Q, %Q, %Q, %s, %s," \
|
||||
"%s, %Q, %Q, %Q, %s, " \
|
||||
"%Q, %s, %s, %s, " \
|
||||
"%s, %s, %d);"
|
||||
|
||||
char *query;
|
||||
int ret;
|
||||
|
||||
query = sqlite3_mprintf(Q_TMPL,
|
||||
dbmfi->id, dbmfi->song_length, dbmfi->data_kind, dbmfi->media_kind,
|
||||
pos, shuffle_pos, dbmfi->path, dbmfi->virtual_path, dbmfi->title,
|
||||
dbmfi->artist, dbmfi->composer, dbmfi->album_artist, dbmfi->album, dbmfi->genre, dbmfi->songalbumid, dbmfi->songartistid,
|
||||
dbmfi->time_modified, dbmfi->artist_sort, dbmfi->album_sort, dbmfi->album_artist_sort, dbmfi->year,
|
||||
dbmfi->type, dbmfi->bitrate, dbmfi->samplerate, dbmfi->channels,
|
||||
dbmfi->track, dbmfi->disc, queue_version);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
fixup_tags_qi(qi);
|
||||
|
||||
ret = bind_qi(db_statements.queue_items_insert, qi);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
// Do not update events here, only caller knows if more items will be added
|
||||
ret = db_statement_run(db_statements.queue_items_insert, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
ret = (int)sqlite3_last_insert_rowid(hdl);
|
||||
if (ret == 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Successful queue item insert but no last_insert_rowid!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
static int
|
||||
queue_add_item(struct db_queue_item *item, int pos, int shuffle_pos, int queue_version)
|
||||
queue_item_add_from_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, composer, album_artist, album, genre, songalbumid, songartistid, " \
|
||||
"time_modified, artist_sort, album_sort, album_artist_sort, year, " \
|
||||
"type, bitrate, samplerate, channels, " \
|
||||
"track, disc, artwork_url, queue_version)" \
|
||||
"VALUES" \
|
||||
"(NULL, %d, %d, %d, %d, " \
|
||||
"%d, %d, %Q, %Q, %Q, " \
|
||||
"%Q, %Q, %Q, %Q, %Q, %" PRIi64 ", %" PRIi64 "," \
|
||||
"%d, %Q, %Q, %Q, %d, " \
|
||||
"%Q, %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", " \
|
||||
"%d, %d, %Q, %d);"
|
||||
|
||||
char *query;
|
||||
struct db_queue_item qi;
|
||||
int ret;
|
||||
|
||||
query = sqlite3_mprintf(Q_TMPL,
|
||||
item->file_id, item->song_length, item->data_kind, item->media_kind,
|
||||
pos, shuffle_pos, item->path, item->virtual_path, item->title,
|
||||
item->artist, item->composer, item->album_artist, item->album, item->genre, item->songalbumid, item->songartistid,
|
||||
item->time_modified, item->artist_sort, item->album_sort, item->album_artist_sort, item->year,
|
||||
item->type, item->bitrate, item->samplerate, item->channels,
|
||||
item->track, item->disc, item->artwork_url, queue_version);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
// No allocations, just the struct content is copied
|
||||
db_queue_item_from_dbmfi(&qi, dbmfi);
|
||||
|
||||
// No tag fixup, we can't touch the strings in qi, plus must assume dbmfi has proper tags
|
||||
|
||||
qi.pos = pos;
|
||||
qi.shuffle_pos = shuffle_pos;
|
||||
qi.queue_version = queue_version;
|
||||
|
||||
ret = bind_qi(db_statements.queue_items_insert, &qi);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
// Do not update events here, only caller knows if more items will be added
|
||||
ret = db_statement_run(db_statements.queue_items_insert, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
ret = (int)sqlite3_last_insert_rowid(hdl);
|
||||
if (ret == 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Successful queue item insert but no last_insert_rowid!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
int
|
||||
db_queue_update_item(struct db_queue_item *qi)
|
||||
static int
|
||||
queue_item_update(struct db_queue_item *qi)
|
||||
{
|
||||
#define Q_TMPL "UPDATE queue SET " \
|
||||
"file_id = %d, song_length = %d, data_kind = %d, media_kind = %d, " \
|
||||
"pos = %d, shuffle_pos = %d, path = '%q', virtual_path = %Q, " \
|
||||
"title = %Q, artist = %Q, album_artist = %Q, album = %Q, " \
|
||||
"composer = %Q, " \
|
||||
"genre = %Q, time_modified = %d, " \
|
||||
"songalbumid = %" PRIi64 ", songartistid = %" PRIi64 ", " \
|
||||
"artist_sort = %Q, album_sort = %Q, album_artist_sort = %Q, " \
|
||||
"year = %d, track = %d, disc = %d, artwork_url = %Q, " \
|
||||
"queue_version = %d " \
|
||||
"WHERE id = %d;"
|
||||
|
||||
int queue_version;
|
||||
char *query;
|
||||
int ret;
|
||||
|
||||
fixup_tags_queue_item(qi);
|
||||
fixup_tags_qi(qi);
|
||||
|
||||
ret = bind_qi(db_statements.queue_items_update, qi);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
// Do not update events here, only caller knows if more items will be updated
|
||||
ret = db_statement_run(db_statements.queue_items_update, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
return qi->id;
|
||||
}
|
||||
|
||||
void
|
||||
db_queue_item_from_mfi(struct db_queue_item *qi, struct media_file_info *mfi)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(qi, 0, sizeof(struct db_queue_item));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qi_mfi_map); i++)
|
||||
{
|
||||
if (qi_mfi_map[i].mfi_offset < 0)
|
||||
continue;
|
||||
|
||||
struct_set(qi, qi_cols_map[i].offset, qi_cols_map[i].type, mfi, qi_mfi_map[i].mfi_offset, true, false);
|
||||
}
|
||||
|
||||
if (!qi->file_id)
|
||||
qi->file_id = DB_MEDIA_FILE_NON_PERSISTENT_ID;
|
||||
}
|
||||
|
||||
void
|
||||
db_queue_item_from_dbmfi(struct db_queue_item *qi, struct db_media_file_info *dbmfi)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(qi, 0, sizeof(struct db_queue_item));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qi_mfi_map); i++)
|
||||
{
|
||||
if (qi_mfi_map[i].dbmfi_offset < 0)
|
||||
continue;
|
||||
|
||||
struct_set(qi, qi_cols_map[i].offset, qi_cols_map[i].type, dbmfi, qi_mfi_map[i].dbmfi_offset, false, true);
|
||||
}
|
||||
|
||||
if (!qi->file_id)
|
||||
qi->file_id = DB_MEDIA_FILE_NON_PERSISTENT_ID;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
db_queue_item_update(struct db_queue_item *qi)
|
||||
{
|
||||
int queue_version;
|
||||
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->composer,
|
||||
qi->genre, qi->time_modified,
|
||||
qi->songalbumid, qi->songartistid,
|
||||
qi->artist_sort, qi->album_sort, qi->album_artist_sort,
|
||||
qi->year, qi->track, qi->disc, qi->artwork_url, queue_version,
|
||||
qi->id);
|
||||
qi->queue_version = queue_version;
|
||||
|
||||
ret = db_query_run(query, 1, 0);
|
||||
ret = queue_item_update(qi);
|
||||
|
||||
/* MPD changes playlist version when metadata changes */
|
||||
// MPD changes playlist version when metadata changes, also makes LISTENER_QUEUE
|
||||
queue_transaction_end(ret, queue_version);
|
||||
|
||||
return ret;
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4888,25 +5009,26 @@ db_queue_add_end(struct db_queue_add_info *queue_add_info, char reshuffle, uint3
|
||||
}
|
||||
|
||||
int
|
||||
db_queue_add_item(struct db_queue_add_info *queue_add_info, struct db_queue_item *item)
|
||||
db_queue_add_next(struct db_queue_add_info *queue_add_info, struct db_queue_item *qi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
fixup_tags_queue_item(item);
|
||||
ret = queue_add_item(item, queue_add_info->pos, queue_add_info->shuffle_pos, queue_add_info->queue_version);
|
||||
if (ret == 0)
|
||||
{
|
||||
qi->pos = queue_add_info->pos;
|
||||
qi->shuffle_pos = queue_add_info->shuffle_pos;
|
||||
qi->queue_version = queue_add_info->queue_version;
|
||||
|
||||
ret = queue_item_add(qi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
}
|
||||
queue_add_info->new_item_id = ret;
|
||||
|
||||
return ret;
|
||||
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4980,7 +5102,7 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id,
|
||||
|
||||
while (((ret = db_query_fetch_file(qp, &dbmfi)) == 0) && (dbmfi.id))
|
||||
{
|
||||
ret = queue_add_file(&dbmfi, pos, queue_count, queue_version);
|
||||
ret = queue_item_add_from_file(&dbmfi, pos, queue_count, queue_version);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -4988,10 +5110,10 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id,
|
||||
break;
|
||||
}
|
||||
|
||||
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 with item id %d\n", dbmfi.id, dbmfi.title, ret);
|
||||
|
||||
if (new_item_id && *new_item_id == 0)
|
||||
*new_item_id = (int) sqlite3_last_insert_rowid(hdl);
|
||||
*new_item_id = ret;
|
||||
if (count)
|
||||
(*count)++;
|
||||
|
||||
@ -5133,11 +5255,16 @@ strdup_if(char *str, int cond)
|
||||
}
|
||||
|
||||
static int
|
||||
queue_enum_fetch(struct query_params *qp, struct db_queue_item *queue_item, int keep_item)
|
||||
queue_enum_fetch(struct query_params *qp, struct db_queue_item *qi, int must_strdup)
|
||||
{
|
||||
const void *srcptr;
|
||||
const char *str;
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
memset(queue_item, 0, sizeof(struct db_queue_item));
|
||||
memset(qi, 0, sizeof(struct db_queue_item));
|
||||
|
||||
if (!qp->stmt)
|
||||
{
|
||||
@ -5157,36 +5284,32 @@ queue_enum_fetch(struct query_params *qp, struct db_queue_item *queue_item, int
|
||||
return -1;
|
||||
}
|
||||
|
||||
queue_item->id = (uint32_t)sqlite3_column_int(qp->stmt, 0);
|
||||
queue_item->file_id = (uint32_t)sqlite3_column_int(qp->stmt, 1);
|
||||
queue_item->pos = (uint32_t)sqlite3_column_int(qp->stmt, 2);
|
||||
queue_item->shuffle_pos = (uint32_t)sqlite3_column_int(qp->stmt, 3);
|
||||
queue_item->data_kind = sqlite3_column_int(qp->stmt, 4);
|
||||
queue_item->media_kind = sqlite3_column_int(qp->stmt, 5);
|
||||
queue_item->song_length = (uint32_t)sqlite3_column_int(qp->stmt, 6);
|
||||
queue_item->path = strdup_if((char *)sqlite3_column_text(qp->stmt, 7), keep_item);
|
||||
queue_item->virtual_path = strdup_if((char *)sqlite3_column_text(qp->stmt, 8), keep_item);
|
||||
queue_item->title = strdup_if((char *)sqlite3_column_text(qp->stmt, 9), keep_item);
|
||||
queue_item->artist = strdup_if((char *)sqlite3_column_text(qp->stmt, 10), keep_item);
|
||||
queue_item->album_artist = strdup_if((char *)sqlite3_column_text(qp->stmt, 11), keep_item);
|
||||
queue_item->album = strdup_if((char *)sqlite3_column_text(qp->stmt, 12), keep_item);
|
||||
queue_item->genre = strdup_if((char *)sqlite3_column_text(qp->stmt, 13), keep_item);
|
||||
queue_item->songalbumid = sqlite3_column_int64(qp->stmt, 14);
|
||||
queue_item->time_modified = sqlite3_column_int(qp->stmt, 15);
|
||||
queue_item->artist_sort = strdup_if((char *)sqlite3_column_text(qp->stmt, 16), keep_item);
|
||||
queue_item->album_sort = strdup_if((char *)sqlite3_column_text(qp->stmt, 17), keep_item);
|
||||
queue_item->album_artist_sort = strdup_if((char *)sqlite3_column_text(qp->stmt, 18), keep_item);
|
||||
queue_item->year = sqlite3_column_int(qp->stmt, 19);
|
||||
queue_item->track = sqlite3_column_int(qp->stmt, 20);
|
||||
queue_item->disc = sqlite3_column_int(qp->stmt, 21);
|
||||
queue_item->artwork_url = strdup_if((char *)sqlite3_column_text(qp->stmt, 22), keep_item);
|
||||
queue_item->queue_version = sqlite3_column_int(qp->stmt, 23);
|
||||
queue_item->composer = strdup_if((char *)sqlite3_column_text(qp->stmt, 24), keep_item);
|
||||
queue_item->songartistid = sqlite3_column_int64(qp->stmt, 25);
|
||||
queue_item->type = strdup_if((char *)sqlite3_column_text(qp->stmt, 26), keep_item);
|
||||
queue_item->bitrate = sqlite3_column_int(qp->stmt, 27);
|
||||
queue_item->samplerate = sqlite3_column_int(qp->stmt, 28);
|
||||
queue_item->channels = sqlite3_column_int(qp->stmt, 29);
|
||||
for (i = 0; i < ARRAY_SIZE(qi_cols_map); i++)
|
||||
{
|
||||
switch (qi_cols_map[i].type)
|
||||
{
|
||||
case DB_TYPE_STRING:
|
||||
str = (const char *)sqlite3_column_text(qp->stmt, i);
|
||||
srcptr = &str;
|
||||
break;
|
||||
|
||||
case DB_TYPE_INT:
|
||||
i32 = sqlite3_column_int(qp->stmt, i);
|
||||
srcptr = &i32;
|
||||
break;
|
||||
|
||||
case DB_TYPE_INT64:
|
||||
i64 = sqlite3_column_int64(qp->stmt, i);
|
||||
srcptr = &i64;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF(E_LOG, L_DB, "BUG! Unknown data type (%d) in queue_enum_fetch()\n", qi_cols_map[i].type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct_set(qi, qi_cols_map[i].offset, qi_cols_map[i].type, srcptr, 0, must_strdup, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -5214,9 +5337,9 @@ db_queue_enum_end(struct query_params *qp)
|
||||
}
|
||||
|
||||
int
|
||||
db_queue_enum_fetch(struct query_params *qp, struct db_queue_item *queue_item)
|
||||
db_queue_enum_fetch(struct query_params *qp, struct db_queue_item *qi)
|
||||
{
|
||||
return queue_enum_fetch(qp, queue_item, 0);
|
||||
return queue_enum_fetch(qp, qi, 0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -5244,7 +5367,7 @@ db_queue_get_pos(uint32_t item_id, char shuffle)
|
||||
}
|
||||
|
||||
static int
|
||||
queue_fetch_byitemid(uint32_t item_id, struct db_queue_item *queue_item, int with_metadata)
|
||||
queue_fetch_byitemid(uint32_t item_id, struct db_queue_item *qi, int with_metadata)
|
||||
{
|
||||
struct query_params qp;
|
||||
int ret;
|
||||
@ -5259,7 +5382,7 @@ queue_fetch_byitemid(uint32_t item_id, struct db_queue_item *queue_item, int wit
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = queue_enum_fetch(&qp, queue_item, with_metadata);
|
||||
ret = queue_enum_fetch(&qp, qi, with_metadata);
|
||||
db_query_end(&qp);
|
||||
sqlite3_free(qp.filter);
|
||||
return ret;
|
||||
@ -5268,46 +5391,46 @@ queue_fetch_byitemid(uint32_t item_id, struct db_queue_item *queue_item, int wit
|
||||
struct db_queue_item *
|
||||
db_queue_fetch_byitemid(uint32_t item_id)
|
||||
{
|
||||
struct db_queue_item *queue_item;
|
||||
struct db_queue_item *qi;
|
||||
int ret;
|
||||
|
||||
queue_item = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!queue_item)
|
||||
qi = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!qi)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Out of memory for queue_item\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
db_transaction_begin();
|
||||
ret = queue_fetch_byitemid(item_id, queue_item, 1);
|
||||
ret = queue_fetch_byitemid(item_id, qi, 1);
|
||||
db_transaction_end();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching queue item by item id\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (queue_item->id == 0)
|
||||
else if (qi->id == 0)
|
||||
{
|
||||
// No item found
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return queue_item;
|
||||
return qi;
|
||||
}
|
||||
|
||||
struct db_queue_item *
|
||||
db_queue_fetch_byfileid(uint32_t file_id)
|
||||
{
|
||||
struct db_queue_item *queue_item;
|
||||
struct db_queue_item *qi;
|
||||
struct query_params qp;
|
||||
int ret;
|
||||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
queue_item = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!queue_item)
|
||||
qi = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!qi)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Out of memory for queue_item\n");
|
||||
return NULL;
|
||||
@ -5322,34 +5445,34 @@ db_queue_fetch_byfileid(uint32_t file_id)
|
||||
{
|
||||
sqlite3_free(qp.filter);
|
||||
db_transaction_end();
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching queue item by file id\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = queue_enum_fetch(&qp, queue_item, 1);
|
||||
ret = queue_enum_fetch(&qp, qi, 1);
|
||||
db_query_end(&qp);
|
||||
sqlite3_free(qp.filter);
|
||||
db_transaction_end();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching queue item by file id\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (queue_item->id == 0)
|
||||
else if (qi->id == 0)
|
||||
{
|
||||
// No item found
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return queue_item;
|
||||
return qi;
|
||||
}
|
||||
|
||||
static int
|
||||
queue_fetch_bypos(uint32_t pos, char shuffle, struct db_queue_item *queue_item, int with_metadata)
|
||||
queue_fetch_bypos(uint32_t pos, char shuffle, struct db_queue_item *qi, int with_metadata)
|
||||
{
|
||||
struct query_params qp;
|
||||
int ret;
|
||||
@ -5367,7 +5490,7 @@ queue_fetch_bypos(uint32_t pos, char shuffle, struct db_queue_item *queue_item,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = queue_enum_fetch(&qp, queue_item, with_metadata);
|
||||
ret = queue_enum_fetch(&qp, qi, with_metadata);
|
||||
db_query_end(&qp);
|
||||
sqlite3_free(qp.filter);
|
||||
return ret;
|
||||
@ -5376,38 +5499,38 @@ queue_fetch_bypos(uint32_t pos, char shuffle, struct db_queue_item *queue_item,
|
||||
struct db_queue_item *
|
||||
db_queue_fetch_bypos(uint32_t pos, char shuffle)
|
||||
{
|
||||
struct db_queue_item *queue_item;
|
||||
struct db_queue_item *qi;
|
||||
int ret;
|
||||
|
||||
queue_item = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!queue_item)
|
||||
qi = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!qi)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MAIN, "Out of memory for queue_item\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
db_transaction_begin();
|
||||
ret = queue_fetch_bypos(pos, shuffle, queue_item, 1);
|
||||
ret = queue_fetch_bypos(pos, shuffle, qi, 1);
|
||||
db_transaction_end();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching queue item by pos id\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (queue_item->id == 0)
|
||||
else if (qi->id == 0)
|
||||
{
|
||||
// No item found
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return queue_item;
|
||||
return qi;
|
||||
}
|
||||
|
||||
static int
|
||||
queue_fetch_byposrelativetoitem(int pos, uint32_t item_id, char shuffle, struct db_queue_item *queue_item, int with_metadata)
|
||||
queue_fetch_byposrelativetoitem(int pos, uint32_t item_id, char shuffle, struct db_queue_item *qi, int with_metadata)
|
||||
{
|
||||
int pos_absolute;
|
||||
int ret;
|
||||
@ -5424,12 +5547,12 @@ queue_fetch_byposrelativetoitem(int pos, uint32_t item_id, char shuffle, struct
|
||||
|
||||
pos_absolute += pos;
|
||||
|
||||
ret = queue_fetch_bypos(pos_absolute, shuffle, queue_item, with_metadata);
|
||||
ret = queue_fetch_bypos(pos_absolute, shuffle, qi, with_metadata);
|
||||
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching item by pos: pos (%d) relative to item with id (%d)\n", pos, item_id);
|
||||
else
|
||||
DPRINTF(E_DBG, L_DB, "Fetch by pos: fetched item (id=%d, pos=%d, file-id=%d)\n", queue_item->id, queue_item->pos, queue_item->file_id);
|
||||
DPRINTF(E_DBG, L_DB, "Fetch by pos: fetched item (id=%d, pos=%d, file-id=%d)\n", qi->id, qi->pos, qi->file_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -5437,13 +5560,13 @@ queue_fetch_byposrelativetoitem(int pos, uint32_t item_id, char shuffle, struct
|
||||
struct db_queue_item *
|
||||
db_queue_fetch_byposrelativetoitem(int pos, uint32_t item_id, char shuffle)
|
||||
{
|
||||
struct db_queue_item *queue_item;
|
||||
struct db_queue_item *qi;
|
||||
int ret;
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Fetch by pos: pos (%d) relative to item with id (%d)\n", pos, item_id);
|
||||
|
||||
queue_item = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!queue_item)
|
||||
qi = calloc(1, sizeof(struct db_queue_item));
|
||||
if (!qi)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MAIN, "Out of memory for queue_item\n");
|
||||
return NULL;
|
||||
@ -5451,26 +5574,26 @@ db_queue_fetch_byposrelativetoitem(int pos, uint32_t item_id, char shuffle)
|
||||
|
||||
db_transaction_begin();
|
||||
|
||||
ret = queue_fetch_byposrelativetoitem(pos, item_id, shuffle, queue_item, 1);
|
||||
ret = queue_fetch_byposrelativetoitem(pos, item_id, shuffle, qi, 1);
|
||||
|
||||
db_transaction_end();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
DPRINTF(E_LOG, L_DB, "Error fetching queue item by pos relative to item id\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (queue_item->id == 0)
|
||||
else if (qi->id == 0)
|
||||
{
|
||||
// No item found
|
||||
free_queue_item(queue_item, 0);
|
||||
free_queue_item(qi, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Fetch by pos: fetched item (id=%d, pos=%d, file-id=%d)\n", queue_item->id, queue_item->pos, queue_item->file_id);
|
||||
DPRINTF(E_DBG, L_DB, "Fetch by pos: fetched item (id=%d, pos=%d, file-id=%d)\n", qi->id, qi->pos, qi->file_id);
|
||||
|
||||
return queue_item;
|
||||
return qi;
|
||||
}
|
||||
|
||||
struct db_queue_item *
|
||||
@ -5604,13 +5727,13 @@ db_queue_clear(uint32_t keep_item_id)
|
||||
}
|
||||
|
||||
static int
|
||||
queue_delete_item(struct db_queue_item *queue_item, int queue_version)
|
||||
queue_delete_item(struct db_queue_item *qi, int queue_version)
|
||||
{
|
||||
char *query;
|
||||
int ret;
|
||||
|
||||
// Remove item with the given item_id
|
||||
query = sqlite3_mprintf("DELETE FROM queue where id = %d;", queue_item->id);
|
||||
query = sqlite3_mprintf("DELETE FROM queue where id = %d;", qi->id);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -5618,7 +5741,7 @@ queue_delete_item(struct db_queue_item *queue_item, int queue_version)
|
||||
}
|
||||
|
||||
// Update pos for all items after the item with given item_id
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1, queue_version = %d WHERE pos > %d;", queue_version, queue_item->pos);
|
||||
query = sqlite3_mprintf("UPDATE queue SET pos = pos - 1, queue_version = %d WHERE pos > %d;", queue_version, qi->pos);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -5626,7 +5749,7 @@ queue_delete_item(struct db_queue_item *queue_item, int queue_version)
|
||||
}
|
||||
|
||||
// Update shuffle_pos for all items after the item with given item_id
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos - 1, queue_version = %d WHERE shuffle_pos > %d;", queue_version, queue_item->shuffle_pos);
|
||||
query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = shuffle_pos - 1, queue_version = %d WHERE shuffle_pos > %d;", queue_version, qi->shuffle_pos);
|
||||
ret = db_query_run(query, 1, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -6759,6 +6882,9 @@ db_open(void)
|
||||
int synchronous;
|
||||
int mmap_size;
|
||||
|
||||
if (!db_path)
|
||||
return -1;
|
||||
|
||||
ret = sqlite3_open(db_path, &hdl);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
@ -6951,8 +7077,12 @@ db_statements_prepare(void)
|
||||
db_statements.playlists_insert = db_statements_prepare_insert(pli_cols_map, ARRAY_SIZE(pli_cols_map), "playlists");
|
||||
db_statements.playlists_update = db_statements_prepare_update(pli_cols_map, ARRAY_SIZE(pli_cols_map), "playlists");
|
||||
|
||||
db_statements.queue_items_insert = db_statements_prepare_insert(qi_cols_map, ARRAY_SIZE(qi_cols_map), "queue");
|
||||
db_statements.queue_items_update = db_statements_prepare_update(qi_cols_map, ARRAY_SIZE(qi_cols_map), "queue");
|
||||
|
||||
if ( !db_statements.files_insert || !db_statements.files_update || !db_statements.files_ping
|
||||
|| !db_statements.playlists_insert || !db_statements.playlists_update
|
||||
|| !db_statements.queue_items_insert || !db_statements.queue_items_update
|
||||
)
|
||||
return -1;
|
||||
|
||||
@ -7196,7 +7326,9 @@ db_init(void)
|
||||
uint32_t files;
|
||||
uint32_t pls;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
// Consistency checks
|
||||
if (ARRAY_SIZE(dbmfi_cols_map) != ARRAY_SIZE(mfi_cols_map))
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "BUG: mfi column maps are not in sync\n");
|
||||
@ -7209,6 +7341,21 @@ db_init(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ARRAY_SIZE(qi_cols_map) != ARRAY_SIZE(qi_mfi_map))
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "BUG: queue_item column maps are not in sync\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qi_cols_map); i++)
|
||||
{
|
||||
if (qi_cols_map[i].offset == qi_mfi_map[i].qi_offset)
|
||||
continue;
|
||||
|
||||
DPRINTF(E_FATAL, L_DB, "BUG: queue_item offset maps are not in sync (at %d)\n", i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
db_path = cfg_getstr(cfg_getsec(cfg, "general"), "db_path");
|
||||
db_rating_updates = cfg_getbool(cfg_getsec(cfg, "library"), "rating_updates");
|
||||
|
||||
|
14
src/db.h
14
src/db.h
@ -543,7 +543,7 @@ void
|
||||
free_query_params(struct query_params *qp, int content_only);
|
||||
|
||||
void
|
||||
free_queue_item(struct db_queue_item *queue_item, int content_only);
|
||||
free_queue_item(struct db_queue_item *qi, int content_only);
|
||||
|
||||
/* Maintenance and DB hygiene */
|
||||
void
|
||||
@ -816,8 +816,14 @@ int
|
||||
db_speaker_get(struct output_device *device, uint64_t id);
|
||||
|
||||
/* Queue */
|
||||
void
|
||||
db_queue_item_from_mfi(struct db_queue_item *qi, struct media_file_info *mfi); // Use free_queue_item(qi, 0) to free
|
||||
|
||||
void
|
||||
db_queue_item_from_dbmfi(struct db_queue_item *qi, struct db_media_file_info *dbmfi); // Do not free qi content
|
||||
|
||||
int
|
||||
db_queue_update_item(struct db_queue_item *queue_item);
|
||||
db_queue_item_update(struct db_queue_item *qi);
|
||||
|
||||
int
|
||||
db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id);
|
||||
@ -838,7 +844,7 @@ int
|
||||
db_queue_add_end(struct db_queue_add_info *queue_add_info, char reshuffle, uint32_t item_id, int ret);
|
||||
|
||||
int
|
||||
db_queue_add_item(struct db_queue_add_info *queue_add_info, struct db_queue_item *item);
|
||||
db_queue_add_next(struct db_queue_add_info *queue_add_info, struct db_queue_item *qi);
|
||||
|
||||
int
|
||||
db_queue_enum_start(struct query_params *qp);
|
||||
@ -847,7 +853,7 @@ void
|
||||
db_queue_enum_end(struct query_params *qp);
|
||||
|
||||
int
|
||||
db_queue_enum_fetch(struct query_params *qp, struct db_queue_item *queue_item);
|
||||
db_queue_enum_fetch(struct query_params *qp, struct db_queue_item *qi);
|
||||
|
||||
struct db_queue_item *
|
||||
db_queue_fetch_byitemid(uint32_t item_id);
|
||||
|
@ -2607,7 +2607,7 @@ jsonapi_reply_queue_tracks_update(struct httpd_request *hreq)
|
||||
return ret;
|
||||
|
||||
if (is_changed)
|
||||
db_queue_update_item(queue_item);
|
||||
db_queue_item_update(queue_item);
|
||||
|
||||
return HTTP_NOCONTENT;
|
||||
}
|
||||
|
@ -1742,47 +1742,11 @@ filescanner_fullrescan()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
map_media_file_to_queue_item(struct db_queue_item *queue_item, struct media_file_info *mfi)
|
||||
{
|
||||
memset(queue_item, 0, sizeof(struct db_queue_item));
|
||||
|
||||
if (mfi->id)
|
||||
queue_item->file_id = mfi->id;
|
||||
else
|
||||
queue_item->file_id = DB_MEDIA_FILE_NON_PERSISTENT_ID;
|
||||
|
||||
queue_item->title = safe_strdup(mfi->title);
|
||||
queue_item->artist = safe_strdup(mfi->artist);
|
||||
queue_item->album_artist = safe_strdup(mfi->album_artist);
|
||||
queue_item->album = safe_strdup(mfi->album);
|
||||
queue_item->genre = safe_strdup(mfi->genre);
|
||||
queue_item->artist_sort = safe_strdup(mfi->artist_sort);
|
||||
queue_item->album_artist_sort = safe_strdup(mfi->album_artist_sort);
|
||||
queue_item->album_sort = safe_strdup(mfi->album_sort);
|
||||
queue_item->path = safe_strdup(mfi->path);
|
||||
queue_item->virtual_path = safe_strdup(mfi->virtual_path);
|
||||
queue_item->data_kind = mfi->data_kind;
|
||||
queue_item->media_kind = mfi->media_kind;
|
||||
queue_item->song_length = mfi->song_length;
|
||||
queue_item->seek = mfi->seek;
|
||||
queue_item->songalbumid = mfi->songalbumid;
|
||||
queue_item->time_modified = mfi->time_modified;
|
||||
queue_item->year = mfi->year;
|
||||
queue_item->track = mfi->track;
|
||||
queue_item->disc = mfi->disc;
|
||||
//queue_item->artwork_url
|
||||
queue_item->type = safe_strdup(mfi->type);
|
||||
queue_item->channels = mfi->channels;
|
||||
queue_item->samplerate = mfi->samplerate;
|
||||
queue_item->bitrate = mfi->bitrate;
|
||||
}
|
||||
|
||||
static int
|
||||
queue_item_stream_add(const char *path, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id)
|
||||
{
|
||||
struct media_file_info mfi;
|
||||
struct db_queue_item item;
|
||||
struct db_queue_item qi;
|
||||
struct db_queue_add_info queue_add_info;
|
||||
int ret;
|
||||
|
||||
@ -1790,12 +1754,12 @@ queue_item_stream_add(const char *path, int position, char reshuffle, uint32_t i
|
||||
|
||||
scan_metadata_stream(&mfi, path);
|
||||
|
||||
map_media_file_to_queue_item(&item, &mfi);
|
||||
db_queue_item_from_mfi(&qi, &mfi);
|
||||
|
||||
ret = db_queue_add_start(&queue_add_info, position);
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = db_queue_add_item(&queue_add_info, &item);
|
||||
ret = db_queue_add_next(&queue_add_info, &qi);
|
||||
ret = db_queue_add_end(&queue_add_info, reshuffle, item_id, ret);
|
||||
if (ret == 0)
|
||||
{
|
||||
@ -1806,7 +1770,7 @@ queue_item_stream_add(const char *path, int position, char reshuffle, uint32_t i
|
||||
}
|
||||
}
|
||||
|
||||
free_queue_item(&item, 1);
|
||||
free_queue_item(&qi, 1);
|
||||
free_mfi(&mfi, 1);
|
||||
|
||||
return 0;
|
||||
|
@ -601,7 +601,7 @@ metadata_update_queue_cb(void *arg)
|
||||
if (metadata->len_ms)
|
||||
queue_item->song_length = metadata->len_ms;
|
||||
|
||||
ret = db_queue_update_item(queue_item);
|
||||
ret = db_queue_item_update(queue_item);
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_PLAYER, "Database error while updating queue with new metadata\n");
|
||||
}
|
||||
|
@ -1080,7 +1080,7 @@ queue_add_track(const char *uri, int position, char reshuffle, uint32_t item_id,
|
||||
ret = db_queue_add_start(&queue_add_info, position);
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = db_queue_add_item(&queue_add_info, &item);
|
||||
ret = db_queue_add_next(&queue_add_info, &item);
|
||||
ret = db_queue_add_end(&queue_add_info, reshuffle, item_id, ret);
|
||||
if (ret == 0)
|
||||
{
|
||||
@ -1122,7 +1122,7 @@ queue_add_album_tracks(json_object *item, int index, int total, enum spotify_req
|
||||
|
||||
map_track_to_queueitem(&queue_item, &track, ¶m->album);
|
||||
|
||||
ret = db_queue_add_item(¶m->queue_add_info, &queue_item);
|
||||
ret = db_queue_add_next(¶m->queue_add_info, &queue_item);
|
||||
|
||||
free_queue_item(&queue_item, 1);
|
||||
|
||||
@ -1236,7 +1236,7 @@ queue_add_playlist_tracks(json_object *item, int index, int total, enum spotify_
|
||||
|
||||
map_track_to_queueitem(&queue_item, &track, NULL);
|
||||
|
||||
ret = db_queue_add_item(queue_add_info, &queue_item);
|
||||
ret = db_queue_add_next(queue_add_info, &queue_item);
|
||||
|
||||
free_queue_item(&queue_item, 1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user