diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index 0cddeaa1a7b2af6f4ae662664f9f25469c0e276d..c2d090799c38f9184c682abf0a28af80f9d4ec4a 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -22,9 +22,11 @@ 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);
+/* Update stuff */
+void database_get_update  (volatile sqlite3 *db, long *timestamp, long *job, int *current);
+void database_stamp       (volatile sqlite3 *db);
+void database_updated     (volatile sqlite3 *db);
+void database_deleted_kara(volatile sqlite3 *db, int **kara_id, size_t *len);
 
 /* Open correctly a database for lektor. */
 bool database_new   (volatile sqlite3 **db);
@@ -41,13 +43,13 @@ bool database_queue_set_paused       (volatile sqlite3 *db, bool paused);
 bool database_queue_set_current_index(volatile sqlite3 *db, int idx);
 bool database_queue_get_current_file (volatile sqlite3 *db, char filepath[PATH_MAX]);
 
-/* Mpv and database synchronisation. */
-bool database_sync_mpv_state(volatile sqlite3 *db, mpv_handle **mpv);
+bool database_get_kara_path(volatile sqlite3 *db, int id, char filepath[PATH_MAX]);
 
 /* Update the database. */
 bool database_update              (volatile sqlite3 *db, const char *kara_dir, int check_timestamp);
 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);
+bool database_update_set_available(volatile sqlite3 *db, int id);
+void database_update_del          (volatile sqlite3 *db, int id);
 
 /* Control the content of the queue. */
 bool database_queue_add_uri(volatile sqlite3 *db, struct lkt_uri *uri, int priority);
@@ -114,6 +116,7 @@ bool database_search_iter(struct lkt_search *item);
 /* Next and prev operation on the queue. */
 bool database_queue_next(volatile sqlite3 *db, char filepath[PATH_MAX]);
 bool database_queue_prev(volatile sqlite3 *db, char filepath[PATH_MAX]);
+bool database_queue_skip_current(volatile sqlite3 *db, char filepath[PATH_MAX]);
 
 /* Set a value in the config table */
 bool database_config_set     (volatile sqlite3 *db, const char *section, const char *key, const char *value);
diff --git a/scripts/init.sql b/scripts/init.sql
index d4e3e1c3c422e4be0017a0f470a40ef6b6e760b6..285457514f1585114e3412b91a7b73c46e9147fa 100644
--- a/scripts/init.sql
+++ b/scripts/init.sql
@@ -119,6 +119,18 @@ CREATE TABLE IF NOT EXISTS 'stickers.plt'
   ) WITHOUT ROWID;
 
 
+-- Update jobs history
+-- Here are stored karas ids present during a certain update job. May be
+-- usefull to keep tracks of kara. Now used to handle the 'deleted' case, i.e.
+-- when a kara was here, but was deleted on kurisu.
+
+CREATE TABLE IF NOT EXISTS updates
+  ( job     INTEGER NOT NULL CHECK(job >= 0)
+  , kara_id INTEGER NOT NULL CHECK(kara_id > 0)
+  , PRIMARY KEY (job, kara_id)
+  ) WITHOUT ROWID;
+
+
 -- 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,
@@ -131,6 +143,7 @@ CREATE TABLE IF NOT EXISTS misc
   ( id              INTEGER PRIMARY KEY DEFAULT 42 CHECK(id = 42)
   , last_update     INTEGER
   , last_end_update INTEGER
+  , update_job      INTEGER NOT NULL CHECK(update_job >= 0)
   );
 
-INSERT OR REPLACE INTO misc (id) VALUES (42);
+INSERT OR REPLACE INTO misc (id, update_job) VALUES (42, 0);
diff --git a/src/commands.c b/src/commands.c
index 22863455515b3aa4d4ab01b21448c40cd035f017..f3337062feb3b3712edbe6f2a553996ab9c548c5 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -271,20 +271,30 @@ command_crop(volatile sqlite3 *db, mpd_idle_flag *watch_mask_ptr)
 bool
 command_delid(volatile sqlite3 *db, struct lkt_win *win, char *id_str, mpd_idle_flag *watch_mask_ptr)
 {
-    UNUSED(win);
     long id;
-    char *endptr = NULL, err = 0;
+    char *endptr = NULL, err = 0, filepath[PATH_MAX];
     int uri = 0;
 
-    *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
     STRTOL(id, id_str, endptr, err);
     RETURN_IF(err, "STRTOL failed", false);
 
-    /* If one day we allow suppression of the current kara, will need the `win`
-       pointer to reload the kara in the same position (but the kara won't be
-       the same). */
     database_queue_current_kara(db, NULL, &uri);
-    RETURN_IF(id == (long) uri, "Can't delete current kara", false);
+
+    if (id == (long) uri) {
+        if (database_queue_skip_current(db, filepath)) {
+            if (!win->load_file(win, filepath)) {
+                LOG_ERROR_SCT("COMMAND", "Failed to skip current kara to delete id %ld", id);
+                return false;
+            }
+        }
+
+        else {
+            LOG_WARN_SCT("COMMAND", "Failed to skip current kara to delete id %ld, stop playback", id);
+            win->close(win);
+        }
+    }
+
+    *watch_mask_ptr |= MPD_IDLE_PLAYER;
     return database_queue_del_id(db, id);
 }
 
diff --git a/src/database/config.c b/src/database/config.c
index eb09db8541c459fc983e2f50da364853b18380fd..f4de2a20c6891cf94b65f44f3c53b45f1cfd48b8 100644
--- a/src/database/config.c
+++ b/src/database/config.c
@@ -134,25 +134,6 @@ error:
     return ret;
 }
 
-bool
-database_config_queue_default(volatile sqlite3 *db)
-{
-    static const char *SQL_DEFAULT =
-        "UPDATE queue_state SET"
-        "  volume = 100,"
-        "  paused = 1,"
-        "  random = 0,"
-        "  repeat = 0,"
-        "  single = 0,"
-        "  consume = 0,"
-        "  current = NULL,"
-        "  duration = 0;";
-    SQLITE_EXEC(db, SQL_DEFAULT, error);
-    return true;
-error:
-    return false;
-}
-
 bool
 database_get_config(volatile sqlite3 *db, const char *option, int *value)
 {
diff --git a/src/database/open.c b/src/database/open.c
index 9c28886822cbb722d6601585f31646453b383418..cb3cb0b17d30a6cef6fa7bb9dddca9f0afbeb642 100644
--- a/src/database/open.c
+++ b/src/database/open.c
@@ -189,33 +189,3 @@ 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/queue.c b/src/database/queue.c
index 8ff68e8410714f2e5dc0c04859ca77b7832760b5..abce4426ed9a77a7d5833570b8a04f71a51a907a 100644
--- a/src/database/queue.c
+++ b/src/database/queue.c
@@ -7,6 +7,31 @@
 #include <stdio.h>
 #include <string.h>
 
+#define sqlite_just_exec(func, query)                                   \
+    bool func (volatile sqlite3 *db) {                                  \
+        SQLITE_EXEC(db, "BEGIN TRANSACTION;" #query "COMMIT;", error);  \
+        return true;                                                    \
+        error:                                                          \
+        SQLITE_DO_ROLLBACK(db);                                         \
+        return false;                                                   \
+    }
+sqlite_just_exec(database_queue_toggle_pause, "UPDATE queue_state SET paused = 1 - paused;")
+sqlite_just_exec(database_queue_crop, "DELETE FROM queue WHERE queue.kara_id <> (SELECT current FROM queue_state LIMIT 1);")
+sqlite_just_exec(database_queue_stop, "UPDATE queue_state SET current = NULL;")
+sqlite_just_exec(database_queue_clear, "DELETE FROM queue;DELETE FROM sqlite_sequence WHERE name = 'queue';UPDATE queue_state SET current = NULL;")
+sqlite_just_exec(database_config_queue_default, "UPDATE queue_state SET volume = 100, paused = 1, random = 0, repeat = 0, single = 0, consume = 0, current = NULL, duration = 0;")
+#undef sqlite_just_exec
+
+bool
+database_queue_set_paused(volatile sqlite3 *db, bool paused)
+{
+    const char *SQL = paused ? "UPDATE queue_state SET paused = 1;" : "UPDATE queue_state SET paused = 0;";
+    SQLITE_EXEC(db, SQL, error);
+    return true;
+error:
+    return false;
+}
+
 /* Find in in database/open.c */
 extern int is_sql_str_invalid(const char *);
 
@@ -251,17 +276,20 @@ database_queue_add_uri(volatile sqlite3 *db, struct lkt_uri *uri, int priority)
 bool
 database_queue_del_id(volatile sqlite3 *db, int id)
 {
-    /* FIXME: Can't pop if its the last kara */
-#define POS_OF_ID "(SELECT position FROM queue WHERE kara_id = %d)"
     static const char *SQL_TEMPLATE =
         "BEGIN TRANSACTION;"
-        "WITH before(pos) AS (SELECT position FROM queue JOIN queue_state WHERE position < current ORDER BY position DESC LIMIT 1) "
-        "UPDATE queue_state SET current = CASE WHEN current IS NULL THEN NULL ELSE (SELECT pos FROM before) END WHERE current > " POS_OF_ID ";"
-        "UPDATE OR REPLACE queue SET position = position - 1 WHERE position > " POS_OF_ID ";"
+        "CREATE TEMPORARY TABLE queue_tmp (position INTEGER, kara_id INTEGER, priority INTEGER);"
+        /* Move the current 'pointer' */
+        "UPDATE queue_state SET current = (SELECT NULLIF(COUNT(position), 0) FROM queue JOIN queue_state ON position <= current AND kara_id != %d);"
+        "DELETE FROM queue WHERE kara_id = %d;"                                                 /* Delete any kara with the specified id */
+        "INSERT INTO queue_tmp(priority, position, kara_id) SELECT priority, position, kara_id FROM queue ORDER BY position ASC;"
+        "DELETE FROM queue;"
+        "INSERT INTO queue(priority, position, kara_id) SELECT priority, ROW_NUMBER() OVER(ORDER BY position ASC), kara_id FROM queue_tmp;"
+        "UPDATE sqlite_sequence SET seq = (SELECT COUNT(*) FROM queue) WHERE name = 'queue';"   /* Update the sqlite_sequence            */
+        "DROP TABLE queue_tmp;"                                                                 /* Erase queue_tmp                       */
         "COMMIT;";
-#undef POS_OF_ID
     char SQL[LKT_MAX_SQLITE_STATEMENT];
-    safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE, id, id, id, id);
+    safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE, id, id);
     SQLITE_EXEC(db, SQL, error);
     return true;
 error:
@@ -322,13 +350,16 @@ error:
 }
 
 bool
-database_queue_toggle_pause(volatile sqlite3 *db)
+database_queue_skip_current(volatile sqlite3 *db, char filepath[PATH_MAX])
 {
-    static const char *SQL_STMT = "UPDATE queue_state SET paused = 1 - paused";
-    SQLITE_EXEC(db, SQL_STMT, error);
-    return true;
-error:
-    return false;
+    if (database_queue_next(db, filepath))
+        return true;
+    else if (database_queue_prev(db, filepath))
+        return true;
+    else {
+        database_queue_stop(db);
+        return false;
+    }
 }
 
 bool
@@ -380,33 +411,6 @@ error:
     return status;
 }
 
-bool
-database_queue_clear(volatile 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;"
-        "COMMIT;";
-    SQLITE_EXEC(db, SQL_STMT, error);
-    return true;
-error:
-    SQLITE_DO_ROLLBACK(db);
-    return false;
-}
-
-bool
-database_queue_crop(volatile sqlite3 *db)
-{
-    static const char *SQL_STMT =
-        "DELETE FROM queue WHERE queue.kara_id <> (SELECT current FROM queue_state LIMIT 1);";
-    SQLITE_EXEC(db, SQL_STMT, error);
-    return true;
-error:
-    return false;
-}
-
 bool
 database_queue_move(volatile sqlite3 *db, int from, int to)
 {
@@ -467,16 +471,6 @@ error:
     return ret;
 }
 
-bool
-database_queue_stop(volatile sqlite3 *db)
-{
-    static const char *SQL_STMT = "UPDATE queue_state SET current = NULL;";
-    SQLITE_EXEC(db, SQL_STMT, error);
-    return true;
-error:
-    return false;
-}
-
 bool
 database_queue_set_current_index(volatile sqlite3 *db, int idx)
 {
@@ -514,8 +508,10 @@ database_queue_get_current_file(volatile sqlite3 *db, char filepath[PATH_MAX])
     SQLITE_PREPARE(db, stmt, SQL_STMT, error);
     code = sqlite3_step(stmt);
 
-    if (code == SQLITE_ROW)
+    if (code == SQLITE_ROW) {
         strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX);
+        filepath[PATH_MAX - 1] = '\0';
+    }
 
     else {
         LOG_ERROR_SCT("DB", "Failed to fetch prev kara: %s", sqlite3_errmsg((sqlite3 *) db));
@@ -529,10 +525,16 @@ error:
 }
 
 bool
-database_queue_set_paused(volatile sqlite3 *db, bool paused)
+database_get_kara_path(volatile sqlite3 *db, int id, char filepath[PATH_MAX])
 {
-    const char *SQL = paused ? "UPDATE queue_state SET paused = 1;" : "UPDATE queue_state SET paused = 0;";
-    SQLITE_EXEC(db, SQL, error);
+    sqlite3_stmt *stmt = NULL;
+    static const char *SQL = "SELECT file_path FROM kara WHERE id = ?;";
+    RETURN_UNLESS(id && db && filepath, "Invalid argument", false);
+    SQLITE_PREPARE(db, stmt, SQL, error);
+    SQLITE_BIND_INT(db, stmt, 1, id, error);
+    SQLITE_STEP_ROW(db, stmt, error);
+    strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX);
+    filepath[PATH_MAX - 1] = '\0';
     return true;
 error:
     return false;
diff --git a/src/database/update.c b/src/database/update.c
index 369df055ec700de599b43b47300194508d5c0f5c..7ff464aa795b96b77fc3bd8d34e054de40049a3c 100644
--- a/src/database/update.c
+++ b/src/database/update.c
@@ -13,8 +13,25 @@
 #include <time.h>
 #include <linux/limits.h>
 
-static bool
-database_add_kara(volatile sqlite3 *db, const char *filename)
+static inline bool
+__add_kara_to_update_job(volatile sqlite3 *db, size_t id)
+{
+    static const char *SQL = NULL;
+    if (id)
+        SQL = "INSERT INTO updates (job, kara_id) SELECT MAX(update_job), ? FROM misc;";
+    else
+        SQL = "INSERT INTO updates (job, kara_id) SELECT MAX(update_job), last_insert_rowid() FROM misc;";
+    sqlite3_stmt *stmt;
+    SQLITE_PREPARE(db, stmt, SQL, error);
+    SQLITE_BIND_INT(db, stmt, 1, (int) id, error);
+    SQLITE_STEP_OK(db, stmt, error);
+    return true;
+error:
+    return false;
+}
+
+static inline bool
+__database_add_kara(volatile sqlite3 *db, const char *filename)
 {
     RETURN_UNLESS(db || filename, "Invalid argument", false);
     static const char *SQL_STMT =
@@ -26,7 +43,7 @@ database_add_kara(volatile sqlite3 *db, const char *filename)
         "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id)"
         "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?, ?";
     sqlite3_stmt *stmt = NULL;
-    long code = SQLITE_OK, status = false, kara_id;
+    long code = SQLITE_OK, status = false, kara_id = 0;
     struct kara_metadata data;
     time_t the_time = time(NULL);
     struct tm *the_local_time = localtime(&the_time);
@@ -42,6 +59,8 @@ database_add_kara(volatile sqlite3 *db, const char *filename)
         return false;
     }
 
+    SQLITE_EXEC(db, "BEGIN TRANSACTION;", error);
+
     /* Try to find an id in the filename, reuse of variables, it's ugly */
     path[PATH_MAX - 1] = '\0';
     memcpy(path, filename, (strlen(filename) + 1) * sizeof(char));
@@ -74,34 +93,40 @@ database_add_kara(volatile sqlite3 *db, const char *filename)
         goto error;
     }
     SQLITE_STEP_DONE(db, stmt, error);
-    status = true;
+    sqlite3_finalize(stmt);
+
+    if (__add_kara_to_update_job(db, kara_id)) {
+        SQLITE_EXEC(db, "COMMIT;", error);
+        return true;
+    }
 error:
     sqlite3_finalize(stmt);
+    SQLITE_DO_ROLLBACK(db);
     return status;
 }
 
 bool
-database_update_set_available(volatile sqlite3 *db, uint64_t id)
+database_update_set_available(volatile sqlite3 *db, int 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);
+    SQLITE_BIND_INT(db, stmt, 1, id, error);
     if (sqlite3_step(stmt) != SQLITE_DONE)
         goto error;
     sqlite3_finalize(stmt);
-    LOG_INFO_SCT("DB", "Kara %ld is now available", id);
+    LOG_INFO_SCT("DB", "Kara %d is now available", id);
     return true;
 error:
     sqlite3_finalize(stmt);
-    LOG_ERROR_SCT("DB", "Failed to set kara %ld available", id);
+    LOG_ERROR_SCT("DB", "Failed to set kara %d 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);
+    RETURN_UNLESS(db && kara_path && mdt && id, "Invalid argument", false);
     static const char *SQL_STMT =
         "INSERT OR REPLACE INTO "
         "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id, available)"
@@ -135,7 +160,7 @@ database_update_add(volatile sqlite3 *db, const char *kara_path, struct kara_met
     }
 
     SQLITE_STEP_DONE(db, stmt, error);
-    ret = true;
+    ret = __add_kara_to_update_job(db, id);
 error:
     sqlite3_finalize(stmt);
 error_no_sqlite:
@@ -148,6 +173,7 @@ database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp)
     DIR *d;
     struct dirent *dir;
     char path[PATH_MAX];
+    long db_timestamp = 0;
     memset(path, 0, PATH_MAX * sizeof(char));
 
     if (!(d = opendir(kara_dir))) {
@@ -161,11 +187,12 @@ database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp)
         strncat(path, dir->d_name, PATH_MAX - 1);
 
         if (dir->d_type == DT_REG) {
-            if (check_timestamp && get_mtime(path) < database_get_timestamp(db)) {
+            database_get_update(db, &db_timestamp, NULL, NULL);
+            if (check_timestamp && get_mtime(path) < db_timestamp) {
                 LOG_INFO_SCT("DB", "Skip update of kara '%s' be cause of timestamps", path);
                 continue;
             }
-            database_add_kara(db, path);
+            __database_add_kara(db, path);
             database_stamp(db);
         }
 
@@ -180,3 +207,71 @@ database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp)
     closedir(d);
     return true;
 }
+
+void
+database_deleted_kara(volatile sqlite3 *db, int **kara_id, size_t *len)
+{
+    static const char *SQL =
+        "SELECT kara.id, file_path FROM kara WHERE kara.id NOT IN"
+        "(SELECT kara_id FROM updates JOIN misc ON job = update_job);";
+    sqlite3_stmt *stmt = NULL;
+    *kara_id = (int *) calloc(LKT_DEFAULT_LIST_SIZE, sizeof(int));
+    *len = 0;
+    RETURN_UNLESS(*kara_id, "Out of memory", NOTHING);
+    SQLITE_PREPARE(db, stmt, SQL, out);
+    size_t size = LKT_DEFAULT_LIST_SIZE;
+    void *new;
+
+    while (sqlite3_step(stmt) == SQLITE_ROW) {
+        if (size == *len) {
+            new = realloc((void *) kara_id, (*len) * 2 * sizeof(void *));
+            GOTO_UNLESS(new, "Out of memory", out);
+            size *= 2;
+            *kara_id = new;
+        }
+        (*kara_id)[(*len)++] = sqlite3_column_int(stmt, 0);
+    }
+
+out:
+    return;
+}
+
+void
+database_get_update(volatile sqlite3 *db, long *timestamp, long *job, int *current)
+{
+    static const char *SQL = "SELECT last_update, update_job, last_update > last_end_update FROM misc WHERE id = 42;";
+    sqlite3_stmt *stmt;
+    SQLITE_PREPARE(db, stmt, SQL, error);
+    SQLITE_STEP_ROW(db, stmt, error);
+    if (timestamp)
+        *timestamp = sqlite3_column_int(stmt, 0);
+    if (job)
+        *job = sqlite3_column_int(stmt, 1);
+    if (current)
+        *current = sqlite3_column_int(stmt, 2);
+    return;
+error:
+    LOG_WARN_SCT("DB", "Failed to get informations about the last update: %s", sqlite3_errmsg((sqlite3 *) db));
+}
+
+void
+database_update_del(volatile sqlite3 *db, int id)
+{
+    static const char *SQL = "DELETE FROM kara WHERE id = ?;";
+    sqlite3_stmt *stmt = NULL;
+    SQLITE_PREPARE(db, stmt, SQL, error);
+    SQLITE_BIND_INT(db, stmt, 1, id, error);
+    SQLITE_STEP_OK(db, stmt, error);
+    LOG_WARN_SCT("DB", "Deleted kara with id '%d' from database", id);
+error:
+    return;
+}
+
+#define sqlite_just_exec(func, query)   \
+    void func (volatile sqlite3 *db) {  \
+        SQLITE_EXEC(db, #query, error); \
+        error: return;                  \
+    }
+sqlite_just_exec(database_stamp, "UPDATE misc SET last_update = strftime('%s','now');")
+sqlite_just_exec(database_updated, "UPDATE misc SET last_end_update = strftime('%s','now'), update_job = update_job + 1;")
+#undef sqlite_just_exec
diff --git a/src/module/mpv.c b/src/module/mpv.c
index 99826ecdc02b568889cfd5e41b85dd8712e5bd02..492ac110f59a2a7f779bf8bcba5fd7225447707e 100644
--- a/src/module/mpv.c
+++ b/src/module/mpv.c
@@ -103,12 +103,17 @@ lmpv_load_file(mpv_handle *ctx, const char *file)
 {
     RETURN_UNLESS(ctx, "Missing mpv ctx", 1);
     RETURN_IF(access(file, R_OK), "Failed to read file", 1);
-    const char *cmd[] = {"loadfile", file, "replace", NULL};
+    const char *cmd1[] = { "loadfile", file, "replace", NULL };
+    const char *cmd2[] = { "set", "pause", "0", NULL };
     int status;
-    if ((status = mpv_command_async(ctx, 0, cmd)) < 0) {
+    if ((status = mpv_command_async(ctx, 0, cmd1)) < 0) {
         LOG_ERROR_SCT("WINDOW", "Failed to add '%s': %s", file, mpv_error_string(status));
         return 1;
     }
+    if ((status = mpv_command_async(ctx, 0, cmd2)) < 0) {
+        LOG_ERROR_SCT("WINDOW", "Failed to set state to play: %s", mpv_error_string(status));
+        return 1;
+    }
     return 0;
 }
 
diff --git a/src/net/downloader.c b/src/net/downloader.c
index a076deef22967bc8079f39795a66b0689b4b90b8..9606701e0e7a89b1bd3f3e15430df3f142864528 100644
--- a/src/net/downloader.c
+++ b/src/net/downloader.c
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <strings.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -324,7 +325,7 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec
     int32_t integer, err;
     struct kara kara;
     char url[URL_MAX_LEN];
-    long filestamp, timestamp;
+    long filestamp = 0, timestamp = 0, db_timestamp = 0;
     char mkvpropedit[PATH_MAX];
     RETURN_UNLESS(len > 0 && json_object_get_array(json), "Json invalid or array empty", NOTHING);
     RETURN_UNLESS(database_config_get_text(db, "externals", "mkvpropedit", mkvpropedit, PATH_MAX - 1),
@@ -365,12 +366,12 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec
         if (safe_json_get_long(kara_json, "unix_timestamp", &timestamp))
             continue;
         filestamp = get_mtime(kara.filename);
-        if (database_get_timestamp(db) >= filestamp && filestamp > timestamp &&
+        database_get_update(db, &db_timestamp, NULL, NULL);
+        if (db_timestamp >= filestamp && filestamp > timestamp &&
             ! kara_metadata_equals(&kara.mdt, kara.filename)) {
             LOG_INFO_SCT("REPO", "Ignore kara '%ld' with path '%s'", kara.id, kara.filename);
             continue;
         }
-        LOG_WARN_SCT("REPO", "Download kara '%ld' with path '%s'", kara.id, kara.filename);
 
         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);
@@ -399,6 +400,21 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec
     }
 }
 
+static inline void
+__handle_deleted_kara(volatile sqlite3 *db)
+{
+    size_t len, i;
+    int *kara_ids;
+    char filepath[PATH_MAX];
+    database_deleted_kara(db, &kara_ids, &len);
+
+    for (i = 0; i < len; ++i) {
+        if (!database_get_kara_path(db, kara_ids[i], filepath))
+            continue;
+        database_update_del(db, kara_ids[i]);
+    }
+}
+
 void *
 __repo_get_all_id_async(void *arg)
 {
@@ -410,6 +426,8 @@ __repo_get_all_id_async(void *arg)
     __handle_got_json(repo->db, repo, json);
     LOG_INFO_SCT("REPO", "%s", "Finished to download and insert kara list");
     json_object_put(json);
+    __handle_deleted_kara(repo->db);
+    LOG_INFO_SCT("REPO", "%s", "Finished to deal with deleted kara");
     database_updated(repo->db);
     return NULL;
 }
diff --git a/src/net/listen.c b/src/net/listen.c
index a31deb4425083a4274d3bd33b79f796b34d8f341..01389c300c467881a113920f753388ba11d44bd0 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -378,6 +378,7 @@ handle_disconnected_client(struct lkt_state *srv, size_t c)
     struct lkt_client *cli = &srv->clients[c - 1];
     for (size_t i = 0; i < cli->buffer_out_len; i++)
         lkt_message_free(cli->buffer_out[i]);
+    cli->buffer_out_len = 0;
 }
 
 static int