diff --git a/src/db.c b/src/db.c index 5b9205e0..761fdf88 100644 --- a/src/db.c +++ b/src/db.c @@ -1493,6 +1493,29 @@ db_build_query_browse(struct query_params *qp, char *field, char *sort_field, ch return 0; } +static int +db_build_query_count_items(struct query_params *qp, char **q) +{ + char *query; + + qp->results = 1; + + if (qp->filter) + query = sqlite3_mprintf("SELECT COUNT(*), SUM(song_length) FROM files f WHERE f.disabled = 0 AND %s;", qp->filter); + else + return -1; + + if (!query) + { + DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); + return -1; + } + + *q = query; + + return 0; +} + int db_query_start(struct query_params *qp) { @@ -1551,6 +1574,10 @@ db_query_start(struct query_params *qp) ret = db_build_query_browse(qp, "year", "year", &query); break; + case Q_COUNT_ITEMS: + ret = db_build_query_count_items(qp, &query); + break; + default: DPRINTF(E_LOG, L_DB, "Unknown query type\n"); return -1; @@ -1805,6 +1832,43 @@ db_query_fetch_group(struct query_params *qp, struct db_group_info *dbgri) return 0; } +int +db_query_fetch_count(struct query_params *qp, struct count_info *ci) +{ + int ret; + + memset(ci, 0, sizeof(struct count_info)); + + if (!qp->stmt) + { + DPRINTF(E_LOG, L_DB, "Query not started!\n"); + return -1; + } + + if (qp->type != Q_COUNT_ITEMS) + { + DPRINTF(E_LOG, L_DB, "Not a count query!\n"); + return -1; + } + + ret = db_blocking_step(qp->stmt); + if (ret == SQLITE_DONE) + { + DPRINTF(E_DBG, L_DB, "End of query results for count query\n"); + return 0; + } + else if (ret != SQLITE_ROW) + { + DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl)); + return -1; + } + + ci->count = sqlite3_column_int(qp->stmt, 0); + ci->length = sqlite3_column_int(qp->stmt, 1); + + return 0; +} + int db_query_fetch_string(struct query_params *qp, char **string) { diff --git a/src/db.h b/src/db.h index bf9b9bbe..cfdad286 100644 --- a/src/db.h +++ b/src/db.h @@ -40,6 +40,7 @@ enum query_type { Q_GROUP_ITEMS = (1 << 9), Q_GROUP_DIRS = Q_F_BROWSE | (1 << 10), Q_BROWSE_YEARS = Q_F_BROWSE | (1 << 11), + Q_COUNT_ITEMS = (1 << 12), }; #define ARTWORK_UNKNOWN 0 @@ -312,6 +313,10 @@ struct watch_enum { sqlite3_stmt *stmt; }; +struct count_info { + uint32_t count; + uint32_t length; +}; char * db_escape_string(const char *str); @@ -364,6 +369,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_count(struct query_params *qp, struct count_info *ci); + int db_query_fetch_string(struct query_params *qp, char **string); diff --git a/src/mpd.c b/src/mpd.c index c39fce45..bd5eb14d 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -2065,6 +2065,63 @@ mpd_get_query_params_find(int argc, char **argv, struct query_params *qp) return 0; } +static int +mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) +{ + struct query_params qp; + struct count_info ci; + int ret; + + if (argc < 3 || ((argc - 1) % 2) != 0) + { + DPRINTF(E_LOG, L_MPD, "Missing argument(s) for command 'find'\n"); + ret = asprintf(errmsg, "Missing argument(s) for command 'find'"); + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_ARG; + } + + memset(&qp, 0, sizeof(struct query_params)); + + qp.type = Q_COUNT_ITEMS; + + mpd_get_query_params_find(argc - 1, argv + 1, &qp); + + ret = db_query_start(&qp); + if (ret < 0) + { + db_query_end(&qp); + + DPRINTF(E_LOG, L_MPD, "Could not start query\n"); + ret = asprintf(errmsg, "Could not start query"); + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_UNKNOWN; + } + + ret = db_query_fetch_count(&qp, &ci); + if (ret < 0) + { + db_query_end(&qp); + + DPRINTF(E_LOG, L_MPD, "Could not fetch query count\n"); + ret = asprintf(errmsg, "Could not fetch query count"); + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_UNKNOWN; + } + + evbuffer_add_printf(evbuf, + "songs: %d\n" + "playtime: %d\n", + ci.count, + (ci.length / 1000)); + + db_query_end(&qp); + + return 0; +} + static int mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) { @@ -3175,12 +3232,10 @@ static struct command mpd_handlers[] = /* * The music database */ - /* { .mpdcommand = "count", .handler = mpd_command_count }, - */ { .mpdcommand = "find", .handler = mpd_command_find