diff --git a/forked-daapd.conf b/forked-daapd.conf index ea485a7a..e2d3a9e8 100644 --- a/forked-daapd.conf +++ b/forked-daapd.conf @@ -217,6 +217,11 @@ mpd { # and will need additional configuration in the MPD client to work). # Set to 0 to disable serving artwork over http. # http_port = 0 + + # By default forked-daapd will - like iTunes - clear the playqueue if playback stops. + # Setting clear_queue_on_stop_disable to true will keep the playlist like MPD does. + # Note that some dacp clients do not show the playqueue if playback is stopped. +# clear_queue_on_stop_disable = false } # SQLite configuration (allows to modify the operation of the SQLite databases) diff --git a/src/conffile.c b/src/conffile.c index fda2be2b..c3fff9a1 100644 --- a/src/conffile.c +++ b/src/conffile.c @@ -139,6 +139,7 @@ static cfg_opt_t sec_mpd[] = { CFG_INT("port", 6600, CFGF_NONE), CFG_INT("http_port", 0, CFGF_NONE), + CFG_BOOL("clear_queue_on_stop_disable", cfg_false, CFGF_NONE), CFG_END() }; diff --git a/src/httpd_dacp.c b/src/httpd_dacp.c index adbb30a8..dd5eae8d 100644 --- a/src/httpd_dacp.c +++ b/src/httpd_dacp.c @@ -1015,7 +1015,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u return; } - player_queue_add(items); + player_queue_add(items, NULL); } else { @@ -1068,6 +1068,9 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u { /* Play from Up Next queue */ pos += status.pos_pl; + + if (status.status == PLAY_STOPPED && pos > 0) + pos--; } } @@ -1253,7 +1256,7 @@ dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **u player_playback_stop(); player_queue_clear(); - player_queue_add(items); + player_queue_add(items, NULL); player_queue_plid(plid); if (shuffle) @@ -1564,28 +1567,24 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf, { player_get_status(&status); - /* Get queue and make songlist only if playing or paused */ - if (status.status != PLAY_STOPPED) + queue = player_queue_get_bypos(abs(span)); + if (queue) { - queue = player_queue_get_bypos(abs(span)); - if (queue) + i = 0; + count = queue_count(queue); + for (n = 0; (n < count) && (n < abs(span)); n++) { - i = 0; - count = queue_count(queue); - for (n = 0; (n < count) && (n < abs(span)); n++) + item = queue_get_byindex(queue, n, 0); + ret = playqueuecontents_add_source(songlist, queueitem_id(item), (n + i + 1), status.plid); + if (ret < 0) { - item = queue_get_byindex(queue, n, 0); - ret = playqueuecontents_add_source(songlist, queueitem_id(item), (n + i + 1), status.plid); - if (ret < 0) - { - DPRINTF(E_LOG, L_DACP, "Could not add song to songlist for playqueue-contents\n"); + DPRINTF(E_LOG, L_DACP, "Could not add song to songlist for playqueue-contents\n"); - dmap_send_error(req, "ceQR", "Out of memory"); - return; - } + dmap_send_error(req, "ceQR", "Out of memory"); + return; } - queue_free(queue); } + queue_free(queue); } } @@ -1787,7 +1786,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf, } else { - player_queue_add(items); + player_queue_add(items, NULL); } } else diff --git a/src/mpd.c b/src/mpd.c index 3377cdde..ffcfbe00 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -1604,13 +1604,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) return ACK_ERROR_UNKNOWN; } - player_queue_add(items); - - ret = player_playback_start(NULL); - if (ret < 0) - { - DPRINTF(E_LOG, L_MPD, "Could not start playback\n"); - } + player_queue_add(items, NULL); return 0; } @@ -1625,6 +1619,7 @@ static int mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) { struct queue_item *items; + uint32_t item_id; int ret; if (argc < 2) @@ -1652,20 +1647,11 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) } - player_queue_add(items); + player_queue_add(items, &item_id); - //TODO [queue] Get queue-item-id for mpd-command addid evbuffer_add_printf(evbuf, - "addid: %s\n" "Id: %d\n", - argv[1], - 0); //ps->id); - - ret = player_playback_start(NULL); - if (ret < 0) - { - DPRINTF(E_LOG, L_MPD, "Could not start playback\n"); - } + item_id); return 0; } @@ -2362,13 +2348,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) return ACK_ERROR_UNKNOWN; } - player_queue_add(items); - - ret = player_playback_start(NULL); - if (ret < 0) - { - DPRINTF(E_LOG, L_MPD, "Could not start playback\n"); - } + player_queue_add(items, NULL); return 0; } @@ -2628,13 +2608,7 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg return ACK_ERROR_UNKNOWN; } - player_queue_add(items); - - ret = player_playback_start(NULL); - if (ret < 0) - { - DPRINTF(E_LOG, L_MPD, "Could not start playback\n"); - } + player_queue_add(items, NULL); return 0; } @@ -3263,13 +3237,7 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm return ACK_ERROR_UNKNOWN; } - player_queue_add(items); - - ret = player_playback_start(NULL); - if (ret < 0) - { - DPRINTF(E_LOG, L_MPD, "Could not start playback\n"); - } + player_queue_add(items, NULL); return 0; } diff --git a/src/player.c b/src/player.c index 17bb5e20..5de52db4 100644 --- a/src/player.c +++ b/src/player.c @@ -165,6 +165,8 @@ struct playerqueue_add_param { struct queue_item *items; int pos; + + uint32_t *item_id_ptr; }; struct playerqueue_move_param @@ -242,6 +244,9 @@ static struct event *exitev; static struct event *cmdev; static pthread_t tid_player; +/* Config values */ +static int clear_queue_on_stop_disabled; + /* Player status */ static enum play_status player_state; static enum repeat_mode repeat; @@ -2165,10 +2170,11 @@ playback_abort(void) source_stop(); - playerqueue_clear(NULL); - evbuffer_drain(audio_buf, evbuffer_get_length(audio_buf)); + if (!clear_queue_on_stop_disabled) + playerqueue_clear(NULL); + status_update(PLAY_STOPPED); metadata_purge(); @@ -2196,6 +2202,7 @@ get_status(struct player_command *cmd) status->plid = cur_plid; status->plversion = cur_plversion; + status->playlistlength = queue_count(queue); switch (player_state) { @@ -2273,7 +2280,6 @@ get_status(struct player_command *cmd) status->next_pos_pl = 0; } - status->playlistlength = queue_count(queue); break; } @@ -3376,8 +3382,10 @@ playerqueue_add(struct player_command *cmd) { struct queue_item *items; uint32_t cur_id; + uint32_t *item_id; items = cmd->arg.queue_add_param.items; + item_id = cmd->arg.queue_add_param.item_id_ptr; queue_add(queue, items); @@ -3387,6 +3395,9 @@ playerqueue_add(struct player_command *cmd) queue_shuffle(queue, cur_id); } + if (item_id) + *item_id = queueitem_item_id(items); + cur_plid = 0; cur_plversion++; @@ -3422,6 +3433,7 @@ static int playerqueue_move_bypos(struct player_command *cmd) { struct player_source *ps_playing; + uint32_t item_id; DPRINTF(E_DBG, L_PLAYER, "Moving song from position %d to be the next song after %d\n", cmd->arg.queue_move_param.from_pos, cmd->arg.queue_move_param.to_pos); @@ -3430,11 +3442,13 @@ playerqueue_move_bypos(struct player_command *cmd) if (!ps_playing) { - DPRINTF(E_LOG, L_PLAYER, "Can't move item, no playing item found\n"); - return -1; + DPRINTF(E_DBG, L_PLAYER, "No playing item found for move by pos\n"); + item_id = 0; } + else + item_id = ps_playing->item_id; - queue_move_bypos(queue, ps_playing->item_id, cmd->arg.queue_move_param.from_pos, cmd->arg.queue_move_param.to_pos, shuffle); + queue_move_bypos(queue, item_id, cmd->arg.queue_move_param.from_pos, cmd->arg.queue_move_param.to_pos, shuffle); cur_plversion++; @@ -3478,6 +3492,7 @@ playerqueue_remove_bypos(struct player_command *cmd) { int pos; struct player_source *ps_playing; + uint32_t item_id; pos = cmd->arg.intval; if (pos < 1) @@ -3490,12 +3505,14 @@ playerqueue_remove_bypos(struct player_command *cmd) if (!ps_playing) { - DPRINTF(E_LOG, L_PLAYER, "Can't remove item at pos %d, no playing item found\n", pos); - return -1; + DPRINTF(E_DBG, L_PLAYER, "No playing item for remove by pos\n"); + item_id = 0; } + else + item_id = ps_playing->item_id; DPRINTF(E_DBG, L_PLAYER, "Removing item from position %d\n", pos); - queue_remove_bypos(queue, ps_playing->item_id, pos, shuffle); + queue_remove_bypos(queue, item_id, pos, shuffle); cur_plversion++; @@ -4209,7 +4226,7 @@ player_queue_get_byindex(int index, int count) * Appends the given media items to the queue */ int -player_queue_add(struct queue_item *items) +player_queue_add(struct queue_item *items, uint32_t *item_id) { struct player_command cmd; int ret; @@ -4219,6 +4236,7 @@ player_queue_add(struct queue_item *items) cmd.func = playerqueue_add; cmd.func_bh = NULL; cmd.arg.queue_add_param.items = items; + cmd.arg.queue_add_param.item_id_ptr = item_id; ret = sync_command(&cmd); @@ -4576,6 +4594,8 @@ player_init(void) player_exit = 0; + clear_queue_on_stop_disabled = cfg_getbool(cfg_getsec(cfg, "mpd"), "clear_queue_on_stop_disable"); + dev_autoselect = 1; dev_list = NULL; diff --git a/src/player.h b/src/player.h index 1383a583..eef8d5b9 100644 --- a/src/player.h +++ b/src/player.h @@ -161,7 +161,7 @@ struct queue * player_queue_get_byindex(int pos, int count); int -player_queue_add(struct queue_item *items); +player_queue_add(struct queue_item *items, uint32_t *item_id); int player_queue_add_next(struct queue_item *items); diff --git a/src/queue.c b/src/queue.c index 136b2941..b6b4ad8a 100644 --- a/src/queue.c +++ b/src/queue.c @@ -336,7 +336,7 @@ queueitem_get_bypos(struct queue *queue, unsigned int item_id, unsigned int pos, return NULL; i = 0; - for (item = item_base; item != queue->head && i < pos; item = item_next(item, shuffle)) + for (item = item_base; i < pos; item = item_next(item, shuffle)) { i++; }