Rename length status item to seconds_total and print it only once.
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index f66310968c67458898bef9edb377a41e68458e97..483ab2526e1c1c4259b871644cbab704e524b73d 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -96,20 +96,6 @@ struct ls_widths {
        unsigned short num_played_width;
 };
 
-/** Data passed to the different compare functions (called by qsort()). */
-struct ls_data {
-       /** Usual audio format handler information. */
-       struct afh_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;
-};
-
 /** Data passed from the ls command handler to its callback function. */
 struct ls_options {
        /** The given command line flags. */
@@ -323,14 +309,18 @@ enum afhi_offsets {
        AFHI_BITRATE_OFFSET = 4,
        /** Position of the frequency. */
        AFHI_FREQUENCY_OFFSET = 8,
+       /** Location of the audio file header. */
+       AFHI_HEADER_OFFSET_OFFSET = 12,
+       /* Length of the audio file header. Zero means: No header. */
+       AFHI_HEADER_LEN_OFFSET = 16,
        /** Number of channels is stored here. */
-       AFHI_CHANNELS_OFFSET = 12,
+       AFHI_CHANNELS_OFFSET = 20,
        /** EOF timeout in ms. */
-       AFHI_EOF_OFFSET = 13,
+       AFHI_EOF_OFFSET = 21,
        /** The tag info position. */
-       AFHI_INFO_STRING_OFFSET = 15,
+       AFHI_INFO_STRING_OFFSET = 23,
        /** Minimal on-disk size of a valid afhi struct. */
-       MIN_AFHI_SIZE = 16
+       MIN_AFHI_SIZE = 24
 };
 
 static unsigned sizeof_afhi_buf(const struct afh_info *afhi)
@@ -348,6 +338,8 @@ static void save_afhi(struct afh_info *afhi, char *buf)
                afhi->seconds_total);
        write_u32(buf + AFHI_BITRATE_OFFSET, afhi->bitrate);
        write_u32(buf + AFHI_FREQUENCY_OFFSET, afhi->frequency);
+       write_u32(buf + AFHI_HEADER_OFFSET_OFFSET, afhi->header_offset);
+       write_u32(buf + AFHI_HEADER_LEN_OFFSET, afhi->header_len);
        write_u8(buf + AFHI_CHANNELS_OFFSET, afhi->channels);
        write_u16(buf + AFHI_EOF_OFFSET, tv2ms(&afhi->eof_tv));
        strcpy(buf + AFHI_INFO_STRING_OFFSET, afhi->info_string); /* OK */
@@ -360,6 +352,8 @@ static void load_afhi(const char *buf, struct afh_info *afhi)
        afhi->bitrate = read_u32(buf + AFHI_BITRATE_OFFSET);
        afhi->frequency = read_u32(buf + AFHI_FREQUENCY_OFFSET);
        afhi->channels = read_u8(buf + AFHI_CHANNELS_OFFSET);
+       afhi->header_offset = read_u32(buf + AFHI_HEADER_OFFSET_OFFSET);
+       afhi->header_len = read_u32(buf + AFHI_HEADER_LEN_OFFSET);
        ms2tv(read_u16(buf + AFHI_EOF_OFFSET), &afhi->eof_tv);
        strcpy(afhi->info_string, buf + AFHI_INFO_STRING_OFFSET);
 }
@@ -679,7 +673,7 @@ int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data *
        int ret = get_hash_of_row(aft_row, &aft_hash);
        struct afsi_change_event_data aced;
        struct osl_object map, chunk_table_obj;
-       char *tmp, *path;
+       char *path;
 
        if (ret < 0)
                return ret;
@@ -720,14 +714,22 @@ int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data *
        ret = load_chunk_info(&chunk_table_obj, &afd->afhi);
        if (ret < 0)
                goto err;
-       ret = get_attribute_text(&afd->afsi.attributes, " ", &tmp);
-       if (ret < 0)
-               goto err;
-       assert(tmp);
-       strncpy(afd->attributes_string, tmp, sizeof(afd->attributes_string));
-       afd->attributes_string[sizeof(afd->attributes_string) - 1] = '\0';
-       free(tmp);
-
+       {
+               struct ls_data d = {
+                       .afhi = afd->afhi,
+                       .afsi = afd->afsi,
+                       .path = path,
+                       .score = afd->score,
+                       .hash = file_hash
+               };
+               struct para_buffer pb = {.buf = NULL};
+               ret = make_status_items(&d, &pb);
+               if (ret < 0)
+                       goto err;
+               strncpy(afd->afs_status_info, pb.buf, AFS_STATUS_INFO_SIZE);
+               afd->afs_status_info[AFS_STATUS_INFO_SIZE - 1] = '\0';
+               free(pb.buf);
+       }
        aced.aft_row = aft_row;
        aced.old_afsi = &afd->afsi;
        afs_event(AFSI_CHANGE, NULL, &aced);
@@ -785,15 +787,21 @@ static short unsigned get_duration_width(int seconds)
        return width + 6;
 }
 
-static void get_duration_buf(int seconds, char *buf, short unsigned max_width)
+static void get_duration_buf(int seconds, char *buf, struct ls_options *opts)
 {
        unsigned hours = seconds / 3600, mins = (seconds % 3600) / 60;
+       short unsigned max_width;
 
-       if (!hours) /* m:ss or mm:ss */
+       if (!hours) { /* m:ss or mm:ss */
+               max_width = opts->mode == LS_MODE_LONG?
+                       opts->widths.duration_width : 4;
                sprintf(buf, "%*u:%02u", max_width - 3, mins, seconds % 60);
-       else /* more than one hour => h:mm:ss, hh:mm:ss, hhh:mm:ss, ... */
+       } else { /* more than one hour => h:mm:ss, hh:mm:ss, hhh:mm:ss, ... */
+               max_width = opts->mode == LS_MODE_LONG?
+                       opts->widths.duration_width : 7;
                sprintf(buf, "%*u:%02u:%02u", max_width - 6, hours, mins,
                        seconds % 60);
+       }
 }
 
 static char *make_attribute_lines(const char *att_bitmap, struct afs_info *afsi)
@@ -809,23 +817,21 @@ static char *make_attribute_lines(const char *att_bitmap, struct afs_info *afsi)
        return att_lines;
 }
 
-static char *make_lyrics_line(struct afs_info *afsi)
+static char *make_lyrics_lines(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);
-       return make_message("%u (%s)", afsi->lyrics_id, lyrics_name);
+       return make_message("lyrics_id: %u\nlyrics_name: %s\n",
+               afsi->lyrics_id, lyrics_name? lyrics_name : "(none)");
 }
 
-static char *make_image_line(struct afs_info *afsi)
+static char *make_image_lines(struct afs_info *afsi)
 {
        char *image_name;
        img_get_name_by_id(afsi->image_id, &image_name);
-       if (!image_name)
-               return make_message("%u", afsi->image_id);
-       return make_message("%u (%s)", afsi->image_id, image_name);
+       return make_message("image_id: %u\nimage_name: %s\n",
+               afsi->image_id, image_name? image_name : "(none)");
 }
 
 static int print_list_item(struct ls_data *d, struct ls_options *opts,
@@ -841,7 +847,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
        struct ls_widths *w = &opts->widths;
        int have_score = opts->flags & LS_FLAG_ADMISSIBLE_ONLY;
        char asc_hash[2 * HASH_SIZE + 1];
-       char *att_lines, *lyrics_line, *image_line;
+       char *att_lines, *lyrics_lines, *image_lines;
 
        if (opts->mode == LS_MODE_SHORT) {
                para_printf(b, "%s\n", d->path);
@@ -852,7 +858,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                sizeof(last_played_time), current_time, opts->mode);
        if (ret < 0)
                return ret;
-       get_duration_buf(afhi->seconds_total, duration_buf, w->duration_width);
+       get_duration_buf(afhi->seconds_total, duration_buf, opts);
        if (have_score) {
                if (opts->mode == LS_MODE_LONG)
                        sprintf(score_buf, "%*li ", w->score_width, d->score);
@@ -891,22 +897,22 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
        }
        hash_to_asc(d->hash, asc_hash);
        att_lines = make_attribute_lines(att_buf, afsi);
-       lyrics_line = make_lyrics_line(afsi);
-       image_line = make_image_line(afsi);
-       /* TODO: Merge this with status items */
+       lyrics_lines = make_lyrics_lines(afsi);
+       image_lines = make_image_lines(afsi);
        if (opts->mode == LS_MODE_VERBOSE) {
                para_printf(b,
                        "%s: %s\n" /* path */
                        "%s%s%s" /* score */
                        "attributes: %s\n"
                        "hash: %s\n"
-                       "image_id: %s\n"
-                       "lyrics_id: %s\n"
+                       "%s" /* image id, image name */
+                       "%s" /* lyrics */
                        "bitrate: %dkbit/s\n"
                        "format: %s\n"
                        "frequency: %dHz\n"
                        "channels: %d\n"
                        "duration: %s\n"
+                       "seconds_total: %lu\n"
                        "num_played: %d\n"
                        "last_played: %s\n"
                        "tag info: %s\n",
@@ -916,13 +922,14 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                                have_score? "\n" : "",
                        att_lines,
                        asc_hash,
-                       image_line,
-                       lyrics_line,
+                       image_lines,
+                       lyrics_lines,
                        afhi->bitrate,
                        audio_format_name(afsi->audio_format_id),
                        afhi->frequency,
                        afhi->channels,
                        duration_buf,
+                       afhi->seconds_total,
                        afsi->num_played,
                        last_played_time,
                        afhi->info_string
@@ -935,9 +942,9 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                        "Received: from\nTo: bar\nFrom: a\n"
                        "Subject: %s\n\n" /* path */
                        "%s%s%s" /* score */
-                       "%s"
+                       "%s\n" /* attributes */
                        "hash: %s\n"
-                       "image_id: %s\n"
+                       "%s\n" /* image id, image name */
                        "lyrics_id: %s\n"
                        "bitrate: %dkbit/s\n"
                        "format: %s\n"
@@ -953,8 +960,8 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                                have_score? "\n" : "",
                        att_lines,
                        asc_hash,
-                       image_line,
-                       lyrics_line,
+                       image_lines,
+                       lyrics_lines,
                        afhi->bitrate,
                        audio_format_name(afsi->audio_format_id),
                        afhi->frequency,
@@ -969,11 +976,24 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                        osl_close_disk_object(lyrics_def.data);
        }
        free(att_lines);
-       free(lyrics_line);
-       free(image_line);
+       free(lyrics_lines);
+       free(image_lines);
        return 1;
 }
 
+int make_status_items(struct ls_data *d, struct para_buffer *pb)
+{
+       struct ls_options opts = {
+               .flags = LS_FLAG_FULL_PATH | LS_FLAG_ADMISSIBLE_ONLY,
+               .mode = LS_MODE_VERBOSE,
+       };
+       time_t current_time;
+
+       time(&current_time);
+       return print_list_item(d, &opts, pb, current_time);
+}
+
+
 static int ls_audio_format_compare(const void *a, const void *b)
 {
        struct ls_data *d1 = *(struct ls_data **)a, *d2 = *(struct ls_data **)b;
@@ -1694,7 +1714,7 @@ static int add_one_audio_file(const char *path, const void *private_data)
        save_audio_file_info(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 && result.data && result.size) {
+       if (ret > 0) {
                ret2 = send_va_buffer(pad->fd, "%s", (char *)result.data);
                free(result.data);
                if (ret >= 0 && ret2 < 0)