From 32596472e1af7c7cae6cd541a00886cf4dba43ef Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Sun, 31 Jan 2021 00:09:56 +0100
Subject: [PATCH] MPD: Add the "swapid" command

---
 inc/lektor/commands.h |  1 +
 inc/lektor/database.h |  2 +-
 man/lkt.template      |  3 +--
 src/base/commands.c   | 49 +++++++++++++++++++++++++++++--------------
 src/database/queue.c  | 10 ++++-----
 src/net/listen.c      |  2 ++
 6 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h
index e5b45e4e..8cc92516 100644
--- a/inc/lektor/commands.h
+++ b/inc/lektor/commands.h
@@ -44,6 +44,7 @@ bool command_move   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
 bool command_shuffle(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
 bool command_dump   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
 bool command_swap   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
+bool command_swapid (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
 bool command_flat   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
 
 bool command_queue_list  (struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX]);
diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index 68b93cc5..be8bcf26 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -87,7 +87,7 @@ struct lkt_callback {
 /* List the content of the queue */
 bool database_queue_list(volatile sqlite3 *db, size_t from, size_t to,
                          struct lkt_callback *callback);
-bool database_queue_probe_id(volatile sqlite3 *db, int id);
+int database_queue_probe_id(volatile sqlite3 *db, int id);
 
 /* Search the database */
 struct lkt_search {
diff --git a/man/lkt.template b/man/lkt.template
index 07ff2e42..7c89fdd6 100644
--- a/man/lkt.template
+++ b/man/lkt.template
@@ -38,8 +38,7 @@ specified index.
 For lektord to be paused, don't do anything is lektord is already paused.
 .TP
 \fBunpause\fP
-Unpause lektord, don't do anything if lektord is already playing or if it is
-stopped. In that case use the \fBplay\fP command.
+Unpause lektord, starts at the begening of the queue if lektord was stopped.
 .TP
 \fBnext\fP
 Play next kara in the queue.
diff --git a/src/base/commands.c b/src/base/commands.c
index f10afa7e..745485c7 100644
--- a/src/base/commands.c
+++ b/src/base/commands.c
@@ -293,9 +293,10 @@ __play_that_file(struct lkt_state *win, int pos)
 {
     char filepath[PATH_MAX];
     RETURN_UNLESS(pos, "Invalid argument", false);
-    RETURN_UNLESS(database_queue_play(win->db, (int) pos), "DB error", false);
+    RETURN_UNLESS(database_queue_play(win->db, pos), "DB error", false);
     RETURN_UNLESS(database_queue_get_current_file(win->db, filepath), "Can't get current kara", false);
     RETURN_IF(MOD_CALL(win->window_mod, "load", filepath), "Can't load file", false);
+    LOG_DEBUG("COMMAND", "Playing queue at index %d, file %s", pos, filepath);
     return true;
 }
 
@@ -513,26 +514,14 @@ command_move(struct lkt_state UNUSED *srv, char *args[LKT_MESSAGE_ARGS_MAX])
     return false;
 }
 
-bool
-command_swap(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX])
+static bool
+__swap_positions(struct lkt_state *srv, int from, int to)
 {
-    long from, to;
-    char *endptr = NULL, err = 0;
-
-    RETURN_UNLESS(args && args[0] && args[1], "Invalid argument", false);
-
-    /* First argument: from */
-    STRTOL(from, args[0], endptr, err);
-    RETURN_IF(err, "STRTOL failed", false);
-
-    /* Second argument: to */
-    STRTOL(to, args[1], endptr, err);
-    RETURN_IF(err, "STRTOL failed", false);
+    RETURN_IF(to == from, "Can't swap with two identic positions", false);
 
     struct lkt_queue_state queue = { .current = -1 };
     database_queue_state(srv->db, &queue);
 
-
     int new_current = (((long) queue.current) == to) ? from
                       : (((long) queue.current) == from) ? to
                       : -1;
@@ -552,6 +541,34 @@ command_swap(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX])
     return sta;
 }
 
+bool
+command_swapid(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX])
+{
+    RETURN_UNLESS(args && args[0] && args[1], "Invalid argument", false);
+    int from = database_queue_probe_id(srv->db, strtol(args[0], NULL, 0));
+    int to   = database_queue_probe_id(srv->db, strtol(args[1], NULL, 0));
+    return __swap_positions(srv, from, to);
+}
+
+bool
+command_swap(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX])
+{
+    long from, to;
+    char *endptr = NULL, err = 0;
+
+    RETURN_UNLESS(args && args[0] && args[1], "Invalid argument", false);
+
+    /* First argument: from */
+    STRTOL(from, args[0], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
+
+    /* Second argument: to */
+    STRTOL(to, args[1], endptr, err);
+    RETURN_IF(err, "STRTOL failed", false);
+
+    return __swap_positions(srv, from, to);
+}
+
 bool
 command_help(struct lkt_state *srv, size_t c, char UNUSED *args[LKT_MESSAGE_ARGS_MAX])
 {
diff --git a/src/database/queue.c b/src/database/queue.c
index dd0a4151..c6882ac0 100644
--- a/src/database/queue.c
+++ b/src/database/queue.c
@@ -802,19 +802,19 @@ error:
     return false;
 }
 
-bool
+int
 database_queue_probe_id(volatile sqlite3 *db, int id)
 {
-    bool sta               = false;
+    int position           = 0; /* The queue begins with the position 1 */
     sqlite3_stmt *stmt     = NULL;
-    static const char *SQL = "SELECT * FROM queue WHERE kara_id = ?;";
+    static const char *SQL = "SELECT position FROM queue WHERE kara_id = ?;";
     SQLITE_PREPARE(db, stmt, SQL, error);
     SQLITE_BIND_INT(db, stmt, 1, id, error);
     SQLITE_STEP_ROW(db, stmt, error);
-    sta = true;
+    position = sqlite3_column_int(stmt, 0);
 error:
     sqlite3_finalize(stmt);
-    return sta;
+    return position;
 }
 
 bool
diff --git a/src/net/listen.c b/src/net/listen.c
index 33114bff..bdde8713 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -207,6 +207,8 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
             err = ! command_shuffle(srv, NULL);
         else if (STR_MATCH(cmd.name, "swap"))
             err = ! command_swap(srv, cmd.args);
+        else if (STR_MATCH(cmd.name, "swapid"))
+            err = ! command_swapid(srv, cmd.args);
         else if (STR_MATCH(cmd.name, "__flat"))
             err = ! command_flat(srv, cmd.args);
 
-- 
GitLab