From dbcf9fb0ab8a0873eacae3e550c709b98c51d8da Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Thu, 9 Apr 2020 19:01:53 +0200
Subject: [PATCH] Can now store the configuration

---
 inc/lektor/database.h   |   7 ++-
 src/commands.c          |  10 ++--
 src/database/config.c   | 127 +++++++++++++++++++++++++++++++++++++++-
 src/module/module_x11.c |   6 +-
 src/net/listen.c        |   2 +-
 5 files changed, 138 insertions(+), 14 deletions(-)

diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index a65a28a9..a6dbe24e 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -98,8 +98,11 @@ bool database_queue_next(sqlite3 *db, char filepath[PATH_MAX]);
 bool database_queue_prev(sqlite3 *db, char filepath[PATH_MAX]);
 
 /* Set a value in the config table */
-bool database_config(sqlite3 *db, const char *option, int value);
-bool database_config_default(sqlite3 *db);
+bool database_config_set(sqlite3 *db, const char *section, const char *key, const char *value);
+bool database_config_get_text(sqlite3 *db, const char *section, const char *key, char *value, size_t len);
+bool database_config_get_int(sqlite3 *db, const char *section, const char *key, int *value);
+bool database_config_queue(sqlite3 *db, const char *option, int value);
+bool database_config_queue_default(sqlite3 *db);
 
 /* Get a value from the config table */
 bool database_get_config(sqlite3 *db, const char *option, int *value);
diff --git a/src/commands.c b/src/commands.c
index b0db8065..32565f6f 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -725,19 +725,19 @@ command_set_playback_option(struct lkt_state *srv, size_t c,
 
     switch (opt) {
     case lkt_playback_option_random:
-        ret = database_config(srv->db, "random", val);
+        ret = database_config_queue(srv->db, "random", val);
         break;
     case lkt_playback_option_single:
-        ret = database_config(srv->db, "single", val);
+        ret = database_config_queue(srv->db, "single", val);
         break;
     case lkt_playback_option_consume:
-        ret = database_config(srv->db, "consume", val);
+        ret = database_config_queue(srv->db, "consume", val);
         break;
     case lkt_playback_option_repeat:
-        ret = database_config(srv->db, "repeat", val);
+        ret = database_config_queue(srv->db, "repeat", val);
         break;
     case lkt_playback_option_volume:
-        ret = database_config(srv->db, "volume", val);
+        ret = database_config_queue(srv->db, "volume", val);
         fprintf(stderr, " . command_set_playback_option: set volume to %ld\n", val);
         ret &= win->set_volume(win, val);
         srv->mpd_idle_events |= MPD_IDLE_MIXER;
diff --git a/src/database/config.c b/src/database/config.c
index 2970a44f..77819dea 100644
--- a/src/database/config.c
+++ b/src/database/config.c
@@ -1,11 +1,132 @@
+#define _POSIX_C_SOURCE 200809L
+
 #include <lektor/database.h>
 
-#include <linux/limits.h>
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 
 bool
-database_config(sqlite3 *db, const char *option, int value)
+database_config_set(sqlite3 *db, const char *section, const char *key, const char *value)
+{
+    static const char *SQL_STMT =
+        "INSERT OR REPLACE INTO"
+        " config (section, key, value)"
+        " VALUES (?, ?, ?);\n";
+    sqlite3_stmt *stmt = 0;
+    bool ret = false;
+    int code;
+
+    if (sqlite3_prepare_v2(db, SQL_STMT, -1, &stmt, 0) != SQLITE_OK) {
+        fprintf(stderr, " ! database_config_set: Failed to prepare statement: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    if (sqlite3_bind_text(stmt, 1, section, -1, 0) != SQLITE_OK ||
+        sqlite3_bind_text(stmt, 2, key, -1, 0) != SQLITE_OK     ||
+        sqlite3_bind_text(stmt, 3, value, -1, 0) != SQLITE_OK) {
+        fprintf(stderr, " ! database_config_set: Failed to bind: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    code = sqlite3_step(stmt);
+
+    if (code != SQLITE_OK && code != SQLITE_DONE) {
+        fprintf(stderr, " ! database_config_set: Failed to insert or replace: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    ret = true;
+error:
+    sqlite3_finalize(stmt);
+    return ret;
+}
+
+bool
+database_config_get_text(sqlite3 *db, const char *section, const char *key, char *value, size_t len)
+{
+    static const char *SQL_STMT =
+        "SELECT value"
+        " FROM config"
+        " WHERE section = ? AND key = ?;\n";
+    sqlite3_stmt *stmt = 0;
+    bool ret = false;
+    int code;
+
+    if (sqlite3_prepare_v2(db, SQL_STMT, -1, &stmt, 0) != SQLITE_OK) {
+        fprintf(stderr, " ! database_config_get_text: Failed to prepare statement: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    if (sqlite3_bind_text(stmt, 1, section, -1, 0) != SQLITE_OK ||
+        sqlite3_bind_text(stmt, 2, key, -1, 0) != SQLITE_OK) {
+        fprintf(stderr, " ! database_config_get_text: Failed to bind: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    code = sqlite3_step(stmt);
+
+    if (code != SQLITE_ROW) {
+        fprintf(stderr, " ! database_config_get_text: Failed to insert or replace: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    const char *row = (const char *) sqlite3_column_text(stmt, 1);
+    strncpy(value, row, len);
+    value[len - 1] = 0;
+    ret = true;
+error:
+    sqlite3_finalize(stmt);
+    return ret;
+}
+
+bool
+database_config_get_int(sqlite3 *db, const char *section, const char *key, int *value)
+{
+    static const char *SQL_STMT =
+        "SELECT CAST(value AS INTEGER)"
+        " FROM config"
+        " WHERE section = ? AND key = ?;\n";
+    sqlite3_stmt *stmt = 0;
+    bool ret = false;
+    int code;
+
+    if (sqlite3_prepare_v2(db, SQL_STMT, -1, &stmt, 0) != SQLITE_OK) {
+        fprintf(stderr, " ! database_config_get_int: Failed to prepare statement: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    if (sqlite3_bind_text(stmt, 1, section, -1, 0) != SQLITE_OK ||
+        sqlite3_bind_text(stmt, 2, key, -1, 0) != SQLITE_OK) {
+        fprintf(stderr, " ! database_config_get_int: Failed to bind: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    code = sqlite3_step(stmt);
+
+    if (code != SQLITE_ROW) {
+        fprintf(stderr, " ! database_config_get_int: Failed to insert or replace: %s\n",
+                sqlite3_errmsg(db));
+        goto error;
+    }
+
+    *value = sqlite3_column_int(stmt, 1);
+    ret = true;
+error:
+    sqlite3_finalize(stmt);
+    return ret;
+}
+
+bool
+database_config_queue(sqlite3 *db, const char *option, int value)
 {
     static const char *SQL_STMT_TMP = "UPDATE queue_state SET %s = ? WHERE id = 42;";
     char SQL_STMT[PATH_MAX];
@@ -41,7 +162,7 @@ error:
 }
 
 bool
-database_config_default(sqlite3 *db)
+database_config_queue_default(sqlite3 *db)
 {
     static const char *SQL_DEFAULT =
         "UPDATE queue_state SET"
diff --git a/src/module/module_x11.c b/src/module/module_x11.c
index 39c584ed..25bcb20f 100644
--- a/src/module/module_x11.c
+++ b/src/module/module_x11.c
@@ -272,18 +272,18 @@ lmpv_handle(struct lkt_win *win, sqlite3 *db, long long int *mpd_idle_events)
             if (!strcmp(prop->name, "ao-volume")
                 && prop->format == MPV_FORMAT_INT64) {
                 ao_volume = *(int *) prop->data;
-                database_config(db, "volume", ao_volume);
+                database_config_queue(db, "volume", ao_volume);
             }
             // File duration //
             if (!strcmp(prop->name, "duration")
                 && prop->format == MPV_FORMAT_INT64) {
                 win_x11->mpv_duration = *(int *) prop->data;
-                database_config(db, "duration", *(int *) prop->data);
+                database_config_queue(db, "duration", *(int *) prop->data);
             }
             if (!strcmp(prop->name, "time-pos")
                 && prop->format == MPV_FORMAT_INT64) {
                 win_x11->mpv_time_pos = *(int *) prop->data;
-                database_config(db, "elapsed", *(int *) prop->data);
+                database_config_queue(db, "elapsed", *(int *) prop->data);
             }
             // Pause state //
             if (!strcmp(prop->name, "pause")
diff --git a/src/net/listen.c b/src/net/listen.c
index 7c7dc5d5..f70f6a4a 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -758,7 +758,7 @@ lkt_listen(lkt_config_t conf)
 
     srv.kara_prefix = kara_dir;
 
-    database_config_default(srv.db);
+    database_config_queue_default(srv.db);
 
     srv.fds_max = 16;
     srv.fds = malloc(srv.fds_max * sizeof(struct pollfd));
-- 
GitLab