diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h index c685230874d05f8d158d6faf8ae724ebbc32b643..47c35a2ddf59df519dd468a6fa0096e1a5f2306f 100644 --- a/inc/lektor/commands.h +++ b/inc/lektor/commands.h @@ -3,6 +3,7 @@ #include <common/common.h> #include <lektor/net.h> #include <lektor/window.h> +#include <lektor/database.h> #include <stdbool.h> @@ -38,7 +39,6 @@ bool command_shuffle(volatile sqlite3 *db, bool command_playid (volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr); bool command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX]); -bool command_queue_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation); /* The playlists */ bool command_plt_create(volatile sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr); @@ -68,7 +68,8 @@ enum lkt_find_action { }; /* Find and send karas in the db that match the search expression */ -bool command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation, enum lkt_find_action action); +bool command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation, + enum lkt_find_action action, bool (*init)(volatile sqlite3 *, char *, char *, struct lkt_search *)); /* Set options for the lektor such as `random`, `single`, `repeat`, etc */ enum lkt_playback_option { diff --git a/src/commands.c b/src/commands.c index 387b7ecebf56796ffd7791db884477f8d16fb040..241e7c5ac1b69489eecd46a1efac7e6376e851c1 100644 --- a/src/commands.c +++ b/src/commands.c @@ -392,13 +392,14 @@ lkt_callback_send_row_v2(struct lkt_state *srv, size_t c, int id, int id_len, co return true; } -static bool -__find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation, +bool +command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation, enum lkt_find_action action, bool(*init)(volatile sqlite3 *, char *, char *, struct lkt_search *)) { char rgx[PATH_MAX], *col_name, *mpd_tag; int count; struct lkt_uri uri; + struct lkt_queue_state queue; struct lkt_search search = { .srv = srv, .c = c, @@ -409,11 +410,9 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo }; /* Check args */ - RETURN_UNLESS(cmd_args && cmd_args[0], "Invalid argument", false); /* Select callback */ - switch (action) { case LKT_FND_ACT_RESPOND: search.call = (void(*)(void)) lkt_callback_send_row_v2; @@ -422,12 +421,22 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo search.call = NULL; break; case LKT_FND_ACT_ENQUEUE: + if (!continuation) { + /* Begin */ + RETURN_UNLESS(database_queue_state(srv->db, &queue), "Failed to get the status of the queue", false); + search.continuation = queue.current + 1; + } search.call = (void(*)(void)) lkt_callback_send_row_v2; search.init = (void(*)(void)) database_queue_add_uri; search.qu_priority = 5; srv->mpd_idle_events |= MPD_IDLE_PLAYLIST; break; case LKT_FND_ACT_ADD: + if (!continuation) { + /* Begin */ + RETURN_UNLESS(database_queue_state(srv->db, &queue), "Failed to get the status of the queue", false); + search.continuation = queue.current + 1; + } search.call = (void(*)(void)) lkt_callback_send_row_v2; search.init = (void(*)(void)) database_queue_add_uri; search.qu_priority = 1; @@ -438,7 +447,6 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo } /* Select the right column */ - mpd_tag = cmd_args[0]; if (!strcasecmp("any", mpd_tag) || !strcasecmp("all", mpd_tag) || !strcasecmp("query", mpd_tag) || !strcasecmp("source", mpd_tag) || !strcasecmp("title", mpd_tag)) { @@ -463,7 +471,6 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo return false; /* Get the regex */ - RETURN_UNLESS(cmd_args[1], "No regex", false); memset(rgx, 0, PATH_MAX * sizeof(char)); @@ -475,7 +482,6 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo uri.value = rgx; /* Make the search langand do the right action */ - RETURN_UNLESS(init(srv->db, col_name, rgx, &search), "Failed to init search", false); for (count = 0; database_search_iter(&search); ++count) @@ -487,19 +493,6 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo return true; } -bool -command_queue_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation) -{ - return __find(srv, c, cmd_args, continuation, LKT_FND_ACT_RESPOND, database_search_queue_init); -} - -bool -command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation, - enum lkt_find_action action) -{ - return __find(srv, c, cmd_args, continuation, action, database_search_database_init); -} - bool command_set_playback_option(struct lkt_state *srv, size_t c, enum lkt_playback_option opt, char *args[LKT_MESSAGE_MAX]) @@ -693,7 +686,7 @@ command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_ /* Convert the first integer. */ STRTOL(val, args[0], endptr, err); - RETURN_IF(err, "STRTOL failed", false); + RETURN_IF(err, "STRTOL failed (from)", false); from = labs(val); /* There is nothing after, is is the song pos version. */ @@ -703,9 +696,9 @@ command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_ /* There is something after, this is the absolute forme of the command. Then parse the second value. Skip the supposed ':' character. */ else { - str = endptr; + str = endptr + strspn(endptr, "-+: "); STRTOL(val, str, endptr, err); - RETURN_IF(err, "STRTOL failed", false); + RETURN_IF(err, "STRTOL failed (to)", false); to = labs(val); if (to < from) { diff --git a/src/net/listen.c b/src/net/listen.c index 1d842149aa773ad54723c3a4f25bdf5a62c17c90..f12e12f4fb2137367955e2ba557e0a06d7894202 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -197,7 +197,7 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) else if (!strcmp(cmd.name, "playlist") || !strcmp(cmd.name, "playlistinfo")) err = !command_queue_list(srv, c, cmd.args); else if (!strcmp(cmd.name, "playlistfind") || !strcmp(cmd.name, "playlistsearch")) - err = ! command_queue_find(srv, c, cmd.args, cmd.cont); + err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_RESPOND, database_search_queue_init); else if (!strcmp(cmd.name, "sticker") && cmd.args[0]) { if (!strcmp(cmd.args[0], "get")) @@ -254,11 +254,11 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) err = !command_idle(srv, c, &cmd); goto end_no_send_status; } else if (!strcmp(cmd.name, "search") || !strcmp(cmd.name, "find")) - err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_RESPOND); + err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_RESPOND, database_search_database_init); else if (!strcmp(cmd.name, "searchadd") || !strcmp(cmd.name, "findadd")) - err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_ADD); + err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_ADD, database_search_queue_init); else if (!strcmp(cmd.name, "__insert")) - err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_ENQUEUE); + err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_ENQUEUE, database_search_queue_init); else err = 2; @@ -389,7 +389,7 @@ handle_outgoing_data(struct lkt_state *srv, size_t c) for (size_t i = 0; i < cli->buffer_out_len; i++) { struct lkt_message *msg = cli->buffer_out[i]; - int n = send(srv->fds[c].fd, msg->data, msg->data_len, 0); + int n = send(srv->fds[c].fd, msg->data, msg->data_len, MSG_NOSIGNAL); if (n <= 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) { cli->buffer_out_len -= i; @@ -397,6 +397,8 @@ handle_outgoing_data(struct lkt_state *srv, size_t c) cli->buffer_out_len); return 0; } + if (errno == EPIPE) + handle_disconnected_client(srv, i); return -1; }