From b7cb0da2c2d375b82ccab8287234226e8dea9604 Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 17 May 2014 14:06:50 +0200 Subject: [PATCH] Modifications to the playqueue-clear command: - do not stop playback when clearing the UpNext queue - clear history, if mode=0x68697374 ("hist") --- src/httpd_dacp.c | 103 +++++++++++++++++++++++++++++------------------ src/player.c | 60 +++++++++++++++++++++++++++ src/player.h | 3 ++ 3 files changed, 127 insertions(+), 39 deletions(-) diff --git a/src/httpd_dacp.c b/src/httpd_dacp.c index e5f20de2..eba3959c 100644 --- a/src/httpd_dacp.c +++ b/src/httpd_dacp.c @@ -1219,51 +1219,50 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf, DPRINTF(E_LOG, L_DACP, "Invalid span value in playqueue-contents request\n"); } - songlist = NULL; i = 0; n = 0; // count of songs in songlist - player_get_status(&status); - - /* Get queue and make songlist only if playing or paused */ - if (status.status != PLAY_STOPPED) + songlist = evbuffer_new(); + if (!songlist) { - songlist = evbuffer_new(); - if (!songlist) - { - DPRINTF(E_LOG, L_DACP, "Could not allocate songlist evbuffer for playqueue-contents\n"); + DPRINTF(E_LOG, L_DACP, "Could not allocate songlist evbuffer for playqueue-contents\n"); - dmap_send_error(req, "ceQR", "Out of memory"); - return; - } + dmap_send_error(req, "ceQR", "Out of memory"); + return; + } - /* - * If the span parameter is negativ make song list for Previously Played, - * otherwise make song list for Up Next and begin with first song after playlist position. - */ - if (span < 0) + /* + * If the span parameter is negativ make song list for Previously Played, + * otherwise make song list for Up Next and begin with first song after playlist position. + */ + if (span < 0) + { + history = player_history_get(); + if (abs(span) > history->count) { - history = player_history_get(); - if (abs(span) > history->count) - { - start_index = history->start_index; - } - else - { - start_index = (history->start_index + history->count - abs(span)) % MAX_HISTORY_COUNT; - } - for (n = 0; n < history->count && n < abs(span); n++) - { - ret = playqueuecontents_add_source(songlist, history->id[(start_index + n) % MAX_HISTORY_COUNT], (n + 1), status.plid); - if (ret < 0) - { - DPRINTF(E_LOG, L_DACP, "Could not add song to songlist for playqueue-contents\n"); - - dmap_send_error(req, "ceQR", "Out of memory"); - return; - } - } + start_index = history->start_index; } else + { + start_index = (history->start_index + history->count - abs(span)) % MAX_HISTORY_COUNT; + } + for (n = 0; n < history->count && n < abs(span); n++) + { + ret = playqueuecontents_add_source(songlist, history->id[(start_index + n) % MAX_HISTORY_COUNT], (n + 1), status.plid); + if (ret < 0) + { + DPRINTF(E_LOG, L_DACP, "Could not add song to songlist for playqueue-contents\n"); + + dmap_send_error(req, "ceQR", "Out of memory"); + return; + } + } + } + else + { + player_get_status(&status); + + /* Get queue and make songlist only if playing or paused */ + if (status.status != PLAY_STOPPED) { /* Fast forward to song currently being played */ head = player_queue_get(); @@ -1271,7 +1270,7 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf, { ps = head; while ((ps->id != status.id) && (ps = next_ps(ps, status.shuffle)) && (ps != head)) - i++; + i++; while ((n < abs(span)) && (ps = next_ps(ps, status.shuffle)) && (ps != head)) { @@ -1365,6 +1364,32 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf, httpd_send_reply(req, HTTP_OK, "OK", evbuf); } +static void +dacp_reply_playqueueedit_clear(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) +{ + const char *param; + int clear_hist; + + clear_hist = 0; + param = evhttp_find_header(query, "mode"); + + /* + * The mode parameter contains the playlist to be cleared. + * If mode=0x68697374 (hex representation of the ascii string "hist") clear the history, + * otherwise the current playlist. + */ + if (strcmp(param,"0x68697374") == 0) + clear_hist = 1; + + player_queue_empty(clear_hist); + + dmap_add_container(evbuf, "cacr", 24); /* 8 + len */ + dmap_add_int(evbuf, "mstt", 200); /* 12 */ + dmap_add_int(evbuf, "miid", 0); /* 12 */ + + httpd_send_reply(req, HTTP_OK, "OK", evbuf); +} + static void dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) { @@ -1630,7 +1655,7 @@ dacp_reply_playqueueedit(struct evhttp_request *req, struct evbuffer *evbuf, cha } if (strcmp(param, "clear") == 0) - dacp_reply_cue_clear(req, evbuf, uri, query); + dacp_reply_playqueueedit_clear(req, evbuf, uri, query); else if (strcmp(param, "playnow") == 0) dacp_reply_cue_play(req, evbuf, uri, query); else if (strcmp(param, "add") == 0) diff --git a/src/player.c b/src/player.c index 64b8fc82..fed17f0e 100644 --- a/src/player.c +++ b/src/player.c @@ -3588,6 +3588,50 @@ queue_clear(struct player_command *cmd) return 0; } +static int +queue_empty(struct player_command *cmd) +{ + int clear_hist; + struct player_source *ps; + + clear_hist = cmd->arg.intval; + if (clear_hist) + { + memset(history, 0, sizeof(struct player_history)); + } + else + { + if (!source_head || !cur_streaming) + return 0; + + // Stop playback if playing and streaming song are not the same + if (!cur_playing || cur_playing != cur_streaming) + { + playback_stop(cmd); + queue_clear(cmd); + return 0; + } + + // Set head to the current playing song + shuffle_head = cur_playing; + source_head = cur_playing; + + // Free all items in the queue except the current playing song + for (ps = source_head->pl_next; ps != source_head; ps = ps->pl_next) + { + source_free(ps); + } + + // Make the queue circular again + source_head->pl_next = source_head; + source_head->pl_prev = source_head; + source_head->shuffle_next = source_head; + source_head->shuffle_prev = source_head; + } + + return 0; +} + static int queue_plid(struct player_command *cmd) { @@ -4111,6 +4155,22 @@ player_queue_clear(void) command_deinit(&cmd); } +void +player_queue_empty(int clear_hist) +{ + struct player_command cmd; + + command_init(&cmd); + + cmd.func = queue_empty; + cmd.func_bh = NULL; + cmd.arg.intval = clear_hist; + + sync_command(&cmd); + + command_deinit(&cmd); +} + void player_queue_plid(uint32_t plid) { diff --git a/src/player.h b/src/player.h index 21f5bded..f233e361 100644 --- a/src/player.h +++ b/src/player.h @@ -173,6 +173,9 @@ player_queue_remove(int ps_pos_remove); void player_queue_clear(void); +void +player_queue_empty(int clear_hist); + void player_queue_plid(uint32_t plid);