diff --git a/inc/common/queue.h b/inc/common/queue.h
index 5d5e5115f2658086054e999a6bab423f4226b1ba..286dd54618f4b9f9fc606ada852d697f9baa6869 100644
--- a/inc/common/queue.h
+++ b/inc/common/queue.h
@@ -3,13 +3,26 @@
 #include <pthread.h>
 #include <common/common.h>
 
+#define LKT_PLAY_STOP   ((void *) (size_t) 0)
+#define LKT_PLAY_PLAY   ((void *) (size_t) 1)
+#define LKT_PLAY_PAUSE  ((void *) (size_t) 2)
+#define LKT_PLAY_TOGGLE ((void *) (size_t) 3)
+
 enum lkt_event_type {
-    lkt_event_null      = 0,            /* NULL         */
-    lkt_event_play_pos  = (1 << 1),     /* size_t       */
-    lkt_event_play_file = (1 << 2),     /* const char*  */
+    lkt_event_null          = 0,        /* NULL         */
+    lkt_event_play_pos      = (1 << 1), /* size_t       */
+    lkt_event_play_file     = (1 << 2), /* const char*  */
+    lkt_event_play_next     = (1 << 3), /* NULL         */
+    lkt_event_play_prev     = (1 << 4), /* NULL         */
+    lkt_event_play_toggle   = (1 << 5), /* size_t, `LKT_PLAY_.*` */
+    lkt_event_prop_vol      = (1 << 6), /* size_t       */
+    lkt_event_prop_dur      = (1 << 7), /* size_t       */
+    lkt_event_prop_time     = (1 << 8), /* size_t       */
 };
 
-#define lkt_event_play (lkt_event_play_pos | lkt_event_play_file)
+#define lkt_event_play (lkt_event_play_pos | lkt_event_play_file |  \
+                        lkt_event_play_next | lkt_event_play_prev   \
+                       )
 
 typedef struct {
     unsigned int type;
diff --git a/inc/lektor/module/module_x11.h b/inc/lektor/module/module_x11.h
deleted file mode 100644
index 14c9fb7e9bdd448a3a39dd49ca1c341836128723..0000000000000000000000000000000000000000
--- a/inc/lektor/module/module_x11.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-#include <sqlite3.h>
-#include <lektor/window.h>
-
-#if defined(_STATIC_MODULES)
-/* The only function with a setted filename */
-int load_x11(void *mod, struct lkt_state *srv, void *handle);
-#endif
-
-/* Below there are needed functions for a window module.
- * Names are not fixed but they follow a convention (to get a code easy
- * to read). They should not be used in lektor! They will be loaded into
- * the struct lkt_win by the module_set_function.
- */
-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);
-bool module_x11_set_volume(struct lkt_win *const win, int vol);
-
-bool module_x11_get_duration(struct lkt_win *const win, int *dur_sec);
-bool module_x11_get_elapsed(struct lkt_win *const win, int *elapsed_sec);
-
-bool module_x11_handle_events(struct lkt_win *const win, volatile sqlite3 *db, mpd_idle_flag *mpd_idle_events);
diff --git a/inc/lektor/module/mpv.h b/inc/lektor/module/mpv.h
index ab28af195e1430dccaaa06cde9745d47f83f17c5..821bdd12b97d4273bc9b275d821515a92dcff647 100644
--- a/inc/lektor/module/mpv.h
+++ b/inc/lektor/module/mpv.h
@@ -2,8 +2,10 @@
 
 #include <sqlite3.h>
 #include <mpv/client.h>
-#include <lektor/net.h>
 #include <common/common.h>
+#include <common/queue.h>
+
+struct lkt_win *win;
 
 void lmpv_free(mpv_handle **ctx);
 mpv_handle *lmpv_new(unsigned long int wid, volatile sqlite3 *db);
@@ -13,5 +15,5 @@ mpv_handle *lmpv_prepare(volatile sqlite3 *db);
 int lmpv_set_volume(mpv_handle *ctx, int vol);
 int lmpv_load_file(mpv_handle *ctx, const char *file);
 int lmpv_toggle_pause(mpv_handle *ctx);
-int lmpv_handle(struct lkt_win *win, mpv_handle *ctx, volatile sqlite3 *db, mpd_idle_flag *mpd_idle_flag,
+int lmpv_handle(struct lkt_win *win, mpv_handle *ctx, struct queue *queue,
                 volatile int *time_pos, volatile int *time_duration);
diff --git a/meson.build b/meson.build
index c5955d01dfd1975683f4823c8836a3f29f837b13..c73a83c2b77a585050199de16d311ac03bd6888f 100644
--- a/meson.build
+++ b/meson.build
@@ -33,9 +33,6 @@ if get_option('static_modules').enabled()
   if get_option('module_sdl').enabled()
     add_global_arguments('-D_STATIC_SDL2', language: 'c')
   endif
-  if get_option('module_x11').enabled()
-    add_global_arguments('-D_STATIC_X11', language: 'c')
-  endif
 endif
 
 ## Module list
@@ -126,20 +123,6 @@ else
   bin_deps = [ declare_dependency( link_with: lib.get_shared_lib(), include_directories: includes) ]
 endif
 
-# X11 window module
-if get_option('module_x11').enabled()
-  assert(dep_x11.found() and dep_mpv.found(), 'Asking to build x11 module, but missing dependencies')
-  lib_mod_x11 = both_libraries ( '_module_x11'
-                               , files(['src/module/module_x11.c', 'src/module/mpv.c'])
-                               , include_directories: includes
-                               , dependencies: [ dep_x11, dep_mpv, bin_deps ]
-                               , install: get_option('static_modules').disabled()
-                               , install_dir: 'lib/lektor' )
-  if get_option('static_modules').enabled()
-    lektor_modules += [ lib_mod_x11.get_static_lib() ]
-  endif
-endif
-
 # SQL2 window module
 if get_option('module_sdl').enabled()
   assert(dep_x11.found() and dep_mpv.found(), 'Asking to build x11 module, but missing dependencies')
diff --git a/src/module/module_sdl2.c b/src/module/module_sdl2.c
index 81292ef28a209cb417b98a0bf4a00a0ad17bd004..b8fdbe640aeede8ab06551f6ea5b01a26fec37fe 100644
--- a/src/module/module_sdl2.c
+++ b/src/module/module_sdl2.c
@@ -1,12 +1,12 @@
 #define _POSIX_C_SOURCE 200809L
 
-#include <lektor/commands.h>
 #include <common/common.h>
+#include <common/queue.h>
 #include <lektor/module/module_sdl2.h>
 #include <lektor/module/mpv.h>
-#include <mthread/mthread.h>
 #include <lektor/thread.h>
 #include <lektor/reg.h>
+#include <lektor/net.h>
 
 #include <sched.h>
 #include <assert.h>
@@ -36,13 +36,11 @@ struct module_sdl2_window {
     volatile int mpv_duration;  /* Because don't need to be persistent  */
 
     /* Thread related */
-    mthread_mutex_t mtx;
     struct poller_thread self;
     volatile int launched;  /* SDL you sucks */
 
     /* Things from the server */
-    volatile sqlite3 *db;
-    mpd_idle_flag *mpd_idle_events;
+    struct queue *queue;
 };
 
 /* Private functions. */
@@ -181,8 +179,7 @@ loop:
         else if (event.key.keysym.sym == SDLK_RETURN    ||
                  event.key.keysym.sym == SDLK_RETURN2   ||
                  event.key.keysym.sym == SDLK_KP_ENTER)
-            command_next(sdl2->db, (struct lkt_win *) win,
-                         sdl2->mpd_idle_events);
+            lkt_queue_send(sdl2->queue, lkt_event_play_next, NULL);
 
         else if (event.key.keysym.sym == SDLK_LEFT) {
             const char *cmd_seek[] = { "seek", "-5", "relative", NULL };
@@ -205,26 +202,26 @@ loop:
 
     case SDL_TEXTINPUT:
         if (STR_MATCH(event.text.text, ">"))
-            command_next(sdl2->db, (struct lkt_win *) win,
-                         sdl2->mpd_idle_events);
+            lkt_queue_send(sdl2->queue, lkt_event_play_next, NULL);
         else if (STR_MATCH(event.text.text, "<"))
-            command_previous(sdl2->db, (struct lkt_win *) win,
-                             sdl2->mpd_idle_events);
+            lkt_queue_send(sdl2->queue, lkt_event_play_prev, NULL);
         else if (STR_MATCH(event.text.text, "o")) {
             const char *cmd[] = { "show-progress", NULL };
             mpv_command_async((mpv_handle *) sdl2->mpv, 0, cmd);
         } else if (STR_MATCH(event.text.text, "i")) {
+            /*
             struct kara_metadata mdt;
             int id;
             char *str;
             if (database_queue_current_kara(sdl2->db, &mdt, &id)) {
                 mdtcat(&mdt, &str);
                 const char *cmd[] = { "show-text", str, "4000", NULL };
-                /* Same size, only on 64bit arch...
-                   FIXME: Do something else in 32bits */
+                // Same size, only on 64bit arch...
+                // FIXME: Do something else in 32bits
                 mpv_command_async((mpv_handle *) sdl2->mpv,
                                   (uint64_t) str, cmd);
             }
+            */
         } else
             LOG_ERROR("WINDOW", "Not handled text '%s'", event.text.text);
         break;
@@ -239,8 +236,7 @@ loop:
 
         if (event.type == wakeup_on_mpv_events)
             lmpv_handle((struct lkt_win *) win, (mpv_handle *) sdl2->mpv,
-                        sdl2->db, sdl2->mpd_idle_events, &sdl2->mpv_time_pos,
-                        &sdl2->mpv_duration);
+                        sdl2->queue, &sdl2->mpv_time_pos, &sdl2->mpv_duration);
     }
 
     if (redraw) {
@@ -287,11 +283,8 @@ module_sdl2_new(struct lkt_win *const win)
         memset(win->window, 0, sizeof(struct module_sdl2_window));
 
         /* Yeah, this is how it is done. */
-        mthread_mutex_t mtx = MTHREAD_MUTEX_INITIALIZER;
         struct module_sdl2_window *sdl2 = win->window;
-        sdl2->mtx = mtx;
-        sdl2->db = win->srv->db;
-        sdl2->mpd_idle_events = &win->srv->mpd_idle_events;
+        sdl2->queue = &win->srv->queue;
 
         /* Start the SDL thread */
         arg = malloc(sizeof(struct poller_thread_arg));
diff --git a/src/module/module_x11.c b/src/module/module_x11.c
deleted file mode 100644
index 061440ab2ad8e0dee9cac3634dc08ffaf9cfd32c..0000000000000000000000000000000000000000
--- a/src/module/module_x11.c
+++ /dev/null
@@ -1,278 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-
-#include <common/common.h>
-#include <lektor/module/module_x11.h>
-#include <lektor/module/mpv.h>
-#include <lektor/database.h>
-#include <lektor/commands.h>
-#include <lektor/reg.h>
-
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <mpv/client.h>
-
-#define WIDTH   400
-#define HEIGHT  200
-
-struct module_x11_window {
-    /* X11 related, the master and slave window */
-    Display *master_display;
-    Display *child_display;
-    Window master_win;
-    Window child_win;
-
-    /* X11 related, some X11 properties */
-    int screen;
-    XSetWindowAttributes attrs;
-    Atom wm_delete;
-    XColor black;
-    bool is_fullscreen;
-
-    /* Mpv related */
-    mpv_handle *mpv;
-    volatile int mpv_time_pos;  // Don't write it in the database       //
-    volatile int mpv_duration;  // Because don't need to be persistent  //
-};
-
-static inline bool
-lx11_new(struct module_x11_window *ret)
-{
-    ret->master_display = XOpenDisplay(NULL);
-    RETURN_UNLESS(ret->master_display, "Can't open display", false);
-    ret->screen = DefaultScreen(ret->master_display);
-    Colormap colormap = DefaultColormap(ret->master_display, ret->screen);
-    XAllocNamedColor(ret->master_display, colormap, "black",
-                     &ret->black, &ret->black);
-
-    // Initialize container window attributes
-    ret->attrs.event_mask
-        = SubstructureRedirectMask
-          | SubstructureNotifyMask
-          | StructureNotifyMask
-          | ExposureMask
-          | KeyReleaseMask
-          | VisibilityChangeMask
-          ;
-    ret->attrs.do_not_propagate_mask = 1;
-    ret->attrs.background_pixel = ret->black.pixel;
-    unsigned long attrs_mask = CWEventMask
-                               | NoEventMask
-                               | CWBackPixel
-                               ;
-
-    // Create and map container window
-    ret->master_win = XCreateWindow(ret->master_display, RootWindow(ret->master_display, ret->screen),
-                                    0, 0, WIDTH, HEIGHT, 1, CopyFromParent, InputOutput,
-                                    CopyFromParent, attrs_mask, &ret->attrs);
-
-    XMapWindow(ret->master_display, ret->master_win);
-    XStoreName(ret->master_display, ret->master_win, "Lektor Player");
-    ret->wm_delete = XInternAtom(ret->master_display, "WM_DELETE_WINDOW", True);
-    XSetWMProtocols(ret->master_display, ret->master_win, &ret->wm_delete, 1);
-
-    ret->child_display = NULL;
-    ret->child_win = 0;
-
-    return true;
-}
-
-static inline bool
-lx11_handle(struct module_x11_window *win)
-{
-    XEvent event;
-
-    RETURN_UNLESS(win && win->mpv, "Invalid argument", true);
-
-    for (;;) {
-
-        if (!XCheckWindowEvent(win->master_display, win->master_win,
-                               win->attrs.event_mask, &event))
-            return true;
-
-        // Map child window when it requests and store its display and window id
-        if (event.type == MapRequest) {
-            XMapWindow(event.xmaprequest.display, event.xmaprequest.window);
-
-            win->child_display = event.xmaprequest.display;
-            win->child_win = event.xmaprequest.window;
-        }
-
-        // Propagate resize event to child window, and also resize it
-        // after MapRequest
-        if (event.type == ConfigureNotify || event.type == MapRequest) {
-            if (win->child_win) {
-                // Get container window attributes
-                XWindowAttributes attrs;
-                XGetWindowAttributes(win->master_display, win->master_win,
-                                     &attrs);
-
-                // Move and resize child
-                XMoveResizeWindow(win->child_display, win->child_win,
-                                  2, 2, attrs.width - 6, attrs.height - 6);
-            }
-        }
-
-        // Key press
-        if (event.type == KeyRelease) {
-            LOG_INFO("WINDOW", "Release key: 0x%x", event.xkey.keycode);
-            if (event.xkey.keycode == 0x47)
-                XClearWindow(win->master_display, win->master_win);
-        }
-
-        // Refresh container window
-        if (event.type == Expose)
-            XClearWindow(win->master_display, win->master_win);
-
-        // Close button
-        if (event.type == ClientMessage) {
-            if ((long unsigned int) event.xclient.data.l[0] == win->wm_delete)
-                return false;
-        }
-
-    }
-    return true;
-}
-
-bool
-module_x11_new(struct lkt_win *const win)
-{
-    RETURN_UNLESS(win, "Invalid argument", false);
-    struct module_x11_window *x11_win = win->window;
-
-    if (x11_win == NULL) {
-        x11_win = calloc(1, sizeof(struct module_x11_window));
-        memset(x11_win, 0, sizeof(struct module_x11_window));
-        RETURN_UNLESS(x11_win, "Out of memory", false);
-        RETURN_UNLESS(lx11_new(x11_win), "Can't create X11 window", false);
-        LOG_INFO("WINDOW", "%s", "Created the X11 window");
-    }
-
-    if (x11_win->mpv == NULL) {
-        x11_win->mpv = lmpv_new(x11_win->master_win, win->srv->db);
-        RETURN_UNLESS(x11_win->mpv, "Failed to create mpv", false);
-    }
-
-    win->window = x11_win;
-    return true;
-}
-
-void
-module_x11_close(struct lkt_win *const win)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", NOTHING);
-    struct module_x11_window *const x11_win = win->window;
-    lmpv_free(&x11_win->mpv);
-    x11_win->child_display = NULL;
-    x11_win->child_win = (x11_win->mpv_time_pos = (x11_win->mpv_duration = 0));
-}
-
-void
-module_x11_free(struct lkt_win *const win)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", NOTHING);
-    struct module_x11_window *const x11_win = win->window;
-    lmpv_free(&x11_win->mpv);
-    XCloseDisplay(x11_win->master_display);
-    free(x11_win);
-    win->window = NULL;
-}
-
-bool
-module_x11_toggle_pause(struct lkt_win *const win)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", false);
-    return ! lmpv_toggle_pause(((struct module_x11_window *) win->window)->mpv);
-}
-
-bool
-module_x11_load_file(struct lkt_win *const win, const char *filepath)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", false);
-    struct module_x11_window *xwin = win->window;
-    bool ret = ! lmpv_load_file(xwin->mpv, filepath);
-    xwin->mpv_duration = 0;
-    xwin->mpv_time_pos = 0;
-    return ret;
-}
-
-bool
-module_x11_set_volume(struct lkt_win *const win, int vol)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", false);
-    return ! lmpv_set_volume(((struct module_x11_window *) win->window)->mpv,
-                             vol);
-}
-
-bool
-module_x11_get_duration(struct lkt_win *const win, int *dur_sec)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", false);
-    struct module_x11_window *win_x11 = win->window;
-    *dur_sec = win_x11->mpv_duration;
-    return true;
-}
-
-bool
-module_x11_get_elapsed(struct lkt_win *const win, int *elapsed_sec)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", false);
-    struct module_x11_window *win_x11 = win->window;
-    *elapsed_sec = win_x11->mpv_time_pos;
-    return true;
-}
-
-bool
-module_x11_handle_events(struct lkt_win *const win, volatile sqlite3 *db,
-                         mpd_idle_flag *mpd_idle_events)
-{
-    RETURN_UNLESS(win && win->window, "Invalid arguments", false);
-    struct module_x11_window *xwin = win->window;
-    return lx11_handle(xwin) &&
-           ! lmpv_handle(win, xwin->mpv, db, mpd_idle_events,
-                         &xwin->mpv_time_pos, &xwin->mpv_duration);
-}
-
-/* The module stuff */
-
-int
-#if ! defined(_STATIC_MODULES)
-module_set_function(void *arg__, struct lkt_state *srv, void *handle__)
-#else
-load_x11(void *arg__, struct lkt_state *srv, void *handle__)
-#endif
-{
-    RETURN_UNLESS(arg__, "Invalid arguments", 1);
-    struct lkt_win *win = (struct lkt_win *) arg__;
-    win->srv            = srv;
-
-    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__;
-
-    return !module_x11_new(&srv->win);
-}
-
-REG_BEGIN(x11_reg)
-REG_ADD_NAMED("new",    module_x11_new)
-REG_ADD_NAMED("free",   module_x11_free)
-REG_ADD_NAMED("handle", module_x11_handle_events)
-REG_ADD(module_x11_close)
-REG_ADD(module_x11_toggle_pause)
-REG_ADD(module_x11_load_file)
-REG_ADD(module_x11_set_volume)
-REG_ADD(module_x11_get_duration)
-REG_ADD(module_x11_get_elapsed)
-REG_END()
-REG_EXPORT(x11_reg)
diff --git a/src/module/mpv.c b/src/module/mpv.c
index 06763230a2e673f62054c8b7238d0dd48d633167..2023814497f05de19df397460c041bf13d582e12 100644
--- a/src/module/mpv.c
+++ b/src/module/mpv.c
@@ -144,15 +144,14 @@ lmpv_toggle_pause(mpv_handle *ctx)
 }
 
 int
-lmpv_handle(struct lkt_win *win, mpv_handle *ctx, volatile sqlite3 *db, mpd_idle_flag *mpd_idle_events,
-            volatile int *time_pos, volatile int *time_duration)
+lmpv_handle(struct lkt_win *win, mpv_handle *ctx, struct queue *queue,
+           volatile int *time_pos, volatile int *time_duration)
 {
-    int ao_volume;
+    size_t ao_volume;
     struct lkt_queue_state state;
     mpv_event *event = NULL;
     mpv_event_property *prop;
-    RETURN_UNLESS(db && mpd_idle_events && ctx && win, "Invalid argument", 1);
-    RETURN_UNLESS(database_queue_state(db, &state), "Failed to get queue state", 1);
+    RETURN_UNLESS(ctx && win, "Invalid argument", 1);
 
 loop:
     event = mpv_wait_event(ctx, 0);
@@ -160,12 +159,12 @@ loop:
     switch (event->event_id) {
     case MPV_EVENT_PAUSE:
     case MPV_EVENT_UNPAUSE:
-        database_queue_toggle_pause(db);
+        lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_TOGGLE);
         break;
 
     case MPV_EVENT_SHUTDOWN:
         *time_pos = (*time_duration = 0);
-        database_queue_stop(db);
+        lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_STOP);
         win->close(win);
         return 1;
 
@@ -174,7 +173,7 @@ loop:
 
     case MPV_EVENT_IDLE:
         if (state.current > 0 && *time_pos > 0)
-            command_next(db, win, mpd_idle_events);
+            lkt_queue_send(queue, lkt_event_play_next, NULL);
         break;
 
     case MPV_EVENT_PROPERTY_CHANGE:
@@ -185,23 +184,27 @@ loop:
         if (STR_MATCH(prop->name, "ao-volume")
             && prop->format == MPV_FORMAT_INT64) {
             ao_volume = *(int *) prop->data;
-            database_config_queue(db, "volume", ao_volume);
+            lkt_queue_send(queue, lkt_event_prop_vol, (void *) ao_volume);
         }
         // File duration //
         if (STR_MATCH(prop->name, "duration")
             && prop->format == MPV_FORMAT_INT64) {
             *time_duration = *(int *) prop->data;
-            database_config_queue(db, "duration", *(int *) prop->data);
+            lkt_queue_send(queue, lkt_event_prop_dur, (void *) (size_t) *time_duration);
         }
         if (STR_MATCH(prop->name, "time-pos")
             && prop->format == MPV_FORMAT_INT64) {
             *time_pos = *(int *) prop->data;
-            database_config_queue(db, "elapsed", *(int *) prop->data);
+            lkt_queue_send(queue, lkt_event_prop_time, (void *) (size_t) *time_pos);
         }
         // Pause state //
         if (STR_MATCH(prop->name, "pause")
-            && prop->format == MPV_FORMAT_FLAG)
-            database_queue_set_paused(db, *(bool *) prop->data);
+            && prop->format == MPV_FORMAT_FLAG) {
+            if (* (bool *) prop->data)
+                lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PAUSE);
+            else
+                lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PLAY);
+        }
         break;
 
     /* Ignored */