diff --git a/player/db/update.c b/player/db/update.c
index cb5b1116332cd04ad0a85136b7941fa509c54067..9ec5ff7831db0312c0f7337262614ec088482dbf 100644
--- a/player/db/update.c
+++ b/player/db/update.c
@@ -20,7 +20,9 @@ static const char SQL_INSERT_NEW_KARA[] =
 
 static void
 convert_legacy_category_type(const char *category, size_t category_len,
-                             const char *type, size_t type_len);
+                             const char *type, size_t type_len,
+                             const char * new_category, size_t * new_category_len,
+                             const char * new_type, size_t * new_type_len);
 
 static void
 serror(sqlite3 *db, const char *msg)
@@ -55,9 +57,71 @@ directories_and_files(const struct dirent *entry)
 
 static void
 convert_legacy_category_type(const char *category, size_t category_len,
-                             const char *type, size_t type_len)
+                             const char *type, size_t type_len,
+                             const char * new_category, size_t * new_category_len,
+                             const char * new_type, size_t * new_type_len)
 {
-    // TODO convert category and type -> category and language
+    // Convert category
+    if (category_len >= 2 && strncmp(category, "ED", 2) == 0)
+    {
+      new_category = "ED/d*";
+      *new_category_len = 5;
+    }
+    else if (category_len >= 2 && strncmp(category, "OP", 2) == 0)
+    {
+      new_category = "OP/d*";
+      *new_category_len = 5;
+    }
+    else if (category_len == 2
+        && (strncmp(category, "IS", 2) == 0
+          || strncmp(category, "PV", 2) == 0
+          || strncmp(category, "MV", 2) == 0))
+    {
+      new_category = category;
+      *new_category_len = category_len;
+    }
+    else if (category_len == 3
+        && (strncmp(category, "CDG", 3) == 0
+          || strncmp(category, "AMV", 3) == 0))
+    {
+      new_category = category;
+      *new_category_len = category_len;
+    }
+    else if (category_len == 4
+        && (strncmp(category, "LIVE", 4) == 0
+          || strncmp(category, "VOCA", 4) == 0))
+    {
+      new_category = category;
+      *new_category_len = category_len;
+    }
+
+    // Convert type
+    if (type_len == 2 && strncmp(type, "vo", 2) == 0)
+    {
+      new_type = "vo";
+      *new_type_len = 2;
+    }
+    else if (type_len == 2 && (strncmp(type, "va", 2) == 0 || strncmp(type, "vf", 2) == 0))
+    {
+      new_type = "va";
+      *new_type_len = 2;
+    }
+    else if (type_len == 3 && (strncmp(type, "cdg", 3) == 0 || strncmp(type, "amv", 3) == 0))
+    {
+      new_type = type;
+      *new_type_len = 3;
+    }
+    else if (type_len == 4 && strncmp(type, "voca", 4) == 0)
+    {
+      new_type = "vocaloid";
+      *new_type_len = 8;
+    }
+    else if ((type_len == 5 && strncmp(type, "autre", 5) == 0)
+        || (type_len == 6 && strncmp(type, "autres", 6) == 0))
+    {
+      new_type = "autres";
+      *new_type_len = 6;
+    }
 }
 
 static int
@@ -69,37 +133,37 @@ update_legacy_file(sqlite3 *db, const char *filename, size_t prefix, time_t last
     if (attrs.st_mtim.tv_sec < last_update)
         return 0;
 
-    const char *pseudo = 0;
-    size_t pseudo_len = 0;
-    const char *category = 0;
-    size_t category_len = 0;
-    const char *name = 0;
-    size_t name_len = 0;
-    const char *type = 0;
-    size_t type_len = 0;
-    const char *title = 0;
-    size_t title_len = 0;
+    const char *pseudo = 0,
+               *old_category = 0,
+               *name = 0,
+               *old_type = 0,
+               *title = 0;
+    size_t pseudo_len = 0,
+           old_category_len = 0,
+           name_len = 0,
+           old_type_len = 0,
+           title_len = 0;
 
     const char *file_path = filename + prefix;
     const char *f = file_path;
-    category_len = strcspn(f, "/");
-    if (!strncmp(f, "nouveaux", category_len)) {
+    old_category_len = strcspn(f, "/");
+    if (!strncmp(f, "nouveaux", old_category_len)) {
         // "Nouveau" kara, in nouveaux/{pseudo}/{category}/...
-        f += category_len + 1;  // Skip "nouveaux/"
+        f += old_category_len + 1;  // Skip "nouveaux/"
         pseudo_len = strcspn(f, "/");
         pseudo = f;
         f += pseudo_len + 1;  // Skip "{pseudo}/"
-        category_len = strcspn(f, "/");
+        old_category_len = strcspn(f, "/");
     }
 
-    category = f;
-    f += category_len + 1;  // Skip "{category}/"
+    old_category = f;
+    f += old_category_len + 1;  // Skip "{category}/"
     name_len = strcspn(f, "-");
     name = f;
     f += name_len + 1;
-    type_len = strcspn(f, "-");
-    type = f;
-    f += type_len + 1;
+    old_type_len = strcspn(f, "-");
+    old_type = f;
+    f += old_type_len + 1;
     title_len = strcspn(f, ".");
     title = f;
 
@@ -108,7 +172,10 @@ update_legacy_file(sqlite3 *db, const char *filename, size_t prefix, time_t last
         return -1;
     }
 
-    convert_legacy_category_type(category, category_len, type, type_len);
+    char * category, * type;
+    size_t type_len, category_len;
+    convert_legacy_category_type(old_category, old_category_len, old_type, old_type_len,
+        category, &category_len, type, &type_len);
 
     int status_code = -1;
     sqlite3_stmt *stmt = 0;
@@ -120,33 +187,33 @@ update_legacy_file(sqlite3 *db, const char *filename, size_t prefix, time_t last
     }
 
     if (sqlite3_bind_text(stmt, 0, name, name_len, 0) != SQLITE_OK) {
-        serror("Failed to bind song_name");
+        serror(db, "Failed to bind song_name");
         goto error;
     }
 
     if (sqlite3_bind_text(stmt, 0, title, title_len, 0) != SQLITE_OK) {
-        serror("Failed to bind song_source");
+        serror(db, "Failed to bind song_source");
         goto error;
     }
 
     if (sqlite3_bind_text(stmt, 0, category, -1, 0) != SQLITE_OK) {
-        serror("Failed to bind category");
+        serror(db, "Failed to bind category");
         goto error;
     }
 
     if (sqlite3_bind_text(stmt, 0, type, -1, 0) != SQLITE_OK) {
-        serror("Failed to bind language");
+        serror(db, "Failed to bind language");
         goto error;
     }
 
     if (sqlite3_bind_text(stmt, 0, file_path, -1, 0) != SQLITE_OK) {
-        serror("Failed to bind file_path");
+        serror(db, "Failed to bind file_path");
         goto error;
     }
 
     if (sqlite3_step(stmt) != SQLITE_DONE) {
         // TODO handle SQLITE_BUSY (should rollback)
-        serror("Failed to execute insert statement");
+        serror(db, "Failed to execute insert statement");
         goto error;
     }
 
@@ -165,7 +232,7 @@ update_directory(sqlite3 *db, const char *root, time_t last_update)
     size_t queue_max = 128;
     size_t queue_len = 0;
 
-    queue = mallocf(queue_max * sizeof(char *));
+    queue = (char**) mallocf(queue_max * sizeof(char *));
     if (!queue)
         goto error;
 
@@ -185,7 +252,7 @@ update_directory(sqlite3 *db, const char *root, time_t last_update)
             size_t dir_len = strlen(dir);
 
             // child length (256) + null byte + slash
-            char *child = mallocf(dir_len + 258);
+            char *child = (char*) mallocf(dir_len + 258);
             if (!child)
                 goto error;
 
@@ -199,7 +266,7 @@ update_directory(sqlite3 *db, const char *root, time_t last_update)
                 free(child);
             } else if (queue_len == queue_max) {
                 queue_max *= 2;
-                char **new_queue = reallocf(queue, queue_max * sizeof(char *));
+                char **new_queue = (char**) reallocf(queue, queue_max * sizeof(char *));
                 if (!new_queue)
                     goto error;
                 queue = new_queue;