mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-26 14:13:18 -05:00
Count playlist items on the fly
This commit is contained in:
parent
30204cbb76
commit
2d1c35b855
158
src/db.c
158
src/db.c
@ -116,12 +116,13 @@ static struct col_type_map pli_cols_map[] =
|
||||
{ pli_offsetof(id), DB_TYPE_INT },
|
||||
{ pli_offsetof(title), DB_TYPE_STRING },
|
||||
{ pli_offsetof(type), DB_TYPE_INT },
|
||||
{ pli_offsetof(items), DB_TYPE_INT },
|
||||
{ pli_offsetof(query), DB_TYPE_STRING },
|
||||
{ pli_offsetof(db_timestamp), DB_TYPE_INT },
|
||||
{ pli_offsetof(disabled), DB_TYPE_INT },
|
||||
{ pli_offsetof(path), DB_TYPE_STRING },
|
||||
{ pli_offsetof(index), DB_TYPE_INT },
|
||||
|
||||
/* items is computed on the fly */
|
||||
};
|
||||
|
||||
#define dbmfi_offsetof(field) offsetof(struct db_media_file_info, field)
|
||||
@ -187,12 +188,13 @@ static ssize_t dbpli_cols_map[] =
|
||||
dbpli_offsetof(id),
|
||||
dbpli_offsetof(title),
|
||||
dbpli_offsetof(type),
|
||||
dbpli_offsetof(items),
|
||||
dbpli_offsetof(query),
|
||||
dbpli_offsetof(db_timestamp),
|
||||
dbpli_offsetof(disabled),
|
||||
dbpli_offsetof(path),
|
||||
dbpli_offsetof(index),
|
||||
|
||||
/* items is computed on the fly */
|
||||
};
|
||||
|
||||
#define wi_offsetof(field) offsetof(struct watch_info, field)
|
||||
@ -212,6 +214,11 @@ static struct col_type_map wi_cols_map[] =
|
||||
static __thread sqlite3 *hdl;
|
||||
|
||||
|
||||
/* Forward */
|
||||
static int
|
||||
db_pl_count_items(int id);
|
||||
|
||||
|
||||
char *
|
||||
db_escape_string(const char *str)
|
||||
{
|
||||
@ -776,6 +783,7 @@ db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli)
|
||||
{
|
||||
int ncols;
|
||||
char **strcol;
|
||||
int id;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
@ -821,6 +829,19 @@ db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli)
|
||||
*strcol = (char *)sqlite3_column_text(qp->stmt, i);
|
||||
}
|
||||
|
||||
id = sqlite3_column_int(qp->stmt, 0);
|
||||
|
||||
i = db_pl_count_items(id);
|
||||
|
||||
dbpli->items = qp->buf;
|
||||
ret = snprintf(qp->buf, sizeof(qp->buf), "%d", i);
|
||||
if ((ret < 0) || (ret >= sizeof(qp->buf)))
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not convert items, buffer too small\n");
|
||||
|
||||
strcpy(qp->buf, "0");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1463,6 +1484,44 @@ db_pl_get_count(int *count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
db_pl_count_items(int id)
|
||||
{
|
||||
#define Q_TMPL "SELECT COUNT(*) FROM playlistitems JOIN songs" \
|
||||
" ON playlistitems.songid = songs.id WHERE songs.disabled = 0 AND playlistitems.playlistid = %d;"
|
||||
char *query;
|
||||
int nsongs;
|
||||
int ret;
|
||||
|
||||
if (id == 1)
|
||||
{
|
||||
ret = db_files_get_count(&nsongs);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not get file count\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nsongs;
|
||||
}
|
||||
|
||||
query = sqlite3_mprintf(Q_TMPL, id);
|
||||
|
||||
if (!query)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = db_get_count(query);
|
||||
|
||||
sqlite3_free(query);
|
||||
|
||||
return ret;
|
||||
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
void
|
||||
db_pl_ping(int id)
|
||||
{
|
||||
@ -1649,6 +1708,8 @@ db_pl_fetch_byquery(char *query)
|
||||
|
||||
pli->items = i;
|
||||
}
|
||||
else
|
||||
pli->items = db_pl_count_items(pli->id);
|
||||
|
||||
return pli;
|
||||
}
|
||||
@ -1681,8 +1742,8 @@ int
|
||||
db_pl_add(char *title, char *path, int *id)
|
||||
{
|
||||
#define QDUP_TMPL "SELECT COUNT(*) FROM playlists WHERE title = '%q' OR path = '%q';"
|
||||
#define QADD_TMPL "INSERT INTO playlists (title, type, items, query, db_timestamp, disabled, path, idx)" \
|
||||
" VALUES ('%q', 0, 0, NULL, %" PRIi64 ", 0, '%q', 0);"
|
||||
#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx)" \
|
||||
" VALUES ('%q', 0, NULL, %" PRIi64 ", 0, '%q', 0);"
|
||||
char *query;
|
||||
char *errmsg;
|
||||
sqlite3_stmt *stmt;
|
||||
@ -1911,90 +1972,6 @@ db_pl_clear_items(int id)
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
void
|
||||
db_pl_update(int id)
|
||||
{
|
||||
#define QPL1_TMPL "UPDATE playlists SET items = %d WHERE id = 1;"
|
||||
#define Q_TMPL "UPDATE playlists SET items = (SELECT COUNT(*) FROM playlistitems JOIN songs" \
|
||||
" ON playlistitems.songid = songs.id WHERE songs.disabled = 0 AND playlistitems.playlistid = %d) WHERE id = %d;"
|
||||
char *query;
|
||||
char *errmsg;
|
||||
int nsongs;
|
||||
int ret;
|
||||
|
||||
if (id == 1)
|
||||
{
|
||||
ret = db_files_get_count(&nsongs);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not get file count\n");
|
||||
return;
|
||||
}
|
||||
|
||||
query = sqlite3_mprintf(QPL1_TMPL, nsongs);
|
||||
}
|
||||
else
|
||||
query = sqlite3_mprintf(Q_TMPL, id, id);
|
||||
|
||||
if (!query)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
|
||||
|
||||
errmsg = NULL;
|
||||
ret = sqlite3_exec(hdl, query, NULL, NULL, &errmsg);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Query error: %s\n", errmsg);
|
||||
|
||||
sqlite3_free(errmsg);
|
||||
sqlite3_free(query);
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_free(query);
|
||||
|
||||
#undef QPL1_TMPL
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
void
|
||||
db_pl_update_all(void)
|
||||
{
|
||||
char *query = "SELECT id FROM playlists;";
|
||||
sqlite3_stmt *stmt;
|
||||
int plid;
|
||||
int ret;
|
||||
|
||||
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
|
||||
|
||||
ret = sqlite3_prepare_v2(hdl, query, strlen(query) + 1, &stmt, NULL);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl));
|
||||
return;
|
||||
}
|
||||
|
||||
while ((ret = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
plid = sqlite3_column_int(stmt, 0);
|
||||
db_pl_update(plid);
|
||||
}
|
||||
|
||||
if (ret != SQLITE_DONE)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl));
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
void
|
||||
db_pl_delete(int id)
|
||||
{
|
||||
@ -2720,7 +2697,6 @@ db_perthread_deinit(void)
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" title VARCHAR(255) NOT NULL," \
|
||||
" type INTEGER NOT NULL," \
|
||||
" items INTEGER NOT NULL," \
|
||||
" query VARCHAR(1024)," \
|
||||
" db_timestamp INTEGER NOT NULL," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
@ -2744,8 +2720,8 @@ db_perthread_deinit(void)
|
||||
");"
|
||||
|
||||
#define Q_PL1 \
|
||||
"INSERT INTO playlists (id, title, type, items, query, db_timestamp, path, idx)" \
|
||||
" VALUES(1, 'Library', 1, 0, '1', 0, '', 0);"
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx)" \
|
||||
" VALUES(1, 'Library', 1, '1', 0, '', 0);"
|
||||
|
||||
#define I_PATH \
|
||||
"CREATE INDEX IF NOT EXISTS idx_path ON songs(path, idx);"
|
||||
|
7
src/db.h
7
src/db.h
@ -43,6 +43,7 @@ struct query_params {
|
||||
|
||||
/* Private query context, keep out */
|
||||
sqlite3_stmt *stmt;
|
||||
char buf[32];
|
||||
};
|
||||
|
||||
struct media_file_info {
|
||||
@ -272,12 +273,6 @@ db_pl_add(char *title, char *path, int *id);
|
||||
int
|
||||
db_pl_add_item(int plid, int mfid);
|
||||
|
||||
void
|
||||
db_pl_update(int id);
|
||||
|
||||
void
|
||||
db_pl_update_all(void);
|
||||
|
||||
void
|
||||
db_pl_delete(int id);
|
||||
|
||||
|
@ -600,8 +600,6 @@ bulk_scan(void)
|
||||
}
|
||||
}
|
||||
|
||||
db_pl_update_all();
|
||||
|
||||
if (playlists)
|
||||
process_deferred_playlists();
|
||||
|
||||
@ -642,8 +640,6 @@ filescanner(void *arg)
|
||||
|
||||
if (!scan_exit)
|
||||
{
|
||||
db_pl_update_all();
|
||||
|
||||
/* Enable inotify */
|
||||
event_add(&inoev, NULL);
|
||||
|
||||
|
@ -220,7 +220,5 @@ scan_m3u_playlist(char *file)
|
||||
|
||||
fclose(fp);
|
||||
|
||||
db_pl_update(pl_id);
|
||||
|
||||
DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user