Implement add -a (add all audio files).
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index 1a0fdc79d5f591172b9edadb759baba072563b3a..99b132dd9d249a9991805068161fc1faf729ada5 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1,3 +1,11 @@
+/*
+ * Copyright (C) 2007 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file aft.c Audio file table functions. */
+
 #include "para.h"
 #include "error.h"
 #include <sys/mman.h>
 #include "string.h"
 #include "vss.h"
 
-#define AFS_AUDIO_FILE_DIR "/home/mp3"
+#define AFS_AUDIO_FILE_DIR "/home/mp3" /* FIXME: Use cwd instead */
 
 static struct osl_table *audio_file_table;
 
+/** The different sorting methods of the ls command. */
+enum ls_sorting_method {
+       /** -sp (default) */
+       LS_SORT_BY_PATH,
+       /** -ss */
+       LS_SORT_BY_SCORE,
+       /** -sl */
+       LS_SORT_BY_LAST_PLAYED,
+       /** -sn */
+       LS_SORT_BY_NUM_PLAYED,
+       /** -sf */
+       LS_SORT_BY_FREQUENCY,
+       /** -sc */
+       LS_SORT_BY_CHANNELS,
+       /** -si */
+       LS_SORT_BY_IMAGE_ID,
+       /** -sy */
+       LS_SORT_BY_LYRICS_ID,
+       /** -sb */
+       LS_SORT_BY_BITRATE,
+       /** -sd */
+       LS_SORT_BY_DURATION,
+       /** -sa */
+       LS_SORT_BY_AUDIO_FORMAT,
+       /** -sh */
+       LS_SORT_BY_HASH,
+};
+
+/** The different listing modes of the ls command. */
+enum ls_listing_mode {
+       /** Default listing mode. */
+       LS_MODE_SHORT,
+       /** -l or -ll */
+       LS_MODE_LONG,
+       /** -lv */
+       LS_MODE_VERBOSE,
+       /** -lm */
+       LS_MODE_MBOX
+};
+
+/** The flags accepted by the ls command. */
+enum ls_flags {
+       /** -p */
+       LS_FLAG_FULL_PATH = 1,
+       /** -a */
+       LS_FLAG_ADMISSIBLE_ONLY = 2,
+       /** -r */
+       LS_FLAG_REVERSE = 4,
+};
+
+/**
+ * The size of the individual output fields of the ls command.
+ *
+ * These depend on the actual content being listed. If, for instance only files
+ * with duration less than an hour are being listed, then the duration with is
+ * made smaller because then the duration is listed as mm:ss rather than
+ * hh:mm:ss.
+ */
+struct ls_widths {
+       /** size of the score field. */
+       unsigned short score_width;
+       /** size of the image id field. */
+       unsigned short image_id_width;
+       /** size of the lyrics id field. */
+       unsigned short lyrics_id_width;
+       /** size of the bitrate field. */
+       unsigned short bitrate_width;
+       /** size of the frequency field. */
+       unsigned short frequency_width;
+       /** size of the duration field. */
+       unsigned short duration_width;
+       /** size of the num played field. */
+       unsigned short num_played_width;
+};
+
+/** Data passed to the different compare functions (called by qsort()). */
+struct ls_data {
+       /** Usual audio format handler information. */
+       struct audio_format_info afhi;
+       /** Audio file selector information. */
+       struct afs_info afsi;
+       /** The full path of the audio file. */
+       char *path;
+       /** The score value (if -a was given). */
+       long score;
+       /** The sha1 hash of audio file. */
+       HASH_TYPE *hash;
+};
+
+struct ls_options {
+       unsigned flags;
+       enum ls_sorting_method sorting;
+       enum ls_listing_mode mode;
+       char **patterns;
+       int num_patterns;
+       struct ls_widths widths;
+       uint32_t array_size;
+       uint32_t num_matching_paths;
+       struct ls_data *data;
+       struct ls_data **data_ptr;
+};
+
 /**
  * Describes the layout of the mmapped-afs info struct.
  *
@@ -482,7 +592,7 @@ static int get_hash_of_row(const struct osl_row *row, HASH_TYPE **hash)
  *
  * \sa get_chunk_table_of_row().
  */
-static int get_afhi_of_row(const struct osl_row *row, struct audio_format_info *afhi)
+int get_afhi_of_row(const struct osl_row *row, struct audio_format_info *afhi)
 {
        struct osl_object obj;
        int ret = osl_get_object(audio_file_table, row, AFTCOL_AFHI,
@@ -573,12 +683,17 @@ err:
 }
 
 static int get_local_time(uint64_t *seconds, char *buf, size_t size,
-       time_t current_time)
+       time_t current_time, enum ls_listing_mode lm)
 {
        struct tm t;
 
        if (!localtime_r((time_t *)seconds, &t))
                return -E_LOCALTIME;
+       if (lm == LS_MODE_MBOX) {
+               if (!strftime(buf, size, "%c", &t))
+                       return -E_STRFTIME;
+               return 1;
+       }
        if (*seconds + 6 * 30 * 24 * 3600 > current_time) {
                if (!strftime(buf, size, "%b %e %k:%M", &t))
                        return -E_STRFTIME;
@@ -637,6 +752,7 @@ static char *make_attribute_line(const char *att_bitmap, struct afs_info *afsi)
 static char *make_lyrics_line(struct afs_info *afsi)
 {
        char *lyrics_name;
+
        lyr_get_name_by_id(afsi->lyrics_id, &lyrics_name);
        if (!lyrics_name)
                return make_message("%u", afsi->lyrics_id);
@@ -664,6 +780,8 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
        struct audio_format_info *afhi = &d->afhi;
        struct ls_widths *w = &opts->widths;
        int have_score = opts->flags & LS_FLAG_ADMISSIBLE_ONLY;
+       char asc_hash[2 * HASH_SIZE + 1];
+       char *att_line, *lyrics_line, *image_line;
 
        if (opts->mode == LS_MODE_SHORT) {
                para_printf(b, "%s\n", d->path);
@@ -671,7 +789,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
        }
        get_attribute_bitmap(&afsi->attributes, att_buf);
        ret = get_local_time(&afsi->last_played, last_played_time,
-               sizeof(last_played_time), current_time);
+               sizeof(last_played_time), current_time, opts->mode);
        if (ret < 0)
                return ret;
        get_duration_buf(afhi->seconds_total, duration_buf, w->duration_width);
@@ -712,14 +830,12 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                );
                return 1;
        }
+       hash_to_asc(d->hash, asc_hash);
+       att_line = make_attribute_line(att_buf, afsi);
+       lyrics_line = make_lyrics_line(afsi);
+       image_line = make_image_line(afsi);
        if (opts->mode == LS_MODE_VERBOSE) {
-               char asc_hash[2 * HASH_SIZE + 1];
-               char *att_line, *lyrics_line, *image_line;
 
-               hash_to_asc(d->hash, asc_hash);
-               att_line = make_attribute_line(att_buf, afsi);
-               lyrics_line = make_lyrics_line(afsi);
-               image_line = make_image_line(afsi);
                para_printf(b,
                        "%s: %s\n" /* path */
                        "%s%s%s" /* score */
@@ -733,7 +849,8 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                        "channels: %d\n"
                        "duration: %s\n"
                        "num_played: %d\n"
-                       "last_played: %s\n\n",
+                       "last_played: %s\n"
+                       "tag info: %s\n",
                        (opts->flags & LS_FLAG_FULL_PATH)?
                                "path" : "file", d->path,
                        have_score? "score: " : "", score_buf,
@@ -748,13 +865,53 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                        afhi->channels,
                        duration_buf,
                        afsi->num_played,
-                       last_played_time
+                       last_played_time,
+                       afhi->info_string
                );
-               free(att_line);
-               free(lyrics_line);
-               free(image_line);
-               return 1;
+       } else { /* mbox mode */
+               struct osl_object lyrics_def;
+               lyr_get_def_by_id(afsi->lyrics_id, &lyrics_def);
+               para_printf(b,
+                       "From foo@localhost %s\n"
+                       "Received: from\nTo: bar\nFrom: a\n"
+                       "Subject: %s\n\n" /* path */
+                       "%s%s%s" /* score */
+                       "attributes: %s\n"
+                       "hash: %s\n"
+                       "image_id: %s\n"
+                       "lyrics_id: %s\n"
+                       "bitrate: %dkbit/s\n"
+                       "format: %s\n"
+                       "frequency: %dHz\n"
+                       "channels: %d\n"
+                       "duration: %s\n"
+                       "num_played: %d\n"
+                       "tag info: %s\n"
+                       "%s%s\n",
+                       last_played_time,
+                       d->path,
+                       have_score? "score: " : "", score_buf,
+                               have_score? "\n" : "",
+                       att_line,
+                       asc_hash,
+                       image_line,
+                       lyrics_line,
+                       afhi->bitrate,
+                       audio_format_name(afsi->audio_format_id),
+                       afhi->frequency,
+                       afhi->channels,
+                       duration_buf,
+                       afsi->num_played,
+                       afhi->info_string,
+                       lyrics_def.data? "Lyrics:\n~~~~~~~\n" : "",
+                       lyrics_def.data? (char *)lyrics_def.data : ""
+               );
+               if (lyrics_def.data)
+                       osl_close_disk_object(lyrics_def.data);
        }
+       free(att_line);
+       free(lyrics_line);
+       free(image_line);
        return 1;
 }
 
@@ -904,7 +1061,7 @@ static int prepare_ls_row(struct osl_row *row, void *ls_opts)
        }
        if (options->num_patterns) {
                for (i = 0; i < options->num_patterns; i++) {
-                       ret = fnmatch(options->patterns[i], path, FNM_PATHNAME);
+                       ret = fnmatch(options->patterns[i], path, 0);
                        if (!ret)
                                break;
                        if (ret == FNM_NOMATCH)
@@ -1244,6 +1401,7 @@ afhi <=> force or no HS
 #define ADD_FLAG_LAZY 1
 #define ADD_FLAG_FORCE 2
 #define ADD_FLAG_VERBOSE 4
+#define ADD_FLAG_ALL 8
 
 /* TODO: change log messages so that they get written to the result buffer */
 
@@ -1407,6 +1565,9 @@ static int add_one_audio_file(const char *arg, const void *private_data)
        ret = verify_path(arg, &path);
        if (ret < 0)
                goto out_free;
+       ret = guess_audio_format(path);
+       if (ret < 0 && !(pad->flags & ADD_FLAG_ALL))
+               goto out_free;
        query.data = path;
        query.size = strlen(path) + 1;
        ret = send_callback_request(path_brother_callback, &query, &result);
@@ -1492,6 +1653,10 @@ int com_add(int fd, int argc, char * const * const argv)
                        i++;
                        break;
                }
+               if (!strcmp(arg, "-a")) {
+                       pad.flags |= ADD_FLAG_ALL;
+                       continue;
+               }
                if (!strcmp(arg, "-l")) {
                        pad.flags |= ADD_FLAG_LAZY;
                        continue;
@@ -1529,60 +1694,99 @@ int com_add(int fd, int argc, char * const * const argv)
 
 }
 
+enum touch_flags {
+       TOUCH_FLAG_FNM_PATHNAME = 1,
+       TOUCH_FLAG_VERBOSE = 2
+};
+
 struct com_touch_options {
-       long num_played;
-       long last_played;
-       long lyrics_id;
-       long image_id;
+       int32_t num_played;
+       int64_t last_played;
+       int32_t lyrics_id;
+       int32_t image_id;
+       unsigned flags;
 };
 
-static int com_touch_callback(const struct osl_object *query,
-               __a_unused struct osl_object *result)
+struct touch_action_data {
+       struct com_touch_options *cto;
+       struct para_buffer pb;
+};
+
+static int touch_audio_file(__a_unused struct osl_table *table,
+               struct osl_row *row, const char *name, void *data)
 {
-       struct com_touch_options *cto = query->data;
-       char *p = (char *)query->data + sizeof(*cto);
-       size_t len;
-       int ret, no_options = cto->num_played < 0 && cto->last_played < 0 &&
-               cto->lyrics_id < 0 && cto->image_id < 0;
-
-       for (;p < (char *)query->data + query->size; p += len + 1) {
-               struct afs_info old_afsi, new_afsi;
-               struct osl_object obj;
-               struct osl_row *row;
+       struct touch_action_data *tad = data;
+       struct osl_object obj;
+       struct afs_info old_afsi, new_afsi;
+       int ret, no_options = tad->cto->num_played < 0 && tad->cto->last_played < 0 &&
+               tad->cto->lyrics_id < 0 && tad->cto->image_id < 0;
 
-               len = strlen(p);
-               ret = aft_get_row_of_path(p, &row);
-               if (ret < 0)
-                       return ret;
-               ret = get_afsi_object_of_row(row, &obj);
-               if (ret < 0)
-                       return ret;
-               ret = load_afsi(&old_afsi, &obj);
-               if (ret < 0)
-                       return ret;
-               new_afsi = old_afsi;
-               if (no_options) {
-                       new_afsi.num_played++;
-                       new_afsi.last_played = time(NULL);
-               } else {
-                       if (cto->lyrics_id >= 0)
-                               new_afsi.lyrics_id = cto->lyrics_id;
-                       if (cto->image_id >= 0)
-                               new_afsi.image_id = cto->image_id;
-                       if (cto->num_played >= 0)
-                               new_afsi.num_played = cto->num_played;
-                       if (cto->last_played >= 0)
-                               new_afsi.last_played = cto->last_played;
-               }
-               save_afsi(&new_afsi, &obj); /* in-place update */
-               ret = mood_update_audio_file(row, &old_afsi);
-               if (ret < 0)
-                       return ret;
+       ret = get_afsi_object_of_row(row, &obj);
+       if (ret < 0) {
+               para_printf(&tad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
+               return 1;
+       }
+       ret = load_afsi(&old_afsi, &obj);
+       if (ret < 0) {
+               para_printf(&tad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
+               return 1;
+       }
+       new_afsi = old_afsi;
+       if (no_options) {
+               new_afsi.num_played++;
+               new_afsi.last_played = time(NULL);
+               if (tad->cto->flags & TOUCH_FLAG_VERBOSE)
+                       para_printf(&tad->pb, "%s: num_played = %u, "
+                               "last_played = now()\n", name,
+                               new_afsi.num_played);
+       } else {
+               if (tad->cto->flags & TOUCH_FLAG_VERBOSE)
+                       para_printf(&tad->pb, "touching %s\n", name);
+               if (tad->cto->lyrics_id >= 0)
+                       new_afsi.lyrics_id = tad->cto->lyrics_id;
+               if (tad->cto->image_id >= 0)
+                       new_afsi.image_id = tad->cto->image_id;
+               if (tad->cto->num_played >= 0)
+                       new_afsi.num_played = tad->cto->num_played;
+               if (tad->cto->last_played >= 0)
+                       new_afsi.last_played = tad->cto->last_played;
        }
+       save_afsi(&new_afsi, &obj); /* in-place update */
+       ret = mood_update_audio_file(row, &old_afsi);
+       if (ret < 0)
+               para_printf(&tad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
        return 1;
 }
 
-int com_touch(__a_unused int fd, int argc, char * const * const argv)
+static int com_touch_callback(const struct osl_object *query,
+               struct osl_object *result)
+{
+       struct touch_action_data tad = {.cto = query->data};
+       int ret;
+       struct pattern_match_data pmd = {
+               .table = audio_file_table,
+               .loop_col_num = AFTCOL_HASH,
+               .match_col_num = AFTCOL_PATH,
+               .patterns = {.data = (char *)query->data + sizeof(*tad.cto),
+                       .size = query->size - sizeof(*tad.cto)},
+               .data = &tad,
+               .action = touch_audio_file
+       };
+       if (tad.cto->flags & TOUCH_FLAG_FNM_PATHNAME)
+               pmd.fnmatch_flags |= FNM_PATHNAME;
+       ret = for_each_matching_row(&pmd);
+       if (ret < 0)
+               para_printf(&tad.pb, "%s\n", PARA_STRERROR(-ret));
+       if (tad.pb.buf) {
+               result->data = tad.pb.buf;
+               result->size = tad.pb.size;
+               return 1;
+       }
+       return ret < 0? ret : 0;
+}
+
+
+int com_touch(int fd, int argc, char * const * const argv)
 {
        struct com_touch_options cto = {
                .num_played = -1,
@@ -1590,7 +1794,8 @@ int com_touch(__a_unused int fd, int argc, char * const * const argv)
                .lyrics_id = -1,
                .image_id = -1
        };
-       struct osl_object options = {.data = &cto, .size = sizeof(cto)};
+       struct osl_object query = {.data = &cto, .size = sizeof(cto)},
+               result;
        int i, ret;
 
 
@@ -1603,78 +1808,121 @@ int com_touch(__a_unused int fd, int argc, char * const * const argv)
                        break;
                }
                if (!strncmp(arg, "-n", 2)) {
-                       ret = para_atol(arg + 2, &cto.num_played);
+                       ret = para_atoi32(arg + 2, &cto.num_played);
                        if (ret < 0)
-                               goto err;
+                               return ret;
                        continue;
                }
                if (!strncmp(arg, "-l", 2)) {
-                       ret = para_atol(arg + 2, &cto.last_played);
+                       ret = para_atoi64(arg + 2, &cto.last_played);
                        if (ret < 0)
-                               goto err;
+                               return ret;
                        continue;
                }
                if (!strncmp(arg, "-y", 2)) {
-                       ret = para_atol(arg + 2, &cto.lyrics_id);
+                       ret = para_atoi32(arg + 2, &cto.lyrics_id);
                        if (ret < 0)
-                               goto err;
+                               return ret;
                        continue;
                }
                if (!strncmp(arg, "-i", 2)) {
-                       ret = para_atol(arg + 2, &cto.image_id);
+                       ret = para_atoi32(arg + 2, &cto.image_id);
                        if (ret < 0)
-                               goto err;
+                               return ret;
+                       continue;
+               }
+               if (!strcmp(arg, "-p")) {
+                       cto.flags |= TOUCH_FLAG_FNM_PATHNAME;
+                       continue;
+               }
+               if (!strcmp(arg, "-v")) {
+                       cto.flags |= TOUCH_FLAG_VERBOSE;
                        continue;
                }
+               break; /* non-option starting with dash */
        }
-       ret = -E_AFT_SYNTAX;
        if (i >= argc)
-               goto err;
-       return send_option_arg_callback_request(&options, argc - i,
-               argv + i, com_touch_callback, NULL);
-err:
+               return -E_AFT_SYNTAX;
+       ret = send_option_arg_callback_request(&query, argc - i,
+               argv + i, com_touch_callback, &result);
+       if (ret > 0) {
+               send_buffer(fd, (char *)result.data);
+               free(result.data);
+       } else
+               send_va_buffer(fd, "%s\n", PARA_STRERROR(-ret));
        return ret;
 }
 
-struct com_rm_options {
+enum rm_flags {
+       RM_FLAG_VERBOSE = 1,
+       RM_FLAG_FORCE = 2,
+       RM_FLAG_FNM_PATHNAME = 4
+};
+
+struct com_rm_data {
        uint32_t flags;
+       struct para_buffer pb;
+       unsigned num_removed;
 };
 
-static int com_rm_callback(const struct osl_object *query,
-               __a_unused struct osl_object *result)
+static int remove_audio_file(__a_unused struct osl_table *table,
+               struct osl_row *row, const char *name, void *data)
 {
-       struct com_rm_options *cro = query->data;
-       char *p = (char *)query->data + sizeof(*cro);
-       size_t len;
+       struct com_rm_data *crd = data;
        int ret;
 
-       for (;p < (char *)query->data + query->size; p += len + 1) {
-               struct osl_row *row;
-
-               len = strlen(p);
-               ret = aft_get_row_of_path(p, &row);
-               if (ret < 0)
-                       return ret;
-               ret = mood_delete_audio_file(row);
-               if (ret < 0)
-                       return ret;
-               ret = osl_del_row(audio_file_table, row);
-               if (ret < 0)
-                       return ret;
-       }
+       if (crd->flags & RM_FLAG_VERBOSE)
+               para_printf(&crd->pb, "removing %s\n", name);
+       ret = mood_delete_audio_file(row);
+       if (ret < 0)
+               para_printf(&crd->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
+       ret = osl_del_row(audio_file_table, row);
+       if (ret < 0)
+               para_printf(&crd->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
+       else
+               crd->num_removed++;
        return 1;
 }
 
-/*
- * TODO options: -v verbose, -f dont stop if file not found
- * -h remove by hash, use fnmatch
- *
- * */
+static int com_rm_callback(const struct osl_object *query,
+               __a_unused struct osl_object *result)
+{
+       struct com_rm_data crd = {.flags = *(uint32_t *)query->data};
+       int ret;
+       struct pattern_match_data pmd = {
+               .table = audio_file_table,
+               .loop_col_num = AFTCOL_HASH,
+               .match_col_num = AFTCOL_PATH,
+               .patterns = {.data = (char *)query->data + sizeof(uint32_t),
+                       .size = query->size - sizeof(uint32_t)},
+               .data = &crd,
+               .action = remove_audio_file
+       };
+       if (crd.flags & RM_FLAG_FNM_PATHNAME)
+               pmd.fnmatch_flags |= FNM_PATHNAME;
+       ret = for_each_matching_row(&pmd);
+       if (ret < 0)
+               para_printf(&crd.pb, "%s\n", PARA_STRERROR(-ret));
+       if (!crd.num_removed && !(crd.flags & RM_FLAG_FORCE))
+               para_printf(&crd.pb, "no matches -- nothing removed\n");
+       else {
+               if (crd.flags & RM_FLAG_VERBOSE)
+                       para_printf(&crd.pb, "removed %u files\n", crd.num_removed);
+       }
+       if (crd.pb.buf) {
+               result->data = crd.pb.buf;
+               result->size = crd.pb.size;
+               return 1;
+       }
+       return ret < 0? ret : 0;
+}
 
-int com_afs_rm(__a_unused int fd, int argc,  char * const * const argv)
+/* TODO options: -r (recursive) */
+int com_afs_rm(int fd, int argc,  char * const * const argv)
 {
-       struct com_rm_options cro = {.flags = 0};
-       struct osl_object options = {.data = &cro, .size = sizeof(cro)};
+       uint32_t flags = 0;
+       struct osl_object query = {.data = &flags, .size = sizeof(flags)},
+               result;
        int i, ret;
 
        for (i = 1; i < argc; i++) {
@@ -1685,13 +1933,29 @@ int com_afs_rm(__a_unused int fd, int argc,  char * const * const argv)
                        i++;
                        break;
                }
+               if (!strcmp(arg, "-f")) {
+                       flags |= RM_FLAG_FORCE;
+                       continue;
+               }
+               if (!strcmp(arg, "-p")) {
+                       flags |= RM_FLAG_FNM_PATHNAME;
+                       continue;
+               }
+               if (!strcmp(arg, "-v")) {
+                       flags |= RM_FLAG_VERBOSE;
+                       continue;
+               }
+               break;
        }
-       ret = -E_AFT_SYNTAX;
        if (i >= argc)
-               goto err;
-       return send_option_arg_callback_request(&options, argc - i,
-               argv + i, com_rm_callback, NULL);
-err:
+               return -E_AFT_SYNTAX;
+       ret = send_option_arg_callback_request(&query, argc - i, argv + i,
+               com_rm_callback, &result);
+       if (ret > 0) {
+               send_buffer(fd, (char *)result.data);
+               free(result.data);
+       } else
+               send_va_buffer(fd, "%s\n", PARA_STRERROR(-ret));
        return ret;
 }
 
@@ -1722,10 +1986,12 @@ static int check_audio_file(struct osl_row *row, void *data)
        }
        ret = lyr_get_name_by_id(afsi.lyrics_id, &blob_name);
        if (ret < 0)
-               para_printf(pb, "%s lyrics id: %s\n", path, PARA_STRERROR(-ret));
+               para_printf(pb, "%s lyrics id %u: %s\n", path, afsi.lyrics_id,
+                       PARA_STRERROR(-ret));
        ret = img_get_name_by_id(afsi.image_id, &blob_name);
        if (ret < 0)
-               para_printf(pb, "%s image id: %s\n", path, PARA_STRERROR(-ret));
+               para_printf(pb, "%s image id %u: %s\n", path, afsi.image_id,
+                       PARA_STRERROR(-ret));
        return 1;
 }
 
@@ -1733,9 +1999,8 @@ int aft_check_callback(__a_unused const struct osl_object *query, struct osl_obj
 {
        struct para_buffer pb = {.buf = NULL};
 
+       para_printf(&pb, "checking audio file table...\n");
        audio_file_loop(&pb, check_audio_file);
-       if (!pb.size)
-               return 0;
        result->data = pb.buf;
        result->size = pb.size;
        return 1;
@@ -1771,10 +2036,9 @@ int aft_init(struct table_info *ti, const char *db)
 
        audio_file_table_desc.dir = db;
        ti->desc = &audio_file_table_desc;
-       ret = osl_open_table(ti->desc, &ti->table);
+       ret = osl_open_table(ti->desc, &audio_file_table);
        if (ret >= 0) {
                unsigned num;
-               audio_file_table = ti->table;
                osl_get_num_rows(audio_file_table, &num);
                PARA_INFO_LOG("audio file table contains %d files\n", num);
                return ret;