mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-15 16:53:18 -05:00
[db,jsonapi] Additional meta data for browse queries
This commit is contained in:
parent
17ba3c6e03
commit
d7086cab00
79
src/db.c
79
src/db.c
@ -420,6 +420,27 @@ static const ssize_t dbgri_cols_map[] =
|
||||
dbgri_offsetof(seek),
|
||||
};
|
||||
|
||||
/* This list must be kept in sync with
|
||||
* - the order of fields in the Q_BROWSE_INFO query
|
||||
* - the name of the fields in struct db_browse_info
|
||||
*/
|
||||
static const ssize_t dbbi_cols_map[] =
|
||||
{
|
||||
dbbi_offsetof(itemname),
|
||||
dbbi_offsetof(itemname_sort),
|
||||
dbbi_offsetof(track_count),
|
||||
dbbi_offsetof(album_count),
|
||||
dbbi_offsetof(artist_count),
|
||||
dbbi_offsetof(song_length),
|
||||
dbbi_offsetof(data_kind),
|
||||
dbbi_offsetof(media_kind),
|
||||
dbbi_offsetof(year),
|
||||
dbbi_offsetof(date_released),
|
||||
dbbi_offsetof(time_added),
|
||||
dbbi_offsetof(time_played),
|
||||
dbbi_offsetof(seek),
|
||||
};
|
||||
|
||||
/* This list must be kept in sync with
|
||||
* - qi_cols_map
|
||||
*/
|
||||
@ -2188,7 +2209,10 @@ db_build_query_browse(struct query_params *qp, struct query_clause *qc)
|
||||
where = browse_clause[qp->type & ~Q_F_BROWSE].where;
|
||||
|
||||
count = sqlite3_mprintf("SELECT COUNT(*) FROM (SELECT %s FROM files f %s AND %s != '' %s);", select, qc->where, where, qc->group);
|
||||
query = sqlite3_mprintf("SELECT %s FROM files f %s AND %s != '' %s %s %s;", select, qc->where, where, qc->group, qc->order, qc->index);
|
||||
query = sqlite3_mprintf("SELECT %s, COUNT(f.id) as track_count, COUNT(DISTINCT f.songalbumid) as album_count, COUNT(DISTINCT f.songartistid) as artist_count, "
|
||||
" SUM(f.song_length), MIN(f.data_kind), MIN(f.media_kind), MAX(f.year), MAX(f.date_released), "
|
||||
" MAX(f.time_added), MAX(f.time_played), MAX(f.seek) FROM files f %s AND %s != '' %s %s %s;",
|
||||
select, qc->where, where, qc->group, qc->order, qc->index);
|
||||
|
||||
return db_build_query_check(qp, count, query);
|
||||
}
|
||||
@ -2522,6 +2546,59 @@ db_query_fetch_group(struct query_params *qp, struct db_group_info *dbgri)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
db_query_fetch_browse(struct query_params *qp, struct db_browse_info *dbbi)
|
||||
{
|
||||
int ncols;
|
||||
char **strcol;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
memset(dbbi, 0, sizeof(struct db_browse_info));
|
||||
|
||||
if (!qp->stmt)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Query not started!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(qp->type & Q_F_BROWSE))
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Not a browse query!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = db_blocking_step(qp->stmt);
|
||||
if (ret == SQLITE_DONE)
|
||||
{
|
||||
DPRINTF(E_DBG, L_DB, "End of query results\n");
|
||||
return 1;
|
||||
}
|
||||
else if (ret != SQLITE_ROW)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ncols = sqlite3_column_count(qp->stmt);
|
||||
|
||||
// We allow more cols in db than in map because the db may be a future schema
|
||||
if (ncols < ARRAY_SIZE(dbbi_cols_map))
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "BUG: database has fewer columns (%d) than dbbi column map (%u)\n", ncols, ARRAY_SIZE(dbbi_cols_map));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dbbi_cols_map); i++)
|
||||
{
|
||||
strcol = (char **) ((char *)dbbi + dbbi_cols_map[i]);
|
||||
|
||||
*strcol = (char *)sqlite3_column_text(qp->stmt, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
db_query_fetch_count(struct query_params *qp, struct filecount_info *fci)
|
||||
{
|
||||
|
21
src/db.h
21
src/db.h
@ -409,6 +409,24 @@ struct db_media_file_info {
|
||||
|
||||
#define dbmfi_offsetof(field) offsetof(struct db_media_file_info, field)
|
||||
|
||||
struct db_browse_info {
|
||||
char *itemname;
|
||||
char *itemname_sort;
|
||||
char *track_count;
|
||||
char *album_count;
|
||||
char *artist_count;
|
||||
char *song_length;
|
||||
char *data_kind;
|
||||
char *media_kind;
|
||||
char *year;
|
||||
char *date_released;
|
||||
char *time_added;
|
||||
char *time_played;
|
||||
char *seek;
|
||||
};
|
||||
|
||||
#define dbbi_offsetof(field) offsetof(struct db_browse_info, field)
|
||||
|
||||
enum strip_type {
|
||||
STRIP_NONE,
|
||||
STRIP_PATH,
|
||||
@ -593,6 +611,9 @@ db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli);
|
||||
int
|
||||
db_query_fetch_group(struct query_params *qp, struct db_group_info *dbgri);
|
||||
|
||||
int
|
||||
db_query_fetch_browse(struct query_params *qp, struct db_browse_info *dbbi);
|
||||
|
||||
int
|
||||
db_query_fetch_count(struct query_params *qp, struct filecount_info *fci);
|
||||
|
||||
|
@ -388,17 +388,42 @@ playlist_to_json(struct db_playlist_info *dbpli)
|
||||
}
|
||||
|
||||
static json_object *
|
||||
genre_to_json(const char *genre)
|
||||
browse_info_to_json(struct db_browse_info *dbbi)
|
||||
{
|
||||
json_object *item;
|
||||
int intval;
|
||||
int ret;
|
||||
|
||||
if (genre == NULL)
|
||||
if (dbbi == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item = json_object_new_object();
|
||||
safe_json_add_string(item, "name", genre);
|
||||
safe_json_add_string(item, "name", dbbi->itemname);
|
||||
safe_json_add_string(item, "name_sort", dbbi->itemname_sort);
|
||||
safe_json_add_int_from_string(item, "track_count", dbbi->track_count);
|
||||
safe_json_add_int_from_string(item, "album_count", dbbi->album_count);
|
||||
safe_json_add_int_from_string(item, "artist_count", dbbi->artist_count);
|
||||
safe_json_add_int_from_string(item, "length_ms", dbbi->song_length);
|
||||
|
||||
safe_json_add_time_from_string(item, "time_played", dbbi->time_played);
|
||||
safe_json_add_time_from_string(item, "time_added", dbbi->time_added);
|
||||
|
||||
ret = safe_atoi32(dbbi->seek, &intval);
|
||||
if (ret == 0)
|
||||
json_object_object_add(item, "in_progress", json_object_new_boolean(intval > 0));
|
||||
|
||||
ret = safe_atoi32(dbbi->media_kind, &intval);
|
||||
if (ret == 0)
|
||||
safe_json_add_string(item, "media_kind", db_media_kind_label(intval));
|
||||
|
||||
ret = safe_atoi32(dbbi->data_kind, &intval);
|
||||
if (ret == 0)
|
||||
safe_json_add_string(item, "data_kind", db_data_kind_label(intval));
|
||||
|
||||
safe_json_add_date_from_string(item, "date_released", dbbi->date_released);
|
||||
safe_json_add_int_from_string(item, "year", dbbi->year);
|
||||
|
||||
return item;
|
||||
}
|
||||
@ -662,18 +687,17 @@ fetch_playlist(bool *notfound, uint32_t playlist_id)
|
||||
static int
|
||||
fetch_genres(struct query_params *query_params, json_object *items, int *total)
|
||||
{
|
||||
struct db_browse_info dbbi;
|
||||
json_object *item;
|
||||
int ret;
|
||||
char *genre;
|
||||
char *sort_item;
|
||||
|
||||
ret = db_query_start(query_params);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
while (((ret = db_query_fetch_string_sort(query_params, &genre, &sort_item)) == 0) && (genre))
|
||||
while (((ret = db_query_fetch_browse(query_params, &dbbi)) == 0) && (dbbi.track_count))
|
||||
{
|
||||
item = genre_to_json(genre);
|
||||
item = browse_info_to_json(&dbbi);
|
||||
if (!item)
|
||||
{
|
||||
ret = -1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user