From 1c409846d536640c61ad4b002bdcbdd1d557782a Mon Sep 17 00:00:00 2001 From: chme Date: Fri, 30 Oct 2015 07:11:34 +0100 Subject: [PATCH 1/3] [player/queue] Add player commands to move queue-items by item-id --- src/player.c | 55 +++++++++++++++++++++++++++++++---- src/player.h | 3 ++ src/queue.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/queue.h | 3 ++ 4 files changed, 131 insertions(+), 12 deletions(-) diff --git a/src/player.c b/src/player.c index 8f4e6072..71c0933a 100644 --- a/src/player.c +++ b/src/player.c @@ -159,6 +159,14 @@ struct playerqueue_add_param int pos; }; +struct playerqueue_move_param +{ + uint32_t item_id; + int from_pos; + int to_pos; + int count; +}; + struct icy_artwork { uint32_t id; @@ -198,11 +206,11 @@ struct player_command enum repeat_mode mode; uint32_t id; int intval; - int ps_pos[2]; struct icy_artwork icy; struct playback_start_param playback_start_param; struct playerqueue_get_param queue_get_param; struct playerqueue_add_param queue_add_param; + struct playerqueue_move_param queue_move_param; } arg; int ret; @@ -3405,8 +3413,8 @@ playerqueue_move_bypos(struct player_command *cmd) { struct player_source *ps_playing; - DPRINTF(E_DBG, L_PLAYER, "Moving song from position %d to be the next song after %d\n", cmd->arg.ps_pos[0], - cmd->arg.ps_pos[1]); + 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); ps_playing = source_now_playing(); @@ -3416,7 +3424,22 @@ playerqueue_move_bypos(struct player_command *cmd) return -1; } - queue_move_bypos(queue, ps_playing->item_id, cmd->arg.ps_pos[0], cmd->arg.ps_pos[1], shuffle); + queue_move_bypos(queue, ps_playing->item_id, cmd->arg.queue_move_param.from_pos, cmd->arg.queue_move_param.to_pos, shuffle); + + cur_plversion++; + + listener_notify(LISTENER_PLAYLIST); + + return 0; +} + +static int +playerqueue_move_byitemid(struct player_command *cmd) +{ + DPRINTF(E_DBG, L_PLAYER, "Moving song with item-id %d to be the next song after index %d\n", + cmd->arg.queue_move_param.item_id, cmd->arg.queue_move_param.to_pos); + + queue_move_byitemid(queue, cmd->arg.queue_move_param.item_id, cmd->arg.queue_move_param.to_pos, 0); cur_plversion++; @@ -4187,8 +4210,28 @@ player_queue_move_bypos(int pos_from, int pos_to) cmd.func = playerqueue_move_bypos; cmd.func_bh = NULL; - cmd.arg.ps_pos[0] = pos_from; - cmd.arg.ps_pos[1] = pos_to; + cmd.arg.queue_move_param.from_pos = pos_from; + cmd.arg.queue_move_param.to_pos = pos_to; + + ret = sync_command(&cmd); + + command_deinit(&cmd); + + return ret; +} + +int +player_queue_move_byitemid(uint32_t item_id, int pos_to) +{ + struct player_command cmd; + int ret; + + command_init(&cmd); + + cmd.func = playerqueue_move_byitemid; + cmd.func_bh = NULL; + cmd.arg.queue_move_param.item_id = item_id; + cmd.arg.queue_move_param.to_pos = pos_to; ret = sync_command(&cmd); diff --git a/src/player.h b/src/player.h index 1ed00e0f..2ec83cb3 100644 --- a/src/player.h +++ b/src/player.h @@ -169,6 +169,9 @@ player_queue_add_next(struct queue_item *items); int player_queue_move_bypos(int ps_pos_from, int ps_pos_to); +int +player_queue_move_byitemid(uint32_t item_id, int pos_to); + int player_queue_remove_bypos(int pos); diff --git a/src/queue.c b/src/queue.c index cca6468d..c3cbef62 100644 --- a/src/queue.c +++ b/src/queue.c @@ -725,7 +725,7 @@ queue_move_bypos(struct queue *queue, unsigned int item_id, unsigned int from_po } // Get the item at the target position - item_next = queueitem_get_bypos(queue, item_id, to_offset, shuffle); + item_next = queueitem_get_bypos(queue, item_id, (to_offset + 1), shuffle); if (!item_next) { DPRINTF(E_LOG, L_PLAYER, "Invalid position given to move items\n"); @@ -744,7 +744,7 @@ queue_move_bypos(struct queue *queue, unsigned int item_id, unsigned int from_po item->next->prev = item->prev; } - // Insert item into the queue befor the item at the target postion + // Insert item into the queue before the item at the target postion if (shuffle) { item_next->shuffle_prev->shuffle_next = item; @@ -755,11 +755,81 @@ queue_move_bypos(struct queue *queue, unsigned int item_id, unsigned int from_po } else { - item_next->next->prev = item; - item->next = item_next->next; + item_next->prev->next = item; + item->prev = item_next->prev; - item_next->next = item; - item->prev = item_next; + item_next->prev = item; + item->next = item_next; + } +} + +/* + * Moves the item with the given item-id to the index to_pos in the play-queue (shuffle = 0) + * or shuffle-queue (shuffle = 1) + * + * @param queue The queue to move item + * @param item_id The item-id of the to be moved + * @param to_pos The index to move the item + * @param shuffle If 0 the position in the play-queue, 1 the position in the shuffle-queue + */ +void +queue_move_byitemid(struct queue *queue, unsigned int item_id, unsigned int to_pos, char shuffle) +{ + struct queue_item *item; + struct queue_item *item_next; + int index; + + // Get the item to be moved + item = queueitem_get_byitemid(queue, item_id); + if (!item) + { + DPRINTF(E_LOG, L_PLAYER, "Item with item-id %d does not exist in the queue\n", item_id); + return; + } + + // Check if the index of the item to move is lower than the target index + // If that is the case, increment the target position, because the given to_pos + // is based on the queue without the moved item. + index = queue_index_byitemid(queue, item_id, shuffle); + if (index < to_pos) + to_pos++; + + // Get the item at the target position + item_next = queueitem_get_byindex(queue, to_pos, shuffle); + if (!item_next) + { + DPRINTF(E_LOG, L_PLAYER, "Invalid position given to move items\n"); + return; + } + + // Remove item from the queue + if (shuffle) + { + item->shuffle_prev->shuffle_next = item->shuffle_next; + item->shuffle_next->shuffle_prev = item->shuffle_prev; + } + else + { + item->prev->next = item->next; + item->next->prev = item->prev; + } + + // Insert item into the queue before the item at the target postion + if (shuffle) + { + item_next->shuffle_prev->shuffle_next = item; + item->shuffle_prev = item_next->shuffle_prev; + + item_next->shuffle_prev = item; + item->shuffle_next = item_next; + } + else + { + item_next->prev->next = item; + item->prev = item_next->prev; + + item_next->prev = item; + item->next = item_next; } } diff --git a/src/queue.h b/src/queue.h index d5b0aacc..90aa66c4 100644 --- a/src/queue.h +++ b/src/queue.h @@ -83,6 +83,9 @@ queue_add_after(struct queue *queue, struct queue_item *item, unsigned int item_ void queue_move_bypos(struct queue *queue, unsigned int item_id, unsigned int from_pos, unsigned int to_offset, char shuffle); +void +queue_move_byitemid(struct queue *queue, unsigned int item_id, unsigned int to_pos, char shuffle); + void queue_remove_byitemid(struct queue *queue, unsigned int item_id); From f9c6aa6c48231fb12bc28f1163309016437840b0 Mon Sep 17 00:00:00 2001 From: chme Date: Fri, 30 Oct 2015 07:12:00 +0100 Subject: [PATCH 2/3] [mpd] Implement command moveid (movings items in the queue by item-id) --- src/mpd.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/src/mpd.c b/src/mpd.c index d68dc0b4..edec3598 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -1748,6 +1748,57 @@ mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errms return 0; } +static int +mpd_command_move(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) +{ + return 0; +} + +static int +mpd_command_moveid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) +{ + uint32_t songid; + uint32_t to_pos; + int ret; + + if (argc < 3) + { + ret = asprintf(errmsg, "Missing argument for command 'moveid'"); + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_ARG; + } + + ret = safe_atou32(argv[1], &songid); + if (ret < 0) + { + ret = asprintf(errmsg, "Argument doesn't convert to integer: '%s'", argv[1]); + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_ARG; + } + + ret = safe_atou32(argv[2], &to_pos); + if (ret < 0) + { + ret = asprintf(errmsg, "Argument doesn't convert to integer: '%s'", argv[2]); + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_ARG; + } + + ret = player_queue_move_byitemid(songid, to_pos); + if (ret < 0) + { + ret = asprintf(errmsg, "Failed to move song with id '%s' to index '%s'", argv[1], argv[2]); + if (ret < 0) + DPRINTF(E_LOG, L_MPD, "Out of memory\n"); + return ACK_ERROR_UNKNOWN; + } + + return 0; +} + /* * Command handler function for 'playlistid' * Displays a list of all songs in the queue, or if the optional argument is given, displays information @@ -3561,7 +3612,6 @@ static struct command mpd_handlers[] = .mpdcommand = "deleteid", .handler = mpd_command_deleteid }, - /* { .mpdcommand = "move", .handler = mpd_command_move @@ -3570,7 +3620,6 @@ static struct command mpd_handlers[] = .mpdcommand = "moveid", .handler = mpd_command_moveid }, - */ // According to the mpd protocol the use of "playlist" is deprecated { .mpdcommand = "playlist", From ba63157429809da802e5dc86e5a0744b881605bd Mon Sep 17 00:00:00 2001 From: chme Date: Fri, 30 Oct 2015 07:47:14 +0100 Subject: [PATCH 3/3] [mpd] Add 'close' command (ignore the command and does not send a response) --- src/mpd.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mpd.c b/src/mpd.c index edec3598..4336595f 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -3839,11 +3839,11 @@ static struct command mpd_handlers[] = /* * Connection settings */ - /* { .mpdcommand = "close", - .handler = mpd_command_close + .handler = mpd_command_ignore }, + /* { .mpdcommand = "kill", .handler = mpd_command_kill @@ -3998,6 +3998,7 @@ mpd_read_cb(struct bufferevent *bev, void *ctx) struct command *command; enum command_list_type listtype; int idle_cmd; + int close_cmd; char *argv[COMMAND_ARGV_MAX]; int argc; @@ -4009,6 +4010,7 @@ mpd_read_cb(struct bufferevent *bev, void *ctx) DPRINTF(E_SPAM, L_MPD, "Received MPD command sequence\n"); idle_cmd = 0; + close_cmd = 0; listtype = COMMAND_LIST_NONE; ncmd = 0; @@ -4057,6 +4059,8 @@ mpd_read_cb(struct bufferevent *bev, void *ctx) idle_cmd = 1; else if (0 == strcmp(argv[0], "noidle")) idle_cmd = 0; + else if (0 == strcmp(argv[0], "close")) + close_cmd = 1; /* * Find the command handler and execute the command function @@ -4104,7 +4108,7 @@ mpd_read_cb(struct bufferevent *bev, void *ctx) * If everything was successful add OK line to signal clients end of message. * If an error occured the necessary ACK line should already be added to the response buffer. */ - if (ret == 0 && idle_cmd == 0) + if (ret == 0 && idle_cmd == 0 && close_cmd == 0) { evbuffer_add(output, "OK\n", 3); }