From 4299de5ac7637abc834ece22d376e097d0cfa2ac Mon Sep 17 00:00:00 2001 From: chme Date: Thu, 28 May 2015 21:31:55 +0200 Subject: [PATCH 1/3] [mpd] implement plchanges to report all songs in the queue as changed (ignores the playlist version parameter). This is necessary in order to get mpd clients (e. g. sonata) relying on this command to display the queue. --- src/mpd.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/mpd.c b/src/mpd.c index a51577d9..4068a601 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -1797,10 +1797,49 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e return 0; } +/* + * Command handler function for 'plchanges' + * Lists all changed songs in the queue since the given playlist version in argv[1]. + */ static int mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) { - DPRINTF(E_WARN, L_MPD, "Ignore command %s\n", argv[0]); + struct player_queue *queue; + int pos_pl; + int i; + int ret; + + /* + * forked-daapd does not keep track of changes in the queue based on the playlist version, + * therefor plchanges returns all songs in the queue as changed ignoring the given version. + */ + queue = player_queue_get(0, -1, 0); + + if (!queue) + { + // Queue is emtpy + return 0; + } + + pos_pl = queue->start_pos; + for (i = 0; i < queue->count; i++) + { + ret = mpd_add_mediainfo_byid(evbuf, queue->queue[i], pos_pl); + if (ret < 0) + { + ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue->queue[i]); + + queue_free(queue); + + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_UNKNOWN; + } + + pos_pl++; + } + + queue_free(queue); return 0; } From 2a04740ca29e98aca95786617796a29e2b12b0ae Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 30 May 2015 05:31:54 +0200 Subject: [PATCH 2/3] [mpd] support "file" argument in list command --- src/db.c | 5 +++++ src/db.h | 32 +++++++++++++++++--------------- src/mpd.c | 30 +++++++++++++++++++++++++----- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/db.c b/src/db.c index a840054e..6e1d3429 100644 --- a/src/db.c +++ b/src/db.c @@ -287,6 +287,7 @@ static const char *sort_clause[] = "ORDER BY f.composer_sort ASC", "ORDER BY f.disc ASC", "ORDER BY f.track ASC", + "ORDER BY f.virtual_path ASC", }; static char *db_path; @@ -1529,6 +1530,10 @@ db_query_start(struct query_params *qp) ret = db_build_query_browse(qp, "track", "track", &query); break; + case Q_BROWSE_VPATH: + ret = db_build_query_browse(qp, "virtual_path", "virtual_path", &query); + break; + case Q_COUNT_ITEMS: ret = db_build_query_count_items(qp, &query); break; diff --git a/src/db.h b/src/db.h index 4b8faefe..6d3e7092 100644 --- a/src/db.h +++ b/src/db.h @@ -27,26 +27,28 @@ enum sort_type { S_COMPOSER, S_DISC, S_TRACK, + S_VPATH, }; #define Q_F_BROWSE (1 << 15) enum query_type { - Q_ITEMS = (1 << 0), - Q_PL = (1 << 1), - Q_PLITEMS = (1 << 2), - Q_BROWSE_ARTISTS = Q_F_BROWSE | (1 << 3), - 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_GROUP_ALBUMS = (1 << 7), - Q_GROUP_ARTISTS = (1 << 8), - 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), - Q_BROWSE_DISCS = Q_F_BROWSE | (1 << 13), - Q_BROWSE_TRACKS = Q_F_BROWSE | (1 << 14), + Q_ITEMS = 1, + Q_PL = 2, + Q_PLITEMS = 3, + Q_BROWSE_ARTISTS = Q_F_BROWSE | 4, + Q_BROWSE_ALBUMS = Q_F_BROWSE | 5, + Q_BROWSE_GENRES = Q_F_BROWSE | 6, + Q_BROWSE_COMPOSERS = Q_F_BROWSE | 7, + Q_GROUP_ALBUMS = 8, + Q_GROUP_ARTISTS = 9, + Q_GROUP_ITEMS = 10, + Q_GROUP_DIRS = Q_F_BROWSE | 11, + Q_BROWSE_YEARS = Q_F_BROWSE | 12, + Q_COUNT_ITEMS = 13, + Q_BROWSE_DISCS = Q_F_BROWSE | 14, + Q_BROWSE_TRACKS = Q_F_BROWSE | 15, + Q_BROWSE_VPATH = Q_F_BROWSE | 16, }; #define ARTWORK_UNKNOWN 0 diff --git a/src/mpd.c b/src/mpd.c index 4068a601..706e8f3e 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -2431,6 +2431,12 @@ mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) qp.sort = S_TRACK; type = "Track: "; } + else if (0 == strcasecmp(argv[1], "file")) + { + qp.type = Q_BROWSE_VPATH; + qp.sort = S_VPATH; + type = "file: "; + } else { DPRINTF(E_WARN, L_MPD, "Unsupported type argument for command 'list': %s\n", argv[1]); @@ -2457,12 +2463,26 @@ mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) if (qp.type & Q_F_BROWSE) { - while (((ret = db_query_fetch_string_sort(&qp, &browse_item, &sort_item)) == 0) && (browse_item)) + if (qp.type == Q_BROWSE_VPATH) { - evbuffer_add_printf(evbuf, - "%s%s\n", - type, - browse_item); + while (((ret = db_query_fetch_string_sort(&qp, &browse_item, &sort_item)) == 0) && (browse_item)) + { + // Remove the first "/" from the virtual_path + evbuffer_add_printf(evbuf, + "%s%s\n", + type, + (browse_item + 1)); + } + } + else + { + while (((ret = db_query_fetch_string_sort(&qp, &browse_item, &sort_item)) == 0) && (browse_item)) + { + evbuffer_add_printf(evbuf, + "%s%s\n", + type, + browse_item); + } } } else From 7f09438621a5526d8597c9ef62f436397d74a919 Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 30 May 2015 05:44:52 +0200 Subject: [PATCH 3/3] [mpd] support "date" argument in find and search commands --- src/mpd.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/mpd.c b/src/mpd.c index 706e8f3e..9c0b28ed 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -2190,6 +2190,14 @@ mpd_get_query_params_find(int argc, char **argv, struct query_params *qp) else c1 = sqlite3_mprintf("(f.track = %d)", num); } + else if (0 == strcasecmp(argv[i], "date")) + { + ret = safe_atou32(argv[i + 1], &num); + if (ret < 0) + c1 = sqlite3_mprintf("(f.year = 0 OR f.year IS NULL)"); + else + c1 = sqlite3_mprintf("(f.year = %d)", num); + } else if (i == 0 && argc == 1) { // Special case: a single token is allowed if listing albums for an artist @@ -2683,6 +2691,14 @@ mpd_get_query_params_search(int argc, char **argv, struct query_params *qp) else c1 = sqlite3_mprintf("(f.track = %d)", num); } + else if (0 == strcasecmp(argv[i], "date")) + { + ret = safe_atou32(argv[i + 1], &num); + if (ret < 0) + c1 = sqlite3_mprintf("(f.year = 0 OR f.year IS NULL)"); + else + c1 = sqlite3_mprintf("(f.year = %d)", num); + } else { DPRINTF(E_WARN, L_MPD, "Parameter '%s' is not supported by forked-daapd and will be ignored\n", argv[i]);