diff --git a/src/DAAP.g b/src/DAAP.g index b19e3137..a6013d89 100644 --- a/src/DAAP.g +++ b/src/DAAP.g @@ -41,7 +41,7 @@ QUOTE : '\''; LPAR : '('; RPAR : ')'; -OPAND : '+'; +OPAND : '+' | ' '; OPOR : ','; NEWLINE : '\r'? '\n'; diff --git a/src/artwork.c b/src/artwork.c index faa3826e..1a7b4b15 100644 --- a/src/artwork.c +++ b/src/artwork.c @@ -879,13 +879,13 @@ artwork_get_group(int id, int max_w, int max_h, int format, struct evbuffer *evb files_art: memset(&qp, 0, sizeof(struct query_params)); - qp.type = Q_GROUPITEMS; + qp.type = Q_GROUP_ITEMS; qp.id = id; ret = db_query_start(&qp); if (ret < 0) { - DPRINTF(E_LOG, L_ART, "Could not start Q_GROUPITEMS query\n"); + DPRINTF(E_LOG, L_ART, "Could not start Q_GROUP_ITEMS query\n"); return -1; } @@ -899,7 +899,7 @@ artwork_get_group(int id, int max_w, int max_h, int format, struct evbuffer *evb db_query_end(&qp); if (ret < 0) - DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUPITEMS results\n"); + DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUP_ITEMS results\n"); else if (got_art > 0) return got_art; diff --git a/src/db.c b/src/db.c index de087467..8a36a48e 100644 --- a/src/db.c +++ b/src/db.c @@ -232,12 +232,13 @@ static const ssize_t dbpli_cols_map[] = }; /* This list must be kept in sync with - * - the order of fields in the Q_GROUPS query + * - the order of fields in the Q_GROUP_ALBUMS and Q_GROUP_ARTISTS query * - the name of the fields in struct group_info */ static const ssize_t dbgri_cols_map[] = { dbgri_offsetof(itemcount), + dbgri_offsetof(groupalbumcount), dbgri_offsetof(id), dbgri_offsetof(persistentid), dbgri_offsetof(songalbumartist), @@ -967,7 +968,7 @@ db_build_query_plitems(struct query_params *qp, char **q) } static int -db_build_query_groups(struct query_params *qp, char **q) +db_build_query_group_albums(struct query_params *qp, char **q) { char *query; char *idx; @@ -983,13 +984,13 @@ db_build_query_groups(struct query_params *qp, char **q) return -1; if (idx && qp->filter) - query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name %s;", G_ALBUMS, qp->filter, idx); + query = sqlite3_mprintf("SELECT COUNT(*), 1, g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name %s;", G_ALBUMS, qp->filter, idx); else if (idx) - query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name %s;", G_ALBUMS, idx); + query = sqlite3_mprintf("SELECT COUNT(*), 1, g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name %s;", G_ALBUMS, idx); else if (qp->filter) - query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name;", G_ALBUMS, qp->filter); + query = sqlite3_mprintf("SELECT COUNT(*), 1, g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name;", G_ALBUMS, qp->filter); else - query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name;", G_ALBUMS); + query = sqlite3_mprintf("SELECT COUNT(*), 1, g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name;", G_ALBUMS); if (!query) { @@ -1003,7 +1004,43 @@ db_build_query_groups(struct query_params *qp, char **q) } static int -db_build_query_groupitems(struct query_params *qp, char **q) +db_build_query_group_artists(struct query_params *qp, char **q) +{ + char *query; + char *idx; + int ret; + + qp->results = db_get_count("SELECT COUNT(DISTINCT f.album_artist) FROM files f WHERE f.disabled = 0;"); + if (qp->results < 0) + return -1; + + /* Get index clause */ + ret = db_build_query_index_clause(qp, &idx); + if (ret < 0) + return -1; + + if (idx && qp->filter) + query = sqlite3_mprintf("SELECT COUNT(*), COUNT(DISTINCT f.album), 1, 1, f.album_artist, f.album_artist FROM files f WHERE f.disabled = 0 AND %s GROUP BY f.album_artist %s;", qp->filter, idx); + else if (idx) + query = sqlite3_mprintf("SELECT COUNT(*), COUNT(DISTINCT f.album), 1, 1, f.album_artist, f.album_artist FROM files f WHERE f.disabled = 0 GROUP BY f.album_artist %s;", idx); + else if (qp->filter) + query = sqlite3_mprintf("SELECT COUNT(*), COUNT(DISTINCT f.album), 1, 1, f.album_artist, f.album_artist FROM files f WHERE f.disabled = 0 AND %s GROUP BY f.album_artist;", qp->filter); + else + query = sqlite3_mprintf("SELECT COUNT(*), COUNT(DISTINCT f.album), 1, 1, f.album_artist, f.album_artist FROM files f WHERE f.disabled = 0 GROUP BY f.album_artist;"); + + if (!query) + { + DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); + return -1; + } + + *q = query; + + return 0; +} + +static int +db_build_query_group_items(struct query_params *qp, char **q) { char *query; char *count; @@ -1189,12 +1226,16 @@ db_query_start(struct query_params *qp) ret = db_build_query_plitems(qp, &query); break; - case Q_GROUPS: - ret = db_build_query_groups(qp, &query); + case Q_GROUP_ALBUMS: + ret = db_build_query_group_albums(qp, &query); break; - case Q_GROUPITEMS: - ret = db_build_query_groupitems(qp, &query); + case Q_GROUP_ARTISTS: + ret = db_build_query_group_artists(qp, &query); + break; + + case Q_GROUP_ITEMS: + ret = db_build_query_group_items(qp, &query); break; case Q_GROUP_DIRS: @@ -1269,7 +1310,7 @@ db_query_fetch_file(struct query_params *qp, struct db_media_file_info *dbmfi) return -1; } - if ((qp->type != Q_ITEMS) && (qp->type != Q_PLITEMS) && (qp->type != Q_GROUPITEMS)) + if ((qp->type != Q_ITEMS) && (qp->type != Q_PLITEMS) && (qp->type != Q_GROUP_ITEMS)) { DPRINTF(E_LOG, L_DB, "Not an items, playlist or group items query!\n"); return -1; @@ -1405,7 +1446,7 @@ db_query_fetch_group(struct query_params *qp, struct db_group_info *dbgri) return -1; } - if (qp->type != Q_GROUPS) + if ((qp->type != Q_GROUP_ALBUMS) && (qp->type != Q_GROUP_ARTISTS)) { DPRINTF(E_LOG, L_DB, "Not a groups query!\n"); return -1; diff --git a/src/db.h b/src/db.h index 99bb9586..e99f8338 100644 --- a/src/db.h +++ b/src/db.h @@ -33,9 +33,10 @@ enum query_type { Q_BROWSE_ALBUMS = Q_F_BROWSE | (1 << 4), Q_BROWSE_GENRES = Q_F_BROWSE | (1 << 5), Q_BROWSE_COMPOSERS = Q_F_BROWSE | (1 << 6), - Q_GROUPS = (1 << 7), - Q_GROUPITEMS = (1 << 8), - Q_GROUP_DIRS = Q_F_BROWSE | (1 << 9), + Q_GROUP_ALBUMS = (1 << 7), + Q_GROUP_ARTISTS = (1 << 8), + Q_GROUP_ITEMS = (1 << 9), + Q_GROUP_DIRS = Q_F_BROWSE | (1 << 10), }; struct query_params { @@ -190,6 +191,7 @@ struct db_group_info { char *persistentid; char *itemname; char *itemcount; + char *groupalbumcount; char *songalbumartist; }; diff --git a/src/dmap_fields.gperf b/src/dmap_fields.gperf index 549882c4..999c9ffb 100644 --- a/src/dmap_fields.gperf +++ b/src/dmap_fields.gperf @@ -101,6 +101,7 @@ const struct dmap_field_map dfm_dmap_aeSP = { -1, static const struct dmap_field_map dfm_dmap_aePS = { -1, -1, -1 }; static const struct dmap_field_map dfm_dmap_ascd = { dbmfi_offsetof(codectype), -1, -1 }; static const struct dmap_field_map dfm_dmap_ascs = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_agac = { -1, -1, dbgri_offsetof(groupalbumcount) }; static const struct dmap_field_map dfm_dmap_agrp = { dbmfi_offsetof(grouping), -1, -1 }; static const struct dmap_field_map dfm_dmap_aeSV = { -1, -1, -1 }; static const struct dmap_field_map dfm_dmap_aePI = { -1, -1, -1 }; @@ -162,6 +163,7 @@ struct dmap_field; "com.apple.itunes.smart-playlist", "aeSP", &dfm_dmap_aeSP, DMAP_TYPE_UBYTE "com.apple.itunes.season-num", "aeSU", &dfm_dmap_aeSU, DMAP_TYPE_UINT "com.apple.itunes.music-sharing-version", "aeSV", &dfm_dmap_aeSV, DMAP_TYPE_UINT +"daap.groupalbumcount", "agac", &dfm_dmap_agac, DMAP_TYPE_UINT "daap.songgrouping", "agrp", &dfm_dmap_agrp, DMAP_TYPE_STRING "daap.databaseplaylists", "aply", &dfm_dmap_aply, DMAP_TYPE_LIST "daap.playlistrepeatmode", "aprm", &dfm_dmap_aprm, DMAP_TYPE_UBYTE diff --git a/src/httpd_daap.c b/src/httpd_daap.c index 5e4690de..1dd54abd 100644 --- a/src/httpd_daap.c +++ b/src/httpd_daap.c @@ -1515,6 +1515,7 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri struct sort_ctx *sctx; const char *param; char **strval; + int group_type; int nmeta; int sort_headers; int ngrp; @@ -1527,8 +1528,17 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri if (!s) return; - /* For now we only support album groups */ - tag = "agal"; + param = evhttp_find_header(query, "group-type"); + if (strcmp(param, "artists") == 0) + { + tag = "agar"; + group_type = Q_GROUP_ARTISTS; + } + else + { + tag = "agal"; + group_type = Q_GROUP_ALBUMS; + } ret = evbuffer_expand(evbuf, 61); if (ret < 0) @@ -1595,7 +1605,7 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri memset(&qp, 0, sizeof(struct query_params)); get_query_params(query, &sort_headers, &qp); - qp.type = Q_GROUPS; + qp.type = group_type; sctx = NULL; if (sort_headers) @@ -1669,8 +1679,9 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri if ((ret == 0) && (val > 0)) dmap_add_int(group, "mimc", val); - /* Song album artist, always added (asaa) */ - dmap_add_string(group, "asaa", dbgri.songalbumartist); + /* Song album artist (asaa), always added if group-type is albums */ + if (group_type == Q_GROUP_ALBUMS) + dmap_add_string(group, "asaa", dbgri.songalbumartist); /* Item id (miid) */ val = 0;