diff --git a/doc/footer b/doc/footer
index 505654ab7b32158c1bb022e91b6a5b4b52ce3034..ec6a4acee7b6427a7f400e4ac2b6dad4d42fc3cc 100644
--- a/doc/footer
+++ b/doc/footer
@@ -1,23 +1,3 @@
-.SH "AUTHOR AND AVAILABILITY"
-Lektor is a karaoke player for POSIX compliant systems (i.e. not MS-Windows)
-writen initially in C. Some may call it Lektor mk 7. It was writen by Hubert
-\'Taiite' HIRTZ, Maël 'Kubat' MARTIN and Louis 'Elliu' GOYARD. These people
-also helped: Loïc 'Sting' ALLÈGRE and Etienne 'Pelle' BRATEAU.
-.PP
-The up\-to\-date source code is available via Git from Gitlab\&. See
-\fBhttps://git\&.iiens\&.net/martin2018/lektor\fP. The source code is
-provided under the \fIISC\fP licence.
-.fi
-.SH "RELATED SITES AND THE LEKTOR FAQ"
-Just see one of the dev from lektor or a bakateux if you have some questions
-about lektor.
-.PP
-.PD 0
-.TP
-\fBhttps://kurisu.iiens.net\fP  The depo site for the karaoke base
-.TP
-\fBhttps://manga.iiens.net\fP   The home website for the Bakaclub
-.PD
 .SH "FILES"
 .PD 0
 .TP
diff --git a/doc/lektor.1 b/doc/lektor.1
index d10932c648eb3379ddb799c7e99cd0be201126dc..8bfa28950ddd1977c257ee23b8ce28b43bca02d4 100644
--- a/doc/lektor.1
+++ b/doc/lektor.1
@@ -84,13 +84,37 @@ the \fBarg\fP should be the author of the kara
 the \fBarg\fP should be a sqlite3 query. The formating string on which the query
 is applied is like \fB"${cat}/${source} - ${type}${song_num?} - ${title}"\fP.
 You usually want to do this.
-.PP
+
 .SH "SUPPORTED LANGUAGES"
 The supported languages in lektor are: \fBjp\fP, \fBfr\fP, \fBsp\fP, \fBen\fP,
 \fBlatin\fP, \fBit\fP, \fBru\fP, \fBmulti\fP and \fBundefined\fP.
+
 .SH "SUPPORTED TYPES"
 The supported types in lektor are: \fBOP\fP, \fBED\fP, \fBIS\fP, \fBAMV\fP,
 \fBVOCA\fP, \fBMV\fP, \fBPV\fP and \fBLIVE\fP.
+
 .SH "SUPPORTED CATEGORIES"
 The supported categories in lektor are: \fBvo\fP, \fBva\fP, \fBcdg\fP,
 \fBamv\fP, \fBvocaloid\fP and \fBautres\fP.
+
+.SH "AUTHOR AND AVAILABILITY"
+Lektor is a karaoke player for POSIX compliant systems (i.e. not MS-Windows)
+writen initially in C. Some may call it Lektor mk 7. It was writen by Hubert
+\'Taiite' HIRTZ, Maël 'Kubat' MARTIN and Louis 'Elliu' GOYARD. These people
+also helped: Loïc 'Sting' ALLÈGRE and Etienne 'Pelle' BRATEAU.
+.PP
+The up\-to\-date source code is available via Git from Gitlab\&. See
+\fBhttps://git\&.iiens\&.net/martin2018/lektor\fP. The source code is
+provided under the \fIISC\fP licence.
+.fi
+
+.SH "RELATED SITES AND THE LEKTOR FAQ"
+Just see one of the dev from lektor or a bakateux if you have some questions
+about lektor.
+.PP
+.PD 0
+.TP
+\fBhttps://kurisu.iiens.net\fP  The depo site for the karaoke base
+.TP
+\fBhttps://manga.iiens.net\fP   The home website for the Bakaclub
+.PD
diff --git a/doc/lkt.1 b/doc/lkt.1
index 153952886d9b2be3df10003ebaae9e221a8f783f..d1ce04e5380170d681ef25c6670d445a445a2354 100644
--- a/doc/lkt.1
+++ b/doc/lkt.1
@@ -92,6 +92,9 @@ This can work only if the currently playong kara is not the last
 \fBqueue add\fP <query>
 Add karas to the queue at the end of it with a valid query
 .TP
+\fBqueue insert\fP <query>
+Add karas to the queue just after the currently playing kara
+.TP
 \fBqueue seek\fP <id>
 Goto to the kara with the specified id in the queue
 .TP
@@ -115,12 +118,6 @@ playing one
 \fBsearch get\fP <query>
 Search and prints the kara that correspond to the query in the database
 .TP
-\fBsearch add\fP <query>
-Search, prints and add to the queue the karas that match the query
-.TP
-\fBsearch insert\fP <query>
-Search, prints and insert into the queue the karas that match the query
-.TP
 \fBsearch plt\fP <plt-name> <query>
 Search, prints and add to an existing playlist the karas that match
 the query
diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h
index c685230874d05f8d158d6faf8ae724ebbc32b643..ba3cb7af0435577c45810c65413a68aaa5db95e2 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>
 
@@ -27,7 +28,7 @@ bool command_stop    (volatile sqlite3 *db, struct lkt_win *win,
 bool command_set_pos(volatile sqlite3 *db, struct lkt_win *win, mpd_idle_flag *watch_mask_ptr, int index);
 
 /* The queue */
-bool command_add    (volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr);
+bool command_add    (volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr, int priority);
 bool command_addid  (volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr);
 bool command_del    (volatile sqlite3 *db, struct lkt_win *win, char *pos_range,                  mpd_idle_flag *watch_mask_ptr);
 bool command_delid  (volatile sqlite3 *db, struct lkt_win *win, char *id,                         mpd_idle_flag *watch_mask_ptr);
@@ -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);
@@ -58,17 +58,9 @@ bool command_idle(struct lkt_state *srv, size_t c, struct lkt_command *cmd);
 /* Cancel the call to the `idle` command. */
 bool command_noidle(struct lkt_state *srv, size_t c);
 
-/* Find commands */
-enum lkt_find_action {
-    LKT_FND_ACT_NONE    = 0,
-    LKT_FND_ACT_RESPOND = 1,
-    LKT_FND_ACT_PRINT   = 2,
-    LKT_FND_ACT_ENQUEUE = 3,
-    LKT_FND_ACT_ADD     = 4,
-};
-
 /* 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,
+                  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/inc/lektor/database.h b/inc/lektor/database.h
index 7494f9a21e70a520a8182a5e5fbafb017088cf79..4da2d086ac7ee9ca666078a5a341594198ef4f21 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -50,14 +50,7 @@ bool database_update_add          (volatile sqlite3 *db, const char *kara_path,
 bool database_update_set_available(volatile sqlite3 *db, uint64_t id);
 
 /* Control the content of the queue. */
-bool database_queue_add_id      (volatile sqlite3 *db, int id,               int priority);
-bool database_queue_add_query   (volatile sqlite3 *db, const char *query,    int priority);
-bool database_queue_add_author  (volatile sqlite3 *db, const char *author,   int priority);
-bool database_queue_add_language(volatile sqlite3 *db, const char *author,   int priority);
-bool database_queue_add_category(volatile sqlite3 *db, const char *author,   int priority);
-bool database_queue_add_type    (volatile sqlite3 *db, const char *author,   int priority);
-bool database_queue_add_plt     (volatile sqlite3 *db, const char *plt_name, int priority);
-
+bool database_queue_add_uri(volatile sqlite3 *db, struct lkt_uri *uri, int priority);
 bool database_queue_del_id (volatile sqlite3 *db, int id);
 bool database_queue_del_pos(volatile sqlite3 *db, int pos);
 bool database_queue_clear  (volatile sqlite3 *db);
@@ -73,7 +66,7 @@ bool database_queue_stop        (volatile sqlite3 *db);
 
 /* A search callback to be called after each matched row */
 struct lkt_callback {
-    bool (*call)(void *args, int id, int id_len, const char *sql_row);
+    bool (*call)(void *args, int pos, int pos_len, int id, int id_len, const char *sql_row);
     struct lkt_state *srv;
     size_t c;
     int iterations;
@@ -90,19 +83,29 @@ struct lkt_search {
         lkt_search_database,
         lkt_search_playlist,
         lkt_search_queue,
+        lkt_search_sticker,
     } type;
-    void (*call)(void); /* Will be casted. */
+
+    void (*call)(void);     /* Called during the iter phase, casted         */
+
     struct lkt_state *srv;
     size_t c;
-    long continuation;  /* Is this a continuation from a previous command? */
-    int msg_count;      /* How much messages we can send. */
+
+    long continuation;      /* The continuation state of the client         */
+    int msg_count;          /* How much messages we can send                */
+    const char *name;       /* Stickers and playlists                       */
+    int st_value;           /* The value of a sticker                       */
+    int st_uri;             /* URI of a sticker                             */
 };
 
-typedef bool (*lkt_search_database_func)(struct lkt_state *srv, size_t c, int id, int id_len,
-        const char *row);
+typedef bool (*lkt_search_init_add_func)(volatile sqlite3 *, struct lkt_uri *, int);
+typedef bool (*lkt_search_database_func)(struct lkt_state *srv, size_t c, int id, int id_len, const char *row);
+typedef bool (*lkt_search_queue_func)   (struct lkt_state *srv, size_t c, int id, int id_len, const char *row);
+typedef bool (*lkt_search_sticker_func) (struct lkt_state *srv, size_t c, const char *sticker, const char *type, int uri, int value);
 
-bool database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
-bool database_search_queue_init   (volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
+bool database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx,  struct lkt_search *ret);
+bool database_search_queue_init   (volatile sqlite3 *db, char *col_name, char *rgx,  struct lkt_search *ret);
+bool database_search_sticker_init (volatile sqlite3 *db, char *type,     char *name, struct lkt_search *ret);
 bool database_search_iter(struct lkt_search *item);
 
 /* Next and prev operation on the queue. */
diff --git a/src/commands.c b/src/commands.c
index bd3dea5d37f13c8c75cf0b095385e4e1a174d4a9..4e2b1a5b585ca60cc51a95184d2eca6f70f1671a 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -177,18 +177,16 @@ bool
 command_play(volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr)
 {
     *watch_mask_ptr |= MPD_IDLE_PLAYER;
-    char *endptr;
-    long pos = 0;
+    char *endptr, err;
+    long pos = 1;
 
     /* Argument handle. */
-
-    pos = args[0] == NULL ? 1 : strtol(args[0], &endptr, 10);
-    RETURN_IF((errno == ERANGE && (pos == LONG_MAX || pos == LONG_MIN)) || (errno != 0 && pos == 0),
-              "Failed: strtol", false);
-    RETURN_IF(endptr == args[0], "No digit found", false);
+    if (args[0]) {
+        STRTOL(pos, args[0], endptr, err);
+        RETURN_IF(err, "STRTOL failed", false);
+    }
 
     /* Do the actual job here. */
-
     database_queue_stop(db);
     RETURN_UNLESS(win->new (win), "Can't create window", false);
     return __play_that_file(db, win, pos);
@@ -198,20 +196,16 @@ bool
 command_playid(volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr)
 {
     *watch_mask_ptr |= MPD_IDLE_PLAYER;
-    char *endptr;
+    char *endptr, err;
     int pos = 0;
     long id;
 
     /* Argument handle. */
-
     RETURN_IF(args[0] == NULL, "Invalid argument", false);
-    id = strtol(args[0], &endptr, 10);
-    RETURN_IF((errno == ERANGE && (id == LONG_MAX || id == LONG_MIN)) || (errno != 0 && id == 0),
-              "Failed: strtol", false);
-    RETURN_IF(endptr == args[0], "No digit found", false);
+    STRTOL(id, args[0], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
 
     /* Do the work. */
-
     database_queue_stop(db);
     RETURN_UNLESS(win->new (win), "Can't create window", false);
     database_queue_seekid(db, (int) id, &pos);
@@ -229,45 +223,19 @@ command_stop(volatile sqlite3 *db, struct lkt_win *win, mpd_idle_flag *watch_mas
 }
 
 bool
-command_add(volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr)
+command_add(volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr, int priority)
 {
     RETURN_UNLESS(args, "Invalid argument", false);
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
     struct lkt_uri uri;
     char *query = args[0];
-    int ret, priority = 1;  /* To be modified according to the command (insert or add) later (TODO) */
-    UNUSED(win);            /* No callbacks to the window for the moment */
+    int ret;        /* To be modified according to the command (insert or add) later (TODO) */
+    UNUSED(win);    /* No callbacks to the window for the moment */
     RETURN_UNLESS(lkt_uri_from(&uri, query), "Failed to parse query", false);
-
-    switch (uri.type) {
-    case uri_query:
-    case uri_fs:
-        ret = database_queue_add_query(db, uri.value, priority);
-        break;
-    case uri_id:
-        ret = database_queue_add_id(db, *(int *) uri.value, priority);
-        break;
-    case uri_type:
-        ret = database_queue_add_type(db, (char *) uri.value, priority);
-        break;
-    case uri_category:
-        ret = database_queue_add_category(db, (char *) uri.value, priority);
-        break;
-    case uri_language:
-        ret = database_queue_add_language(db, (char *) uri.value, priority);
-        break;
-    case uri_author:
-        ret = database_queue_add_author(db, (char *) uri.value, priority);
-        break;
-    case uri_playlist:
-        ret = database_queue_add_plt(db, (char *) uri.value, priority);
-        break;
-    default:
-        ret = false;
-        break;
-    }
-
+    ret = database_queue_add_uri(db, &uri, priority);
     lkt_uri_free(&uri);
+    if (!ret)
+        LOG_ERROR_SCT("COMMAND", "Failed to add with priority %d in queue", priority);
     return ret;
 }
 
@@ -275,19 +243,15 @@ bool
 command_addid(volatile sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr)
 {
     UNUSED(win);
-    long id;
-    char *endptr, *id_str;
-    int priority = 1;
-
     RETURN_UNLESS(args, "Invalid argument", false);
-    id_str = args[0];
-    errno = 0;
+    long id;
+    char *endptr = NULL, err = 0;
+    struct lkt_uri uri = { .type = uri_id };
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
-    id = strtol(id_str, &endptr, 10);
-    RETURN_IF((errno == ERANGE && (id == LONG_MAX || id == LONG_MIN)) || (errno != 0 && id == 0),
-              "Failed: strtol", false);
-    RETURN_IF(endptr == args[0], "No digit found", false);
-    return database_queue_add_id(db, id, priority);
+    STRTOL(id, args[0], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
+    uri.value = (void *) (size_t) id;
+    return database_queue_add_uri(db, &uri, 1);
 }
 
 inline bool
@@ -309,15 +273,12 @@ command_delid(volatile sqlite3 *db, struct lkt_win *win, char *id_str, mpd_idle_
 {
     UNUSED(win);
     long id;
-    char *endptr;
+    char *endptr = NULL, err = 0;
     int uri = 0;
 
-    errno = 0;
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
-    id = strtol(id_str, &endptr, 10);
-    RETURN_IF((errno == ERANGE && (id == LONG_MAX || id == LONG_MIN)) || (errno != 0 && id == 0),
-              "Failed: strtol", false);
-    RETURN_IF(endptr == id_str, "No digit found", false);
+    STRTOL(id, id_str, endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
 
     /* If one day we allow suppression of the current kara, will need the `win`
        pointer to reload the kara in the same position (but the kara won't be
@@ -331,25 +292,18 @@ bool
 command_move(volatile sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr)
 {
     long from, to;
-    char *endptr;
+    char *endptr, err;
 
     RETURN_UNLESS(args && args[0] && args[1], "Invalid argument", false);
-    errno = 0;
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
 
     /* First argument: from */
-
-    from = strtol(args[0], &endptr, 10);
-    RETURN_IF((errno == ERANGE && (from == LONG_MAX || from == LONG_MIN)) || (errno != 0 && from == 0),
-              "Failed: strtol", false);
-    RETURN_IF(endptr == args[0], "No digit found", false);
+    STRTOL(from, args[0], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
 
     /* Second argument: to */
-
-    to = strtol(args[1], &endptr, 10);
-    RETURN_IF((errno == ERANGE && (to == LONG_MAX || to == LONG_MIN)) || (errno != 0 && to == 0),
-              "Failed: strtol", false);
-    RETURN_IF(endptr == args[0], "No digit found", false);
+    STRTOL(to, args[1], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
 
     return database_queue_move(db, from, to);
 }
@@ -420,26 +374,18 @@ command_noidle(struct lkt_state *srv, size_t c)
 }
 
 /* Functions for the searchadd and the search mpd commands */
-static bool
-lkt_callback_print_row_v1(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
-{
-    UNUSED(srv);
-    printf(" . from client %ld:\t%*d:%s\n", c, id_len, id, sql_row);
-    return true;
-}
-
-static bool
-lkt_callback_send_row_v1(void *_args, int id, int id_len, const char *sql_row)
+bool
+lkt_callback_send_row_v1(void *_args, int pos_len, int pos, int id, int id_len, const char *sql_row)
 {
     struct lkt_callback *args = (struct lkt_callback *) _args;
     struct lkt_message *out;
     out = lkt_message_new();
-    out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%*d %s\n", id_len, id, sql_row);
+    out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%*d: %*d %s\n", pos_len, pos, id_len, id, sql_row);
     lkt_state_send(args->srv, args->c, out);
     return true;
 }
 
-static bool
+bool
 lkt_callback_send_row_v2(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
 {
     struct lkt_message *out = lkt_message_new();
@@ -448,25 +394,9 @@ lkt_callback_send_row_v2(struct lkt_state *srv, size_t c, int id, int id_len, co
     return true;
 }
 
-static bool
-lkt_callback_insert_v1(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
-{
-    UNUSED(sql_row, id_len, c);
-    return database_queue_add_id(srv->db, id, 5) &&
-           lkt_callback_send_row_v2(srv, c, id, id_len, sql_row);
-}
-
-static bool
-lkt_callback_add_v2(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
-{
-    UNUSED(sql_row, id_len, c);
-    return database_queue_add_id(srv->db, id, 1) &&
-           lkt_callback_send_row_v2(srv, c, id, id_len, sql_row);
-}
-
-static bool
-__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 *))
+bool
+command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation,
+             bool(*init)(volatile sqlite3 *, char *, char *, struct lkt_search *))
 {
     char rgx[PATH_MAX], *col_name, *mpd_tag;
     int count;
@@ -475,62 +405,31 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo
         .c = c,
         .continuation = continuation,
         .msg_count = lkt_remaining_msg(srv, c) - 3, /* Reserve slots for OK/ACK and continue: */
+        .call = (void(*)(void)) lkt_callback_send_row_v2,
     };
 
     /* 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;
-        break;
-    case LKT_FND_ACT_PRINT:
-        search.call = (void(*)(void)) lkt_callback_print_row_v1;
-        break;
-    case LKT_FND_ACT_ENQUEUE:
-        search.call = (void(*)(void)) lkt_callback_insert_v1;
-        srv->mpd_idle_events |= MPD_IDLE_PLAYLIST;
-        break;
-    case LKT_FND_ACT_ADD:
-        search.call = (void(*)(void)) lkt_callback_add_v2;
-        srv->mpd_idle_events |= MPD_IDLE_PLAYLIST;
-        break;
-    default:
-        return false;
-    }
-
     /* Select the right column */
-
     mpd_tag = cmd_args[0];
-
-    if (!strcasecmp("any", mpd_tag) ||
-        !strcasecmp("all", mpd_tag) ||
-        !strcasecmp("a", mpd_tag))
+    if (!strcasecmp("any", mpd_tag) || !strcasecmp("all", mpd_tag) || !strcasecmp("query", mpd_tag) ||
+        !strcasecmp("source", mpd_tag) || !strcasecmp("title", mpd_tag)) {
         col_name = LKT_DATABASE_KARA_COLUMNT_ANY;
-    else if (!strcasecmp("author", mpd_tag))
+    } else if (!strcasecmp("author", mpd_tag)) {
         col_name = LKT_DATABASE_NAME_KAUTHOR;
-    else if (!strcasecmp("source", mpd_tag))
-        col_name = LKT_DATABASE_NAME_KNAME;
-    else if (!strcasecmp("title", mpd_tag))
-        col_name = LKT_DATABASE_NAME_KTITLE;
-    else if (!strcasecmp("category", mpd_tag) || !strcasecmp("cat", mpd_tag))
+    } else if (!strcasecmp("category", mpd_tag) || !strcasecmp("cat", mpd_tag)) {
         col_name = LKT_DATABASE_NAME_KCAT;
-    else if (!strcasecmp("type", mpd_tag))
+    } else if (!strcasecmp("type", mpd_tag)) {
         col_name = LKT_DATABASE_NAME_KTYPE;
-    else if (!strcasecmp("language", mpd_tag) || !strcasecmp("lang", mpd_tag))
+    } else if (!strcasecmp("language", mpd_tag) || !strcasecmp("lang", mpd_tag)) {
         col_name = LKT_DATABASE_NAME_KLANG;
-    else if (!strcasecmp("date", mpd_tag))
-        col_name = LKT_DATABASE_NAME_KAUTHOR_YEAR;
-    else if (!strcasecmp("id", mpd_tag))
+    } else if (!strcasecmp("id", mpd_tag)) {
         col_name = LKT_DATABASE_NAME_KID;
-    else
+    } else
         return false;
 
     /* Get the regex */
-
     RETURN_UNLESS(cmd_args[1], "No regex", false);
     memset(rgx, 0, PATH_MAX * sizeof(char));
 
@@ -541,7 +440,6 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo
     }
 
     /* 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)
@@ -549,41 +447,27 @@ __find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], lo
 
     if (count)
         lkt_set_continuation(srv, c, continuation + count);
+    else
+        LOG_WARN_SCT("COMMAND", "%s", "Nothing found");
 
     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])
 {
     RETURN_UNLESS(srv, "Invalid argument", false);
     UNUSED(c);
-    long val, ret = false;
-    char *endptr;
+    long val;
+    char *endptr, ret = false;
     struct lkt_win *win = &srv->win;
 
     if (args == NULL || args[0] == NULL)
         val = 0;
     else {
-        errno = 0;
-        val = strtol(args[0], &endptr, 10);
-        RETURN_IF((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0),
-                  "Failed: strtol", false);
-        RETURN_IF(endptr == args[0], "No digit found", false);
+        STRTOL(val, args[0], endptr, ret);
+        RETURN_IF(ret, "STRTOL failed", false);
 
         // No values can exceed those boundings, no matter the option //
         if (val < 0)
@@ -668,21 +552,17 @@ end_plt_add_uri:
 bool
 command_plt_remove(volatile sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], mpd_idle_flag *watch_mask_ptr)
 {
-    char *endptr;
-    long pos;
-
     RETURN_UNLESS(args && args[0], "Invalid argument", false);
+    char *endptr, err;
+    long pos;
 
     if (args[1] == NULL) {
         *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
         return database_plt_remove(db, args[0]);
     }
 
-    pos = strtol(args[1], &endptr, 10);
-    RETURN_IF((errno == ERANGE && (pos == LONG_MAX || pos == LONG_MIN)) || (errno != 0 && pos == 0),
-              "Failed: strtol", false);
-    RETURN_IF(endptr == args[1], "No digit found", false);
-
+    STRTOL(pos, args[1], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
     return database_plt_remove_pos(db, args[0], pos);
 }
@@ -755,7 +635,7 @@ command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_
 {
     unsigned int from, to, tmp_switch;
     long val;
-    char *endptr, *str;
+    char *endptr, err, *str;
     struct lkt_callback callback = {
         .call = lkt_callback_send_row_v1,
         .srv = srv,
@@ -765,13 +645,8 @@ command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_
     RETURN_UNLESS(args && args[0] && strlen(args[0]), "Invalid argument", false);
 
     /* Convert the first integer. */
-    errno = 0;
-    str = args[0] + strspn(args[0], "-+ "); // Skip not permited chars (NO NEGATIVE!) //
-    val = (unsigned int) strtol(str, &endptr, 0);
-    RETURN_IF((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0),
-              "Invalid argument", false);
-    RETURN_IF(endptr == args[0], "No digit found", false);
-
+    STRTOL(val, args[0], endptr, err);
+    RETURN_IF(err, "STRTOL failed (from)", false);
     from = labs(val);
 
     /* There is nothing after, is is the song pos version. */
@@ -781,12 +656,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 + strspn(endptr, "-+: "); // NO NEGATIVE! //
-        val = strtol(str, &endptr, 0);
-        RETURN_IF((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0),
-                  "Invalid argument", false);
-        RETURN_IF(endptr == args[0], "No digit found", false);
-
+        str = endptr + strspn(endptr, "-+: ");
+        STRTOL(val, str, endptr, err);
+        RETURN_IF(err, "STRTOL failed (to)", false);
         to = labs(val);
 
         if (to < from) {
@@ -809,9 +681,11 @@ only_one:
     /* The command is used with a range specifier. */
 is_a_range:
     if (to - from + 1 < lkt_remaining_msg(srv, c) - 2) {
+        LOG_INFO_SCT("COMMAND", "Got range %d:%d, no continuation needed", from, to);
         lkt_set_continuation(srv, c, 0);
         return database_queue_list(srv->db, from, to, &callback);
     } else {
+        LOG_INFO_SCT("COMMAND", "Got range %d:%d, continuation needed", from, to);
         to = from + lkt_remaining_msg(srv, c) - 3;
         lkt_set_continuation(srv, c, to + 1);
         return database_queue_list(srv->db, from, to, &callback);
@@ -922,14 +796,16 @@ bool
 command_sticker_get(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
     RETURN_UNLESS(argv[0] && argv[1] && argv[2] && !argv[3], "Invalid argument", false);
-    int uri = atoi(argv[1]); /* FIXME: Use strtol. */
+    int uri, err;
+    char *endptr;
+    STRTOL(uri, argv[1], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
     struct sticker_callback cb = {
         .srv = srv,
         .c = c,
         .call = sticker_send_one_value,
     };
-    RETURN_UNLESS(database_sticker_get(srv->db, argv[0], argv[2], uri, &cb), "Failed to get sticker",
-                  false);
+    RETURN_UNLESS(database_sticker_get(srv->db, argv[0], argv[2], uri, &cb), "Failed to get sticker", false);
     return true;
 }
 
@@ -938,8 +814,11 @@ command_sticker_set(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS
 {
     UNUSED(c);
     RETURN_UNLESS(argv[0] && argv[1] && argv[2] && argv[3] && !argv[4], "Invalid argument", false);
-    int uri = atoi(argv[1]);    /* FIXME: Use strtol. */
-    int value = atoi(argv[4]);  /* FIXME: Use strtol. */
+    int uri, value, err1, err2;
+    char *endptr;
+    STRTOL(uri, argv[1], endptr, err1);
+    STRTOL(value, argv[4], endptr, err2);
+    RETURN_IF(err1 || err2, "STRTOL failed", false);
     RETURN_UNLESS(database_sticker_set(srv->db, argv[0], argv[2], uri, value), "Failed to get sticker", false);
     srv->mpd_idle_events |= MPD_IDLE_STICKER;
     return true;
diff --git a/src/database/find.c b/src/database/find.c
index 9956610cdab7b533234b3cfa46a2280f3910ecf0..c95a2374aa30b9ff2ad2c5716b0f00da61c56889 100644
--- a/src/database/find.c
+++ b/src/database/find.c
@@ -3,6 +3,7 @@
 #include <common/common.h>
 #include <lektor/database.h>
 
+#include <strings.h>
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
@@ -18,20 +19,54 @@ database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx, s
         "SELECT id, any_col, (SELECT MAX(len) FROM content)"
         "FROM content LIMIT %d OFFSET %d;";
     char SQL_STMT[LKT_MAX_SQLITE_STATEMENT];
+    ret->type = lkt_search_database;
 
+    /* Search part */
     snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TEMPLATE, col_name,
              ret->msg_count, ret->continuation);
     SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0;
     SQLITE_PREPARE(db, ret->stmt, SQL_STMT, error);
     SQLITE_BIND_TEXT(db, ret->stmt, 1, rgx, error);
     ret->db = db;
-    /* Assign the callback. */
     return true;
 error:
     sqlite3_finalize(ret->stmt);
     return false;
 }
 
+bool
+database_search_sticker_init(volatile sqlite3 *db, char *type, char *name, struct lkt_search *ret)
+{
+    /* No bound checks in strcats, should be fine. Possible SQL injection, depend on the `type`. */
+    static const char *SQL_all_types =
+        "SELECT name, sts.id, value FROM 'stickers' LEFT OUTER JOIN "
+        "( SELECT id, sticker, value FROM 'stickers.song'"
+        "  UNION"
+        "  SELECT id, sticker, value FROM 'stickers.plt'"
+        ") AS sts"
+        "ON sts.sticker = 'stickers'.id";
+    static const char *SQL_one_type =
+        "SELECT name, 'stickers.%s'.id, value "
+        "FROM 'stickers' "
+        "LEFT OUTER JOIN 'stickers' "
+        "ON 'stickers'.id = 'stickers.%s'.sticker";
+    static const char *SQL_check_name = " AND name = ?;";
+    char SQL[LKT_MAX_SQLITE_STATEMENT];
+
+    if (type == NULL)
+        memcpy(SQL, SQL_all_types, strlen(SQL_all_types) + 1);
+    else
+        sprintf(SQL, SQL_one_type, type, type);
+    strcat(SQL, name ? SQL_check_name : ";");
+
+    SQLITE_PREPARE(db, ret->stmt, SQL, error);
+    if (name)
+        SQLITE_BIND_TEXT(db, ret->stmt, 1, name, error)
+        return true;
+error:
+    sqlite3_finalize(ret->stmt);
+    return false;
+}
 
 bool
 database_search_queue_init(volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret)
@@ -46,14 +81,15 @@ database_search_queue_init(volatile sqlite3 *db, char *col_name, char *rgx, stru
         "SELECT id, any_col, (SELECT MAX(len) FROM content)"
         "FROM content LIMIT %d OFFSET %d;";
     char SQL_STMT[LKT_MAX_SQLITE_STATEMENT];
+    ret->type = lkt_search_queue;
 
+    /* Search part */
     snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TEMPLATE, col_name,
              ret->msg_count, ret->continuation);
     SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0;
     SQLITE_PREPARE(db, ret->stmt, SQL_STMT, error);
     SQLITE_BIND_TEXT(db, ret->stmt, 1, rgx, error);
     ret->db = db;
-    /* Assign the callback. */
     return true;
 error:
     sqlite3_finalize(ret->stmt);
@@ -65,16 +101,17 @@ database_search_iter(struct lkt_search *item)
 {
     const char *sql_row;
     int id, code, id_len;
-
-    code = sqlite3_step(item->stmt);
-
     RETURN_UNLESS(item, "Exit because item is NULL, end iterations", false);
+    GOTO_UNLESS(item->call, "Call function is NULL, terminate the search", end);
+    code = sqlite3_step(item->stmt);
 
     if (code == SQLITE_DONE)
-        goto error_or_done;
+        goto end;
 
-    if (code != SQLITE_ROW)
-        goto error;
+    if (code != SQLITE_ROW) {
+        LOG_ERROR_SCT("DB", "Step failed, expected a ROW or a DONE: %s", sqlite3_errmsg((sqlite3 *) item->db));
+        goto end;
+    }
 
     switch (item->type) {
     case lkt_search_database:
@@ -83,14 +120,17 @@ database_search_iter(struct lkt_search *item)
         id_len = sqlite3_column_int(item->stmt, 2);
         return ((lkt_search_database_func) item->call)(item->srv, item->c, id, id_len, sql_row);
     case lkt_search_queue:
+        id = sqlite3_column_int(item->stmt, 0);
+        sql_row = (const char *) sqlite3_column_text(item->stmt, 1);
+        id_len = sqlite3_column_int(item->stmt, 2);
+        return ((lkt_search_queue_func) item->call)(item->srv, item->c, id, id_len, sql_row);
     case lkt_search_playlist:
     default:
-        goto error;
+        LOG_WARN_SCT("DB", "Search operation %d is not implemented", item->type);
+        goto end;
     }
 
-error:
-    LOG_ERROR_SCT("DB", "sqlite3_step failed: %s", sqlite3_errmsg((sqlite3 *) item->db));
-error_or_done:
+end:
     sqlite3_finalize(item->stmt);
     return false;
 }
diff --git a/src/database/queue.c b/src/database/queue.c
index a8bf8a55a43b2bbc35a200e051b169aaaa37d76e..c936b1fccc79cdb696268487faf1455c7eb08605 100644
--- a/src/database/queue.c
+++ b/src/database/queue.c
@@ -106,15 +106,13 @@ queue_add_with_col_like_str(volatile sqlite3 *db, const char *col, const char *v
         " );"
         /* Separate karas that are after the current one */
         "INSERT INTO queue_tmp (kara_id, priority)"
-        " SELECT kara_id, priority"
-        " FROM queue"
-        " WHERE position > " CURRENT_POS_OR_0 ";"
+        " SELECT kara_id, priority FROM queue WHERE position > " CURRENT_POS_OR_0
+        " ORDER BY priority DESC, position ASC;"
         "DELETE FROM queue WHERE position > " CURRENT_POS_OR_0 ";"
         /* Insert back */
         "INSERT INTO queue (position, kara_id, priority)"
         " SELECT position + " CURRENT_POS_OR_0 ", kara_id, priority"
-        " FROM queue_tmp"
-        " ORDER BY priority, position;"
+        " FROM queue_tmp;"
         /* Drop temporary tables */
         "DROP TABLE queue_tmp;"
         "DELETE FROM sqlite_sequence WHERE name = 'queue_tmp';";
@@ -137,8 +135,10 @@ queue_add_with_col_like_str(volatile sqlite3 *db, const char *col, const char *v
     sqlite3_finalize(stmt);
 
     /* Reorder kara that are after the current one, do this shit only if priority > 1... */
-    if (priority > 1)
+    if (priority > 1) {
         SQLITE_EXEC(db, SQL_REORDER, error);
+        LOG_INFO_SCT("DB", "%s", "Queue has been reordered");
+    }
 
     /* End */
     SQLITE_EXEC(db, "COMMIT;", error);
@@ -172,13 +172,14 @@ database_queue_add_plt(volatile sqlite3 *db, const char *plt_name, int priority)
         " , priority INTEGER NOT NULL DEFAULT 1 CHECK(priority > 0 AND priority < 6)"
         " );"
         /* Separate karas that are after the current one */
-        "INSERT INTO queue_tmp (kara_id, priority) SELECT kara_id, priority FROM queue WHERE position > " CURRENT_POS_OR_0 ";"
+        "INSERT INTO queue_tmp (kara_id, priority)"
+        " SELECT kara_id, priority FROM queue WHERE position > " CURRENT_POS_OR_0
+        " ORDER BY priority DESC, position ASC;"
         "DELETE FROM queue WHERE position > " CURRENT_POS_OR_0 ";"
         /* Insert back */
         "INSERT INTO queue (position, kara_id, priority)"
         " SELECT position + " CURRENT_POS_OR_0 ", kara_id, priority"
-        " FROM queue_tmp"
-        " ORDER BY priority, position;"
+        " FROM queue_tmp;"
         /* Drop temporary tables */
         "DROP TABLE queue_tmp;"
         "DELETE FROM sqlite_sequence WHERE name = 'queue_tmp';";
@@ -207,22 +208,6 @@ error:
     return false;
 }
 
-#define database_queue_add(suffix, column_name)                                             \
-    bool                                                                                    \
-    database_queue_add_ ## suffix (volatile sqlite3 *db, const char *query, int priority)   \
-    {                                                                                       \
-        bool status = queue_add_with_col_like_str(db, column_name, query, priority);        \
-        LOG_INFO("%s " #suffix " '%s' with priority of %d",                                 \
-                 status ? "Successfully added" : "Failed to add", query, priority);         \
-        return status;                                                                      \
-    }
-database_queue_add(query,    LKT_DATABASE_KARA_ALL)
-database_queue_add(author,   LKT_DATABASE_NAME_KAUTHOR)
-database_queue_add(language, LKT_DATABASE_NAME_KLANG)
-database_queue_add(category, LKT_DATABASE_NAME_KCAT)
-database_queue_add(type,     LKT_DATABASE_NAME_KTYPE)
-#undef database_queue_add
-
 bool
 database_queue_add_id(volatile sqlite3 *db, int id, int priority)
 {
@@ -239,6 +224,31 @@ error:
     return status;
 }
 
+bool
+database_queue_add_uri(volatile sqlite3 *db, struct lkt_uri *uri, int priority)
+{
+    switch (uri->type) {
+    case uri_query:
+    case uri_fs:
+        return queue_add_with_col_like_str(db, LKT_DATABASE_KARA_ALL, uri->value, priority);
+    case uri_id:
+        return database_queue_add_id(db, *(int *) uri->value, priority);
+    case uri_type:
+        return queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KTYPE, uri->value, priority);
+    case uri_category:
+        return queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KCAT, uri->value, priority);
+    case uri_language:
+        return queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KLANG, uri->value, priority);
+    case uri_author:
+        return queue_add_with_col_like_str(db, LKT_DATABASE_NAME_KAUTHOR, uri->value, priority);
+    case uri_playlist:
+        return database_queue_add_plt(db, (char *) uri->value, priority);
+    default:
+        LOG_WARN_SCT("DB", "Add to queue for uri of type %d is not implemented", uri->type);
+        return false;
+    }
+}
+
 bool
 database_queue_del_id(volatile sqlite3 *db, int id)
 {
@@ -582,13 +592,13 @@ database_queue_list(volatile sqlite3 *db, size_t from, size_t to, struct lkt_cal
 {
     const char *SQL_STMT =
         "WITH content AS ("
-        " SELECT kara.id AS id, string, LENGTH(CAST(kara.id AS TEXT)) AS len"
+        " SELECT kara.id AS id, string, LENGTH(CAST(kara.id AS TEXT)) AS len, position, LENGTH(CAST(position AS TEXT)) AS pos_len"
         "  FROM queue"
         "  JOIN kara ON kara_id = kara.id"
         "  WHERE position >= ? AND position <= ?"
         "  GROUP BY position ORDER BY position ASC, priority DESC)"
-        "SELECT id, string, (SELECT MAX(len) FROM content) FROM content;";
-    int code, id, id_len;
+        "SELECT id, string, (SELECT MAX(len) FROM content), position, (SELECT MAX(pos_len) FROM content) FROM content;";
+    int code, id, id_len, pos, pos_len;
     const char *row;
     bool ret = false;
     sqlite3_stmt *stmt;
@@ -600,13 +610,14 @@ database_queue_list(volatile sqlite3 *db, size_t from, size_t to, struct lkt_cal
     for (;;) {
         code = sqlite3_step(stmt);
 
-
         if (code == SQLITE_ROW) {
             id = sqlite3_column_int(stmt, 0);
             row = (const char *) sqlite3_column_text(stmt, 1);
             id_len = sqlite3_column_int(stmt, 2);
+            pos = sqlite3_column_int(stmt, 3);
+            pos_len = sqlite3_column_int(stmt, 4);
             ++(callback->iterations);
-            if (callback->call(callback, id, id_len, row))
+            if (callback->call(callback, pos_len, pos, id, id_len, row))
                 continue;
             else
                 break;
@@ -615,8 +626,10 @@ database_queue_list(volatile sqlite3 *db, size_t from, size_t to, struct lkt_cal
         else if (code == SQLITE_OK || code == SQLITE_DONE)
             goto done;
 
-        else
+        else {
+            LOG_ERROR_SCT("DB", "Failed: %s", sqlite3_errmsg((sqlite3 *) db));
             break;
+        }
     }
 
 done:
diff --git a/src/main/lkt.c b/src/main/lkt.c
index a3230844dd5b6ad15864405a3c37e4cfabbc03ea..ea03894d8bd2574d6c0eb9acca7b65c1d0bafae6 100644
--- a/src/main/lkt.c
+++ b/src/main/lkt.c
@@ -63,6 +63,7 @@ lkt_valid_type(const char *type)
 {
     return (STR_MATCH(type, "all")      ||
             STR_MATCH(type, "any")      ||
+            STR_MATCH(type, "query")    ||
             STR_MATCH(type, "id")       ||
             STR_MATCH(type, "title")    ||
             STR_MATCH(type, "type")     ||
@@ -510,32 +511,39 @@ queue_delete__(struct lkt_cmd_args *args)
     fail("Invalid argument");
 }
 
+static inline void
+send_cmd_with_uri(FILE *sock, char *cmd, int argc, const char **argv)
+{
+    int i;
+    char buf[LKT_MESSAGE_MAX] = {0};
+    for (i = 1; i < argc - 1; ++i) {
+        strncat(buf, argv[i], LKT_MESSAGE_MAX - 1);
+        strncat(buf, " ", LKT_MESSAGE_MAX - 1);
+    }
+    strncat(buf, argv[i], LKT_MESSAGE_MAX - 1);
+    strncat(buf, "\n", LKT_MESSAGE_MAX - 1);
+    (void) write_socket_format(sock, "%s %s://%s", cmd, argv[0], buf);
+}
+
 noreturn void
 queue_add__(struct lkt_cmd_args *args)
 {
     char buff[3];
-    int i;
-
-    if (args->argc < 1)
-        fail("Invalid argument, the add command should takes at least two arguments: queue add <query>");
-
-    if (!lkt_valid_type(args->argv[0]))
-        fail("Invalid argument, the type given to the add command is invalid");
-
+    fail_if(args->argc < 1, "Invalid arguments");
+    fail_if(!lkt_valid_type(args->argv[0]), "Invalid query type");
     FILE *sock = lkt_connect();
+    send_cmd_with_uri(sock, "add", args->argc, args->argv);
+    exit_with_status(sock, buff);
+}
 
-    (void) write_socket(sock, "add ", 4 * sizeof(char));
-    (void) write_socket(sock, args->argv[0], strlen(args->argv[0]));
-    (void) write_socket(sock, "://", 3 * sizeof(char));
-
-    for (i = 1; i < args->argc - 1; ++i) {
-        (void) write_socket(sock, args->argv[i], strlen(args->argv[i]));
-        (void) write_socket(sock, " ", sizeof(char));
-    }
-
-    /* Here we have `i == argc - 1`. */
-    (void) write_socket(sock, args->argv[i], strlen(args->argv[i]));
-    (void) write_socket(sock, "\n", sizeof(char));
+noreturn void
+queue_insert__(struct lkt_cmd_args *args)
+{
+    char buff[3];
+    fail_if(args->argc < 1, "Invalid arguments");
+    fail_if(!lkt_valid_type(args->argv[0]), "Invalid query type");
+    FILE *sock = lkt_connect();
+    send_cmd_with_uri(sock, "__insert", args->argc, args->argv);
     exit_with_status(sock, buff);
 }
 
@@ -791,8 +799,6 @@ redo:
 #define search_with_cmd(func, cmd) /* I don't want to write always the same things */ \
     noreturn void func (struct lkt_cmd_args *args) { search_with_cmd__(args, #cmd); }
 search_with_cmd(search_get__,    search)
-search_with_cmd(search_add__,    searchadd)
-search_with_cmd(search_insert__, __insert)
 search_with_cmd(search_plt__,    listplaylist)
 search_with_cmd(search_count__,  count)
 search_with_cmd(search_queue__,  playlistfind)
@@ -801,6 +807,7 @@ search_with_cmd(search_queue__,  playlistfind)
 /* Parsing stuff. */
 
 static struct lkt_cmd_opt options_queue[] = {
+    { .name = "insert",     .call = queue_insert__ },
     { .name = "pos",        .call = queue_pos__    },
     { .name = "pop",        .call = queue_pop__    },
     { .name = "add",        .call = queue_add__    },
@@ -821,8 +828,6 @@ static struct lkt_cmd_opt options_plt[] = {
 
 static struct lkt_cmd_opt options_search[] = {
     { .name = "get",        .call = search_get__    },
-    { .name = "add",        .call = search_add__    },
-    { .name = "insert",     .call = search_insert__ },
     { .name = "plt",        .call = search_plt__    },
     { .name = "count",      .call = search_count__  },
     { .name = "queue",      .call = search_queue__  },
diff --git a/src/net/listen.c b/src/net/listen.c
index 23d4fddf2cb64900788e5dbca88b132ba662518b..0aa570f4ab740bf10aa4c14bf05b84976c4a90cb 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, database_search_queue_init);
 
         else if (!strcmp(cmd.name, "sticker") && cmd.args[0]) {
             if (!strcmp(cmd.args[0], "get"))
@@ -213,8 +213,10 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
         else if (!strcmp(cmd.name, "help"))
             err = !command_help(srv, c);
 
-        else if (!strcmp(cmd.name, "add"))
-            err = !command_add((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events);
+        else if (!strcmp(cmd.name, "__insert"))
+            err = !command_add((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events, 5);
+        else if (!strcmp(cmd.name, "searchadd") || !strcmp(cmd.name, "findadd") || !strcmp(cmd.name, "add"))
+            err = !command_add((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events, 1);
         else if (!strcmp(cmd.name, "addid"))
             err = !command_addid((sqlite3 *) srv->db, &srv->win, cmd.args, &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "deleteid"))
@@ -253,14 +255,8 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
         else if (!strcmp(cmd.name, "idle")) {
             err = !command_idle(srv, c, &cmd);
             goto end_no_send_status;
-        } else if (!strcmp(cmd.name, "searchadd") ||
-                   !strcmp(cmd.name, "findadd"))
-            err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_ADD);
-        else if (!strcmp(cmd.name, "search") ||
-                 !strcmp(cmd.name, "find"))
-            err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_RESPOND);
-        else if (!strcmp(cmd.name, "__insert"))
-            err = ! command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_ENQUEUE);
+        } else if (!strcmp(cmd.name, "search") || !strcmp(cmd.name, "find"))
+            err = ! command_find(srv, c, cmd.args, cmd.cont, database_search_database_init);
         else
             err = 2;
 
@@ -391,7 +387,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;
@@ -399,6 +395,10 @@ handle_outgoing_data(struct lkt_state *srv, size_t c)
                         cli->buffer_out_len);
                 return 0;
             }
+            if (errno == EPIPE) {
+                LOG_WARN_SCT("NETWORK", "Client %ld is out, free all its messages", c);
+                handle_disconnected_client(srv, i);
+            }
             return -1;
         }