diff --git a/doc/lektord.1 b/doc/lektord.1
index 13ca581972f64ea79bd2c4a2e07b50f22b18f5eb..66245cf2900548f5b488318b667df9bdbb787b76 100644
--- a/doc/lektord.1
+++ b/doc/lektord.1
@@ -9,18 +9,19 @@ You may be interested in other related programs like:
 .PP
 .PD 0
 .TP
-\fIkaradata\fP      Metadata manipulation around matroska files for lektor
+\fIlktadm\fP        Administration of lektor from a separate executable
 .TP
-\fIlkinfo\fP        Metadata printing with lektor compatible matroska files
+\fIlkt\fP           A standard client for lektord
 .PD
 .SH "DESCRIPTION"
 .PP
 Lektor allows one to interactivelly and remotly interact with the player. The
-lektor daemon is mpd compatible.
+lektor daemon is mpd compatible, even if some functionnalities may differ.
+You can almost use \fBmpc\fP with lektord.
 .SH "AUTHOR"
 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 and Maël 'Kubat' MARTIN.
+\'Taiite' HIRTZ, Maël 'Kubat' MARTIN and Louis 'Elliu' GOYARD.
 .SH "AVAILABILITY"
 I don't know what to do in this section.
 .PP
@@ -37,6 +38,20 @@ Just see one of the dev from lektor or a bakateux.
 .TP
 \fBhttps://manga.iiens.net\fP   The home website for the Bakaclub
 .PD
+.SH "INSTALLATION"
+You may install lektor from source like this:
+.sp
+.RS 4
+.nf
+\fB
+% sudo mkdir /home/kara && sudo chown USER:USER /home/kara
+% git clone https://git.iiens.net/martin2018/lektor && cd lektor
+% mkdir build && meson build && cd build && ninja   # Compilation
+% sudo meson install --no-rebuild                   # Install
+% sudo chown USER:USER /home/kara/kara.db           # Or you will have some problems
+.fi \fR
+.P
+.RE
 .SH "INVOCATION"
 To simply launch the daemon do not set any flag. The following flags are
 interpreted by the shell when invoked to determine where the shell will read
@@ -45,36 +60,32 @@ commands from:
 .PD 0
 .TP
 .PD
-\fB\-\-init\fP
-Write default config files on the FS. May create folder if they doesn't exist.
-If a configuration is already present it may be overwriten.
-.TP
-\fB\-\-populate\fP
-Read the configuration and populate the sqlite3 database with the found
-compatible matroska video files from the FS.
+\fB\-\-help\fP / \fB\-h\fP
+Prints the help message.
 .TP
 \fB\-\-version\fP / \fB\-v\fP
 Print the version of the lektor daemon.
 .PP
-If the lektor daemon is launched without configuration the behaviour is not
-determined. When installing from scratch the following commands need to be
-launched \fBin order\fP:
+If the lektor daemon is launched without a configuration file, it will exit
+with the code \fB1\fP. To init the default configuration file (normally done
+by meson during the install), you should just use:
 .sp
 .RS 4
 .nf
 \fB
-% lektord --init
-% karadata --init
-% lektord --populate
+% mkdir ~/.config/lektor/
+% lktadm init conf > ~/.config/lektor/lektor.ini
 % lektord
 .fi \fR
 .P
 .RE
 .PP
-When downloading karas directly from \fIkurisu\fP the \fBkaradata --init\fP
-should not be needed.
+You should edit the configuration file to set correct path to \fB.so\fP file,
+those files are modules for the window of lektord.
 .SH "SUPPORTED URIS"
-When searching the database, the following URIs are supported by lektor:
+When searching the database, the following URIs are supported by lektor. Those
+URIs are hidden, you should not use them, but here is some documentation about
+them.
 .PP
 .PD 0
 .TP
@@ -121,21 +132,15 @@ The supported categories in lektor are: \fBvo\fP, \fBva\fP, \fBcdg\fP,
 .SH "FILES"
 .PD 0
 .TP
-\fB$HOME/.config/lektor/config\fP                       general config file
+\fB$HOME/.config/lektor/lektor.ini\fP                   general config file for the user
 .TP
 \fB/home/kara/\fP                                       default prefix for the bakabase
 .TP
 \fB/home/kara/kara.db\fP                                default sqlite3 base for the bakabase
-.TP
-\fB$HOME/.local/libexec/lektor_info.csh\fP              script used to get informations about a running instance of lektor
-.TP
-\fB$HOME/.local/libexec/lektor_info_multiline.csh\fP    same, but with multiline output
-.TP
-\fB$HOME/.local/etc/lektor_host\fP                      the file storing the host to look to for the lektord running instance
 .PD
 .SH "SEE ALSO"
-\fIkaradata\fP(1),
-\fIlkinfo\fP(1),
+\fIlktadm\fP(1),
+\fIlkt\fP(1),
 \fImpc\fP(1),
 \fImpd\fP(1)
 .PP
diff --git a/inc/common/common.h b/inc/common/common.h
index 09d87d2d509af17bb1e02fa8f0ea9ab8a80dd553..010317a55701bac4c098445ba77458d04ac06c93 100644
--- a/inc/common/common.h
+++ b/inc/common/common.h
@@ -5,3 +5,8 @@
 
 #define not_implemented() __not_implemented(__func__,__FILE__,__LINE__)
 extern void __not_implemented(const char *func, char *file, int line);
+
+#define UNUSED(...) __unused((void *) __VA_ARGS__)
+void __unused(void *, ...);
+
+long get_mtime(const char *path);
diff --git a/inc/lektor/bufferfd.h b/inc/lektor/bufferfd.h
index 97bc0237268efdc33f5757032c108be91187dc35..c6e4ccbc826bcc4608bc1f67618aa2bff3c36f71 100644
--- a/inc/lektor/bufferfd.h
+++ b/inc/lektor/bufferfd.h
@@ -23,7 +23,7 @@
 
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <stdint.h>
 #include <stdlib.h>
 
diff --git a/inc/lektor/cmd.h b/inc/lektor/cmd.h
index 3ac6c3ad47698fa9996cce8320b3462ce945bc5e..de18772650d1e335c7fdfc9e1aa937a4ee2e555e 100644
--- a/inc/lektor/cmd.h
+++ b/inc/lektor/cmd.h
@@ -1,6 +1,5 @@
 #pragma once
 
-#include <lektor/define.h>
 #include <stdnoreturn.h>
 #include <stddef.h>
 
diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h
index 9e029011cb6b3c482da6393a6b2cea5ff9d7678d..8ea3e82fbb321e50a1f17a144296a5949fb4f52c 100644
--- a/inc/lektor/commands.h
+++ b/inc/lektor/commands.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <lektor/net.h>
 #include <lektor/window.h>
 
@@ -15,50 +15,43 @@
 
 /* Querying lektor's status */
 bool command_currentsong(struct lkt_state *srv, size_t c);
-bool command_status(struct lkt_state *srv, size_t c);
+bool command_status     (struct lkt_state *srv, size_t c);
 
 /* Controlling playback */
-bool command_next(sqlite3 *db, struct lkt_win *win, enum mpd_idle_flag *watch_mask_ptr);
-bool command_pause(sqlite3 *db, struct lkt_win *win, enum mpd_idle_flag *watch_mask_ptr);
-bool command_previous(sqlite3 *db, struct lkt_win *win, enum mpd_idle_flag *watch_mask_ptr);
-bool command_play(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX],
-                  enum mpd_idle_flag *watch_mask_ptr);
-bool command_stop(sqlite3 *db, struct lkt_win *win, enum mpd_idle_flag *watch_mask_ptr);
+bool command_next    (sqlite3 *db, struct lkt_win *win,                                   enum mpd_idle_flag *watch_mask_ptr);
+bool command_pause   (sqlite3 *db, struct lkt_win *win,                                   enum mpd_idle_flag *watch_mask_ptr);
+bool command_previous(sqlite3 *db, struct lkt_win *win,                                   enum mpd_idle_flag *watch_mask_ptr);
+bool command_play    (sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
+bool command_stop    (sqlite3 *db, struct lkt_win *win,                                   enum mpd_idle_flag *watch_mask_ptr);
 
 bool command_set_pos(sqlite3 *db, struct lkt_win *win, enum mpd_idle_flag *watch_mask_ptr, int index);
 
 /* The queue */
-bool command_add(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX],
-                 enum mpd_idle_flag *watch_mask_ptr);
-bool command_addid(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX],
-                   enum mpd_idle_flag *watch_mask_ptr);
-bool command_del(sqlite3 *db, struct lkt_win *win, char *pos_range, enum mpd_idle_flag *watch_mask_ptr);
-bool command_delid(sqlite3 *db, struct lkt_win *win, char *id, enum mpd_idle_flag *watch_mask_ptr);
-bool command_clear(sqlite3 *db, enum mpd_idle_flag *watch_mask_ptr);
-bool command_crop(sqlite3 *db, enum mpd_idle_flag *watch_mask_ptr);
-bool command_move(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
-bool command_shuffle(sqlite3 *db, enum mpd_idle_flag *watch_mask_ptr);
+bool command_add    (sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
+bool command_addid  (sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
+bool command_del    (sqlite3 *db, struct lkt_win *win, char *pos_range,                  enum mpd_idle_flag *watch_mask_ptr);
+bool command_delid  (sqlite3 *db, struct lkt_win *win, char *id,                         enum mpd_idle_flag *watch_mask_ptr);
+bool command_clear  (sqlite3 *db,                                                        enum mpd_idle_flag *watch_mask_ptr);
+bool command_crop   (sqlite3 *db,                                                        enum mpd_idle_flag *watch_mask_ptr);
+bool command_move   (sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX],                      enum mpd_idle_flag *watch_mask_ptr);
+bool command_shuffle(sqlite3 *db,                                                        enum mpd_idle_flag *watch_mask_ptr);
+bool command_playid (sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX], enum 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_playid(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX],
-                    enum mpd_idle_flag *watch_mask_ptr);
-bool command_queue_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX],
-                        long continuation);
+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(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
 bool command_plt_remove(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
-bool command_plt_clear(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
+bool command_plt_clear (sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
 bool command_plt_rename(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
 bool command_plt_export(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
 bool command_plt_import(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
-bool command_plt_add(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
+bool command_plt_add   (sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr);
 
 /* The help */
 bool command_help(struct lkt_state *srv, size_t c);
 
-/* Update the database */
-bool command_update(struct lkt_state *srv, enum mpd_idle_flag *watch_mask_ptr);
-
 /* Respond to the idle command */
 bool command_idle(struct lkt_state *srv, size_t c, struct lkt_command *cmd);
 
@@ -74,8 +67,7 @@ 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);
 
 /* Set options for the lektor such as `random`, `single`, `repeat`, etc */
 enum lkt_playback_option {
@@ -87,20 +79,20 @@ enum lkt_playback_option {
     lkt_playback_option_volume,
 };
 
-bool command_set_playback_option(struct lkt_state *srv, size_t c, enum lkt_playback_option opt,
-                                 char *args[LKT_MESSAGE_ARGS_MAX]);
+bool command_set_playback_option(struct lkt_state *srv, size_t c, enum lkt_playback_option opt, char *args[LKT_MESSAGE_ARGS_MAX]);
 
 /* Authentificate users */
-bool command_password(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_password(struct lkt_state *srv, size_t c,              char *argv[LKT_MESSAGE_ARGS_MAX]);
 bool command_user_add(struct lkt_state *srv, size_t c, sqlite3 *db, char *argv[LKT_MESSAGE_ARGS_MAX]);
 
 /* Program management control */
 bool command_restart(struct lkt_state *srv, size_t c);
-bool command_kill(struct lkt_state *srv, size_t c);
-bool command_rescan(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_kill   (struct lkt_state *srv, size_t c);
+bool command_update (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_rescan (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
 
 /* Sticker management */
-bool command_sticker_get(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_sticker_set(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_sticker_get   (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_sticker_set   (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
 bool command_sticker_delete(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_sticker_list(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_sticker_list  (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
diff --git a/inc/lektor/common.h b/inc/lektor/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..3495f2519ccaadb965b05807dab896e78c3056c5
--- /dev/null
+++ b/inc/lektor/common.h
@@ -0,0 +1,130 @@
+#pragma once
+
+#include <common/macro.h>
+#include <common/define.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* Defines */
+
+#define URL_MAX_LEN     1024
+#define DEFAULT_URL     "https://kurisu.iiens.net"
+#define GET_ID_JSON     DEFAULT_URL "/api_karas.php?id=%ld"
+#define GET_ID_FILE     DEFAULT_URL "/download.php?id=%ld"
+
+#define SELF_EXECUTABLE_LINUX           "/proc/self/exe"
+#define SELF_EXECUTABLE_FREEBSD         "/proc/curproc/file"
+#define SELF_EXECUTABLE_SOLARIS         "/proc/self/path/a.out"
+
+
+#define LKT_MAX_SQLITE_STATEMENT        1024
+#define PROTECTED_DATABASE              "disk"
+
+#define LKT_DATABASE_NAME_KID           "id"
+#define LKT_DATABASE_NAME_KNAME         "source_name"
+#define LKT_DATABASE_NAME_KTITLE        "song_title"
+#define LKT_DATABASE_NAME_KCAT          "category"
+#define LKT_DATABASE_NAME_KTYPE         "song_type"
+#define LKT_DATABASE_NAME_KAUTHOR       "author_name"
+#define LKT_DATABASE_NAME_KAUTHOR_YEAR  "author_year"
+#define LKT_DATABASE_NAME_KLANG         "language"
+#define LKT_DATABASE_KARA_COLUMNT_ANY   "any_col"
+#define LKT_DATABASE_KARA_ALL           "string"
+
+#define LEKTOR_TAG_MAX                  256
+#define LKT_MESSAGE_ARGS_MAX            32
+#define LKT_MESSAGE_MAX                 2048
+#define LKT_DEFAULT_LIST_SIZE           10
+
+enum mpd_idle_flag {
+    MPD_IDLE_NONE               = 0,
+
+    MPD_IDLE_DATABASE           = ( 1 << 1  ),
+    MPD_IDLE_UPDATE             = ( 1 << 2  ),
+    MPD_IDLE_STORED_PLAYLIST    = ( 1 << 3  ),
+    MPD_IDLE_PLAYLIST           = ( 1 << 4  ),
+    MPD_IDLE_PLAYER             = ( 1 << 5  ),
+    MPD_IDLE_MIXER              = ( 1 << 6  ),
+    MPD_IDLE_OUTPUT             = ( 1 << 7  ),
+    MPD_IDLE_OPTIONS            = ( 1 << 8  ),
+    MPD_IDLE_PARTITION          = ( 1 << 9  ),
+    MPD_IDLE_STICKER            = ( 1 << 10 ),
+    MPD_IDLE_SUBSCRIPTION       = ( 1 << 11 ),
+    MPD_IDLE_MESSAGE            = ( 1 << 12 ),
+
+    MPD_IDLE_ALL =
+        MPD_IDLE_DATABASE | MPD_IDLE_UPDATE | MPD_IDLE_STORED_PLAYLIST  |
+        MPD_IDLE_PLAYLIST | MPD_IDLE_PLAYER | MPD_IDLE_MIXER            |
+        MPD_IDLE_OUTPUT | MPD_IDLE_OPTIONS | MPD_IDLE_PARTITION         |
+        MPD_IDLE_STICKER | MPD_IDLE_SUBSCRIPTION | MPD_IDLE_MESSAGE,
+};
+
+#define LKT_BACKLOG         32
+#define COMMAND_LIST_MAX    64
+#define BUFFER_OUT_MAX      16
+#define MPD_VERSION         "0.21.16"
+
+/* Macros */
+
+#define SQLITE_PREPARE(db, stmt, SQL, goto_label)                               \
+    if (sqlite3_prepare_v2((sqlite3 *) db, SQL, -1, &(stmt), 0) != SQLITE_OK) { \
+        LOG_ERROR_SCT("DB", "Failed to prepare statement: %s",                  \
+                      sqlite3_errmsg((sqlite3 *) db));                          \
+        goto goto_label;                                                        \
+    }
+
+#define SQLITE_EXEC(db, SQL, goto_label)                                        \
+    if (sqlite3_exec((sqlite3 *) db, SQL, NULL, NULL, NULL) != SQLITE_OK) {     \
+        LOG_ERROR_SCT("DB", "Failed to exec statement: %s",                     \
+                      sqlite3_errmsg((sqlite3 *) db));                          \
+        goto goto_label;                                                        \
+    }
+
+#define SQLITE_BIND_TEXT(db, stmt, pos, text, error)                    \
+    if (sqlite3_bind_text(stmt, pos, text, -1, 0) != SQLITE_OK) {       \
+        LOG_ERROR_SCT("DB", "Failed to bind text %s at pos %d: %s",     \
+                      text, pos, sqlite3_errmsg((sqlite3 *) db));       \
+        goto error;                                                     \
+    }
+
+#define SQLITE_BIND_INT(db, stmt, pos, integer, error)                  \
+    if (sqlite3_bind_int(stmt, pos, integer) != SQLITE_OK) {            \
+        LOG_ERROR_SCT("DB", "Failed to bind int %d at pos %d: %s",      \
+                      integer, pos, sqlite3_errmsg((sqlite3 *) db));    \
+        goto error;                                                     \
+    }
+
+#define SQLITE_STEP(db, stmt, code, error)                              \
+    if (sqlite3_step(stmt) != code) {                                   \
+        LOG_ERROR_SCT("DB", "Failed to step: %s",                       \
+                      sqlite3_errmsg((sqlite3 *) db));                  \
+        goto error;                                                     \
+    }
+
+#define SQLITE_STEP_ROW(db, stmt, error)    SQLITE_STEP(db, stmt, SQLITE_ROW, error)
+#define SQLITE_STEP_DONE(db, stmt, error)   SQLITE_STEP(db, stmt, SQLITE_DONE, error)
+#define SQLITE_STEP_OK(db, stmt, error)     SQLITE_STEP(db, stmt, SQLITE_OK, error)
+
+#define SQLITE_DO_ROLLBACK(db)                                          \
+    sqlite3_exec((sqlite3 *) db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL);
+
+/* Random things */
+
+/* Read `bytes` as the big endian representation of a 32-bit unsigned integer.
+   `n` is the number of bytes in `bytes`
+   Returns 0 if n is 0.
+   Restriction: n <= 4 */
+uint32_t be_uint32_t(const uint8_t bytes[], size_t n);
+
+/* Same as `be_uint32_t` but for 64-bit unsigned integers.
+   Restriction: n <= 8 */
+uint64_t be_uint64_t(const uint8_t bytes[], size_t n);
+
+/* Trim the string `str` of the char `c` from the right and the left.
+   The string may not be null terminated.
+   Returns a pointer to the the trimmed string
+   Restrictions: the len of the string must be `len`. */
+char *trim(char *str, size_t len, char c);
+
+/* Get a line from stdin safely. */
+int get_stdin_line(const char *prompt, char *buf, size_t len);
diff --git a/inc/lektor/config.h b/inc/lektor/config.h
index fc013160204b3dd3f45f7fc5ff0aa9789a38da8a..618de57c06aacfaf1cb041d704032f1e7dbe7441 100644
--- a/inc/lektor/config.h
+++ b/inc/lektor/config.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <stddef.h>
 #include <sqlite3.h>
 
diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index 3ec3f63d3cb119d57f6a03b60b7cb23132aa7866..f74e2a16332743df3e584b1da30aa229c5bad011 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <lektor/mkv.h>
 #include <lektor/uri.h>
 
@@ -22,57 +22,62 @@ struct lkt_queue_state {
     int length;
 };
 
+long database_get_timestamp(volatile sqlite3 *db);
+void database_stamp(volatile sqlite3 *db);
+void database_updated(volatile sqlite3 *db);
+
 /* Open correctly a database for lektor. */
-bool database_new(sqlite3 **db);
-bool database_open(sqlite3 *db, const char *dbpath);
+bool database_new   (sqlite3 **db);
+bool database_init  (const char *dbpath);
+bool database_open  (sqlite3 *db, const char *dbpath);
 bool database_attach(sqlite3 *db, const char *name, const char *dbpath);
 bool database_detach(sqlite3 *db, const char *name);
 
 /* Get information on the queue and currently playing kara. */
-bool database_queue_state(sqlite3 *db, struct lkt_queue_state *res);
+bool database_queue_state       (sqlite3 *db, struct lkt_queue_state *res);
 bool database_queue_current_kara(sqlite3 *db, struct kara_metadata *res, int *id);
 
-bool database_queue_set_paused(sqlite3 *db, bool paused);
+bool database_queue_set_paused       (sqlite3 *db, bool paused);
 bool database_queue_set_current_index(sqlite3 *db, int idx);
-bool database_queue_get_current_file(sqlite3 *db, char filepath[PATH_MAX]);
+bool database_queue_get_current_file (sqlite3 *db, char filepath[PATH_MAX]);
 
 /* Mpv and database synchronisation. */
 bool database_sync_mpv_state(sqlite3 *db, mpv_handle **mpv);
 
 /* Update the database. */
-bool database_update(sqlite3 *db, const char *kara_dir);
-bool database_update_add(sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id,
-                         bool avail);
+bool database_update(volatile sqlite3 *db, const char *kara_dir);
+bool database_update_add(volatile sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail);
+bool database_update_set_available(volatile sqlite3 *db, uint64_t id);
 
 /* Control the content of the queue. */
-bool database_queue_add_id(sqlite3 *db, int id, int priority);
-bool database_queue_add_query(sqlite3 *db, const char *query, int priority);
-bool database_queue_add_author(sqlite3 *db, const char *author, int priority);
-bool database_queue_add_language(sqlite3 *db, const char *author, int priority);
-bool database_queue_add_category(sqlite3 *db, const char *author, int priority);
-bool database_queue_add_type(sqlite3 *db, const char *author, int priority);
-bool database_queue_add_plt(sqlite3 *db, const char *plt_name, int priority);
-
-bool database_queue_insert_query(sqlite3 *db, const char *query, int pos);
-bool database_queue_insert_id(sqlite3 *db, int id);
-bool database_queue_insert_author(sqlite3 *db, const char *author);
+bool database_queue_add_id      (sqlite3 *db, int id,               int priority);
+bool database_queue_add_query   (sqlite3 *db, const char *query,    int priority);
+bool database_queue_add_author  (sqlite3 *db, const char *author,   int priority);
+bool database_queue_add_language(sqlite3 *db, const char *author,   int priority);
+bool database_queue_add_category(sqlite3 *db, const char *author,   int priority);
+bool database_queue_add_type    (sqlite3 *db, const char *author,   int priority);
+bool database_queue_add_plt     (sqlite3 *db, const char *plt_name, int priority);
+
+bool database_queue_insert_query   (sqlite3 *db, const char *query, int pos);
+bool database_queue_insert_id      (sqlite3 *db, int id);
+bool database_queue_insert_author  (sqlite3 *db, const char *author);
 bool database_queue_insert_language(sqlite3 *db, const char *author);
 bool database_queue_insert_category(sqlite3 *db, const char *author);
-bool database_queue_insert_type(sqlite3 *db, const char *author);
-bool database_queue_insert_plt(sqlite3 *db, const char *plt_name);
+bool database_queue_insert_type    (sqlite3 *db, const char *author);
+bool database_queue_insert_plt     (sqlite3 *db, const char *plt_name);
 
-bool database_queue_del_id(sqlite3 *db, int id);
+bool database_queue_del_id (sqlite3 *db, int id);
 bool database_queue_del_pos(sqlite3 *db, int pos);
-bool database_queue_clear(sqlite3 *db);
-bool database_queue_crop(sqlite3 *db);
-bool database_queue_move(sqlite3 *db, int from, int to);
+bool database_queue_clear  (sqlite3 *db);
+bool database_queue_crop   (sqlite3 *db);
+bool database_queue_move   (sqlite3 *db, int from, int to);
 bool database_queue_shuffle(sqlite3 *db);
-bool database_queue_seekid(sqlite3 *db, int id, int *out_pos);
+bool database_queue_seekid (sqlite3 *db, int id, int *out_pos);
 
 /* Control the playing state of the queue. */
 bool database_queue_toggle_pause(sqlite3 *db);
-bool database_queue_play(sqlite3 *db, int pos);
-bool database_queue_stop(sqlite3 *db);
+bool database_queue_play        (sqlite3 *db, int pos);
+bool database_queue_stop        (sqlite3 *db);
 
 /* A search callback to be called after each matched row */
 struct lkt_callback {
@@ -105,7 +110,7 @@ typedef bool (*lkt_search_database_func)(struct lkt_state *srv, size_t c, int id
         const char *row);
 
 bool database_search_database_init(sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
-bool database_search_queue_init(sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
+bool database_search_queue_init   (sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
 bool database_search_iter(struct lkt_search *item);
 
 /* Next and prev operation on the queue. */
@@ -113,11 +118,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_set(sqlite3 *db, const char *section, const char *key, const char *value);
+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_exists(sqlite3 *db, const char *section, const char *key);
-bool database_config_queue(sqlite3 *db, const char *option, int value);
+bool database_config_get_int (sqlite3 *db, const char *section, const char *key, int *value);
+bool database_config_exists  (sqlite3 *db, const char *section, const char *key);
+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 */
@@ -131,16 +136,16 @@ struct lkt_playlist_metadata {
 };
 
 /* Control playlists */
-bool database_plt_create(sqlite3 *db, const char *name);
-bool database_plt_remove(sqlite3 *db, const char *name);
+bool database_plt_create    (sqlite3 *db, const char *name);
+bool database_plt_remove    (sqlite3 *db, const char *name);
 bool database_plt_remove_pos(sqlite3 *db, const char *name, int pos);
-bool database_plt_clear(sqlite3 *db, const char *name);
-bool database_plt_rename(sqlite3 *db, const char *old_name, const char *new_name);
+bool database_plt_clear     (sqlite3 *db, const char *name);
+bool database_plt_rename    (sqlite3 *db, const char *old_name, const char *new_name);
 
 bool database_plt_export(sqlite3 *db, const char *name);
 bool database_plt_import(sqlite3 *db, const char *name);
 
-bool database_plt_add_uri(sqlite3 *db, const char *name, struct lkt_uri_t *uri);
+bool database_plt_add_uri(sqlite3 *db, const char *name, struct lkt_uri *uri);
 
 /* User control, yeah, MPD authentification sucks. */
 bool database_user_authentificate(sqlite3 *db, const char *password);
@@ -155,10 +160,9 @@ struct sticker_callback {
     bool (*call)(void *args, const char *sticker, const char *type, int uri, int value);
 };
 
-bool database_sticker_create(sqlite3 *db, const char *name);
-bool database_sticker_delete(sqlite3 *db, const char *name);
+bool database_sticker_create        (sqlite3 *db, const char *name);
+bool database_sticker_delete        (sqlite3 *db, const char *name);
 bool database_sticker_delete_specify(sqlite3 *sb, const char *type, int uri, const char *name);
-bool database_sticker_list(sqlite3 *db, const char *type, struct sticker_callback *call);
-bool database_sticker_set(sqlite3 *db, const char *type, const char *name, int uri, int value);
-bool database_sticker_get(sqlite3 *db, const char *type, const char *name, int uri,
-                          struct sticker_callback *call);
+bool database_sticker_list          (sqlite3 *db, const char *type, struct sticker_callback *call);
+bool database_sticker_set           (sqlite3 *db, const char *type, const char *name, int uri, int value);
+bool database_sticker_get           (sqlite3 *db, const char *type, const char *name, int uri, struct sticker_callback *call);
diff --git a/inc/lektor/define.h b/inc/lektor/define.h
deleted file mode 100644
index d68144f42a19e9dae0c1378489aa92e005361c8e..0000000000000000000000000000000000000000
--- a/inc/lektor/define.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include <common/define.h>
-
-#define LKT_MAX_SQLITE_STATEMENT    1024
-#define PROTECTED_DATABASE          "disk"
-
-#define LKT_DATABASE_NAME_KID           "id"
-#define LKT_DATABASE_NAME_KNAME         "source_name"
-#define LKT_DATABASE_NAME_KTITLE        "song_title"
-#define LKT_DATABASE_NAME_KCAT          "song_type"
-#define LKT_DATABASE_NAME_KTYPE         "category"
-#define LKT_DATABASE_NAME_KAUTHOR       "author_name"
-#define LKT_DATABASE_NAME_KAUTHOR_YEAR  "author_year"
-#define LKT_DATABASE_NAME_KLANG         "language"
-#define LKT_DATABASE_KARA_COLUMNT_ANY   "any_col"
-#define LKT_DATABASE_KARA_ALL           "string"
-
-#define LEKTOR_TAG_MAX          256
-#define LKT_MESSAGE_ARGS_MAX    32
-#define LKT_MESSAGE_MAX         2048
-#define LKT_DEFAULT_LIST_SIZE   10
-
-enum mpd_idle_flag {
-    MPD_IDLE_NONE               = 0,
-
-    MPD_IDLE_DATABASE           = ( 1 << 1  ),
-    MPD_IDLE_UPDATE             = ( 1 << 2  ),
-    MPD_IDLE_STORED_PLAYLIST    = ( 1 << 3  ),
-    MPD_IDLE_PLAYLIST           = ( 1 << 4  ),
-    MPD_IDLE_PLAYER             = ( 1 << 5  ),
-    MPD_IDLE_MIXER              = ( 1 << 6  ),
-    MPD_IDLE_OUTPUT             = ( 1 << 7  ),
-    MPD_IDLE_OPTIONS            = ( 1 << 8  ),
-    MPD_IDLE_PARTITION          = ( 1 << 9  ),
-    MPD_IDLE_STICKER            = ( 1 << 10 ),
-    MPD_IDLE_SUBSCRIPTION       = ( 1 << 11 ),
-    MPD_IDLE_MESSAGE            = ( 1 << 12 ),
-
-    MPD_IDLE_ALL =
-        MPD_IDLE_DATABASE | MPD_IDLE_UPDATE | MPD_IDLE_STORED_PLAYLIST  |
-        MPD_IDLE_PLAYLIST | MPD_IDLE_PLAYER | MPD_IDLE_MIXER            |
-        MPD_IDLE_OUTPUT | MPD_IDLE_OPTIONS | MPD_IDLE_PARTITION         |
-        MPD_IDLE_STICKER | MPD_IDLE_SUBSCRIPTION | MPD_IDLE_MESSAGE,
-};
-
-#define LKT_BACKLOG         32
-#define COMMAND_LIST_MAX    64
-#define BUFFER_OUT_MAX      16
-#define MPD_VERSION         "0.21.16"
-
diff --git a/inc/lektor/macro.h b/inc/lektor/macro.h
deleted file mode 100644
index 48c66716fec43acae1c01471611bcd0c95a87113..0000000000000000000000000000000000000000
--- a/inc/lektor/macro.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-#include <common/macro.h>
-
-#define SQLITE_PREPARE(db, stmt, SQL, goto_label)                       \
-    if (sqlite3_prepare_v2(db, SQL, -1, &(stmt), 0) != SQLITE_OK) {     \
-        LOG_ERROR_SCT("DB", "Failed to prepare statement: %s",          \
-                      sqlite3_errmsg(db));                              \
-        goto goto_label;                                                \
-    }
-
-#define SQLITE_EXEC(db, SQL, goto_label)                                \
-    if (sqlite3_exec(db, SQL, NULL, NULL, NULL) != SQLITE_OK) {         \
-        LOG_ERROR_SCT("DB", "Failed to exec statement: %s",             \
-                      sqlite3_errmsg(db));                              \
-        goto goto_label;                                                \
-    }
-
-#define SQLITE_BIND_TEXT(db, stmt, pos, text, error)                    \
-    if (sqlite3_bind_text(stmt, pos, text, -1, 0) != SQLITE_OK) {       \
-        LOG_ERROR_SCT("DB", "Failed to bind text %s at pos %d: %s",     \
-                      text, pos, sqlite3_errmsg(db));                   \
-        goto error;                                                     \
-    }
-
-#define SQLITE_BIND_INT(db, stmt, pos, integer, error)                  \
-    if (sqlite3_bind_int(stmt, pos, integer) != SQLITE_OK) {            \
-        LOG_ERROR_SCT("DB", "Failed to bind int %d at pos %d: %s",      \
-                      integer, pos, sqlite3_errmsg(db));                \
-        goto error;                                                     \
-    }
-
-#define SQLITE_STEP(db, stmt, code, error)                              \
-    if (sqlite3_step(stmt) != code) {                                   \
-        LOG_ERROR_SCT("DB", "Failed to step and get a row: %s",         \
-                      sqlite3_errmsg(db));                              \
-        goto error;                                                     \
-    }
-
-#define SQLITE_STEP_ROW(db, stmt, error)    SQLITE_STEP(db, stmt, SQLITE_ROW, error)
-#define SQLITE_STEP_DONE(db, stmt, error)   SQLITE_STEP(db, stmt, SQLITE_DONE, error)
-#define SQLITE_STEP_OK(db, stmt, error)     SQLITE_STEP(db, stmt, SQLITE_OK, error)
-
-#define SQLITE_DO_ROLLBACK(db)                                          \
-    sqlite3_exec(db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL);
diff --git a/inc/lektor/mkv.h b/inc/lektor/mkv.h
index 681315934b96e0b0b5557ef0dbaaeea50d20f71b..c88114269b99f7087f27a031160f77922faf0cff 100644
--- a/inc/lektor/mkv.h
+++ b/inc/lektor/mkv.h
@@ -23,7 +23,7 @@
  */
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <linux/limits.h>
 #include <stddef.h>
 
@@ -56,8 +56,7 @@ struct kara {
 int kara_metadata_read(struct kara_metadata *dst, const char *filename);
 
 /* Write metadata to a mkv file */
-int kara_metadata_write(struct kara_metadata *mdt, const char *filename,
-                        const char *mkvpropedit);
+int kara_metadata_write(struct kara_metadata *mdt, const char *filename, const char *mkvpropedit);
 
 /* Set the metadata for the file according to its path. */
 int metadata_set_file(char *karapath, const char *mkvpropedit);
diff --git a/inc/lektor/module/module_sdl2.h b/inc/lektor/module/module_sdl2.h
index e4a2dd2c8c602baa453b69c8e20233f6e9cbd1e1..90eacc578aa4d769643c33c59e9eff5ff847fd22 100644
--- a/inc/lektor/module/module_sdl2.h
+++ b/inc/lektor/module/module_sdl2.h
@@ -1,6 +1,5 @@
 #pragma once
 
-#include <lektor/define.h>
 #include <stdbool.h>
 #include <sqlite3.h>
 #include <lektor/window.h>
@@ -16,6 +15,7 @@ int module_set_function(void *mod, void *handle);
 bool module_sdl2_new(struct lkt_win *const win);
 void module_sdl2_close(struct lkt_win *const win);
 void module_sdl2_free(struct lkt_win *const win);
+void module_sdl2_attach(struct lkt_win *const win, void *server);
 
 bool module_sdl2_toggle_pause(struct lkt_win *const win);
 bool module_sdl2_load_file(struct lkt_win *const win, const char *filepath);
diff --git a/inc/lektor/module/module_x11.h b/inc/lektor/module/module_x11.h
index 880452463c30b72ac7f1e6405a91abf92a6df7ba..0ea84737be6fed8b92296da2d9dc3b46483ed552 100644
--- a/inc/lektor/module/module_x11.h
+++ b/inc/lektor/module/module_x11.h
@@ -1,6 +1,5 @@
 #pragma once
 
-#include <lektor/define.h>
 #include <stdbool.h>
 #include <sqlite3.h>
 #include <lektor/window.h>
@@ -16,6 +15,7 @@ int module_set_function(void *mod, void *handle);
 bool module_x11_new(struct lkt_win *const win);
 void module_x11_close(struct lkt_win *const win);
 void module_x11_free(struct lkt_win *const win);
+void module_x11_attach(struct lkt_win *const win, void *server);
 
 bool module_x11_toggle_pause(struct lkt_win *const win);
 bool module_x11_load_file(struct lkt_win *const win, const char *filepath);
diff --git a/inc/lektor/net.h b/inc/lektor/net.h
index 20caa955aaee2f512405b8f5d9458824073df24a..f6a7f4afc8349ccb53c491ee70d69697a7ffbe8c 100644
--- a/inc/lektor/net.h
+++ b/inc/lektor/net.h
@@ -1,10 +1,19 @@
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/mkv.h>
+#include <lektor/common.h>
 #include <lektor/config.h>
 #include <lektor/window.h>
+#include <lektor/thread.h>
+#include <lektor/uri.h>
+
 #include <sqlite3.h>
 #include <mpv/client.h>
+#include <curl/curl.h>
+#include <sqlite3.h>
+#include <json-c/json.h>
+#include <inttypes.h>
+#include <stdbool.h>
 
 #include <stddef.h>
 
@@ -14,11 +23,34 @@ struct lkt_command {
     long cont;
 };
 
+/* Repository, e.g. Kurisu */
+struct lkt_repo {
+    /* Just the repo */
+    const char *name;
+    const char *base_url;
+    const char *kara_dir;
+    const char *get_all_json;
+    const char *get_id_json;
+    const char *get_id_file;
+    const uint64_t version;
+
+    /* The database */
+    volatile sqlite3 *db;
+};
+
+int  repo_new (struct lkt_repo *const repo, const char *name, const char *url, volatile sqlite3 *db);
+void repo_free(struct lkt_repo *const repo);
+
+int repo_get_id          (struct lkt_repo *const repo, const uint64_t id, struct kara_metadata *mdt);
+int repo_update          (struct lkt_repo *const repo);
+int repo_download_id_sync(struct lkt_repo *const repo, const uint64_t id, const char *kara_path, struct kara_metadata *mdt);
+
 /* Create and destruct a command structure. */
 struct lkt_command lkt_command_parse(char *raw);
 struct lkt_command lkt_command_clone(struct lkt_command *c);
 void lkt_command_free(struct lkt_command *c);
 
+/* Messages that are send and recieved */
 struct lkt_message {
     size_t ref_count;
     char data[LKT_MESSAGE_MAX];
@@ -36,10 +68,12 @@ struct lkt_state {
     size_t fds_len;
     size_t fds_max;
 
-    sqlite3 *db;
+    volatile sqlite3 *db;
     const char *kara_prefix;
 
-    enum mpd_idle_flag mpd_idle_events;
+    struct lkt_repo repo;
+
+    volatile enum mpd_idle_flag mpd_idle_events;
 
     struct lkt_win win;
 };
@@ -50,7 +84,7 @@ void lkt_state_send(struct lkt_state *srv, size_t c, struct lkt_message *msg);
 /* Get and set continuation state for a client. */
 size_t lkt_remaining_msg(struct lkt_state *srv, size_t c);
 
-int lkt_get_continuation(struct lkt_state *srv, size_t c);
+int  lkt_get_continuation(struct lkt_state *srv, size_t c);
 void lkt_set_continuation(struct lkt_state *srv, size_t c, int i);
 
 /* Get the mask to watch for events for a given client, to be used with the `idle` command.
@@ -62,3 +96,4 @@ bool lkt_client_auth(struct lkt_state *srv, size_t c, bool set_auth);
 
 /* The server's listen function. */
 int lkt_listen(void);
+
diff --git a/inc/lektor/repo.h b/inc/lektor/repo.h
deleted file mode 100644
index 11b127e9cad0febc66484c4b30392a6fc90590a9..0000000000000000000000000000000000000000
--- a/inc/lektor/repo.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include <lektor/define.h>
-#include <lektor/mkv.h>
-#include <lektor/thread.h>
-#include <curl/curl.h>
-#include <sqlite3.h>
-#include <json-c/json.h>
-#include <inttypes.h>
-#include <stdbool.h>
-
-struct lkt_repo {
-    const char *name;
-    const char *base_url;
-    const char *kara_dir;
-    const char *get_all_json;
-    const char *get_id_json;
-    const char *get_id_file;
-    const uint64_t version;
-};
-
-int repo_new(struct lkt_repo *const repo, const char *name, const char *url);
-void repo_free(struct lkt_repo *const repo);
-
-/* Only one possible repo thread is authorized. */
-int repo_new_thread(struct lkt_repo *const repo);
-int repo_join_thread(void);
-
-/* Get metadata of a kara. */
-int repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata *mdt);
-int repo_get_alljson_sync(struct lkt_repo *const repo, struct json_object **json);
-int repo_get_allid_async(void);
-
-/* Download a kara. */
-int repo_download_id_sync(struct lkt_repo *const repo, sqlite3 *db, const uint64_t id,
-                          const char *kara_path, struct kara_metadata *mdt_ret);
-int repo_download_id_async(const size_t id);
-int repo_get_kara_async(struct kara **downloaded);
diff --git a/inc/lektor/thread.h b/inc/lektor/thread.h
index dcd3d75c23ede39f42f314ea098e04c1bb1a812b..3e5e07a7ec809eedcda4642e8ac47233f2fd4e75 100644
--- a/inc/lektor/thread.h
+++ b/inc/lektor/thread.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <pthread.h>
 #include <sys/types.h>
 
@@ -28,18 +28,17 @@ struct poller_thread_arg {
 
 
 /* Create a new thread. Returns 0 on success, a non zero value on error. */
-int lkt_th_new(struct poller_thread *th, unsigned int init_sizes,
-               void *(*func)(struct poller_thread_arg *), void *args);
+int poller_new(struct poller_thread *th, unsigned int init_sizes, void *(*func)(struct poller_thread_arg *), void *args);
 
 /* Joins a thread. Returns 0 on success, a non zero value on error. */
-int lkt_th_join(struct poller_thread *th, void **ret);
+int poller_join(struct poller_thread *th, void **ret);
 
 /* Input qeueu manipulations. */
-int lkt_th_append_input(struct poller_thread *th, void *ptr);
-int lkt_th_pop_input(struct poller_thread *th, void **ptr);
-int lkt_th_head_input(struct poller_thread *th, void **ptr);
+int poller_append_input(struct poller_thread *th, void *ptr);
+int poller_pop_input   (struct poller_thread *th, void **ptr);
+int poller_head_input  (struct poller_thread *th, void **ptr);
 
 /* Output qeueu manipulations. */
-int lkt_th_append_output(struct poller_thread *th, void *ptr);
-int lkt_th_pop_output(struct poller_thread *th, void **ptr);
-int lkt_th_head_output(struct poller_thread *th, void **ptr);
+int poller_append_output(struct poller_thread *th, void *ptr);
+int poller_pop_output   (struct poller_thread *th, void **ptr);
+int poller_head_output  (struct poller_thread *th, void **ptr);
diff --git a/inc/lektor/uri.h b/inc/lektor/uri.h
index ea2d76631c7e5990d02bc5c43856e16d30486496..c9a4d932566e8432b932bcbe676d69803d6cab41 100644
--- a/inc/lektor/uri.h
+++ b/inc/lektor/uri.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <stddef.h>
 #include <stddef.h>
 #include <stdbool.h>
@@ -16,7 +16,7 @@ enum lkt_uri_type {
     uri_query,
 };
 
-struct lkt_uri_t {
+struct lkt_uri {
     enum lkt_uri_type type;
     void *value;
 
@@ -24,5 +24,9 @@ struct lkt_uri_t {
 };
 
 /* Create and delete URIs */
-bool lkt_uri_from(struct lkt_uri_t *ret, char *const str);
-void lkt_uri_free(struct lkt_uri_t *ret);
+bool lkt_uri_from(struct lkt_uri *ret, char *const str);
+void lkt_uri_free(struct lkt_uri *ret);
+
+/* Make an URL to download from kurisu.
+   base_url is the prefix for the api, e.g. https://kurisu.iiens.net/api_kara.php */
+int lkt_uri_to_url(struct lkt_uri *uri, const char *base_url, char *ret, size_t len);
diff --git a/inc/lektor/utils.h b/inc/lektor/utils.h
deleted file mode 100644
index aa175cc8f40d0410a82acdd9677487e98a7edfb3..0000000000000000000000000000000000000000
--- a/inc/lektor/utils.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Random things. */
-#pragma once
-
-#include <lektor/define.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-/* Read `bytes` as the big endian representation of a 32-bit unsigned integer.
-   `n` is the number of bytes in `bytes`
-   Returns 0 if n is 0.
-   Restriction: n <= 4 */
-uint32_t be_uint32_t(const uint8_t bytes[], size_t n);
-
-/* Same as `be_uint32_t` but for 64-bit unsigned integers.
-   Restriction: n <= 8 */
-uint64_t be_uint64_t(const uint8_t bytes[], size_t n);
-
-/* Trim the string `str` of the char `c` from the right and the left.
-   The string may not be null terminated.
-   Returns a pointer to the the trimmed string
-   Restrictions: the len of the string must be `len`. */
-char *trim(char *str, size_t len, char c);
-
-/* Get a line from stdin safely. */
-int get_stdin_line(const char *prompt, char *buf, size_t len);
diff --git a/inc/lektor/window.h b/inc/lektor/window.h
index 35d87fbccbab09cdc17f8537d9b87527dc7b0975..624c05c8284414c2f9b00e2c9ce570d7a9a4b281 100644
--- a/inc/lektor/window.h
+++ b/inc/lektor/window.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <stdbool.h>
 #include <sqlite3.h>
 
@@ -15,9 +15,10 @@ struct lkt_win {
     void *handle;                       /* the libdl handle                                 */
 
     /* Create and free the window */
-    bool (*new)(struct lkt_win *win);   /* Create a window or only the mpv context          */
-    void (*close)(struct lkt_win *win); /* Close the mpv context, not the window.           */
-    void (*free)(struct lkt_win *win);  /* Entirelly liberate all the resources             */
+    bool (*new)(struct lkt_win *win);                   /* Create a window or only the mpv context  */
+    void (*close)(struct lkt_win *win);                 /* Close the mpv context, not the window    */
+    void (*free)(struct lkt_win *win);                  /* Entirelly liberate all the resources     */
+    void (*attach)(struct lkt_win *win, void *server);  /* Get properties from the struct lkt_state */
 
     /* Playback control */
     bool (*toggle_pause)(struct lkt_win *win);
@@ -25,7 +26,6 @@ struct lkt_win {
     bool (*set_volume)(struct lkt_win *win, int vol);
 
     /* Get playback properties */
-    // bool (*is_paused)(struct lkt_win *win, bool *ret);
     bool (*get_duration)(struct lkt_win *win, int *dur_sec);
     bool (*get_elapsed)(struct lkt_win *win, int *elapsed_sec);
 
diff --git a/inc/mthread/mthread.h b/inc/mthread/mthread.h
index c708a4414d54bce351aaa564ee4a5b4da46c9f2d..869e0ddd4c3b0ecfc0b1e4eaca697a5a5761046a 100644
--- a/inc/mthread/mthread.h
+++ b/inc/mthread/mthread.h
@@ -9,8 +9,11 @@ typedef struct mthread_list_s mthread_list_t;
 struct mthread_s;
 typedef struct mthread_s *mthread_t;
 
-struct mthread_attr_s;
-typedef struct mthread_attr_s mthread_attr_t;
+typedef enum {
+    ATTR_NONE           = 0,
+    ATTR_DETACHED       = (1 << 1),
+    ATTR_DETACHED_FREE  = (1 << 2),
+} mthread_attr_t;
 
 struct mthread_mutex_s {
     volatile int nb_thread;
@@ -45,38 +48,35 @@ typedef struct mthread_sem_s mthread_sem_t;
 
 /* Function for handling threads.  */
 
-int mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr, void *(*__start_routine) (void *),
-                   void *__arg);
+extern int mthread_create(mthread_t *__threadp, const mthread_attr_t __attr, void *(*__start_routine) (void *), void *__arg);
 
-mthread_t mthread_self(void);
-int mthread_equal(mthread_t __thread1, mthread_t __thread2);
-void mthread_exit(void *__retval);
-int mthread_join(mthread_t __th, void **__thread_return);
+extern mthread_t mthread_self(void);
+extern int  mthread_equal (mthread_t __thread1, mthread_t __thread2);
+extern void mthread_exit  (void *__retval);
+extern int  mthread_join  (mthread_t __th, void **__thread_return);
 
 /* Functions for mutex handling.  */
 
-int mthread_mutex_init (mthread_mutex_t *__mutex,
-                        const mthread_mutexattr_t *__mutex_attr);
-int mthread_mutex_destroy(mthread_mutex_t *__mutex);
-int mthread_mutex_trylock(mthread_mutex_t *__mutex);
-int mthread_mutex_lock(mthread_mutex_t *__mutex);
-int mthread_mutex_unlock(mthread_mutex_t *__mutex);
+extern int mthread_mutex_init   (mthread_mutex_t *__mutex, const mthread_mutexattr_t *__mutex_attr);
+extern int mthread_mutex_destroy(mthread_mutex_t *__mutex);
+extern int mthread_mutex_trylock(mthread_mutex_t *__mutex);
+extern int mthread_mutex_lock   (mthread_mutex_t *__mutex);
+extern int mthread_mutex_unlock (mthread_mutex_t *__mutex);
 
 /* Functions for handling conditional variables.  */
 
-int mthread_cond_init(mthread_cond_t *__cond,
-                      const mthread_condattr_t *__cond_attr);
-int mthread_cond_destroy(mthread_cond_t *__cond);
-int mthread_cond_signal(mthread_cond_t *__cond);
-int mthread_cond_broadcast(mthread_cond_t *__cond);
-int mthread_cond_wait(mthread_cond_t *__cond, mthread_mutex_t *__mutex);
+extern int mthread_cond_init     (mthread_cond_t *__cond, const mthread_condattr_t *__cond_attr);
+extern int mthread_cond_destroy  (mthread_cond_t *__cond);
+extern int mthread_cond_signal   (mthread_cond_t *__cond);
+extern int mthread_cond_broadcast(mthread_cond_t *__cond);
+extern int mthread_cond_wait     (mthread_cond_t *__cond, mthread_mutex_t *__mutex);
 
 /* Functions for handling thread-specific data.  */
 
-int mthread_key_create(mthread_key_t *__key, void (*__destr_function) (void *));
-int mthread_key_delete(mthread_key_t __key);
-int mthread_setspecific(mthread_key_t __key, const void *__pointer);
-void *mthread_getspecific(mthread_key_t __key);
+extern int  mthread_key_create  (mthread_key_t *__key, void (*__destr_function) (void *));
+extern int  mthread_key_delete  (mthread_key_t __key);
+extern int  mthread_setspecific (mthread_key_t __key, const void *__pointer);
+extern void *mthread_getspecific(mthread_key_t __key);
 
 
 /* Functions for handling initialization.  */
@@ -88,22 +88,21 @@ void *mthread_getspecific(mthread_key_t __key);
 
    The initialization functions might throw exception which is why
    this function is not marked with .  */
-int mthread_once(mthread_once_t *__once_control, void (*__init_routine) (void));
+extern int mthread_once(mthread_once_t *__once_control, void (*__init_routine) (void));
 
 /* Functions for handling semaphore.  */
 
-int mthread_sem_init(mthread_sem_t *sem, unsigned int value);
-int mthread_sem_wait(mthread_sem_t *sem);     /* P(sem), wait(sem) */
-int mthread_sem_post(mthread_sem_t *sem);     /* V(sem), signal(sem) */
+extern int mthread_sem_init(mthread_sem_t *sem, unsigned int value);
+extern int mthread_sem_wait(mthread_sem_t *sem);     /* P(sem), wait(sem) */
+extern int mthread_sem_post(mthread_sem_t *sem);     /* V(sem), signal(sem) */
 
-int mthread_sem_getvalue(mthread_sem_t *sem, int *sval);
-int mthread_sem_trywait(mthread_sem_t *sem);
+extern int mthread_sem_getvalue(mthread_sem_t *sem, int *sval);
+extern int mthread_sem_trywait (mthread_sem_t *sem);
+extern int mthread_sem_destroy (mthread_sem_t *sem);  /* undo sem_init() */
 
-int mthread_sem_destroy(mthread_sem_t *sem);  /* undo sem_init() */
-
-void mthread_yield();
+extern void mthread_yield();
 
 /* Initialize mthread. */
 
-void mthread_init(void);
-void *mthread_main(void *arg);
+extern void mthread_init(void);
+extern void *mthread_main(void *arg);
diff --git a/inc/mthread/mthread_internal.h b/inc/mthread/mthread_internal.h
index c4eb661d17602bc96fd4bb81395e9176ae039a26..0462d0cf9ea8a4139e3178279770d6941a23a504 100644
--- a/inc/mthread/mthread_internal.h
+++ b/inc/mthread/mthread_internal.h
@@ -29,6 +29,7 @@ typedef struct {
 } mthread_virtual_processor_t;
 
 typedef enum { RUNNING, BLOCKED, ZOMBIE } mthread_status_t;
+typedef volatile enum { JOINABLE = 0, DETACHED = 1, DETACHED_FREE = 2 } mthread_detached_flag_t;
 
 #define INIT_KEYS_LIST 48
 
@@ -45,6 +46,7 @@ struct mthread_s {
     void *(*__start_routine) (void *);
     volatile struct mthread_s *next;
     volatile mthread_status_t status;
+    mthread_detached_flag_t detached;
     int not_migrable;
     mthread_virtual_processor_t *vp;
     void *stack;
@@ -53,17 +55,17 @@ struct mthread_s {
 
 #define MTHREAD_LIST_INIT { .first = NULL, .last = NULL, .lock = 0 }
 
-int mthread_test_and_set(mthread_tst_t *atomic);
-void mthread_spinlock_lock(mthread_tst_t *atomic);
+int  mthread_test_and_set   (mthread_tst_t *atomic);
+void mthread_spinlock_lock  (mthread_tst_t *atomic);
 void mthread_spinlock_unlock(mthread_tst_t *atomic);
-int mthread_get_vp_rank();
+int  mthread_get_vp_rank();
 
 void *safe_malloc(size_t size);
 
 void mthread_insert_first(struct mthread_s *item, mthread_list_t *list);
-void mthread_insert_last(struct mthread_s *item, mthread_list_t *list);
+void mthread_insert_last (struct mthread_s *item, mthread_list_t *list);
+int  mthread_list_test   (struct mthread_s *item, mthread_list_t *list);
 struct mthread_s *mthread_remove_first(mthread_list_t *list);
-int mthread_list_test(struct mthread_s *item, mthread_list_t *list);
 
 void __mthread_yield(mthread_virtual_processor_t *vp);
 mthread_virtual_processor_t *mthread_get_vp();
diff --git a/meson.build b/meson.build
index f0ab5baa0a7cd7152eab37b7b0fabbc9b72ff50d..0e421b7bb22354e6a359dacc415542c66d8aa7b6 100644
--- a/meson.build
+++ b/meson.build
@@ -14,9 +14,9 @@ project( 'lektor'
        )
 
 libdl   = meson.get_compiler('c').find_library('dl')
-dep_x11 = dependency('x11', required : false)
-dep_mpv = dependency('mpv', required : false)
-dep_sdl = dependency('sdl2', required : false)
+dep_x11 = dependency('x11',  required: false)
+dep_mpv = dependency('mpv',  required: false)
+dep_sdl = dependency('sdl2', required: false)
 
 ## Get architecture
 archi = run_command('uname', '-p').stdout().strip()
@@ -26,8 +26,8 @@ endif
 if archi == 'unknown'
   archi = run_command('arch').stdout().strip()
 endif
-add_global_arguments('-D' + archi + '_ARCH', language : 'c')
-add_global_arguments('-D_REENTRANT', language : 'c')
+add_global_arguments('-D' + archi + '_ARCH', language: 'c')
+add_global_arguments('-D_REENTRANT', language: 'c')
 
 ## Sources for mthread
 mthread_sources = [ 'src/mthread/mthread.c'
@@ -56,12 +56,10 @@ core_sources =  [ 'src/mkv/bufferfd.c'
                 , 'src/net/command.c'
                 , 'src/net/listen.c'
                 , 'src/net/message.c'
+                , 'src/net/downloader.c'
                 , 'src/config.c'
-                , 'src/utils.c'
                 , 'src/uri.c'
                 , 'src/ini/ini.c'
-                , 'src/repo/curl.c'
-                , 'src/repo/async.c'
                 , 'src/thread.c'
                 ]
 
@@ -69,78 +67,77 @@ core_sources =  [ 'src/mkv/bufferfd.c'
 includes = include_directories('inc')
 
 # Server
-core_deps = [ dependency('sqlite3', version : '>= 3.31.0')
+core_deps = [ dependency('sqlite3', version: '>= 3.31.0')
             , dependency('libcurl')
             , dependency('json-c')
-            , dependency('threads', required : true)
+            , dependency('threads', required: true)
             ]
 
 common_deps = [ declare_dependency( link_with: static_library( 'common'
                                                              , files('src/common.c')
-                                                             , include_directories : includes )
+                                                             , include_directories: includes )
                                   , include_directories: includes ) ]
 
 mthread_deps = [ declare_dependency( link_with: static_library( 'mthread'
                                                               , files(mthread_sources)
-                                                              , include_directories : includes )
+                                                              , include_directories: includes )
                                    , include_directories: includes
-                                   , dependencies : [ common_deps ] ) ]
+                                   , dependencies: [ common_deps ] ) ]
 
-lib = static_library( meson.project_name()
+initsql_deps = [ declare_dependency( link_with: static_library( 'initsql'
+                                                              , [ custom_target('init.c'
+                                                                               , output: 'sql_init.c'
+                                                                               , input: 'scripts/init.sql'
+                                                                               , command: [ find_program('xxd'), '-i', '@INPUT@', '@OUTPUT@']) ] ) ) ]
+
+lib = static_library( 'lektor'
                     , files(core_sources)
-                    , include_directories : includes
-                    , dependencies : [ core_deps, libdl, common_deps ]
-                    )
+                    , include_directories: includes
+                    , dependencies: [ core_deps, libdl, common_deps, mthread_deps, initsql_deps ] )
 
 bin_deps = [ declare_dependency( link_with: lib, include_directories: includes) ]
 
 srv = executable( meson.project_name() + 'd'
                 , files('src/main/server.c')
-                , include_directories : includes
-                , dependencies : [ bin_deps, mthread_deps ]
-                , install : true
-                )
+                , include_directories: includes
+                , dependencies: [ bin_deps ]
+                , install: true )
 
 # Admin executable
-metadata = executable( 'lktadm'
-                     , files('src/main/lktadm.c', 'src/cmd.c')
-                     , include_directories : includes
-                     , dependencies : bin_deps
-                     , install : true
-                     )
+lktadm = executable( 'lktadm'
+                   , files('src/main/lktadm.c', 'src/cmd.c')
+                   , include_directories : includes
+                   , dependencies: [ bin_deps ]
+                   , install: true )
 
 # Client executable
 lkt = executable( 'lkt'
-                , files('src/main/lkt.c', 'src/cmd.c')
-                , include_directories : includes
-                , install : true
-                )
+                , files('src/main/lkt.c', 'src/cmd.c', 'src/common.c')
+                , include_directories: includes
+                , install: true )
 
 # X11 window module
 if dep_x11.found() and dep_mpv.found()
   lib_mod_x11 = shared_library ( '_module_x11'
                                , files(['src/module/module_x11.c', 'src/module/mpv.c'])
-                               , include_directories : includes
-                               , dependencies : [ dep_x11, dep_mpv, mthread_deps ]
-                               , link_with : lib
-                               , install : true
-                               , install_dir : 'lib/lektor'
-                               )
+                               , include_directories: includes
+                               , dependencies: [ dep_x11, dep_mpv ]
+                               , link_with: lib
+                               , install: true
+                               , install_dir: 'lib/lektor' )
 endif
 
 # SQL2 window module
 if dep_sdl.found() and dep_mpv.found()
   lib_mod_sdl = shared_library ( '_module_sdl2'
                                , files(['src/module/module_sdl2.c', 'src/module/mpv.c'])
-                               , include_directories : includes
-                               , dependencies : [ dep_sdl, dep_mpv, mthread_deps ]
-                               , link_with : lib
-                               , install : true
-                               , install_dir : 'lib/lektor'
-                               )
+                               , include_directories: includes
+                               , dependencies: [ dep_sdl, dep_mpv ]
+                               , link_with: lib
+                               , install: true
+                               , install_dir: 'lib/lektor' )
 endif
 
 # Install
-install_data('scripts/init.sql', install_dir : 'share/lektor')
 install_man('doc/lektord.1')
 meson.add_install_script('scripts/install.sh')
diff --git a/scripts/astyle.sh b/scripts/astyle.sh
index 234f53306ce89f4bae644ad4f84e57ad3b1cdd05..0a4a45c565660898d023d54c4bab3e9fec5fb02d 100755
--- a/scripts/astyle.sh
+++ b/scripts/astyle.sh
@@ -10,7 +10,7 @@ OPTIONS='
   --break-return-type
   --convert-tabs
   --close-templates
-  --max-code-length=110
+  --max-code-length=140
   --mode=c
   --lineend=linux
   --quiet'
diff --git a/scripts/init.sql b/scripts/init.sql
index 3f36cb0a701e9e062c57390e4acc7a741ac4c835..21bffe9af33706a6d66816515760044f95c59789 100644
--- a/scripts/init.sql
+++ b/scripts/init.sql
@@ -20,9 +20,9 @@ CREATE TABLE IF NOT EXISTS kara
   , author_year INTEGER CHECK(author_year > 0)
   , available   INTEGER CHECK(available = 0 OR available = 1) DEFAULT 1 NOT NULL
   , string      TEXT GENERATED ALWAYS AS
-    ( song_type || ' - ' || language || ' / ' || source_name || ' - ' || category ||
+    ( category || ' - ' || language || ' / ' || source_name || ' - ' || song_type ||
       song_number || ' - ' || song_name || ' [ ' || author_name || ' ]' ||
-      CASE WHEN available = 0 THEN '(U)' ELSE '' END
+      CASE WHEN available = 0 THEN ' (U)' ELSE '' END
     ) STORED
   );
 
@@ -32,7 +32,8 @@ CREATE TABLE IF NOT EXISTS kara_type
   );
 
 INSERT OR REPLACE INTO kara_type (id, name) VALUES
-  (1, 'vo'), (2, 'va'), (3, 'amv'), (4, 'cdg'), (5, 'autres'), ( 6, 'vocaloid');
+  (1, 'ED/d*'), (2, 'OP/d*'), (3, 'AMV'), (4, 'IS'), (5, 'VOCA'), (6, 'LIVE'),
+  (7, 'CDG'), (8, 'PV'), (9, 'MV');
 
 CREATE TABLE IF NOT EXISTS kara_category
   ( id   INTEGER PRIMARY KEY
@@ -40,8 +41,7 @@ CREATE TABLE IF NOT EXISTS kara_category
   );
 
 INSERT OR REPLACE INTO kara_category (id, name) VALUES
-  (1, 'ED/d*'), (2, 'OP/d*'), (3, 'AMV'), (4, 'IS'), (5, 'VOCA'), (6, 'LIVE'),
-  (7, 'CDG'), (8, 'PV'), (9, 'MV');
+  (1, 'vo'), (2, 'va'), (3, 'amv'), (4, 'cdg'), (5, 'autres'), ( 6, 'vocaloid');
 
 CREATE TABLE IF NOT EXISTS language
   ( id   INTEGER PRIMARY KEY
@@ -121,12 +121,16 @@ CREATE TABLE IF NOT EXISTS 'stickers.plt'
 
 -- Some useful values:
 -- last_update is the timestamp of the last time the table of kara has been
--- updated.  This is so lektor doesn't have to read all kara in the filesystem,
+-- updated. This is so lektor doesn't have to read all kara in the filesystem,
 -- just the new ones (where their modified timestamp is greater than
--- last_update).  If last_update is NULL then the database is empty.
+-- last_update). If last_update is NULL then the database is empty.
+-- the last_end_update is here to mark a synchronisation point. Multiple
+-- update can be done (updating last_update), but a general update can be
+-- in progress.
 CREATE TABLE IF NOT EXISTS misc
-  ( id          INTEGER PRIMARY KEY DEFAULT 42 CHECK(id = 42)
-  , last_update INTEGER
+  ( id              INTEGER PRIMARY KEY DEFAULT 42 CHECK(id = 42)
+  , last_update     INTEGER
+  , last_end_update INTEGER
   );
 
 INSERT OR REPLACE INTO misc (id) VALUES (42);
@@ -141,5 +145,3 @@ CREATE VIEW IF NOT EXISTS queue_ AS
     priority,
     queue.position AS old_position
   FROM queue;
-
-.exit
diff --git a/src/cmd.c b/src/cmd.c
index f5c0c61991087bd5e05d4e287b8e191aae8e6435..ae46c8b299db796e69d335b267d9ffdfa827b2db 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -1,7 +1,7 @@
 #define _POSIX_C_SOURCE 200809L
 
 #include <lektor/cmd.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 #include <sys/types.h>
 #include <stdlib.h>
 #include <strings.h>
diff --git a/src/commands.c b/src/commands.c
index 23acfc3854697086a69b918456db801584ae076d..890c26d318cdbf69c6e1600c1426c2baa6b67030 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -1,11 +1,12 @@
 #define _POSIX_C_SOURCE 200809L
 
-#include <lektor/macro.h>
+#include <common/common.h>
+#include <lektor/common.h>
 #include <lektor/commands.h>
 #include <lektor/database.h>
 #include <lektor/net.h>
 #include <lektor/uri.h>
-#include <lektor/repo.h>
+#include <mthread/mthread.h>
 
 #include <errno.h>
 #include <linux/limits.h>
@@ -18,10 +19,6 @@
 #include <poll.h>
 #include <unistd.h>
 
-#define SELF_EXECUTABLE_LINUX   "/proc/self/exe"
-#define SELF_EXECUTABLE_FREEBSD "/proc/curproc/file"
-#define SELF_EXECUTABLE_SOLARIS "/proc/self/path/a.out"
-
 inline bool
 command_restart(struct lkt_state *srv, size_t c)
 {
@@ -51,12 +48,32 @@ command_restart(struct lkt_state *srv, size_t c)
     abort();
 }
 
+bool
+command_update(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
+{
+    UNUSED(argv);
+    RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false);
+    srv->mpd_idle_events |= MPD_IDLE_UPDATE;
+    srv->mpd_idle_events |= MPD_IDLE_DATABASE;
+    return ! repo_update(&srv->repo);
+}
+
+static inline void *
+__rescan(void * arg)
+{
+    struct lkt_state *srv = arg;
+    database_update(srv->db, srv->kara_prefix);
+    return NULL;
+}
+
 bool
 command_rescan(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
-    (void) argv;
+    UNUSED(argv);
     RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false);
-    return ! repo_get_allid_async();
+    srv->mpd_idle_events |= MPD_IDLE_UPDATE;
+    srv->mpd_idle_events |= MPD_IDLE_DATABASE;
+    return ! mthread_create(NULL, ATTR_DETACHED_FREE, __rescan, srv);
 }
 
 inline bool
@@ -77,7 +94,7 @@ command_currentsong(struct lkt_state *srv, size_t c)
 
     memset(&kara, 0, sizeof(struct kara_metadata));
 
-    if (!database_queue_current_kara(srv->db, &kara, NULL))
+    if (!database_queue_current_kara((sqlite3 *) srv->db, &kara, NULL))
         LOG_ERROR_SCT("COMMAND", "%s", "Failed to get information about the current kara");
 
     out = lkt_message_new();
@@ -107,8 +124,8 @@ command_status(struct lkt_state *srv, size_t c)
 
     RETURN_UNLESS(srv, "Invalid argument", false);
     win = &srv->win;
-    RETURN_UNLESS(database_queue_state(srv->db, &queue_state), "Can't determine playback status", false);
-    database_queue_current_kara(srv->db, NULL, &songid);
+    RETURN_UNLESS(database_queue_state((sqlite3 *) srv->db, &queue_state), "Can't determine playback status", false);
+    database_queue_current_kara((sqlite3 *) srv->db, NULL, &songid);
     win->get_elapsed(win, &elapsed);
     win->get_duration(win, &duration);
 
@@ -233,10 +250,10 @@ command_add(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX],
 {
     RETURN_UNLESS(args, "Invalid argument", false);
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
-    struct lkt_uri_t uri;
+    struct lkt_uri uri;
     char *query = args[0];
     int ret, priority = 1;  /* To be modified according to the command (insert or add) later (TODO) */
-    (void) win;         // No callbacks to the window for the moment
+    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) {
@@ -275,7 +292,7 @@ bool
 command_addid(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX],
               enum mpd_idle_flag *watch_mask_ptr)
 {
-    (void) win;
+    UNUSED(win);
     long id;
     char *endptr, *id_str;
     int priority = 1;
@@ -308,7 +325,7 @@ command_crop(sqlite3 *db, enum mpd_idle_flag *watch_mask_ptr)
 bool
 command_delid(sqlite3 *db, struct lkt_win *win, char *id_str, enum mpd_idle_flag *watch_mask_ptr)
 {
-    (void) win;
+    UNUSED(win);
     long id;
     char *endptr;
     int uri = 0;
@@ -367,14 +384,6 @@ command_help(struct lkt_state *srv, size_t c)
     return true;
 }
 
-bool
-command_update(struct lkt_state *srv, enum mpd_idle_flag *watch_mask_ptr)
-{
-    *watch_mask_ptr |= MPD_IDLE_UPDATE;
-    *watch_mask_ptr |= MPD_IDLE_DATABASE;
-    return database_update(srv->db, srv->kara_prefix);
-}
-
 bool
 command_idle(struct lkt_state *srv, size_t c, struct lkt_command *cmd)
 {
@@ -432,7 +441,7 @@ command_noidle(struct lkt_state *srv, size_t c)
 static bool
 lkt_callback_print_row_v1(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
 {
-    (void) srv;
+    UNUSED(srv);
     printf(" . from client %ld:\t%*d:%s\n", c, id_len, id, sql_row);
     return true;
 }
@@ -460,10 +469,8 @@ lkt_callback_send_row_v2(struct lkt_state *srv, size_t c, int id, int id_len, co
 static bool
 lkt_callback_insert_v1(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
 {
-    (void) c;
-    (void) sql_row;
-    (void) id_len;
-    return database_queue_add_id(srv->db, id, 5);
+    UNUSED(sql_row, id_len, c);
+    return database_queue_add_id((sqlite3 *) srv->db, id, 5);
 }
 
 static bool
@@ -540,7 +547,7 @@ __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);
+    RETURN_UNLESS(init((sqlite3 *) srv->db, col_name, rgx, &search), "Failed to init search", false);
 
     for (count = 0; database_search_iter(&search); ++count)
         continue;
@@ -569,8 +576,7 @@ command_set_playback_option(struct lkt_state *srv, size_t c, enum lkt_playback_o
                             char *args[LKT_MESSAGE_MAX])
 {
     RETURN_UNLESS(srv, "Invalid argument", false);
-
-    (void) c;
+    UNUSED(c);
     long val, ret = false;
     char *endptr;
     struct lkt_win *win = &srv->win;
@@ -593,19 +599,19 @@ command_set_playback_option(struct lkt_state *srv, size_t c, enum lkt_playback_o
 
     switch (opt) {
     case lkt_playback_option_random:
-        ret = database_config_queue(srv->db, "random", val);
+        ret = database_config_queue((sqlite3 *) srv->db, "random", val);
         break;
     case lkt_playback_option_single:
-        ret = database_config_queue(srv->db, "single", val);
+        ret = database_config_queue((sqlite3 *) srv->db, "single", val);
         break;
     case lkt_playback_option_consume:
-        ret = database_config_queue(srv->db, "consume", val);
+        ret = database_config_queue((sqlite3 *) srv->db, "consume", val);
         break;
     case lkt_playback_option_repeat:
-        ret = database_config_queue(srv->db, "repeat", val);
+        ret = database_config_queue((sqlite3 *) srv->db, "repeat", val);
         break;
     case lkt_playback_option_volume:
-        ret = database_config_queue(srv->db, "volume", val);
+        ret = database_config_queue((sqlite3 *) srv->db, "volume", val);
         LOG_INFO_SCT("COMMAND", "Set volume to %ld", val);
         ret &= win->set_volume(win, val);
         srv->mpd_idle_events |= MPD_IDLE_MIXER;
@@ -626,8 +632,8 @@ command_set_pos(sqlite3 *db, struct lkt_win *win, enum mpd_idle_flag *watch_mask
 {
     char filepath[PATH_MAX];
     *watch_mask_ptr |= MPD_IDLE_PLAYER;
-    RETURN_UNLESS(database_queue_set_current_index(db, index), "Failed to set position in queue", false);
-    RETURN_UNLESS(database_queue_get_current_file(db, filepath), "Failed to get filename", false);
+    RETURN_UNLESS(database_queue_set_current_index((sqlite3 *)db, index), "Failed to set position in queue", false);
+    RETURN_UNLESS(database_queue_get_current_file((sqlite3 *)db, filepath), "Failed to get filename", false);
     return win->load_file(win, filepath);
 }
 
@@ -637,7 +643,7 @@ command_plt_add(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_fla
     RETURN_UNLESS(args && args[0], "Invalid argument", false);
 
     bool ret = false;
-    struct lkt_uri_t uri;
+    struct lkt_uri uri;
 
     if (args[1] == NULL)
         ret = database_plt_create(db, args[0]);
@@ -732,7 +738,7 @@ bool
 command_plt_add_uri(sqlite3 *db, char *args[LKT_MESSAGE_ARGS_MAX], enum mpd_idle_flag *watch_mask_ptr)
 {
     RETURN_UNLESS(args && args[0] && args[1], "Invalid argument", false);
-    struct lkt_uri_t uri;
+    struct lkt_uri uri;
     RETURN_UNLESS(lkt_uri_from(&uri, args[1]), "Failed to parse uri", false);
     bool ret = database_plt_add_uri(db, args[0], &uri);
     lkt_uri_free(&uri);
@@ -803,25 +809,25 @@ command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_
     /* The command is used in its relative forme, display elements from the
        current one. */
 only_one:
-    return database_queue_list(srv->db, from, from, &callback);
+    return database_queue_list((sqlite3 *) srv->db, from, from, &callback);
 
     /* The command is used with a range specifier. */
 is_a_range:
     if (to - from + 1 < lkt_remaining_msg(srv, c) - 2) {
         lkt_set_continuation(srv, c, 0);
-        return database_queue_list(srv->db, from, to, &callback);
+        return database_queue_list((sqlite3 *) srv->db, from, to, &callback);
     } else {
         to = from + lkt_remaining_msg(srv, c) - 3;
         lkt_set_continuation(srv, c, to + 1);
-        return database_queue_list(srv->db, from, to, &callback);
+        return database_queue_list((sqlite3 *) srv->db, from, to, &callback);
     }
 }
 
 bool
 command_password(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
-    RETURN_UNLESS(argv[0] && !argv[1], "Invalid argument", false);
-    RETURN_UNLESS(database_user_authentificate(srv->db, argv[0]), "Failed to authentificate user", false);
+    RETURN_UNLESS(argv[0], "Invalid argument", false);
+    RETURN_UNLESS(database_user_authentificate((sqlite3 *) srv->db, argv[0]), "Failed to authentificate user", false);
     lkt_client_auth(srv, c, true);
     return true;
 }
@@ -829,7 +835,7 @@ command_password(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MA
 bool
 command_user_add(struct lkt_state *srv, size_t c, sqlite3 *db, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
-    RETURN_UNLESS(argv[0] && argv[1] && !argv[2], "Invalid argument", false);
+    RETURN_UNLESS(argv[0] && argv[1], "Invalid argument", false);
     RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false);
     RETURN_UNLESS(database_user_add(db, argv[0], argv[1]), "Failed to add user", false);
     return false;
@@ -840,9 +846,7 @@ command_user_add(struct lkt_state *srv, size_t c, sqlite3 *db, char *argv[LKT_ME
 static bool
 sticker_send_one_value(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    (void) sticker;
-    (void) type;
-    (void) uri;
+    UNUSED(sticker, type, uri);
     struct sticker_callback *args = (struct sticker_callback *) _args;
     struct lkt_message *out = lkt_message_new();
     out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "value: %d\n", value);
@@ -865,7 +869,7 @@ static bool
 sticker_send_check_uri(void *_args, const char *sticker, const char *type, int uri, int value)
 {
     struct sticker_callback *args = (struct sticker_callback *) _args;
-    (void) type;
+    UNUSED(type);
 
     if (uri == args->uri) {
         struct lkt_message *out = lkt_message_new();
@@ -881,7 +885,7 @@ sticker_send_value_check_uri_name(void *_args, const char *sticker, const char *
 {
     struct sticker_callback *args = (struct sticker_callback *) _args;
     struct lkt_message *out;
-    (void) type;
+    UNUSED(type);
 
     if (uri == args->uri || !strcasecmp(sticker, args->name)) {
         out = lkt_message_new();
@@ -895,7 +899,7 @@ sticker_send_value_check_uri_name(void *_args, const char *sticker, const char *
 static bool
 sticker_check_is_present_eq(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    (void) type;
+    UNUSED(type);
     struct sticker_callback *args = (struct sticker_callback *) _args;
     args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value == args->value);
     return true;
@@ -904,7 +908,7 @@ sticker_check_is_present_eq(void *_args, const char *sticker, const char *type,
 static bool
 sticker_check_is_present_lt(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    (void) type;
+    UNUSED(type);
     struct sticker_callback *args = (struct sticker_callback *) _args;
     args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value < args->value);
     return true;
@@ -913,7 +917,7 @@ sticker_check_is_present_lt(void *_args, const char *sticker, const char *type,
 static bool
 sticker_check_is_present_gt(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    (void) type;
+    UNUSED(type);
     struct sticker_callback *args = (struct sticker_callback *) _args;
     args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value > args->value);
     return true;
@@ -929,18 +933,19 @@ command_sticker_get(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS
         .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((sqlite3 *) srv->db, argv[0], argv[2], uri, &cb), "Failed to get sticker",
+                  false);
     return true;
 }
 
 bool
 command_sticker_set(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
-    (void) c;
+    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. */
-    RETURN_UNLESS(database_sticker_set(srv->db, argv[0], argv[2], uri, value), "Failed to get sticker", false);
+    RETURN_UNLESS(database_sticker_set((sqlite3 *) srv->db, argv[0], argv[2], uri, value), "Failed to get sticker", false);
     srv->mpd_idle_events |= MPD_IDLE_STICKER;
     return true;
 }
@@ -977,18 +982,18 @@ command_sticker_list(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARG
 
 just_list_all:
     callback.call = sticker_send_all;
-    return database_sticker_list(srv->db, argv[0], &callback);
+    return database_sticker_list((sqlite3 *) srv->db, argv[0], &callback);
 
 simple_list_command:
     callback.uri  = atoi(argv[1]);   /* FIXME: Use strtol. */
     callback.call = sticker_send_check_uri;
-    return database_sticker_list(srv->db, argv[0], &callback);
+    return database_sticker_list((sqlite3 *) srv->db, argv[0], &callback);
 
 list_stickers_in_uri:
     callback.uri  = atoi(argv[1]);  /* FIXME: Use strtol. */
     callback.name = argv[2];
     callback.call = sticker_send_value_check_uri_name;
-    return database_sticker_list(srv->db, argv[0], &callback);
+    return database_sticker_list((sqlite3 *) srv->db, argv[0], &callback);
     return false;
 
 list_stickers_check_value:
@@ -998,13 +1003,13 @@ list_stickers_check_value:
     switch (argv[3][0]) {
     case '=':
         callback.call = sticker_check_is_present_eq;
-        return database_sticker_list(srv->db, argv[0], &callback);
+        return database_sticker_list((sqlite3 *) srv->db, argv[0], &callback);
     case '<':
         callback.call = sticker_check_is_present_lt;
-        return database_sticker_list(srv->db, argv[0], &callback);
+        return database_sticker_list((sqlite3 *) srv->db, argv[0], &callback);
     case '>':
         callback.call = sticker_check_is_present_gt;
-        return database_sticker_list(srv->db, argv[0], &callback);
+        return database_sticker_list((sqlite3 *) srv->db, argv[0], &callback);
     default:
         return 0;
     }
@@ -1017,9 +1022,9 @@ unknown:
 bool
 command_sticker_delete(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
-    (void) c;
+    UNUSED(c);
     RETURN_UNLESS(argv[0] && argv[1], "Invalid argument", false);
     int uri = atoi(argv[1]);
     srv->mpd_idle_events |= MPD_IDLE_STICKER;
-    return database_sticker_delete_specify(srv->db, argv[0], uri, argv[2]);
+    return database_sticker_delete_specify((sqlite3 *) srv->db, argv[0], uri, argv[2]);
 }
diff --git a/src/common.c b/src/common.c
index f0195a6c88ec9b2660bfd091499dceab267044de..6b906e78c4bce33b04ba60c3e9c465ddba1ea56d 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1,6 +1,9 @@
 #include <common/common.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
 
 void
 __not_implemented(const char *func, char *file, int line)
@@ -9,4 +12,126 @@ __not_implemented(const char *func, char *file, int line)
     abort();
 }
 
+inline void
+__unused(void *dummy, ...)
+{
+    (void) dummy;
+}
+
+uint32_t
+be_uint32_t(const uint8_t bytes[], size_t n)
+{
+    uint32_t res = 0;
+    for (size_t i = 0; i < n; i++)
+        res = (res << 8u) | bytes[i];
+    return res;
+}
+
+uint64_t
+be_uint64_t(const uint8_t bytes[], size_t n)
+{
+    uint64_t res = 0;
+    for (size_t i = 0; i < n; i++)
+        res = (res << 8u) | bytes[i];
+    return res;
+}
 
+char *
+trim(char *str, size_t len, char c)
+{
+    char *res = (char *) str;
+    char *end;
+
+    for (; len != 0 && *res == c; ++str, --len)
+        continue;
+
+    if (*res == 0)
+        return res;
+
+    end = res + len - sizeof(char);
+    len = 0;
+
+    for (; res < end && *end == c; --end, ++len)
+        continue;
+
+    if (len > 0)
+        end[1] = 0;
+
+    return res;
+}
+
+int
+is_utf8(const char *string)
+{
+    if (!string)
+        return 1;
+
+    const unsigned char *bytes = (const unsigned char *)string;
+    while (*bytes) {
+        /* ASCII */
+        if  (bytes[0] == 0x09 || bytes[0] == 0x0A ||
+             bytes[0] == 0x0D || (0x20 <= bytes[0] && bytes[0] <= 0x7E)) {
+            bytes += 1;
+            continue;
+        }
+
+        /* non-overlong 2-byte */
+        if ((0xC2 <= bytes[0] && bytes[0] <= 0xDF) &&
+            (0x80 <= bytes[1] && bytes[1] <= 0xBF)) {
+            bytes += 2;
+            continue;
+        }
+
+        if ( (bytes[0] == 0xE0 &&
+              (0xA0 <= bytes[1] && bytes[1] <= 0xBF)  &&
+              (0x80 <= bytes[2] && bytes[2] <= 0xBF)) ||    /* excluding overlongs */
+             (((0xE1 <= bytes[0] && bytes[0] <= 0xEC) ||
+               bytes[0] == 0xEE || bytes[0] == 0xEF)  &&
+              (0x80 <= bytes[1] && bytes[1] <= 0xBF)  &&
+              (0x80 <= bytes[2] && bytes[2] <= 0xBF)) ||    /* straight 3-byte */
+             (bytes[0] == 0xED &&
+              (0x80 <= bytes[1] && bytes[1] <= 0x9F)  &&
+              (0x80 <= bytes[2] && bytes[2] <= 0xBF))) {    /* excluding surrogates */
+            bytes += 3;
+            continue;
+        }
+
+        if ( (bytes[0] == 0xF0  &&                          /* planes 1-3 */
+              (0x90 <= bytes[1] && bytes[1] <= 0xBF)  &&
+              (0x80 <= bytes[2] && bytes[2] <= 0xBF)  &&
+              (0x80 <= bytes[3] && bytes[3] <= 0xBF)) ||
+             ((0xF1 <= bytes[0] && bytes[0] <= 0xF3)  &&
+              (0x80 <= bytes[1] && bytes[1] <= 0xBF)  &&
+              (0x80 <= bytes[2] && bytes[2] <= 0xBF)  &&
+              (0x80 <= bytes[3] && bytes[3] <= 0xBF)) ||    /* planes 4-15 */
+             (bytes[0] == 0xF4 &&
+              (0x80 <= bytes[1] && bytes[1] <= 0x8F)  &&
+              (0x80 <= bytes[2] && bytes[2] <= 0xBF)  &&
+              (0x80 <= bytes[3] && bytes[3] <= 0xBF))) {    /* plane 16 */
+            bytes += 4;
+            continue;
+        }
+
+        return 2;
+    }
+
+    return 0;
+}
+
+int
+get_stdin_line(const char *prompt, char *buf, size_t len)
+{
+    if (prompt)
+        fprintf(stdout, "%s", prompt);
+    if (!fgets(buf, len, stdin))
+        return 1;
+    buf[len - 1] = 0u;
+    return is_utf8(buf);
+}
+
+inline long
+get_mtime(const char *path)
+{
+    struct stat statbuf;
+    return (stat(path, &statbuf) == -1) ? 0 : statbuf.st_mtime;
+}
diff --git a/src/config.c b/src/config.c
index 29b85b49cee97229cc2d4afb4b79102793c93855..7f1b3ada29f604d5212325d8e3343933aefe045b 100644
--- a/src/config.c
+++ b/src/config.c
@@ -90,7 +90,7 @@ static int
 #if INI_HANDLER_LINENO
 handler(void *user, const char *section, const char *name, const char *value, int lineno)
 {
-    (void) lineno;
+    UNUSED(lineno);
 #else
 handler(void *user, const char *section, const char *name, const char *value)
 {
diff --git a/src/database/config.c b/src/database/config.c
index a2aa57d5c9d17c37d66585e918b325dd4ce83d70..60c59427d60ebee07a688a36882d9f37cfb6c279 100644
--- a/src/database/config.c
+++ b/src/database/config.c
@@ -1,7 +1,7 @@
 #define _POSIX_C_SOURCE 200809L
 
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 
 #include <limits.h>
 #include <stdio.h>
diff --git a/src/database/find.c b/src/database/find.c
index 56ac88822330b08ef006a2050704fc3f8bb47447..e801b631e548c0ed88c097fa3928b848e32cfbc7 100644
--- a/src/database/find.c
+++ b/src/database/find.c
@@ -1,7 +1,7 @@
 #define _POSIX_C_SOURCE 200809L
 
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 
 #include <limits.h>
 #include <stdio.h>
diff --git a/src/database/open.c b/src/database/open.c
index e27425871c58f447f4d42e94274ad81830e57628..61414c90395852fbf6838cd4428b46f8a7428688 100644
--- a/src/database/open.c
+++ b/src/database/open.c
@@ -1,7 +1,7 @@
 #define _POSIX_C_SOURCE 200809L
 
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -38,6 +38,10 @@ static const char *const SQL_MEM_SCHEM =
     "  , PRIMARY KEY (section, key)"
     "  ) WITHOUT ROWID;\n";
 
+/* Should be, defined scripts_init_sql and its length scripts_init_sql_len */
+extern unsigned char ___scripts_init_sql[];
+extern int ___scripts_init_sql_len;
+
 #define INVALID_CHARS_DBPATH    ":?!'\""
 #define HEAP_LIMIT_SOFT         100 * 1024 * 1024
 #define HEAP_LIMIT_HARD         150 * 1024 * 1024
@@ -52,11 +56,10 @@ is_sql_str_invalid(const char *str)
 bool
 database_new(sqlite3 **db)
 {
-    /* SQLITE_OPEN_FULLMUTEX for serialized mode */
-    static int flags = SQLITE_OPEN_READWRITE    |
-                       SQLITE_OPEN_SHAREDCACHE  |
-                       SQLITE_OPEN_NOFOLLOW     |
-                       SQLITE_OPEN_NOMUTEX;
+    static int flags = SQLITE_OPEN_READWRITE    |   /* Open in RW mode              */
+                       SQLITE_OPEN_SHAREDCACHE  |   /* hHared cache for databases   */
+                       SQLITE_OPEN_NOFOLLOW     |   /* Don't follow symlinks        */
+                       SQLITE_OPEN_FULLMUTEX;       /* Serialized                   */
     RETURN_IF(SQLITE_OK != sqlite3_enable_shared_cache(1), "Failed to enable shared cache", false);
     RETURN_IF(sqlite3_soft_heap_limit64(HEAP_LIMIT_SOFT) < 0, "Failed to set soft heap limit", false);
     RETURN_IF(sqlite3_hard_heap_limit64(HEAP_LIMIT_HARD) < 0, "Failed to set soft heap limit", false);
@@ -175,3 +178,46 @@ database_detach(sqlite3 *db, const char *name)
     LOG_INFO_SCT("DB", "Database '%s' detached", name);
     return true;
 }
+
+bool
+database_init(const char *dbpath)
+{
+    sqlite3 *db;
+    GOTO_IF(SQLITE_OK != sqlite3_open(dbpath, &db), "Failed to open the database", error);
+    SQLITE_EXEC(db, (const char *) ___scripts_init_sql, error);
+    LOG_INFO_SCT("DB", "Initialized the 'disk' database successfully, path was '%s'", dbpath);
+    return true;
+error:
+    LOG_ERROR_SCT("DB", "Failed to init the 'disk' database, path was '%s'", dbpath);
+    return false;
+}
+
+long
+database_get_timestamp(volatile sqlite3 *db)
+{
+    long ret = 0;
+    static const char *SQL = "SELECT last_update FROM misc WHERE id = 42;";
+    sqlite3_stmt *stmt;
+    SQLITE_PREPARE(db, stmt, SQL, error);
+    SQLITE_STEP_ROW(db, stmt, error);
+    ret = sqlite3_column_int(stmt, 0);
+error:
+    sqlite3_finalize(stmt);
+    return ret;
+}
+
+void
+database_stamp(volatile sqlite3 *db)
+{
+    SQLITE_EXEC(db, "UPDATE misc SET last_update = strftime('%s','now');", error);
+error:
+    return;
+}
+
+void
+database_updated(volatile sqlite3 *db)
+{
+    SQLITE_EXEC(db, "UPDATE misc SET last_end_update = strftime('%s','now');", error);
+error:
+    return;
+}
diff --git a/src/database/playlist.c b/src/database/playlist.c
index f1f458fc0c89e07402b42a12c2cd9a2358969d86..086f580bd911e19526e4bb4ad3b248e918995323 100644
--- a/src/database/playlist.c
+++ b/src/database/playlist.c
@@ -2,7 +2,7 @@
 
 #include <common/common.h>
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 #include <stdio.h>
 #include <strings.h>
 
@@ -151,7 +151,7 @@ error:
 }
 
 bool
-database_plt_add_uri(sqlite3 *db, const char *name, struct lkt_uri_t *uri)
+database_plt_add_uri(sqlite3 *db, const char *name, struct lkt_uri *uri)
 {
     static const char *SQL =
         "WITH plt_id(id) AS (SELECT playlist.id AS id FROM playlist WHERE name COLLATE nocase = ?) "
diff --git a/src/database/queue.c b/src/database/queue.c
index 6520009cfc38c2cc2e5f1ddd5f5227769ab90e80..341455f016c363839f23ba996643ef70a84ef045 100644
--- a/src/database/queue.c
+++ b/src/database/queue.c
@@ -1,7 +1,7 @@
 #define _POSIX_C_SOURCE 200809L
 
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 
 #include <linux/limits.h>
 #include <stdio.h>
@@ -268,15 +268,15 @@ database_queue_next(sqlite3 *db, char filepath[PATH_MAX])
 {
     static const char *SQL_STMT =
         "SELECT file_path, position, RANDOM()"
-        "  FROM kara"
-        "  JOIN queue_ ON kara.id = queue_.kara_id"
-        "  JOIN queue_state"
-        "    ON current IS NULL"
-        "    OR (CASE WHEN (SELECT single FROM queue_state LIMIT 1) = 1 THEN position = current"
-        "             WHEN (SELECT random FROM queue_state LIMIT 1) = 1 THEN position <> current"
-        "             ELSE position > current END)"
-        "  ORDER BY CASE WHEN (SELECT random FROM queue_state LIMIT 1) = 1 THEN RANDOM() ELSE 2 END"
-        "  LIMIT 1";
+        " FROM kara"
+        " JOIN queue_ ON kara.id = queue_.kara_id"
+        " JOIN queue_state"
+        "  ON available = 1 AND current IS NULL OR"
+        "  CASE WHEN (SELECT single FROM queue_state) = 1 THEN position = current"
+        "       WHEN (SELECT random FROM queue_state) = 1 THEN position <> current"
+        "       ELSE position > current END"
+        " ORDER BY CASE WHEN (SELECT random FROM queue_state) = 1 THEN RANDOM() ELSE 2 END"
+        " LIMIT 1";
     char SQL_UPDATE[LKT_MAX_SQLITE_STATEMENT];
     bool status = false;
     int code = SQLITE_OK, id;
@@ -332,7 +332,7 @@ database_queue_prev(sqlite3 *db, char filepath[PATH_MAX])
     static const char *SQL_STMT =
         "SELECT file_path, position "
         "  FROM kara"
-        "  JOIN queue_ ON kara.id = queue_.kara_id"
+        "  JOIN queue_ ON kara.id = queue_.kara_id AND available = 1"
         "  JOIN queue_state ON CASE "
         "    WHEN (SELECT single FROM queue_state LIMIT 1) = 1 THEN position = current"
         "    ELSE queue_.position < queue_state.current"
@@ -380,9 +380,11 @@ bool
 database_queue_clear(sqlite3 *db)
 {
     static const char *SQL_STMT =
+        "BEGIN TRANSACTION;"
         "DELETE FROM queue;"
         "DELETE FROM sqlite_sequence WHERE name = 'queue';"
-        "UPDATE queue_state SET current = NULL;";
+        "UPDATE queue_state SET current = NULL;"
+        "COMMIT TRANSACTION;";
     SQLITE_EXEC(db, SQL_STMT, error);
     return true;
 error:
@@ -578,11 +580,9 @@ database_queue_shuffle(sqlite3 *db)
         "DELETE FROM sqlite_sequence WHERE name = 'queue_tmp';"
         /* Set the current to the right kara when needed.  */
         "UPDATE queue_state"
-        "  SET current ="
-        "  CASE"
+        "  SET current = CASE"
         "    WHEN current NOT NULL THEN 1"
-        "    ELSE NULL"
-        "  END;"
+        "    ELSE NULL END;"
         "COMMIT;";
     SQLITE_EXEC(db, SQL, error);
     return true;
@@ -600,8 +600,7 @@ database_queue_list(sqlite3 *db, size_t from, size_t to, struct lkt_callback *ca
         "  JOIN kara ON kara_id = kara.id"
         "  WHERE position >= ? AND position <= ?"
         "  GROUP BY position ORDER BY position)"
-        "SELECT id, string, (SELECT MAX(len) FROM content)"
-        " FROM content;";
+        "SELECT id, string, (SELECT MAX(len) FROM content) FROM content;";
     int code, id, id_len;
     const char *row;
     bool ret = false;
diff --git a/src/database/stickers.c b/src/database/stickers.c
index 9d172285c9d6c4cb235f734fbc456240665036db..1b4c023b00baf88ff10bbe0f93e4a7fd1332c435 100644
--- a/src/database/stickers.c
+++ b/src/database/stickers.c
@@ -1,6 +1,6 @@
 #define _POSIX_C_SOURCE 200809L
 
-#include <lektor/macro.h>
+#include <lektor/common.h>
 #include <lektor/database.h>
 #include <string.h>
 #include <strings.h>
@@ -13,9 +13,7 @@ database_sticker_create(sqlite3 *db, const char *name)
     static const char *INSERT =
         "WITH id_max (id) AS (SELECT MAX(id) FROM 'stickers')"
         "INSERT INTO 'stickers' (id, name)"
-        " SELECT"
-        "  CASE WHEN id_max.id IS NULL THEN 1 ELSE id_max.id + 1 END,"
-        "  ?"
+        " SELECT CASE WHEN id_max.id IS NULL THEN 1 ELSE id_max.id + 1 END, ?"
         " FROM id_max"
         "WHERE NOT EXISTS (SELECT 1 FROM 'stickers' WHERE name = ?);";
     sqlite3_stmt *stmt;
@@ -34,8 +32,7 @@ error:
 bool
 database_sticker_delete(sqlite3 *db, const char *name)
 {
-    static const char *INSERT =
-        "DELETE FROM 'stickers' WHERE name = ?;";
+    static const char *INSERT = "DELETE FROM 'stickers' WHERE name = ?;";
     sqlite3_stmt *stmt;
     int ret = false;
     RETURN_IF(strlen(name) == 0, "A sticker name must be at least one character long", ret);
diff --git a/src/database/update.c b/src/database/update.c
index a3b64b2a1cbac804dfa26fccf0c65f929d962291..80429007333c98526a9efa5988b88f498ddbcd33 100644
--- a/src/database/update.c
+++ b/src/database/update.c
@@ -1,8 +1,10 @@
 #define _POSIX_C_SOURCE 200809L
 #define _DEFAULT_SOURCE
 
+#include <common/common.h>
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
+
 #include <stdbool.h>
 #include <sqlite3.h>
 #include <stdio.h>
@@ -13,7 +15,7 @@
 #include <linux/limits.h>
 
 static bool
-database_add_kara(sqlite3 *db, const char *filename)
+database_add_kara(volatile sqlite3 *db, const char *filename)
 {
     RETURN_UNLESS(db || filename, "Invalid argument", false);
     static const char *SQL_STMT =
@@ -21,8 +23,7 @@ database_add_kara(sqlite3 *db, const char *filename)
         "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number)"
         "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?";
     sqlite3_stmt *stmt = NULL;
-    bool status = false;
-    int code = SQLITE_OK;
+    int code = SQLITE_OK, status = false;
     struct kara_metadata data;
     time_t the_time = time(NULL);
     struct tm *the_local_time = localtime(&the_time);
@@ -37,17 +38,17 @@ database_add_kara(sqlite3 *db, const char *filename)
 
     SQLITE_PREPARE(db, stmt, SQL_STMT, error);
 
-    if ((sqlite3_bind_text(stmt, 1, data.song_name, -1, 0) != SQLITE_OK)    ||
+    if ((sqlite3_bind_text(stmt, 1, data.song_name,   -1, 0) != SQLITE_OK)  ||
         (sqlite3_bind_text(stmt, 2, data.source_name, -1, 0) != SQLITE_OK)  ||
-        (sqlite3_bind_text(stmt, 3, data.category, -1, 0) != SQLITE_OK)     ||
-        (sqlite3_bind_text(stmt, 4, data.song_type, -1, 0) != SQLITE_OK)    ||
-        (sqlite3_bind_text(stmt, 5, data.language, -1, 0) != SQLITE_OK)     ||
-        (sqlite3_bind_text(stmt, 6, filename, -1, 0) != SQLITE_OK)          ||
-        (sqlite3_bind_int(stmt, 7, 0) != SQLITE_OK)                         ||
+        (sqlite3_bind_text(stmt, 3, data.category,    -1, 0) != SQLITE_OK)  ||
+        (sqlite3_bind_text(stmt, 4, data.song_type,   -1, 0) != SQLITE_OK)  ||
+        (sqlite3_bind_text(stmt, 5, data.language,    -1, 0) != SQLITE_OK)  ||
+        (sqlite3_bind_text(stmt, 6, filename,         -1, 0) != SQLITE_OK)  ||
+        (sqlite3_bind_int (stmt, 7, 0)                       != SQLITE_OK)  ||
         (sqlite3_bind_text(stmt, 8, data.author_name, -1, 0) != SQLITE_OK)  ||
-        (sqlite3_bind_int(stmt,  9, data.song_number) != SQLITE_OK)
+        (sqlite3_bind_int (stmt, 9, data.song_number)        != SQLITE_OK)
        ) {
-        LOG_ERROR_SCT("DB", "Failed to bind for kara %s: %s", filename, sqlite3_errmsg(db));
+        LOG_ERROR_SCT("DB", "Failed to bind for kara %s: %s", filename, sqlite3_errmsg((sqlite3 *) db));
         goto error;
     }
 
@@ -59,7 +60,25 @@ error:
 }
 
 bool
-database_update_add(sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail)
+database_update_set_available(volatile sqlite3 *db, uint64_t id)
+{
+    static const char *SQL_STMT = "UPDATE kara SET available = 1 WHERE id = ?;";
+    sqlite3_stmt *stmt;
+    SQLITE_PREPARE(db, stmt, SQL_STMT, error);
+    SQLITE_BIND_INT(db, stmt, 1, (int) id, error);
+    if (sqlite3_step(stmt) != SQLITE_DONE)
+        goto error;
+    sqlite3_finalize(stmt);
+    LOG_INFO_SCT("DB", "Kara %ld is now available", id);
+    return true;
+error:
+    sqlite3_finalize(stmt);
+    LOG_ERROR_SCT("DB", "Failed to set kara %ld available", id);
+    return false;
+}
+
+bool
+database_update_add(volatile sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail)
 {
     RETURN_UNLESS(db && kara_path && mdt, "Invalid argument", false);
     static const char *SQL_STMT =
@@ -67,8 +86,7 @@ database_update_add(sqlite3 *db, const char *kara_path, struct kara_metadata *md
         "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id, available)"
         "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?, ?, ?";
     sqlite3_stmt *stmt = NULL;
-    int code = SQLITE_OK;
-    bool ret = false;
+    int code = SQLITE_OK, ret = false;
     time_t the_time = time(NULL);
     struct tm *the_local_time = localtime(&the_time);
     char year[10];
@@ -79,19 +97,19 @@ database_update_add(sqlite3 *db, const char *kara_path, struct kara_metadata *md
 
     SQLITE_PREPARE(db, stmt, SQL_STMT, error);
 
-    if ((sqlite3_bind_text(stmt, 1, mdt->song_name, -1, 0) != SQLITE_OK)    ||
-        (sqlite3_bind_text(stmt, 2, mdt->source_name, -1, 0) != SQLITE_OK)  ||
-        (sqlite3_bind_text(stmt, 3, mdt->category, -1, 0) != SQLITE_OK)     ||
-        (sqlite3_bind_text(stmt, 4, mdt->song_type, -1, 0) != SQLITE_OK)    ||
-        (sqlite3_bind_text(stmt, 5, mdt->language, -1, 0) != SQLITE_OK)     ||
-        (sqlite3_bind_text(stmt, 6, kara_path, -1, 0) != SQLITE_OK)         ||
-        (sqlite3_bind_int(stmt, 7, 0) != SQLITE_OK) /* TODO */              ||  /* No new kara added (TODO). */
-        (sqlite3_bind_text(stmt, 8, mdt->author_name, -1, 0) != SQLITE_OK)  ||
-        (sqlite3_bind_int(stmt,  9, mdt->song_number) != SQLITE_OK)         ||
-        (sqlite3_bind_int(stmt, 10, id) != SQLITE_OK)                       ||
-        (sqlite3_bind_int(stmt, 11, avail) != SQLITE_OK)
+    if ((sqlite3_bind_text(stmt,  1, mdt->song_name,   -1, 0) != SQLITE_OK) ||
+        (sqlite3_bind_text(stmt,  2, mdt->source_name, -1, 0) != SQLITE_OK) ||
+        (sqlite3_bind_text(stmt,  3, mdt->category,    -1, 0) != SQLITE_OK) ||
+        (sqlite3_bind_text(stmt,  4, mdt->song_type,   -1, 0) != SQLITE_OK) ||
+        (sqlite3_bind_text(stmt,  5, mdt->language,    -1, 0) != SQLITE_OK) ||
+        (sqlite3_bind_text(stmt,  6, kara_path,        -1, 0) != SQLITE_OK) ||
+        (sqlite3_bind_int (stmt,  7, 0) != SQLITE_OK) /* TODO */            ||  /* No new kara added (TODO). */
+        (sqlite3_bind_text(stmt,  8, mdt->author_name, -1, 0) != SQLITE_OK) ||
+        (sqlite3_bind_int (stmt,  9, mdt->song_number)        != SQLITE_OK) ||
+        (sqlite3_bind_int (stmt, 10, id)                      != SQLITE_OK) ||
+        (sqlite3_bind_int (stmt, 11, avail)                   != SQLITE_OK)
        ) {
-        LOG_ERROR_SCT("DB", "Failed to bind argument for kara %s: %s", kara_path, sqlite3_errmsg(db));
+        LOG_ERROR_SCT("DB", "Failed to bind argument for kara %s: %s", kara_path, sqlite3_errmsg((sqlite3 *) db));
         goto error;
     }
 
@@ -104,7 +122,7 @@ error_no_sqlite:
 }
 
 bool
-database_update(sqlite3 *db, const char *kara_dir)
+database_update(volatile sqlite3 *db, const char *kara_dir)
 {
     DIR *d;
     struct dirent *dir;
@@ -121,15 +139,21 @@ database_update(sqlite3 *db, const char *kara_dir)
         strncat(path, "/", PATH_MAX - 1);
         strncat(path, dir->d_name, PATH_MAX - 1);
 
-        if (dir->d_type == DT_REG)
+        if (dir->d_type == DT_REG) {
+            if (get_mtime(path) < database_get_timestamp(db))
+                continue;
             database_add_kara(db, path);
-        else if (dir->d_type == DT_DIR &&
-                 strcmp(dir->d_name, ".") != 0 &&
+            database_stamp(db);
+        }
+
+        else if (dir->d_type == DT_DIR          &&
+                 strcmp(dir->d_name, ".")  != 0 &&
                  strcmp(dir->d_name, "..") != 0)
             database_update(db, path);
     }
 
     LOG_INFO("Passed directory '%s'", kara_dir);
+    database_updated(db);
     closedir(d);
     return true;
 }
diff --git a/src/database/user.c b/src/database/user.c
index b6330b2d3319591a86e21683105afc25d6d88176..11936d7492527e567ad371ad362987e18f093161 100644
--- a/src/database/user.c
+++ b/src/database/user.c
@@ -1,7 +1,7 @@
 #define _POSIX_C_SOURCE 200809L
 
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 #include <stdio.h>
 
 bool
diff --git a/src/main/lkt.c b/src/main/lkt.c
index e8820e1a1ee42dc5b73fc94b7d68b4046d2c900b..6ed06b2230d591b1e0892b0d3641df14e0efbe82 100644
--- a/src/main/lkt.c
+++ b/src/main/lkt.c
@@ -66,6 +66,7 @@ fail(const char *message)
 typedef struct {
     const char *host;   /* Serveur host, may be resolved.   */
     const char *port;   /* Serveur port.                    */
+    const char *pwd;    /* The password for the user.       */
     const char **argv;  /* Pointer to the argv from the main
                            function.                        */
     int argc;           /* Argument count of the args.      */
@@ -75,6 +76,7 @@ typedef struct {
 
 static const char *host;
 static const char *port;
+static const char *password;
 static const char *LKT_QUEUE_DEFAULT[] = { "10" };
 
 /* Communication functions and fonction that interact with lektor stuff. */
@@ -246,6 +248,68 @@ prev__(struct lkt_cmd_args *args)
     lkt_send_and_exit(cmd__, sizeof(cmd__));    /* In bytes. */
 }
 
+noreturn void
+simple_send_with_password__(const char *cmd)
+{
+    if (!password)
+        fail("Password not provided");
+    static const char cmd__[] = "password %s\n%s\nclose\n";
+    FILE *sock = lkt_connect();
+    exit(write_socket_format(sock, cmd__, password, cmd));
+}
+
+noreturn void
+restart__(struct lkt_cmd_args *args)
+{
+    if (args->argc != 0)
+        fail("Invalid argument, the previous command takes no arguments");
+    simple_send_with_password__("restart");
+}
+
+noreturn void
+kill__(struct lkt_cmd_args *args)
+{
+    if (args->argc != 0)
+        fail("Invalid argument, the previous command takes no arguments");
+    simple_send_with_password__("kill");
+}
+
+noreturn void
+rescan_or_update__(struct lkt_cmd_args *args, const char *cmd)
+{
+    if (!password)
+        fail("Password not provided");
+    FILE *sock = lkt_connect();
+    char buff[LKT_MESSAGE_MAX];
+    int i;
+
+    /* All the db */
+    if (args->argc == 0)
+        exit(write_socket_format(sock, "password %s\n%s\n", password, cmd));
+
+    /* With a query */
+    else {
+        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
+        for (i = 0; i < args->argc; ++i)
+            strncat(buff, args->argv[i], LKT_MESSAGE_MAX - 1);
+        exit(write_socket_format(sock, "password %s\n%s %s\n", password, cmd, buff));
+    }
+
+    abort();
+}
+
+noreturn void
+rescan__(struct lkt_cmd_args *args)
+{
+    rescan_or_update__(args, "rescan");
+}
+
+noreturn void
+update__(struct lkt_cmd_args *args)
+{
+    rescan_or_update__(args, "update");
+}
+
 noreturn void
 stop__(struct lkt_cmd_args *args)
 {
@@ -305,6 +369,23 @@ error:
     exit(EXIT_FAILURE);
 }
 
+noreturn void
+ping__(struct lkt_cmd_args *args)
+{
+    if (args->argc != 0)
+        fail("Invalid argument, the ping command takes no arguments");
+    char buff[6] = {0};
+    FILE *sock = lkt_connect();
+    if (write_socket(sock, "ping\nclose\n", sizeof("ping\n")))
+        fail("Failed to send the ping to lektord");
+    if (read_socket(sock, buff, 6 * sizeof(char)) <= 0)
+        fail("Failed to recieve the response of lektord");
+    if (strncmp(buff, "OK", 2))
+        fail("ACK");
+    write(1, "OK\n", sizeof("OK\n"));
+    exit(EXIT_SUCCESS);
+}
+
 noreturn void
 current__(struct lkt_cmd_args *args)
 {
@@ -868,7 +949,7 @@ search_add__(struct lkt_cmd_args *args)
 noreturn void
 search_insert__(struct lkt_cmd_args *args)
 {
-    (void) args;
+    UNUSED(args);
     fail("Not implemented");
 }
 
@@ -921,6 +1002,24 @@ static struct lkt_cmd_opt options_search[] = {
     LKT_OPT_NULL,
 };
 
+static struct lkt_cmd_opt options_admin[] = {
+    { .name = "ping",       .call = ping__,     .help = "Only pings the server"                                             },
+    { .name = "kill",       .call = kill__,     .help = "Kills the lektord server"                                          },
+    { .name = "restart",    .call = restart__,  .help = "Restarts the lektord server"                                       },
+    { .name = "rescan",     .call = rescan__,   .help = "Scan the filesystem and update the database with present files"    },
+    { .name = "update",     .call = update__,   .help = "Update the database with files present on Kurisu"                  },
+    LKT_OPT_NULL,
+};
+
+noreturn void
+admin__(struct lkt_cmd_args *args)
+{
+    if (args->argc == 0)
+        fail("Invalid argument, you must specify a sub command for the admin command");
+
+    lkt_cmd_parse(options_admin, args->argc, args->argv, help);
+}
+
 noreturn void
 queue__(struct lkt_cmd_args *args)
 {
@@ -949,16 +1048,17 @@ plt__(struct lkt_cmd_args *args)
 }
 
 static struct lkt_cmd_opt options_[] = {
-    { .name = "current",  .call = current__, .help = "Get the current playing song"                         },
-    { .name = "play",     .call = play__,    .help = "Toggle play/pause, may starts at a specified index"   },
-    { .name = "next",     .call = next__,    .help = "Play the next kara in the queue"                      },
-    { .name = "previous", .call = prev__,    .help = "Play the previous kara in the queue"                  },
-    { .name = "queue",    .call = queue__,   .help = "The queue sub-command",          .sub = options_queue },
-    { .name = "shuffle",  .call = shuffle__, .help = "Shuffle the queue"                                    },
-    { .name = "status",   .call = status__,  .help = "Get the status of lektord"                            },
-    { .name = "stop",     .call = stop__,    .help = "Stop playing the queue, won't close lektord's window" },
-    { .name = "plt",      .call = plt__,     .help = "The playlist sub-command",         .sub = options_plt },
-    { .name = "search",   .call = search__,  .help = "The search sub-command",        .sub = options_search },
+    { .name = "current",  .call = current__, .help = "Get the current playing song"                                                 },
+    { .name = "play",     .call = play__,    .help = "Toggle play/pause, may starts at a specified index"                           },
+    { .name = "next",     .call = next__,    .help = "Play the next kara in the queue"                                              },
+    { .name = "previous", .call = prev__,    .help = "Play the previous kara in the queue"                                          },
+    { .name = "queue",    .call = queue__,   .help = "The queue sub-command",                               .sub = options_queue    },
+    { .name = "shuffle",  .call = shuffle__, .help = "Shuffle the queue"                                                            },
+    { .name = "status",   .call = status__,  .help = "Get the status of lektord"                                                    },
+    { .name = "stop",     .call = stop__,    .help = "Stop playing the queue, won't close lektord's window"                         },
+    { .name = "plt",      .call = plt__,     .help = "The playlist sub-command",                            .sub = options_plt      },
+    { .name = "search",   .call = search__,  .help = "The search sub-command",                              .sub = options_search   },
+    { .name = "admin",    .call = admin__,   .help = "Administration commands",                             .sub = options_admin    },
     LKT_OPT_NULL,
 };
 
@@ -967,9 +1067,7 @@ static struct lkt_cmd_opt options_[] = {
 static void
 sigpipe__(int sig)
 {
-    (void) sig;
-    static const char *errmsg = "Exit because sigpipe\n";
-    write(2, errmsg, strlen(errmsg));
+    LOG_ERROR_SCT("GENERAL", "Exit because of signal sigpipe (%d)", sig);
     exit(EXIT_FAILURE);
 }
 
@@ -993,6 +1091,11 @@ parse_args(args_t *args, int argc, const char **argv)
             args->port = (argv[i] + len + 1);
             ++got;
         }
+
+        else if (STR_NMATCH("pwd", argv[i], len)) {
+            args->pwd = (argv[i] + len + 1);
+            ++got;
+        }
     }
 
     args->argv = &argv[got + 1];
@@ -1016,8 +1119,9 @@ main(int argc, const char **argv)
 
     parse_args(&args, argc, argv);
 
-    host = args.host;
-    port = args.port;
+    host     = args.host;
+    port     = args.port;
+    password = args.pwd;
 
     /* Communication with lektor. */
     lkt_cmd_parse(options_, args.argc, args.argv, help);
diff --git a/src/main/lktadm.c b/src/main/lktadm.c
index 5676ad2ec7caaeeb574df389304d6e132722a3cb..352d21ed5ecb5a572a712216dec9d5b13264bc3f 100644
--- a/src/main/lktadm.c
+++ b/src/main/lktadm.c
@@ -7,8 +7,8 @@
 #include <lektor/config.h>
 #include <lektor/mkv.h>
 #include <lektor/database.h>
-#include <lektor/repo.h>
-#include <lektor/utils.h>
+#include <lektor/net.h>
+#include <lektor/common.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -63,33 +63,10 @@ open_db(void)
         fail("Not found database->init_script");
 }
 
-noreturn void
-help(void)
-{
-    static const char *help__ =
-        "USAGE lktadm <COMMAND> [ARGS [...]]:\n"
-        "\n"
-        "COMMANDS:\n"
-        "    init                   the init sub command\n"
-        "    get <id>               get the metadata of a kara from kurisu\n"
-        "    download <id> <path>   download\n"
-        "    cat <path>             display the metadata of a mkv file\n"
-        "    conf                   prints the default config file to stdout\n"
-        "\n"
-        "INIT COMMANDS:\n"
-        "    database               write the default empty database\n"
-        "    popualte               populate the database from the filesystem\n"
-        "    metadata               write metadata to mkv files on the disk using theirs path\n"
-        "    file <path>            init the metadata for a single file by its path\n"
-        "\n";
-    write(1, help__, strlen(help__));
-    exit(EXIT_SUCCESS);
-}
-
 noreturn void
 conf__(struct lkt_cmd_args *args)
 {
-    (void) args;
+    UNUSED(args);
     fprintf(stdout, "%s\n", lkt_default_config_file);
     LOG_INFO("%s", "You may redirect this output to ~/.config/lektor/lektor.ini");
     exit(EXIT_SUCCESS);
@@ -119,7 +96,7 @@ cat__(struct lkt_cmd_args *args)
 noreturn void
 init_metadata__(struct lkt_cmd_args *args)
 {
-    (void) args;
+    UNUSED(args);
     open_db();
     metadata_set_directory(kara_dir, mkvpropedit);
     exit(EXIT_SUCCESS);
@@ -128,8 +105,10 @@ init_metadata__(struct lkt_cmd_args *args)
 noreturn void
 init_populate__(struct lkt_cmd_args *args)
 {
-    (void) args;
+    UNUSED(args);
     open_db();
+    if (!database_open(db, db_path))
+        fail("Failed to open database");
     database_update(db, kara_dir);
     sqlite3_close(db);
     exit(EXIT_SUCCESS);
@@ -194,7 +173,7 @@ get__(struct lkt_cmd_args *args)
 
     int i = atoi(args->argv[0]);
 
-    if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net"))
+    if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net", NULL))
         fail("Cound not create repo");
 
     if (repo_get_id(&repo, i, &data))
@@ -216,37 +195,9 @@ get__(struct lkt_cmd_args *args)
 noreturn void
 init_database__(struct lkt_cmd_args *args)
 {
-    (void) args;
-    pid_t pid;
-    int wstatus, status, fd;
+    UNUSED(args);
     open_db();
-    char *sqlite_args[] = { sqlite3_bin, db_path, NULL };
-
-    if ((pid = fork()) == 0) {
-        if ((fd = open(init_script, O_RDONLY)) < 0)
-            fail("Can't open %s in O_RDONLY", init_script);
-
-        if (dup2(fd, 0) < 0)
-            fail("Failed to duplicate %s to stdin", init_script);
-
-        execvp(sqlite_args[0], sqlite_args);
-        fail("Failed to execute %s: %s", sqlite3_bin, strerror(errno));
-    }
-
-    else if (pid < 0)
-        fail("Failed to fork: %s", strerror(errno));
-
-    else {
-        do
-            if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1)
-                fail("Failed to wait children: %s\n", strerror(errno));
-        while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
-
-        if ((status = WEXITSTATUS(wstatus)))
-            fail("Children failed with status %d\n", status);
-    }
-
-    exit(EXIT_SUCCESS);
+    exit(!database_init(db_path));
 }
 
 noreturn void
@@ -259,10 +210,10 @@ download__(struct lkt_cmd_args *args)
     struct kara_metadata data;
     int i = atoi(args->argv[0]);
 
-    if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net"))
+    if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net", NULL))
         fail("Could not create the repo");
 
-    if (repo_download_id_sync(&repo, NULL, i, args->argv[1], &data))
+    if (repo_download_id_sync(&repo, i, args->argv[1], &data))
         fail("Cound not download json for kara %d", i);
 
     printf("Kara %d at %s\n"
@@ -288,7 +239,7 @@ static struct lkt_cmd_opt options_init[] = {
 noreturn void
 init__(struct lkt_cmd_args *args)
 {
-    lkt_cmd_parse(options_init, args->argc, args->argv, help);
+    lkt_cmd_parse(options_init, args->argc, args->argv, NULL);
 }
 
 static struct lkt_cmd_opt options[] = {
diff --git a/src/mkv/mkv.c b/src/mkv/mkv.c
index 8cb9dc6aa9cc9091dd9e319d2f8feacaa211dde0..39efb961d862e45aed4616d9259ae61693524455 100644
--- a/src/mkv/mkv.c
+++ b/src/mkv/mkv.c
@@ -7,7 +7,7 @@
 
 #include <lektor/bufferfd.h>
 #include <lektor/mkv.h>
-#include <lektor/utils.h>
+#include <lektor/common.h>
 
 #define MKV_TAG_MAX 64
 
diff --git a/src/module/module_sdl2.c b/src/module/module_sdl2.c
index 6ec3defe8b96ce5667fc47e791bc5cc82ecb62b1..2432ca9d591188348e67630ebf577fe0cb9b634a 100644
--- a/src/module/module_sdl2.c
+++ b/src/module/module_sdl2.c
@@ -36,6 +36,10 @@ struct module_sdl2_window {
     mthread_mutex_t mtx;
     struct poller_thread self;
     volatile int launched;  /* SDL you sucks */
+
+    /* Things from the server */
+    volatile sqlite3 *db;
+    volatile enum mpd_idle_flag *mpd_idle_events;
 };
 
 /* Private functions. */
@@ -43,14 +47,14 @@ struct module_sdl2_window {
 static inline void *
 get_proc_address_mpv(void *fn_ctx, const char *name)
 {
-    (void) fn_ctx;
+    UNUSED(fn_ctx);
     return SDL_GL_GetProcAddress(name);
 }
 
 static inline void
 on_mpv_events(void *ctx)
 {
-    (void) ctx;
+    UNUSED(ctx);
     SDL_Event event = { .type = wakeup_on_mpv_events };
     SDL_PushEvent(&event);
 }
@@ -58,7 +62,7 @@ on_mpv_events(void *ctx)
 static inline void
 on_mpv_render_update(void *ctx)
 {
-    (void) ctx;
+    UNUSED(ctx);
     SDL_Event event = { .type = wakeup_on_mpv_render_update };
     SDL_PushEvent(&event);
 }
@@ -182,6 +186,11 @@ loop:
             if (flags & MPV_RENDER_UPDATE_FRAME)
                 redraw = 1;
         }
+
+        if (event.type == wakeup_on_mpv_events)
+            lmpv_handle((struct lkt_win *) win, (mpv_handle *) sdl2->mpv, (sqlite3 *) sdl2->db,
+                        (enum mpd_idle_flag *) &sdl2->mpd_idle_events, (int *) &sdl2->mpv_time_pos,
+                        (int *) &sdl2->mpv_duration);
     }
 
     if (redraw) {
@@ -219,16 +228,17 @@ module_set_function(void *arg__, void *handle__)
     RETURN_UNLESS(arg__ && handle__, "Invalid argument", 1);
     struct lkt_win *win = (struct lkt_win *) arg__;
 
-    win->new = module_sdl2_new;
-    win->close = module_sdl2_close;
-    win->free = module_sdl2_free;
-    win->toggle_pause = module_sdl2_toggle_pause;
-    win->load_file = module_sdl2_load_file;
-    win->set_volume = module_sdl2_set_volume;
-    win->get_duration = module_sdl2_get_duration;
-    win->get_elapsed = module_sdl2_get_elapsed;
-    win->handle_events = module_sdl2_handle_events;
-    win->handle = handle__;
+    win->new            = module_sdl2_new;
+    win->close          = module_sdl2_close;
+    win->free           = module_sdl2_free;
+    win->toggle_pause   = module_sdl2_toggle_pause;
+    win->load_file      = module_sdl2_load_file;
+    win->set_volume     = module_sdl2_set_volume;
+    win->get_duration   = module_sdl2_get_duration;
+    win->get_elapsed    = module_sdl2_get_elapsed;
+    win->handle_events  = module_sdl2_handle_events;
+    win->attach         = module_sdl2_attach;
+    win->handle         = handle__;
 
     return 0;
 }
@@ -251,7 +261,7 @@ module_sdl2_new(struct lkt_win *const win)
         struct poller_thread_arg *arg = calloc(1, sizeof(struct poller_thread_arg));
         RETURN_UNLESS(arg, "Out of memory", false);
         arg->args = win;
-        RETURN_IF(lkt_th_new(&((struct module_sdl2_window *) win->window)->self,
+        RETURN_IF(poller_new(&((struct module_sdl2_window *) win->window)->self,
                              LKT_DEFAULT_LIST_SIZE, sdl_thread__, arg),
                   "Failed to launch the SDL thread", false);
     }
@@ -325,11 +335,19 @@ module_sdl2_get_elapsed(struct lkt_win *const win, int *elapsed_sec)
     return true;
 }
 
+void
+module_sdl2_attach(struct lkt_win *const win, void *server)
+{
+    RETURN_UNLESS(win && server, "Invalid arguments", NOTHING);
+    struct lkt_state *srv = server;
+    struct module_sdl2_window *sdl2 = win->window;
+    sdl2->db = srv->db;
+    sdl2->mpd_idle_events = &srv->mpd_idle_events;
+}
+
 bool
 module_sdl2_handle_events(struct lkt_win *const win, sqlite3 *db, enum mpd_idle_flag *mpd_idle_events)
 {
-    struct module_sdl2_window *sdl2 = win->window;
-    RETURN_UNLESS(sdl2, "Can't handle events from a NULL window", false);
-    return ! lmpv_handle(win, (mpv_handle *) sdl2->mpv, db, mpd_idle_events,
-                         (int *) &sdl2->mpv_time_pos, (int *) &sdl2->mpv_duration);
+    UNUSED(win, db, mpd_idle_events);
+    return true;
 }
diff --git a/src/module/module_x11.c b/src/module/module_x11.c
index a8f821c53b4a4b1aff0ab9ed6b0e1a86e2473e5d..bec80557594f741c7df43ad4f07fa5230d75afec 100644
--- a/src/module/module_x11.c
+++ b/src/module/module_x11.c
@@ -1,5 +1,8 @@
+#define _POSIX_C_SOURCE 200809L
+
+#include <common/common.h>
 #include <lektor/module/module_x11.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 #include <lektor/module/mpv.h>
 #include <lektor/database.h>
 #include <lektor/commands.h>
@@ -46,16 +49,17 @@ module_set_function(void *arg__, void *handle__)
     RETURN_UNLESS(arg__ && handle__, "Invalid arguments", 1);
     struct lkt_win *win = (struct lkt_win *) arg__;
 
-    win->new = module_x11_new;
-    win->close = module_x11_close;
-    win->free = module_x11_free;
-    win->toggle_pause = module_x11_toggle_pause;
-    win->load_file = module_x11_load_file;
-    win->set_volume = module_x11_set_volume;
-    win->get_duration = module_x11_get_duration;
-    win->get_elapsed = module_x11_get_elapsed;
-    win->handle_events = module_x11_handle_events;
-    win->handle = handle__;
+    win->new            = module_x11_new;
+    win->close          = module_x11_close;
+    win->free           = module_x11_free;
+    win->toggle_pause   = module_x11_toggle_pause;
+    win->load_file      = module_x11_load_file;
+    win->set_volume     = module_x11_set_volume;
+    win->get_duration   = module_x11_get_duration;
+    win->get_elapsed    = module_x11_get_elapsed;
+    win->handle_events  = module_x11_handle_events;
+    win->attach         = module_x11_attach;
+    win->handle         = handle__;
 
     return 0;
 }
@@ -211,6 +215,12 @@ module_x11_free(struct lkt_win *const win)
     win->window = NULL;
 }
 
+void
+module_x11_attach(struct lkt_win *const win, void *server)
+{
+    UNUSED(win, server);
+}
+
 bool
 module_x11_toggle_pause(struct lkt_win *const win)
 {
diff --git a/src/module/mpv.c b/src/module/mpv.c
index bf193417d71e92510491f64c558b4ec03d95edfd..735ba8d91509a97efeef61f41e4e9a62c0b9fc46 100644
--- a/src/module/mpv.c
+++ b/src/module/mpv.c
@@ -4,7 +4,7 @@
 #include <lektor/module/mpv.h>
 #include <lektor/commands.h>
 #include <lektor/database.h>
-#include <lektor/macro.h>
+#include <lektor/common.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
@@ -133,7 +133,7 @@ lmpv_handle(struct lkt_win *win, mpv_handle *ctx, sqlite3 *db, enum mpd_idle_fla
     struct lkt_queue_state state;
     mpv_event *event = NULL;
     mpv_event_property *prop;
-    RETURN_UNLESS(ctx && win, "Invalid argument", 1);
+    RETURN_UNLESS(db && mpd_idle_events && ctx && win, "Invalid argument", 1);
     RETURN_UNLESS(database_queue_state(db, &state), "Failed to get queue state", 1);
 
 loop:
@@ -184,6 +184,13 @@ loop:
             && prop->format == MPV_FORMAT_FLAG)
             database_queue_set_paused(db, *(bool *) prop->data);
         break;
+
+    /* Ignored */
+    case MPV_EVENT_VIDEO_RECONFIG:
+    case MPV_EVENT_AUDIO_RECONFIG:
+    case MPV_EVENT_COMMAND_REPLY:
+        break;
+
     default:
         LOG_WARN_SCT("WINDOW", "Unhandled mpv event '%s'", mpv_event_name(event->event_id));
         break;
diff --git a/src/mthread/mthread.c b/src/mthread/mthread.c
index 4944174f9b70ed5ce3dae073c32d02ec46122b75..561a779a0674e356bc535f02615f4201c91c54f2 100644
--- a/src/mthread/mthread.c
+++ b/src/mthread/mthread.c
@@ -20,6 +20,11 @@ __mthread_clear_keys(mthread_t *thread)
     unsigned int i;
     struct keys_list *keys = &(*thread)->keys;
 
+    if (!keys) {
+        keys->first_avail = 0;
+        return;
+    }
+
     for (i = 0; i < keys->first_avail; ++i)
         mthread_key_delete(keys->list[i]);
 
@@ -36,9 +41,10 @@ mthread_list_init(mthread_list_t *list)
 static inline void
 mthread_init_thread(struct mthread_s *thread)
 {
-    thread->next   = NULL;
-    thread->status = RUNNING;
-    thread->res    = NULL;
+    thread->detached = JOINABLE;
+    thread->next     = NULL;
+    thread->status   = RUNNING;
+    thread->res      = NULL;
 }
 
 void
@@ -91,17 +97,13 @@ extern int
 mthread_list_test(struct mthread_s *item, mthread_list_t *list)
 {
     struct mthread_s *it = (struct mthread_s *) list->last;
-
     while (it && it != item)
         it = (struct mthread_s *) it->next;
-
     return it == item;
 }
 
 static inline int
-mthread_mctx_set(struct mthread_s *mctx,
-                 void (*func) (void *), char *stack, size_t size,
-                 void *arg)
+mthread_mctx_set(struct mthread_s *mctx, void (*func) (void *), char *stack, size_t size, void *arg)
 {
     /* fetch current context */
     RETURN_IF(getcontext(&(mctx->uc)) != 0, "Error in getcontext", 1);
@@ -202,8 +204,7 @@ mthread_get_vp_rank()
 }
 
 static inline void
-mthread_init_vp(mthread_virtual_processor_t *vp, struct mthread_s *idle,
-                struct mthread_s *current, int rank)
+mthread_init_vp(mthread_virtual_processor_t *vp, struct mthread_s *idle, struct mthread_s *current, int rank)
 {
     vp->current = current;
     vp->idle    = idle;
@@ -216,7 +217,7 @@ mthread_init_vp(mthread_virtual_processor_t *vp, struct mthread_s *idle,
 void *
 mthread_main(void *arg)
 {
-    (void)arg;
+    UNUSED(arg);
     mthread_virtual_processor_t *vp = mthread_get_vp();
     while (1) {
         sched_yield();
@@ -233,7 +234,6 @@ mthread_init_lib(long i)
     char *stack               = (char *) safe_malloc(MTHREAD_DEFAULT_STACK);
     struct mthread_s *mctx    = (struct mthread_s *) safe_malloc(sizeof(struct mthread_s));
     mthread_init_thread(mctx);
-
     mthread_list_init(&(joined_list));
 
     if (i == 0) {
@@ -256,12 +256,16 @@ static void
 mthread_start_thread(void *arg)
 {
     struct mthread_s *mctx = (struct mthread_s *)arg;
-    LOG_INFO_SCT("THREAD INIT", "Thread %p started", arg);
+    LOG_INFO_SCT("THREAD", "Thread %p started", arg);
     mthread_virtual_processor_t *vp = mthread_get_vp();
     __mthread_yield(vp);
     mctx->res    = mctx->__start_routine(mctx->arg);
     mctx->status = ZOMBIE;
-    LOG_INFO_SCT("THREAD END", "Thread %p ended (%d)", arg, vp->rank);
+    LOG_INFO_SCT("THREAD", "Thread %p ended (%d)", arg, vp->rank);
+    if (mctx->detached) {
+        LOG_INFO_SCT("THREAD", "Thread %p (vp: %d) was detached, join it", arg, vp->rank);
+        mthread_join(mctx, NULL);
+    }
     vp = mthread_get_vp();
     __mthread_yield(vp);
 }
@@ -289,8 +293,7 @@ mthread_init(void)
    if ATTR is NULL), and call function START_ROUTINE with given
    arguments ARG.  */
 int
-mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr,
-               void *(*__start_routine) (void *), void *__arg)
+mthread_create(mthread_t *__threadp, const mthread_attr_t __attr, void *(*__start_routine) (void *), void *__arg)
 {
     if (is_mthread_init == 0) {
         __mthread_lib_init(0);
@@ -299,23 +302,30 @@ mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr,
 
     mthread_virtual_processor_t *vp = mthread_get_vp();
 
-    if (__attr == NULL) {
-        struct mthread_s *mctx = mthread_remove_first(&(joined_list));
-        if (mctx == NULL) {
-            mctx = safe_malloc(sizeof(struct mthread_s));
-            memset(mctx, 0, sizeof(struct mthread_s));
-        }
-        char *stack = mctx->stack ? mctx->stack : safe_malloc(MTHREAD_DEFAULT_STACK);
-
-        mthread_init_thread(mctx);
-        LOG_INFO_SCT("THREAD INIT", "Create thread %p", (void *) mctx);
-        mctx->arg = __arg;
-        mctx->__start_routine = __start_routine;
-        mthread_mctx_set(mctx, mthread_start_thread, stack, MTHREAD_DEFAULT_STACK, mctx);
-        mthread_insert_last(mctx, &(vp->ready_list));
+    struct mthread_s *mctx = mthread_remove_first(&(joined_list));
+    if (mctx == NULL) {
+        mctx = safe_malloc(sizeof(struct mthread_s));
+        memset(mctx, 0, sizeof(struct mthread_s));
+    }
+    char *stack = mctx->stack ? mctx->stack : safe_malloc(MTHREAD_DEFAULT_STACK);
+
+    mthread_init_thread(mctx);
+
+    if (__attr) {
+        if (__attr & ATTR_DETACHED)
+            mctx->detached = DETACHED;
+        if (__attr & ATTR_DETACHED_FREE)
+            mctx->detached = DETACHED_FREE;
+    }
+
+    LOG_INFO_SCT("THREAD INIT", "Create thread %p", (void *) mctx);
+    mctx->arg = __arg;
+    mctx->__start_routine = __start_routine;
+    mthread_mctx_set(mctx, mthread_start_thread, stack, MTHREAD_DEFAULT_STACK, mctx);
+    mthread_insert_last(mctx, &(vp->ready_list));
+
+    if (__threadp)
         *__threadp = mctx;
-    } else
-        not_implemented();
 
     return 0;
 }
diff --git a/src/mthread/mthread_cond.c b/src/mthread/mthread_cond.c
index 00ebe3098d947dd670f2c56511f250828b9bc2bf..ba25bae0edf1343cd114e6d31ffb5e2ca502fc04 100644
--- a/src/mthread/mthread_cond.c
+++ b/src/mthread/mthread_cond.c
@@ -1,3 +1,5 @@
+#define _POSIX_C_SOURCE 200809L
+
 #include <mthread/mthread_internal.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/src/mthread/mthread_debug.c b/src/mthread/mthread_debug.c
index 8adcdc702748a074547bade6992c5654ceae9d2a..3230f8163e040045d7781b1c524770ec013b4ed5 100644
--- a/src/mthread/mthread_debug.c
+++ b/src/mthread/mthread_debug.c
@@ -1,3 +1,5 @@
+#define _POSIX_C_SOURCE 200809L
+
 #include <mthread/mthread_internal.h>
 #include <assert.h>
 
diff --git a/src/mthread/mthread_key.c b/src/mthread/mthread_key.c
index fc9741bc40ce4bff6fc115586a50de65e65ab9ce..bfd5403cee699c1de3a06a60af0024d317ab73be 100644
--- a/src/mthread/mthread_key.c
+++ b/src/mthread/mthread_key.c
@@ -1,3 +1,5 @@
+#define _POSIX_C_SOURCE 200809L
+
 #include <mthread/mthread_internal.h>
 #include <errno.h>
 #include <stdlib.h>
diff --git a/src/mthread/mthread_mutex.c b/src/mthread/mthread_mutex.c
index b82ec5f1924b9dabcc8996bd3a3185e72aa15ac1..b9ee9843b5fbcf17fe7e0c35827cf2e9ea0e8b90 100644
--- a/src/mthread/mthread_mutex.c
+++ b/src/mthread/mthread_mutex.c
@@ -1,3 +1,6 @@
+#define _POSIX_C_SOURCE 200809L
+
+#include <common/common.h>
 #include <errno.h>
 #include <string.h>
 #include <mthread/mthread_internal.h>
@@ -9,14 +12,12 @@
 int
 mthread_mutex_init(mthread_mutex_t *__mutex, const mthread_mutexattr_t *__mutex_attr)
 {
-    (void) __mutex_attr;
-
+    UNUSED(__mutex_attr);
     __mutex->list        = safe_malloc(sizeof(mthread_list_t));
     __mutex->list->first = NULL;
     __mutex->list->last  = NULL;
     __mutex->nb_thread   = 0;
     __mutex->lock        = 0;
-
     LOG_INFO("%s", "MUTEX initialized");
     return 0;
 }
diff --git a/src/mthread/mthread_once.c b/src/mthread/mthread_once.c
index acab4bcf75aae21aa4fb6314e77fd3e23ef7f3ab..9a269a39c13c61a7fac78fd713321ee9d8a17416 100644
--- a/src/mthread/mthread_once.c
+++ b/src/mthread/mthread_once.c
@@ -1,5 +1,8 @@
+#define _POSIX_C_SOURCE 200809L
+
 #include <mthread/mthread_internal.h>
 #include <errno.h>
+
 /* Functions for handling initialization.  */
 
 /* Guarantee that the initialization function INIT_ROUTINE will be called
diff --git a/src/mthread/mthread_sem.c b/src/mthread/mthread_sem.c
index 9c5534aea1896b3412f931fae2f0793b85fad2fb..6d5acbcfc7b2ea4ce26c15b13e2fc33b364e21c8 100644
--- a/src/mthread/mthread_sem.c
+++ b/src/mthread/mthread_sem.c
@@ -1,3 +1,5 @@
+#define _POSIX_C_SOURCE 200809L
+
 #include <mthread/mthread_internal.h>
 
 /* Functions for handling semaphore.  */
diff --git a/src/mthread/mthread_tst.c b/src/mthread/mthread_tst.c
index 35bae1659166ef8c934ebbf7e2671a8bbe1623cf..422eb485afe966b0e3aa996f797bdb03da6dcf9b 100644
--- a/src/mthread/mthread_tst.c
+++ b/src/mthread/mthread_tst.c
@@ -1,3 +1,5 @@
+#define _POSIX_C_SOURCE 200809L
+
 #include <mthread/mthread_internal.h>
 #include <sched.h>
 
diff --git a/src/repo/curl.c b/src/net/downloader.c
similarity index 50%
rename from src/repo/curl.c
rename to src/net/downloader.c
index 03fb6e98d73fd5038a4ab92a53b470792be0ffde..76a9307a49ae7d002b7962c781e0b721d1a2f040 100644
--- a/src/repo/curl.c
+++ b/src/net/downloader.c
@@ -1,21 +1,22 @@
 #define _POSIX_C_SOURCE 200809L
 
-#include <lektor/repo.h>
-#include <lektor/macro.h>
-#include <lektor/database.h>
 #include <errno.h>
-#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
 #include <string.h>
+#include <limits.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
-static volatile unsigned int curl_init = false;
+#include <common/common.h>
+#include <mthread/mthread.h>
+#include <lektor/common.h>
+#include <lektor/database.h>
+#include <lektor/net.h>
 
-#define URL_MAX_LEN 1024
-#define DEFAULT_URL "https://kurisu.iiens.net"
-#define GET_ID_JSON DEFAULT_URL "/api_karas.php?id=%ld"
-#define GET_ID_FILE DEFAULT_URL "/download.php?id=%ld"
+static volatile unsigned int curl_init = false;
 
 struct memory {
     void *mem;
@@ -52,7 +53,7 @@ write_disk__(char *data, size_t size, size_t nmem, void *user)
 }
 
 int
-repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_)
+repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_, volatile sqlite3 *db)
 {
     if (!curl_init) {
         curl_global_init(CURL_GLOBAL_ALL);
@@ -60,24 +61,18 @@ repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_)
     } else
         ++curl_init;
 
-    const size_t init_size = 30;
-    uint64_t *calloc1 = calloc(init_size, sizeof(uint64_t));
-    RETURN_UNLESS(calloc1, "Out of memory", errno = ENOMEM);
-    uint64_t *calloc2 = calloc(init_size, sizeof(uint64_t));
-    if (!calloc2) {
-        free(calloc1);
-        LOG_ERROR_SCT("MEMORY", "%s", "Out of memory");
-        return ENOMEM;
-    }
-
     struct lkt_repo repo = {
+        /* Just the repo */
         .name = name_,
         .base_url = url_,
         .get_id_json = GET_ID_JSON,
         .get_id_file = GET_ID_FILE,
-        .get_all_json = DEFAULT_URL "/api_karas.php",
+        .get_all_json = DEFAULT_URL "/api_karas.php", // TODO
         .kara_dir = "/home/kara/", // TODO
         .version = 1,
+
+        /* The db */
+        .db = db,
     };
 
     memcpy(repo_, &repo, sizeof(struct lkt_repo));
@@ -87,16 +82,12 @@ repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_)
 void
 repo_free(struct lkt_repo *const repo)
 {
+    UNUSED(repo);
     --curl_init;
-
-    free((void *) repo->base_url);
-    free((void *) repo->kara_dir);
-
     if (!curl_init)
         curl_global_cleanup();
 }
-
-int
+static inline int
 safe_json_get_string(struct json_object *jobj, const char *key, char *content, const size_t len)
 {
     const char *got;
@@ -109,20 +100,41 @@ safe_json_get_string(struct json_object *jobj, const char *key, char *content, c
     return 0;
 }
 
-int
+static inline int
 safe_json_get_int32(struct json_object *json, const char *key, int32_t *ret)
 {
     struct json_object *field;
     RETURN_UNLESS(json_object_object_get_ex(json, key, &field), "Key not found", 1);
     errno = 0;
     *ret = json_object_get_int(field);
-    RETURN_IF(errno = EINVAL, "Invalid 32bit integer", 1);
     RETURN_IF(*ret == INT32_MAX || *ret == INT32_MIN, "Out of bound 32bit integer", 1);
     return 0;
 }
 
+static inline long
+get_digit_number(long i)
+{
+    int count = 0;
+    while (i) {
+        i /= 10;
+        ++count;
+    }
+    return count;
+}
+
 int
-repo_get_alljson_sync(struct lkt_repo *const repo, struct json_object **json)
+safe_json_get_long(struct json_object *json, const char *key, long *ret)
+{
+    const int len = get_digit_number(LONG_MAX);
+    char content[len], *endptr, err;
+    if (safe_json_get_string(json, key, content, len))
+        return 1;
+    STRTOL(*ret, content, endptr, err);
+    return err;
+}
+
+static inline int
+__json_sync(struct lkt_repo *const repo, struct json_object **json)
 {
     RETURN_UNLESS(json, "Invalid argument", 1);
 
@@ -162,10 +174,9 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata
     CURLcode res;
     struct json_object *jobj, *field;
     int ret = 1, err = 0;
+    char url[URL_MAX_LEN];
 
     RETURN_UNLESS(mdt, "Invalid argument", 1);
-    char *url = calloc(URL_MAX_LEN, sizeof(char));
-    RETURN_UNLESS(url, "Out of memory", errno = ENOMEM);
 
     struct memory file = {
         .mem = NULL,
@@ -180,11 +191,9 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata
     curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_mem__);
     curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &file);
     curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
-    res = curl_easy_perform(curl_handle);
 
-    if (res != CURLE_OK) {
+    if (CURLE_OK != (res = curl_easy_perform(curl_handle))) {
         LOG_ERROR_SCT("CURL", "curl_easy_perform failed: %s", curl_easy_strerror(res));
-        free(url);
         free(file.mem);
         curl_easy_cleanup(curl_handle);
         return 1;
@@ -232,87 +241,201 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata
 
     ret = 0;
 err:
-    free(url);
     json_object_put(jobj); /* Delete object. */
     return ret;
 }
 
-int
-repo_download_id_sync(struct lkt_repo *const repo, sqlite3 *db, const uint64_t id, const char *kara_path,
-                      struct kara_metadata *mdt_ret)
+static inline int
+__download_kara(const char *url, const char *path, int override)
 {
-    RETURN_UNLESS(kara_path, "Invalid argument", 1);
-    struct kara_metadata mdt;
     CURL *curl_handle;
-    int ret = 1, fd;
-    char *url = calloc(URL_MAX_LEN, sizeof(char));
-    char *ct;
-    RETURN_UNLESS(url, "Out of memory", errno = ENOMEM);
-
-    if (repo_get_id(repo, id, mdt_ret ? mdt_ret : &mdt)) {
-        LOG_ERROR("%s", "Failed to get kara metadata from kurisu");
-        goto err_no_curl;
-    }
-
     errno = 0;
-    fd = open(kara_path,
-              O_WRONLY | O_APPEND | O_CREAT | O_EXCL | O_NOFOLLOW,
-              S_IRUSR | S_IWUSR);
+    char *ct, ret = 1;
+    int fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
 
+retest:
     if (fd < 0) {
-        if (errno == EEXIST)
-            LOG_ERROR("File '%s' already exists", kara_path);
+        if (errno == EEXIST && ! override)
+            LOG_ERROR("File '%s' already exists", path);
+
+        else if (errno == EEXIST && override) {
+            if (unlink(path)) {
+                LOG_ERROR_SCT("REPO", "Failed to unlink file '%s'", path);
+                return 1;
+            }
+
+            fd = open(path, O_WRONLY | O_CREAT | O_NOFOLLOW, S_IRUSR | S_IWUSR);
+            override = false;
+            goto retest;
+        }
 
         else
-            LOG_ERROR("Could not open file '%s'", kara_path);
+            LOG_ERROR("Could not open file '%s'", path);
 
-        goto err_no_curl;
+        return 1;
     }
 
-    /* Download the kara... (TODO) */
-
     struct file file = {
-        .path = kara_path,
+        .path = path,
         .fd = fd,
     };
 
-    memset(url, 0, URL_MAX_LEN * sizeof(char));
-    snprintf(url, URL_MAX_LEN - 1, repo->get_id_file, id);
-    url[URL_MAX_LEN - 1] = 0;
     curl_handle = curl_easy_init();
     curl_easy_setopt(curl_handle, CURLOPT_URL, url);
     curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_disk__);
     curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &file);
     curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
-    ret = curl_easy_perform(curl_handle);
 
-    if (ret != CURLE_OK) {
+    if (CURLE_OK != (ret = curl_easy_perform(curl_handle))) {
         LOG_ERROR_SCT("CURL", "curl_easy_perform failed: %s", curl_easy_strerror(ret));
         goto err;
     }
 
-    if (CURLE_OK == ( ret = curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_TYPE, &ct)))
-        LOG_INFO_SCT("CURL", "Content-Type is '%s'", ct);
-    else {
+    if (CURLE_OK != (ret = curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_TYPE, &ct))) {
         LOG_ERROR_SCT("CURL", "Failed to get Content-Type: %s", curl_easy_strerror(ret));
         goto err;
     }
 
-    if (!db) {
-        LOG_INFO("%s", "Skip database update here");
-        goto no_db_update;
+    ret = 0;
+err:
+    curl_easy_cleanup(curl_handle);
+    return ret;
+}
+
+int
+repo_download_id_sync(struct lkt_repo *const repo, const uint64_t id, const char *kara_path, struct kara_metadata *mdt_ret)
+{
+    RETURN_UNLESS(kara_path, "Invalid argument", 1);
+    struct kara_metadata mdt;
+    char url[URL_MAX_LEN];
+
+    if (repo_get_id(repo, id, mdt_ret ? mdt_ret : &mdt)) {
+        LOG_ERROR("%s", "Failed to get kara metadata from kurisu");
+        return 1;
     }
 
-    if (! database_update_add(db, kara_path, mdt_ret ? mdt_ret : &mdt, id, true)) {
+    memset(url, 0, URL_MAX_LEN * sizeof(char));
+    snprintf(url, URL_MAX_LEN - 1, repo->get_id_file, id);
+    url[URL_MAX_LEN - 1] = 0;
+
+    if (__download_kara(url, kara_path, false)) {
+        LOG_ERROR_SCT("REPO", "Failed to download kara '%s' with url '%s'", kara_path, url);
+        return 1;
+    }
+
+    if (repo->db && !database_update_add((sqlite3 *) repo->db, kara_path, mdt_ret ? mdt_ret : &mdt, id, true)) {
         LOG_ERROR("%s", "Failed to add kara to database");
-        goto err;
+        return 1;
+    }
+
+    return 0;
+}
+
+/* Get all the kara, make them unavailable */
+
+static inline void
+__handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_object *json)
+{
+    size_t i, len = json_object_array_length(json);
+    struct json_object *kara_json;
+    int32_t integer, err;
+    struct kara *kara;
+    char url[URL_MAX_LEN];
+    long filestamp, timestamp;
+    RETURN_UNLESS(len > 0 && json_object_get_array(json), "Json invalid or array empty", NOTHING);
+
+    LOG_INFO_SCT("REPO", "Starting to process json for repo %s", repo->name);
+    for (i = 0; i < len; ++i) {
+        kara_json = json_object_array_get_idx(json, i);
+        kara = calloc(1, sizeof(struct kara));
+        RETURN_UNLESS(kara, "Out of memory", NOTHING);
+        err = 0;
+
+        /* Get the id of the kara. */
+        if (safe_json_get_int32(kara_json, "id", &integer))
+            continue;
+        kara->id = integer;
+
+        /* Craft a fake filepath here, it will be used later. */
+        size_t kara_dir_len = strlen(repo->kara_dir);
+        memcpy(kara->filename, repo->kara_dir, sizeof(char) * (kara_dir_len + 1));
+        if (kara->filename[kara_dir_len - 1] != '/') {
+            strncat(kara->filename, "/", PATH_MAX - 1);
+            kara->filename[++kara_dir_len] = 0;
+        }
+        snprintf(kara->filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d.mkv", integer);
+        kara->filename[PATH_MAX - 1] = 0;
+        LOG_INFO_SCT("REPO", "Crafted filename is '%s'", kara->filename);
+
+        /* Timestamp verification */
+        if (safe_json_get_long(kara_json, "unix_timestamp", &timestamp))
+            continue;
+        filestamp = get_mtime(kara->filename);
+        if (database_get_timestamp(db) < filestamp) {
+            LOG_WARN_SCT("REPO", "Kara file %s is more recent than database timestamp, download it", kara->filename);
+            goto do_it;
+        }
+        if (filestamp > timestamp) {
+            LOG_INFO_SCT("REPO", "Ignore kara '%ld', last timestamp was %ld, new is %ld", kara->id, filestamp, timestamp);
+            continue;
+        }
+do_it:
+
+        err |= safe_json_get_string(kara_json, "song_name",   kara->mdt.song_name,   LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "source_name", kara->mdt.source_name, LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "category",    kara->mdt.category,    LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "language",    kara->mdt.language,    LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "author_name", kara->mdt.author_name, LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "song_type",   kara->mdt.song_type,   LEKTOR_TAG_MAX);
+        GOTO_IF(err, "Invalid json", err);
+
+        if (safe_json_get_int32(kara_json, "song_number", &kara->mdt.song_number))
+            goto err;
+
+        if (!database_update_add((sqlite3 *) db, kara->filename, &kara->mdt, kara->id, false)) {
+            LOG_ERROR_SCT("REPO", "Could not add unavailable kara %ld to db", kara->id);
+            continue;
+        }
+
+        snprintf(url, URL_MAX_LEN - 1, repo->get_id_file, kara->id);
+        url[URL_MAX_LEN - 1] = '\0';
+
+        if (__download_kara(url, kara->filename, true)) {
+            LOG_WARN_SCT("REPO", "Could not download kara %ld at path '%s'", kara->id, kara->filename);
+            continue;
+        }
+
+        if (!database_update_set_available((sqlite3 *) db, kara->id)) {
+            LOG_WARN_SCT("REPO", "Could not set kara %ld available", kara->id);
+            continue;
+        }
+
+        database_stamp(db);
+
+        LOG_INFO_SCT("REPO", "Added kara %ld from repo %s, filepath is %s", kara->id, repo->name, kara->filename);
     }
 
-no_db_update:
-    ret = 0;
 err:
-    curl_easy_cleanup(curl_handle);
-err_no_curl:
-    free(url);
-    return ret;
+    free(kara);
+}
+
+static inline void *
+__repo_get_all_id_async(void *arg)
+{
+    struct json_object *json;
+    struct lkt_repo *const repo = arg;
+    LOG_INFO_SCT("REPO", "Download kara list from %s (%s), directory is %s",
+                 repo->name, repo->base_url, repo->kara_dir);
+    __json_sync(repo, &json);
+    __handle_got_json(repo->db, repo, json);
+    LOG_INFO_SCT("REPO", "%s", "Finished to download and insert kara list");
+    json_object_put(json);
+    database_updated(repo->db);
+    return NULL;
+}
+
+inline int
+repo_update(struct lkt_repo *const repo)
+{
+    return mthread_create(NULL, ATTR_DETACHED, __repo_get_all_id_async, repo);
 }
diff --git a/src/net/listen.c b/src/net/listen.c
index 9a6a226d9ee4ce6bfc0da82ba0a88919b54afa94..690c1844c6111d77864a47a7a01d5fd648c59a14 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -1,10 +1,8 @@
 #define _POSIX_C_SOURCE 200809L
 
 #include <lektor/commands.h>
-#include <lektor/macro.h>
-#include <lektor/define.h>
+#include <lektor/common.h>
 #include <lektor/database.h>
-#include <lektor/repo.h>
 #include <lektor/net.h>
 #include <ini/ini.h>
 
@@ -155,16 +153,18 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
     case MPD_IDLE_NONE:
         /* Commands that requires authentification. */
         if (!strcmp(cmd.name, "__adduser"))
-            err = ! command_user_add(srv, c, srv->db, cmd.args);
+            err = ! command_user_add(srv, c, (sqlite3 *) srv->db, cmd.args);
         else if (!strcmp(cmd.name, "__restart"))
             err = ! command_restart(srv, c);
         else if (!strcmp(cmd.name, "kill"))
             err = ! command_kill(srv, c);
+        else if (!strcmp(cmd.name, "update"))
+            err = ! command_update(srv, c, cmd.args);
         else if (!strcmp(cmd.name, "rescan"))
             err = ! command_rescan(srv, c, cmd.args);
 
         /* Commands that are available if not in idle mode */
-        if (!strcmp(cmd.name, "currentsong"))
+        else if (!strcmp(cmd.name, "currentsong"))
             err = !command_currentsong(srv, c);
         else if (!strcmp(cmd.name, "status"))
             err = !command_status(srv, c);
@@ -175,25 +175,26 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
             err = 0;
 
         else if (!strcmp(cmd.name, "next"))
-            err = !command_next(srv->db, &srv->win, &srv->mpd_idle_events);
+            err = !command_next((sqlite3 *) srv->db, &srv->win, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "pause"))
-            err = !command_pause(srv->db, &srv->win, &srv->mpd_idle_events);
+            err = !command_pause((sqlite3 *) srv->db, &srv->win, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "previous"))
-            err = !command_previous(srv->db, &srv->win, &srv->mpd_idle_events);
+            err = !command_previous((sqlite3 *) srv->db, &srv->win, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "play"))
-            err = ! command_play(srv->db, &srv->win, cmd.args, &srv->mpd_idle_events);
+            err = ! command_play((sqlite3 *) srv->db, &srv->win, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "playid"))
-            err = ! command_playid(srv->db, &srv->win, cmd.args, &srv->mpd_idle_events);
+            err = ! command_playid((sqlite3 *) srv->db, &srv->win, cmd.args,
+                                   (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "stop"))
-            err = !command_stop(srv->db, &srv->win, &srv->mpd_idle_events);
+            err = !command_stop((sqlite3 *) srv->db, &srv->win, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "clear"))
-            err = !command_clear(srv->db, &srv->mpd_idle_events);
+            err = !command_clear((sqlite3 *) srv->db, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "crop"))
-            err = !command_crop(srv->db, &srv->mpd_idle_events);
+            err = !command_crop((sqlite3 *) srv->db, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "moveid"))
-            err = !command_move(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = !command_move((sqlite3 *) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "shuffle"))
-            err = !command_shuffle(srv->db, &srv->mpd_idle_events);
+            err = !command_shuffle((sqlite3 *) srv->db, (enum mpd_idle_flag *) &srv->mpd_idle_events);
 
         else if (!strcmp(cmd.name, "playlist") || !strcmp(cmd.name, "playlistinfo"))
             err = !command_queue_list(srv, c, cmd.args);
@@ -213,31 +214,29 @@ 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, "__dbupdate"))
-            err = !command_update(srv, &srv->mpd_idle_events);
 
         else if (!strcmp(cmd.name, "add"))
-            err = !command_add(srv->db, &srv->win, cmd.args, &srv->mpd_idle_events);
+            err = !command_add((sqlite3 *) srv->db, &srv->win, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "addid"))
-            err = !command_addid(srv->db, &srv->win, cmd.args, &srv->mpd_idle_events);
+            err = !command_addid((sqlite3 *) srv->db, &srv->win, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "deleteid"))
             err = ! (cmd.args[0] != NULL &&
-                     command_delid(srv->db, &srv->win, cmd.args[0], &srv->mpd_idle_events));
+                     command_delid((sqlite3 *) srv->db, &srv->win, cmd.args[0], (enum mpd_idle_flag *) &srv->mpd_idle_events));
 
         else if (!strcmp(cmd.name, "playlistclear"))
-            err = ! command_plt_clear(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = ! command_plt_clear((sqlite3 *) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "rename"))
-            err = ! command_plt_rename(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = ! command_plt_rename((sqlite3 * ) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "playlistdelete"))
-            err = ! command_plt_remove(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = ! command_plt_remove((sqlite3 *) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "playlistadd"))
-            err = ! command_plt_add(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = ! command_plt_add((sqlite3 *) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "rm") && cmd.args[0] != NULL && cmd.args[1] == NULL)
-            err = ! command_plt_remove(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = ! command_plt_remove((sqlite3 *) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "save"))
-            err = ! command_plt_export(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = ! command_plt_export((sqlite3 *) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
         else if (!strcmp(cmd.name, "__import"))
-            err = ! command_plt_import(srv->db, cmd.args, &srv->mpd_idle_events);
+            err = ! command_plt_import((sqlite3 *) srv->db, cmd.args, (enum mpd_idle_flag *) &srv->mpd_idle_events);
 
         else if (!strcmp(cmd.name, "random"))
             err = !command_set_playback_option(srv, c, lkt_playback_option_random, cmd.args);
@@ -686,53 +685,6 @@ lkt_client_auth(struct lkt_state *srv, size_t c, bool set)
     return srv->clients[c - 1].authentificated |= set;
 }
 
-static inline void
-handle_repo_hevents(struct lkt_state *srv)
-{
-    struct kara *kara;
-
-    for (;;) {
-        if (repo_get_kara_async(&kara))
-            goto get_out;
-
-        switch (kara->action) {
-        /* Add the downloaded kara to the database. */
-        case kara_action_add:
-            if (!database_update_add(srv->db, kara->filename, &kara->mdt, kara->id, true)) {
-                LOG_ERROR("Failed to add downloaded kara with id %lu and path %s", kara->id, kara->filename);
-                goto get_out;
-            }
-
-            LOG_INFO("Added kara %lu with path %s to database", kara->id, kara->filename);
-
-            break;
-
-        /* Add the mdt of the kara to the database. Mark it unavailable. */
-        case kara_action_unavail:
-            if (!database_update_add(srv->db, kara->filename, &kara->mdt, kara->id, false)) {
-                LOG_ERROR("Failed to add kara with id %lu with flag unavailable", kara->id);
-                goto get_out;
-            }
-
-            LOG_INFO("Added kara %lu to database and set it to unavailable", kara->id);
-
-            break;
-
-        case kara_action_none:
-        default:
-            break;
-        }
-
-        free(kara);
-        kara = NULL;
-    }
-
-    /* Just get out of the loop. */
-get_out:
-    if (kara)
-        free(kara);
-}
-
 int
 lkt_listen(void)
 {
@@ -740,7 +692,6 @@ lkt_listen(void)
     RETURN_UNLESS(memory, "Out of memory", 5);
 
     struct lkt_state srv;
-    struct lkt_repo repo;
     int autoclear;
     char *const db_path  = memory;                  /* Size is PATH_MAX.        */
     char *const kara_dir = memory + PATH_MAX + 1;   /* Size is PATH_MAX.        */
@@ -751,26 +702,26 @@ lkt_listen(void)
     memset(&srv, 0, sizeof(struct lkt_state));
 
     /* Initialize the system. */
-    RETURN_UNLESS(database_new(&srv.db), "Failed to initialize the memory database", 1);
+    RETURN_UNLESS(database_new((sqlite3 **) &srv.db), "Failed to initialize the memory database", 1);
     RETURN_IF(config_detect_file(conf_file, PATH_MAX), "Failed to find a config file", 1);
-    RETURN_IF(config_new(srv.db, conf_file), "Failed to read configuration file", 1);
+    RETURN_IF(config_new((sqlite3 *) srv.db, conf_file), "Failed to read configuration file", 1);
 
     /* Finish to initialize. */
-    RETURN_UNLESS(database_config_get_text(srv.db, "database", "db_path", db_path, PATH_MAX), "Cfg error", 2);
-    RETURN_UNLESS(database_open(srv.db, db_path), "Can't open database", 1);
+    RETURN_UNLESS(database_config_get_text((sqlite3 *) srv.db, "database", "db_path", db_path, PATH_MAX), "Cfg error", 2);
+    RETURN_UNLESS(database_open((sqlite3 *) srv.db, db_path), "Can't open database", 1);
 
     /* Read the configuration. */
-    RETURN_UNLESS(database_config_get_int(srv.db, "player", "autoclear", &autoclear), "Cfg error", 2);
-    RETURN_UNLESS(database_config_get_text(srv.db, "database", "kara_dir", kara_dir, PATH_MAX), "Cfg error", 2);
-    RETURN_UNLESS(database_config_get_text(srv.db, "server", "host", host, HOST_NAME_MAX), "Cfg error", 2);
-    RETURN_UNLESS(database_config_get_text(srv.db, "server", "port", port, 5), "Cfg error", 2);
-    RETURN_UNLESS(database_config_get_text(srv.db, "player", "module", player_mod, INI_MAX_LINE), "Cfg error", 2);
+    RETURN_UNLESS(database_config_get_int( (sqlite3 *) srv.db, "player",   "autoclear", &autoclear),               "Cfg error", 2);
+    RETURN_UNLESS(database_config_get_text((sqlite3 *) srv.db, "database", "kara_dir",  kara_dir, PATH_MAX),       "Cfg error", 2);
+    RETURN_UNLESS(database_config_get_text((sqlite3 *) srv.db, "server",   "host",      host, HOST_NAME_MAX),      "Cfg error", 2);
+    RETURN_UNLESS(database_config_get_text((sqlite3 *) srv.db, "server",   "port",      port, 5),                  "Cfg error", 2);
+    RETURN_UNLESS(database_config_get_text((sqlite3 *) srv.db, "player",   "module",    player_mod, INI_MAX_LINE), "Cfg error", 2);
 
     if (kara_dir[strlen(kara_dir) - 1] != '/')
         strncat(kara_dir, "/", PATH_MAX - 1);
 
     srv.kara_prefix = kara_dir;
-    database_config_queue_default(srv.db);
+    database_config_queue_default((sqlite3 *) srv.db);
 
     srv.fds_max = 16;
     srv.fds     = calloc(srv.fds_max, sizeof(struct pollfd));
@@ -784,24 +735,21 @@ lkt_listen(void)
     srv.fds_len = 1;
 
     if (autoclear)
-        database_queue_clear(srv.db);
+        database_queue_clear((sqlite3 *) srv.db);
 
-    RETURN_UNLESS(load_module_by_name(srv.db, player_mod, &srv.win), "Can't load module", 3);
+    RETURN_UNLESS(load_module_by_name((sqlite3 *) srv.db, player_mod, &srv.win), "Can't load module", 3);
     RETURN_UNLESS(srv.win.new(&srv.win), "Can't create window", 3);
-    RETURN_IF(repo_new(&repo, "kurisu", "https://kurisu.iiens.net"), "Failed to create repo", 4);
-    RETURN_IF(repo_new_thread(&repo), "Failed to launch repo thread", 4);
+    srv.win.attach(&srv.win, &srv);
+    RETURN_IF(repo_new(&srv.repo, "kurisu", "https://kurisu.iiens.net", srv.db), "Failed to create repo", 4);
 
     for (;;) {
         if (handle_network_events(&srv) < 0)
             break;
         if (handle_idle_events(&srv) < 0)
             break;
-        srv.win.handle_events(&srv.win, srv.db, &srv.mpd_idle_events);
-        handle_repo_hevents(&srv);
+        srv.win.handle_events(&srv.win, (sqlite3 *) srv.db, (enum mpd_idle_flag *) &srv.mpd_idle_events);
     }
 
-    repo_join_thread();
     srv.win.free(&srv.win);
-
     return -1;
 }
diff --git a/src/repo/async.c b/src/repo/async.c
deleted file mode 100644
index aeeb98a4ed99c217a35448cbf93cdd8aa8d46efb..0000000000000000000000000000000000000000
--- a/src/repo/async.c
+++ /dev/null
@@ -1,233 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <limits.h>
-
-#include <mthread/mthread.h>
-#include <lektor/macro.h>
-#include <lektor/repo.h>
-#include <lektor/thread.h>
-
-static struct poller_thread repo_thread;
-
-static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
-static volatile int init = 0;
-static volatile int stop = 0;
-static volatile int all_json = 0;
-
-int
-repo_join_thread(void)
-{
-    int ret = 1;
-    RETURN_IF(pthread_mutex_lock(&mtx), "Failed to lock mutex", 3);
-    GOTO_UNLESS(init, "Repo thread no launched, can't join", error);
-    stop = 1;
-    GOTO_IF(pthread_join(repo_thread.th, NULL), "Failed to join repo thread", error);
-    LOG_INFO("%s", "repo thread joined");
-    ret = 0;
-error:
-    RETURN_IF(pthread_mutex_unlock(&mtx), "Failed to unlock mutex", 3);
-    return ret;
-}
-
-/* Find it in the repo/curl.c file. */
-extern int
-safe_json_get_string(struct json_object *jobj, const char *key, char *content, const size_t len);
-extern int
-safe_json_get_int32(struct json_object *json, const char *key, int32_t *ret);
-
-static inline void
-__handle_got_json(struct poller_thread *self, struct lkt_repo *repo, struct json_object *json)
-{
-    size_t i, len = json_object_array_length(json);
-    struct json_object *kara_json;
-    int32_t integer;
-    struct kara *kara;
-    int err;
-
-    RETURN_UNLESS(len > 0 && json_object_get_array(json), "Json invalid or array empty", NOTHING);
-
-    for (i = 0; i < len; ++i) {
-        kara_json = json_object_array_get_idx(json, i);
-        kara = calloc(1, sizeof(struct kara));
-        err = 0;
-
-        /* Get the id of the kara. */
-        if (safe_json_get_int32(kara_json, "id", &integer))
-            goto err;
-
-        /* Craft a fake filepath here, it will be used later. */
-        size_t kara_dir_len = strlen(repo->kara_dir);
-        memcpy(kara->filename, repo->kara_dir, sizeof(char) * (kara_dir_len + 1));
-        if (kara->filename[kara_dir_len - 1] != '/') {
-            strncat(kara->filename, "/", PATH_MAX - 1);
-            kara->filename[++kara_dir_len] = 0;
-        }
-        integer = snprintf(kara->filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d", integer);
-        kara->filename[PATH_MAX - 1] = 0;
-        LOG_INFO("Crafted filename is '%s'", kara->filename);
-
-        RETURN_UNLESS(kara, "Out of memory", NOTHING);
-
-        /* Get the fields from the json. */
-        err |= safe_json_get_string(kara_json, "song_name", kara->mdt.song_name, LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "source_name", kara->mdt.source_name, LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "category", kara->mdt.category, LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "language", kara->mdt.language, LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "author_name", kara->mdt.author_name, LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "song_type", kara->mdt.song_type, LEKTOR_TAG_MAX);
-
-        if (err)
-            goto err;
-
-        /* Get the song number. */
-        if (safe_json_get_int32(kara_json, "song_number", &kara->mdt.song_number))
-            goto err;
-
-        /* Append. */
-        if (lkt_th_append_output(self, kara)) {
-            LOG_ERROR("%s", "Could not append downloaded kara mdt");
-            goto err;
-        }
-
-        continue;
-err:
-        free(kara);
-    }
-}
-
-static void *
-__repo_thread_function(struct poller_thread_arg *arg)
-{
-    size_t head;
-    struct lkt_repo *repo = arg->args;
-    struct poller_thread *self = arg->self;
-    struct kara *kara;
-    struct json_object *json = NULL;
-    char path[PATH_MAX];
-    free(arg);
-
-    LOG_INFO("%s", "Starting the repo thread");
-
-    for (;;) {
-        GOTO_IF(pthread_mutex_lock(&mtx), "Failed to lock mutex", end_loop);
-
-        if (all_json) {
-            repo_get_alljson_sync(repo, &json);
-            __handle_got_json(self, repo, json);
-            json_object_put(json);
-        }
-
-        if (stop) {
-            if (pthread_mutex_unlock(&mtx))
-                LOG_ERROR("Failed to unlock mutex: %s", strerror(errno));
-            break;
-        }
-
-        head = 0;
-
-        /* size_t has the size of a pointer (thus of a void *). */
-        if (lkt_th_pop_input(self, (void **) &head)) {
-            LOG_ERROR("%s", "Failed to get the head of the input list");
-            goto end_loop; /* Just skip all the loop to the yield function. */
-        }
-
-        /* Did we pop something? */
-        if (NULL == (void *) head)
-            goto end_loop;
-
-        snprintf(path, PATH_MAX - 1, "%s%lu.mkv", repo->kara_dir, head);
-        path[PATH_MAX - 1] = 0;
-        kara = calloc(1, sizeof(struct kara));
-
-        if (NULL == kara) {
-            LOG_ERROR_SCT("MEMORY", "%s", "Out of memory");
-            goto end_loop;
-        }
-
-        if (repo_download_id_sync(repo, NULL, head, path, &kara->mdt)) {
-            LOG_ERROR("Failed to download kara with id %lu", head);
-            goto try_later;
-        }
-
-        /* Copy data to the structure that we will pass to the main thread. */
-        kara->action = kara_action_add;
-        kara->id = head;
-        memcpy(kara->filename, path, (strlen(path) + 1) * sizeof(char));
-
-        if (lkt_th_append_output(self, (void *) kara)) {
-            LOG_ERROR("Failed to append to output, orphan kara %lu", head);
-            free(kara);
-            goto end_loop;
-        }
-
-        LOG_INFO("Append kara %lu with path %s to out pool", kara->id, kara->filename);
-
-        kara = NULL;
-        goto end_loop;
-
-try_later:
-        if (kara)
-            free(kara);
-
-        /* Retry later. TODO: Implements a retry counter. */
-        if (lkt_th_append_input(self, (void *) head))
-            LOG_ERROR("%s", "Failed to get the head of the input list");
-
-end_loop:
-        sched_yield();
-        sleep(1);
-    }
-
-    LOG_INFO("%s", "Stopping the repo thread");
-    return NULL;
-}
-
-int
-repo_new_thread(struct lkt_repo *const repo)
-{
-    RETURN_IF(init, "Already running", 1);
-    struct poller_thread_arg *arg = calloc(1, sizeof(struct poller_thread_arg));
-    RETURN_UNLESS(arg, "Out of memory", errno = ENOMEM);
-    arg->args = repo;
-    RETURN_IF(lkt_th_new(&repo_thread, LKT_DEFAULT_LIST_SIZE, __repo_thread_function, arg), "Thread error", 1);
-    init = 1;
-    return 0;
-}
-
-int
-repo_download_id_async(const size_t id)
-{
-    RETURN_IF(id == 0, "Invalid argument", 1);
-    RETURN_IF(lkt_th_append_input(&repo_thread, (void *) id), "Failed to push downloaded id", id);
-    LOG_INFO("Asked to download kara with id %lu", id);
-    return 0;
-}
-
-int
-repo_get_kara_async(struct kara **downloaded)
-{
-    /* Is there a kara that has been downloaded? */
-    if (lkt_th_pop_output(&repo_thread, (void **) downloaded))
-        goto err;
-
-    if (!*downloaded)
-        goto err;
-
-    return 0;
-err:
-    *downloaded = NULL;
-    return 1;
-}
-
-inline int
-repo_get_allid_async(void)
-{
-    RETURN_IF(pthread_mutex_lock(&mtx), "Failed to lock mutex", 3);
-    all_json = 1;
-    RETURN_IF(pthread_mutex_unlock(&mtx), "Failed to lock mutex", 3);
-    return 0;
-}
diff --git a/src/thread.c b/src/thread.c
index 4969c93320d752211f0c7482bbf487dced727a33..e4e3f1074945c1cae565f986c7d74efb1439bfc8 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -26,7 +26,7 @@ __start(void *args__)
 }
 
 int
-lkt_th_new(struct poller_thread *th, unsigned int init_sizes,
+poller_new(struct poller_thread *th, unsigned int init_sizes,
            void *(*func)(struct poller_thread_arg *), void *args)
 {
     pthread_mutex_t mtx1 = PTHREAD_MUTEX_INITIALIZER;
@@ -73,7 +73,7 @@ out_of_memory:
 }
 
 int
-lkt_th_join(struct poller_thread *th, void **ret)
+poller_join(struct poller_thread *th, void **ret)
 {
     int sta = pthread_join(th->th, ret);
 
@@ -157,21 +157,21 @@ end:
 }
 
 int
-lkt_th_append_input(struct poller_thread *th, void *ptr)
+poller_append_input(struct poller_thread *th, void *ptr)
 {
     return th_append((unsigned int *) &th->input_len, (unsigned int *) &th->input_size,
                      (void ***) &th->input_cells, &th->input_lock, ptr);
 }
 
 int
-lkt_th_append_output(struct poller_thread *th, void *ptr)
+poller_append_output(struct poller_thread *th, void *ptr)
 {
     return th_append((unsigned int *) &th->output_len, (unsigned int *) &th->output_size,
                      (void ***) &th->output_cells, &th->output_lock, ptr);
 }
 
 int
-lkt_th_pop_input(struct poller_thread *th, void **ptr)
+poller_pop_input(struct poller_thread *th, void **ptr)
 {
     return th_pop((unsigned int *) &th->input_len, (void **) th->input_cells,
                   &th->input_lock, ptr);
@@ -179,20 +179,20 @@ lkt_th_pop_input(struct poller_thread *th, void **ptr)
 
 
 int
-lkt_th_pop_output(struct poller_thread *th, void **ptr)
+poller_pop_output(struct poller_thread *th, void **ptr)
 {
     return th_pop((unsigned int *) &th->output_len, (void **) th->output_cells,
                   &th->output_lock, ptr);
 }
 
 int
-lkt_th_head_input(struct poller_thread *th, void **ptr)
+poller_head_input(struct poller_thread *th, void **ptr)
 {
     return th_head((unsigned int) th->input_len, (void **) th->input_cells, &th->input_lock, ptr);
 }
 
 int
-lkt_th_head_output(struct poller_thread *th, void **ptr)
+poller_head_output(struct poller_thread *th, void **ptr)
 {
     return th_head((unsigned int) th->output_len, (void **) th->output_cells, &th->output_lock, ptr);
 }
diff --git a/src/uri.c b/src/uri.c
index 8219ef1a587bd20eb875d1c39363d32327bc45dd..ac8634be845720818b767601c8f5358d318dcd2d 100644
--- a/src/uri.c
+++ b/src/uri.c
@@ -7,7 +7,7 @@
 #include <limits.h>
 
 bool
-lkt_uri_from(struct lkt_uri_t *ret, char *const str)
+lkt_uri_from(struct lkt_uri *ret, char *const str)
 {
     char *val, *endptr;
     size_t len;
@@ -80,7 +80,7 @@ lkt_uri_from(struct lkt_uri_t *ret, char *const str)
 }
 
 void
-lkt_uri_free(struct lkt_uri_t *ret)
+lkt_uri_free(struct lkt_uri *ret)
 {
     if (NULL == ret)
         return;
@@ -88,3 +88,47 @@ lkt_uri_free(struct lkt_uri_t *ret)
     if (ret->_allocated)
         free(ret->value);
 }
+
+/* Support a subrange of URIs. */
+static inline int
+__lkt_to_str(struct lkt_uri *uri, char *ret, size_t len)
+{
+    switch (uri->type) {
+    case uri_id:
+        snprintf(ret, len - 1, "id=%s", (char *) uri->value);
+        break;
+    case uri_type:
+        snprintf(ret, len - 1, "type=%s", (char *) uri->value);
+        break;
+    case uri_author:
+        snprintf(ret, len - 1, "author=%s", (char *) uri->value);
+        break;
+    case uri_category:
+        snprintf(ret, len - 1, "cat=%s", (char *) uri->value);
+        break;
+    case uri_query:
+        snprintf(ret, len - 1, "search=%s", (char *) uri->value);
+        break;
+    default:
+        LOG_ERROR("URI type %d may not be supported by kurisu, generate an error", uri->type);
+        return 1;
+    }
+
+    ret[len - 1] = '\0';
+    return 0;
+}
+
+int
+lkt_uri_to_url(struct lkt_uri *uri, const char *base_url, char *ret, size_t len)
+{
+    RETURN_UNLESS(uri && base_url && ret && len > 0, "Invalid argument", 1);
+
+    /* Craft URL */
+    memset(ret, 0, len);
+    memcpy(ret, base_url, sizeof(char) * strlen(base_url));
+    strncat(ret, "?", len - 1);
+
+    /* The query */
+    size_t init_len = strlen(ret);
+    return __lkt_to_str(uri, ret + init_len, len - init_len);
+}
diff --git a/src/utils.c b/src/utils.c
deleted file mode 100644
index c01ce5a628ed3c640f8bf76051d1b31653defefe..0000000000000000000000000000000000000000
--- a/src/utils.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include <lektor/utils.h>
-#include <string.h>
-#include <stdio.h>
-
-uint32_t
-be_uint32_t(const uint8_t bytes[], size_t n)
-{
-    uint32_t res = 0;
-    for (size_t i = 0; i < n; i++)
-        res = (res << 8u) | bytes[i];
-    return res;
-}
-
-uint64_t
-be_uint64_t(const uint8_t bytes[], size_t n)
-{
-    uint64_t res = 0;
-    for (size_t i = 0; i < n; i++)
-        res = (res << 8u) | bytes[i];
-    return res;
-}
-
-char *
-trim(char *str, size_t len, char c)
-{
-    char *res = (char *) str;
-    char *end;
-
-    for (; len != 0 && *res == c; ++str, --len)
-        continue;
-
-    if (*res == 0)
-        return res;
-
-    end = res + len - sizeof(char);
-    len = 0;
-
-    for (; res < end && *end == c; --end, ++len)
-        continue;
-
-    if (len > 0)
-        end[1] = 0;
-
-    return res;
-}
-
-int
-is_utf8(const char *string)
-{
-    if (!string)
-        return 1;
-
-    const unsigned char *bytes = (const unsigned char *)string;
-    while (*bytes) {
-        /* ASCII */
-        if  (bytes[0] == 0x09 || bytes[0] == 0x0A ||
-             bytes[0] == 0x0D || (0x20 <= bytes[0] && bytes[0] <= 0x7E)) {
-            bytes += 1;
-            continue;
-        }
-
-        /* non-overlong 2-byte */
-        if ((0xC2 <= bytes[0] && bytes[0] <= 0xDF) &&
-            (0x80 <= bytes[1] && bytes[1] <= 0xBF)) {
-            bytes += 2;
-            continue;
-        }
-
-        if ( (bytes[0] == 0xE0 &&
-              (0xA0 <= bytes[1] && bytes[1] <= 0xBF)  &&
-              (0x80 <= bytes[2] && bytes[2] <= 0xBF)) ||    /* excluding overlongs */
-             (((0xE1 <= bytes[0] && bytes[0] <= 0xEC) ||
-               bytes[0] == 0xEE || bytes[0] == 0xEF)  &&
-              (0x80 <= bytes[1] && bytes[1] <= 0xBF)  &&
-              (0x80 <= bytes[2] && bytes[2] <= 0xBF)) ||    /* straight 3-byte */
-             (bytes[0] == 0xED &&
-              (0x80 <= bytes[1] && bytes[1] <= 0x9F)  &&
-              (0x80 <= bytes[2] && bytes[2] <= 0xBF))) {    /* excluding surrogates */
-            bytes += 3;
-            continue;
-        }
-
-        if ( (bytes[0] == 0xF0  &&                          /* planes 1-3 */
-              (0x90 <= bytes[1] && bytes[1] <= 0xBF)  &&
-              (0x80 <= bytes[2] && bytes[2] <= 0xBF)  &&
-              (0x80 <= bytes[3] && bytes[3] <= 0xBF)) ||
-             ((0xF1 <= bytes[0] && bytes[0] <= 0xF3)  &&
-              (0x80 <= bytes[1] && bytes[1] <= 0xBF)  &&
-              (0x80 <= bytes[2] && bytes[2] <= 0xBF)  &&
-              (0x80 <= bytes[3] && bytes[3] <= 0xBF)) ||    /* planes 4-15 */
-             (bytes[0] == 0xF4 &&
-              (0x80 <= bytes[1] && bytes[1] <= 0x8F)  &&
-              (0x80 <= bytes[2] && bytes[2] <= 0xBF)  &&
-              (0x80 <= bytes[3] && bytes[3] <= 0xBF))) {    /* plane 16 */
-            bytes += 4;
-            continue;
-        }
-
-        return 2;
-    }
-
-    return 0;
-}
-
-int
-get_stdin_line(const char *prompt, char *buf, size_t len)
-{
-    if (prompt)
-        fprintf(stdout, "%s", prompt);
-    if (!fgets(buf, len, stdin))
-        return 1;
-    buf[len - 1] = 0u;
-    return is_utf8(buf);
-}