]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - aft.c
make send_callback_request() and friends take a result handler.
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index 51703aa4583ace19696db9e317e9135a9d285904..d6abc13d9c22854f7a2f12092f5a79e70998231c 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -58,7 +58,9 @@ enum ls_listing_mode {
        /** -lv */
        LS_MODE_VERBOSE,
        /** -lm */
-       LS_MODE_MBOX
+       LS_MODE_MBOX,
+       /** -lc */
+       LS_MODE_CHUNKS
 };
 
 /** The flags accepted by the ls command. */
@@ -660,6 +662,7 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
                AFTCOL_CHUNKS, &chunk_table_obj);
        if (ret < 0)
                return ret;
+       afd->afhi.chunk_table = NULL;
        ret = mmap_full_file(path, O_RDONLY, &map.data,
                &map.size, &afd->fd);
        if (ret < 0)
@@ -697,10 +700,8 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
        aced.old_afsi = &old_afsi;
        afs_event(AFSI_CHANGE, NULL, &aced);
        ret = save_afd(afd);
-       free(afd->afhi.chunk_table);
-       if (ret < 0)
-               goto err;
 err:
+       free(afd->afhi.chunk_table);
        osl_close_disk_object(&chunk_table_obj);
        return ret;
 }
@@ -804,8 +805,8 @@ static char *make_image_lines(struct afs_info *afsi)
 
 static char *make_filename_lines(const char *path, unsigned flags)
 {
-       char *basename, *dirname;
-       char *ret;
+       char *dirname, *ret;
+       const char *basename;
 
        if (!(flags & LS_FLAG_FULL_PATH))
                return make_message("%s: %s\n",
@@ -814,13 +815,41 @@ static char *make_filename_lines(const char *path, unsigned flags)
        dirname = para_dirname(path);
        ret = make_message("%s: %s\n%s: %s\n%s: %s\n",
                status_item_list[SI_PATH], path,
-               status_item_list[SI_DIRECTORY], dirname,
-               status_item_list[SI_BASENAME], basename);
-       free(basename);
+               status_item_list[SI_DIRECTORY], dirname? dirname : "?",
+               status_item_list[SI_BASENAME], basename? basename : "?");
        free(dirname);
        return ret;
 }
 
+static int print_chunk_table(struct ls_data *d, struct para_buffer *b)
+{
+       struct osl_object chunk_table_obj;
+       struct osl_row *aft_row;
+       int ret, i;
+       char *buf;
+
+       ret = aft_get_row_of_hash(d->hash, &aft_row);
+       if (ret < 0)
+               return ret;
+       ret = osl_open_disk_object(audio_file_table, aft_row,
+               AFTCOL_CHUNKS, &chunk_table_obj);
+       if (ret < 0)
+               return ret;
+       para_printf(b, "%s\n"
+               "chunk_time: %lu:%lu\nchunk_offsets: ",
+               d->path,
+               (long unsigned) d->afhi.chunk_tv.tv_sec,
+               (long unsigned) d->afhi.chunk_tv.tv_usec
+       );
+       buf = chunk_table_obj.data;
+       for (i = 0; i <= d->afhi.chunks_total; i++)
+               para_printf(b, "%u ",
+                       (unsigned) read_u32(buf + 4 * i));
+       osl_close_disk_object(&chunk_table_obj);
+       para_printf(b, "\n");
+       return 1;
+}
+
 static int print_list_item(struct ls_data *d, struct ls_options *opts,
        struct para_buffer *b, time_t current_time)
 {
@@ -840,6 +869,8 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                para_printf(b, "%s\n", d->path);
                return 1;
        }
+       if (opts->mode == LS_MODE_CHUNKS)
+               return print_chunk_table(d, b);
        get_attribute_bitmap(&afsi->attributes, att_buf);
        ret = get_local_time(&afsi->last_played, last_played_time,
                sizeof(last_played_time), current_time, opts->mode);
@@ -887,13 +918,15 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
        lyrics_lines = make_lyrics_lines(afsi);
        image_lines = make_image_lines(afsi);
        filename_lines = make_filename_lines(d->path, opts->flags);
-       if (opts->mode == LS_MODE_MBOX)
+       if (opts->mode == LS_MODE_MBOX) {
+               const char *bn = para_basename(d->path);
                para_printf(b,
                        "From foo@localhost %s\n"
                        "Received: from\nTo: bar\nFrom: a\n"
                        "Subject: %s\n\n",
                        last_played_time,
-                       d->path);
+                       bn? bn : "?");
+       }
        para_printf(b,
                "%s" /* filename stuff */
                "%s%s%s%s" /* score */
@@ -1251,7 +1284,7 @@ static int com_ls_callback(const struct osl_object *query,
        ret = 1;
 out:
        ls_output->data = b.buf;
-       ls_output->size = b.size;
+       ls_output->size = b.offset;
        free(opts->data);
        free(opts->data_ptr);
        free(opts->patterns);
@@ -1268,8 +1301,7 @@ int com_ls(int fd, int argc, char * const * const argv)
        enum ls_sorting_method sort = LS_SORT_BY_PATH;
        enum ls_listing_mode mode = LS_MODE_SHORT;
        struct ls_options opts = {.patterns = NULL};
-       struct osl_object query = {.data = &opts, .size = sizeof(opts)},
-               ls_output;
+       struct osl_object query = {.data = &opts, .size = sizeof(opts)};
 
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
@@ -1299,6 +1331,9 @@ int com_ls(int fd, int argc, char * const * const argv)
                        case 'm':
                                mode = LS_MODE_MBOX;
                                continue;
+                       case 'c':
+                               mode = LS_MODE_CHUNKS;
+                               continue;
                        default:
                                return -E_AFT_SYNTAX;
                        }
@@ -1364,11 +1399,7 @@ int com_ls(int fd, int argc, char * const * const argv)
        opts.mode = mode;
        opts.num_patterns = argc - i;
        ret = send_option_arg_callback_request(&query, opts.num_patterns,
-               argv + i, com_ls_callback, &ls_output);
-       if (ret > 0) {
-               ret = send_buffer(fd, (char *)ls_output.data);
-               free(ls_output.data);
-       }
+               argv + i, com_ls_callback, send_result, &fd);
        return ret;
 }
 
@@ -1635,7 +1666,7 @@ out:
        if (!msg.buf)
                return 0;
        result->data = msg.buf;
-       result->size = msg.size;
+       result->size = msg.offset;
        return 1;
 }
 
@@ -1676,30 +1707,32 @@ static int hash_sister_callback(const struct osl_object *query,
        return 1;
 }
 
-static int add_one_audio_file(const char *path, const void *private_data)
+int get_row_pointer_from_result(struct osl_object *result, void *private)
+{
+       struct osl_row **row = private;
+       *row = result->data;
+       return 1;
+}
+
+static int add_one_audio_file(const char *path, void *private_data)
 {
        int ret, send_ret = 1;
        uint8_t format_num = -1;
-       const struct private_add_data *pad = private_data;
+       struct private_add_data *pad = private_data;
        struct afh_info afhi, *afhi_ptr = NULL;
        struct osl_row *pb = NULL, *hs = NULL; /* path brother/hash sister */
-       struct osl_object map, obj = {.data = NULL}, query, result = {.data = NULL};
+       struct osl_object map, obj = {.data = NULL}, query;
        HASH_TYPE hash[HASH_SIZE];
 
-       afhi.header_offset = 0;
-       afhi.header_len = 0;
        ret = guess_audio_format(path);
        if (ret < 0 && !(pad->flags & ADD_FLAG_ALL))
                goto out_free;
        query.data = (char *)path;
        query.size = strlen(path) + 1;
-       ret = send_callback_request(path_brother_callback, &query, &result);
+       ret = send_callback_request(path_brother_callback, &query,
+               get_row_pointer_from_result, &pb);
        if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND)
                goto out_free;
-       if (ret >= 0) {
-               pb = *(struct osl_row **)result.data;
-               free(result.data);
-       }
        ret = 1;
        if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
                if (pad->flags & ADD_FLAG_VERBOSE)
@@ -1715,13 +1748,10 @@ static int add_one_audio_file(const char *path, const void *private_data)
        /* Check whether the database contains a file with the same hash. */
        query.data = hash;
        query.size = HASH_SIZE;
-       ret = send_callback_request(hash_sister_callback, &query, &result);
+       ret = send_callback_request(hash_sister_callback, &query,
+               get_row_pointer_from_result, &hs);
        if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND)
                goto out_unmap;
-       if (ret >= 0) {
-               hs = *(struct osl_row **)result.data;
-               free(result.data);
-       }
        /* Return success if we already know this file. */
        ret = 1;
        if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
@@ -1749,11 +1779,7 @@ static int add_one_audio_file(const char *path, const void *private_data)
        }
        save_add_callback_buffer(hash, path, afhi_ptr, pad->flags, format_num, &obj);
        /* Ask afs to consider this entry for adding. */
-       ret = send_callback_request(com_add_callback, &obj, &result);
-       if (ret > 0) {
-               send_ret = send_va_buffer(pad->fd, "%s", (char *)result.data);
-               free(result.data);
-       }
+       ret = send_callback_request(com_add_callback, &obj, send_result, &pad->fd);
        goto out_free;
 
 out_unmap:
@@ -1869,6 +1895,8 @@ struct touch_action_data {
        struct com_touch_options *cto;
        /** Message buffer. */
        struct para_buffer pb;
+       /** How many audio files matched the given pattern. */
+       unsigned num_matches;
 };
 
 static int touch_audio_file(__a_unused struct osl_table *table,
@@ -1911,6 +1939,7 @@ static int touch_audio_file(__a_unused struct osl_table *table,
                if (tad->cto->last_played >= 0)
                        new_afsi.last_played = tad->cto->last_played;
        }
+       tad->num_matches++;
        save_afsi(&new_afsi, &obj); /* in-place update */
        aced.aft_row = row;
        aced.old_afsi = &old_afsi;
@@ -1937,9 +1966,12 @@ static int com_touch_callback(const struct osl_object *query,
        ret = for_each_matching_row(&pmd);
        if (ret < 0)
                para_printf(&tad.pb, "%s\n", para_strerror(-ret));
+       else
+               if (!tad.num_matches)
+                       para_printf(&tad.pb, "no matches\n");
        if (tad.pb.buf) {
                result->data = tad.pb.buf;
-               result->size = tad.pb.size;
+               result->size = tad.pb.offset;
                return 1;
        }
        return ret < 0? ret : 0;
@@ -1953,8 +1985,7 @@ int com_touch(int fd, int argc, char * const * const argv)
                .lyrics_id = -1,
                .image_id = -1
        };
-       struct osl_object query = {.data = &cto, .size = sizeof(cto)},
-               result;
+       struct osl_object query = {.data = &cto, .size = sizeof(cto)};
        int i, ret;
 
 
@@ -2003,11 +2034,8 @@ int com_touch(int fd, int argc, char * const * const argv)
        if (i >= argc)
                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 if (ret < 0)
+               argv + i, com_touch_callback, send_result, &fd);
+       if (ret < 0)
                send_va_buffer(fd, "%s\n", para_strerror(-ret));
        return ret;
 }
@@ -2050,7 +2078,7 @@ static int remove_audio_file(__a_unused struct osl_table *table,
 }
 
 static int com_rm_callback(const struct osl_object *query,
-               __a_unused struct osl_object *result)
+               struct osl_object *result)
 {
        struct com_rm_action_data crd = {.flags = *(uint32_t *)query->data};
        int ret;
@@ -2076,7 +2104,7 @@ static int com_rm_callback(const struct osl_object *query,
        }
        if (crd.pb.buf) {
                result->data = crd.pb.buf;
-               result->size = crd.pb.size;
+               result->size = crd.pb.offset;
                return 1;
        }
        return ret < 0? ret : 0;
@@ -2086,8 +2114,7 @@ static int com_rm_callback(const struct osl_object *query,
 int com_rm(int fd, int argc,  char * const * const argv)
 {
        uint32_t flags = 0;
-       struct osl_object query = {.data = &flags, .size = sizeof(flags)},
-               result;
+       struct osl_object query = {.data = &flags, .size = sizeof(flags)};
        int i, ret;
 
        for (i = 1; i < argc; i++) {
@@ -2115,11 +2142,8 @@ int com_rm(int fd, int argc,  char * const * const argv)
        if (i >= argc)
                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 if (ret < 0)
+               com_rm_callback, send_result, &fd);
+       if (ret < 0)
                send_va_buffer(fd, "%s\n", para_strerror(-ret));
        return ret;
 }
@@ -2224,7 +2248,7 @@ out:
        }
        if (cad.pb.buf) {
                result->data = cad.pb.buf;
-               result->size = cad.pb.size;
+               result->size = cad.pb.offset;
                return 1;
        }
        return ret < 0? ret : 0;
@@ -2234,8 +2258,7 @@ int com_cpsi(int fd, int argc,  char * const * const argv)
 {
        unsigned flags = 0;
        int i, ret;
-       struct osl_object options = {.data = &flags, .size = sizeof(flags)},
-               result;
+       struct osl_object options = {.data = &flags, .size = sizeof(flags)};
 
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
@@ -2276,11 +2299,8 @@ int com_cpsi(int fd, int argc,  char * const * const argv)
        if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
                flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
        ret = send_option_arg_callback_request(&options, argc - i, argv + i,
-               com_cpsi_callback, &result);
-       if (ret > 0) {
-               send_buffer(fd, (char *)result.data);
-               free(result.data);
-       } else
+               com_cpsi_callback, send_result, &fd);
+       if (ret < 0)
                send_va_buffer(fd, "%s\n", para_strerror(-ret));
        return ret;
 }
@@ -2338,7 +2358,7 @@ int aft_check_callback(__a_unused const struct osl_object *query, struct osl_obj
        para_printf(&pb, "checking audio file table...\n");
        audio_file_loop(&pb, check_audio_file);
        result->data = pb.buf;
-       result->size = pb.size;
+       result->size = pb.offset;
        return 1;
 
 }