Fix SIGUSR1 handling on Solaris.
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index 57df793fb8b16ec1c111e21b5928d44872c9248f..1d6a5070488ba3beb84a42f37dd0de2d3c0c3789 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -622,6 +622,7 @@ int load_afd(int shmid, struct audio_file_data *afd)
  * Mmap the given audio file and update statistics.
  *
  * \param aft_row Determines the audio file to be opened and updated.
+ * \param score The score of the audio file.
  * \param afd Result pointer.
  *
  * On success, the numplayed field of the audio file selector info is increased
@@ -630,8 +631,8 @@ int load_afd(int shmid, struct audio_file_data *afd)
  *
  * \return Positive shmid on success, negative on errors.
  */
-int open_and_update_audio_file(struct osl_row *aft_row,
-       struct audio_file_data *afd, long score)
+int open_and_update_audio_file(struct osl_row *aft_row, long score,
+       struct audio_file_data *afd)
 {
        HASH_TYPE *aft_hash, file_hash[HASH_SIZE];
        struct osl_object afsi_obj;
@@ -807,9 +808,8 @@ static char *make_filename_lines(const char *path, unsigned flags)
        char *ret;
 
        if (!(flags & LS_FLAG_FULL_PATH))
-               return make_message("%s: %s\n%s:\n",
-                       status_item_list[SI_BASENAME], path,
-                       status_item_list[SI_DIRECTORY]);
+               return make_message("%s: %s\n",
+                       status_item_list[SI_BASENAME], path);
        basename = para_basename(path),
        dirname = para_dirname(path);
        ret = make_message("%s: %s\n%s: %s\n%s: %s\n",
@@ -887,82 +887,60 @@ 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_VERBOSE) {
-               para_printf(b,
-                       "%s" /* filename stuff */
-                       "%s%s%s%s" /* score */
-                       "%s\n" /* attributes */
-                       "%s: %s\n" /* hash */
-                       "%s" /* image id, image name */
-                       "%s" /* lyrics */
-                       "%s: %dkbit/s\n" /* bitrate */
-                       "%s: %s\n" /* format */
-                       "%s: %dHz\n" /* frequency */
-                       "%s: %d\n" /* channels */
-                       "%s: %s\n" /* duration */
-                       "%s: %lu\n" /* seconds total */
-                       "%s: %d\n" /* num_played */
-                       "%s: %s\n" /* last_played */
-                       "%s\n", /* tag info */
-                       filename_lines,
-                       have_score? status_item_list[SI_SCORE] : "",
-                               have_score? ": " : "",
-                               score_buf,
-                               have_score? "\n" : "",
-                       att_lines,
-                       status_item_list[SI_HASH], asc_hash,
-                       image_lines,
-                       lyrics_lines,
-                       status_item_list[SI_BITRATE], afhi->bitrate,
-                       status_item_list[SI_FORMAT], audio_format_name(afsi->audio_format_id),
-                       status_item_list[SI_FREQUENCY], afhi->frequency,
-                       status_item_list[SI_CHANNELS], afhi->channels,
-                       status_item_list[SI_DURATION], duration_buf,
-                       status_item_list[SI_SECONDS_TOTAL], afhi->seconds_total,
-                       status_item_list[SI_NUM_PLAYED], afsi->num_played,
-                       status_item_list[SI_LAST_PLAYED], last_played_time,
-                       afhi->info_string
-               );
-       } else { /* mbox mode */ /* FIXME: merge with verbose output */
-               struct osl_object lyrics_def;
-               lyr_get_def_by_id(afsi->lyrics_id, &lyrics_def);
+       if (opts->mode == LS_MODE_MBOX)
                para_printf(b,
                        "From foo@localhost %s\n"
                        "Received: from\nTo: bar\nFrom: a\n"
-                       "Subject: %s\n\n" /* path */
-                       "%s%s%s" /* score */
-                       "%s\n" /* attributes */
-                       "hash: %s\n"
-                       "%s\n" /* image id, image name */
-                       "lyrics_id: %s\n"
-                       "bitrate: %dkbit/s\n"
-                       "format: %s\n"
-                       "frequency: %dHz\n"
-                       "channels: %d\n"
-                       "duration: %s\n"
-                       "num_played: %d\n"
-                       "%s\n" /* tag info */
-                       "%s%s\n",
+                       "Subject: %s\n\n",
                        last_played_time,
-                       d->path,
-                       have_score? "score: " : "", score_buf,
-                               have_score? "\n" : "",
-                       att_lines,
-                       asc_hash,
-                       image_lines,
-                       lyrics_lines,
-                       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);
+                       d->path);
+       para_printf(b,
+               "%s" /* filename stuff */
+               "%s%s%s%s" /* score */
+               "%s\n" /* attributes */
+               "%s: %s\n" /* hash */
+               "%s" /* image id, image name */
+               "%s" /* lyrics */
+               "%s: %dkbit/s\n" /* bitrate */
+               "%s: %s\n" /* format */
+               "%s: %dHz\n" /* frequency */
+               "%s: %d\n" /* channels */
+               "%s: %s\n" /* duration */
+               "%s: %lu\n" /* seconds total */
+               "%s: %s\n" /* last played time */
+               "%s: %d\n" /* num_played */
+               "%s" /* tag info */
+               "%s: %lu\n" /* chunk time */
+               "%s: %lu\n", /* num chunks */
+               filename_lines,
+               have_score? status_item_list[SI_SCORE] : "",
+                       have_score? ": " : "",
+                       score_buf,
+                       have_score? "\n" : "",
+               att_lines,
+               status_item_list[SI_HASH], asc_hash,
+               image_lines,
+               lyrics_lines,
+               status_item_list[SI_BITRATE], afhi->bitrate,
+               status_item_list[SI_FORMAT], audio_format_name(afsi->audio_format_id),
+               status_item_list[SI_FREQUENCY], afhi->frequency,
+               status_item_list[SI_CHANNELS], afhi->channels,
+               status_item_list[SI_DURATION], duration_buf,
+               status_item_list[SI_SECONDS_TOTAL], afhi->seconds_total,
+               status_item_list[SI_LAST_PLAYED], last_played_time,
+               status_item_list[SI_NUM_PLAYED], afsi->num_played,
+               afhi->info_string,
+               status_item_list[SI_CHUNK_TIME], tv2ms(&afhi->chunk_tv),
+               status_item_list[SI_NUM_CHUNKS], afhi->chunks_total
+       );
+       if (opts->mode == LS_MODE_MBOX) {
+               struct osl_object lyrics_def;
+               lyr_get_def_by_id(afsi->lyrics_id, &lyrics_def);
+               if (lyrics_def.data) {
+                       para_printf(b, "Lyrics:\n~~~~~~~\n%s",
+                               (char *)lyrics_def.data);
+                       osl_close_disk_object(&lyrics_def);
+               }
        }
        free(att_lines);
        free(lyrics_lines);
@@ -974,25 +952,25 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
 void make_empty_status_items(char *buf)
 {
        sprintf(buf,
-               "%s:\n" /* path */
-               "%s:\n" /* dirname */
-               "%s:\n" /* basename */
-               "%s:\n" /* score */
-               "%s:\n" /* attributes bitnmap */
-               "%s:\n" /* attributes txt */
-               "%s:\n" /* hash */
-               "%s:\n" /* image id */
-               "%s:\n" /* image name */
-               "%s:\n" /* lyrics id */
-               "%s:\n" /* lyrics name */
-               "%s:\n" /* bitrate */
-               "%s:\n" /* format */
-               "%s:\n" /* frequency */
-               "%s:\n" /* channels */
-               "%s:\n" /* duration */
-               "%s:\n" /* seconds total */
-               "%s:\n" /* num played */
-               "%s:\n" /* last played */
+               "%s: \n" /* path */
+               "%s: \n" /* dirname */
+               "%s: \n" /* basename */
+               "%s: \n" /* score */
+               "%s: \n" /* attributes bitnmap */
+               "%s: \n" /* attributes txt */
+               "%s: \n" /* hash */
+               "%s: \n" /* image id */
+               "%s: \n" /* image name */
+               "%s: \n" /* lyrics id */
+               "%s: \n" /* lyrics name */
+               "%s: \n" /* bitrate */
+               "%s: \n" /* format */
+               "%s: \n" /* frequency */
+               "%s: \n" /* channels */
+               "%s: \n" /* duration */
+               "%s: \n" /* seconds total */
+               "%s: \n" /* num played */
+               "%s: \n" /* last played */
                ,
                status_item_list[SI_PATH],
                status_item_list[SI_DIRECTORY],
@@ -1455,7 +1433,8 @@ static void save_audio_file_info(HASH_TYPE *hash, const char *path,
        pos += afhi_size;
        PARA_DEBUG_LOG("size: %zu, chunks start at %d\n", size, pos);
        write_u16(buf + AFTROW_CHUNKS_OFFSET_POS, pos);
-       save_chunk_table(afhi, buf + pos);
+       if (afhi)
+               save_chunk_table(afhi, buf + pos);
        PARA_DEBUG_LOG("last byte in buf: %p\n", buf + size - 1);
        obj->data = buf;
        obj->size = size;
@@ -1677,7 +1656,7 @@ static int hash_sister_callback(const struct osl_object *query,
 
 static int add_one_audio_file(const char *path, const void *private_data)
 {
-       int ret, ret2;
+       int ret, send_ret = 1;
        uint8_t format_num = -1;
        const struct private_add_data *pad = private_data;
        struct afh_info afhi, *afhi_ptr = NULL;
@@ -1702,7 +1681,7 @@ static int add_one_audio_file(const char *path, const void *private_data)
        ret = 1;
        if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       ret = send_va_buffer(pad->fd, "lazy-ignore: %s\n", path);
+                       send_ret = send_va_buffer(pad->fd, "lazy-ignore: %s\n", path);
                goto out_free;
        }
        /* We still want to add this file. Compute its hash. */
@@ -1711,27 +1690,27 @@ static int add_one_audio_file(const char *path, const void *private_data)
                goto out_free;
        hash_function(map.data, map.size, hash);
 
-       /* Check whether database contains file with the same hash. */
+       /* 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);
        if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND)
-               goto out_free;
+               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))) {
+       if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       ret = send_va_buffer(pad->fd,
+                       send_ret = send_va_buffer(pad->fd,
                                "%s exists, not forcing update\n", path);
                goto out_unmap;
        }
        /*
-        * we won't recalculate the audio format info and the chunk table if
-        * there is a hash sister unless in FORCE mode.
+        * We won't recalculate the audio format info and the chunk table if
+        * there is a hash sister and FORCE was not given.
         */
        if (!hs || (pad->flags & ADD_FLAG_FORCE)) {
                ret = compute_afhi(path, map.data, map.size, &afhi);
@@ -1740,34 +1719,32 @@ static int add_one_audio_file(const char *path, const void *private_data)
                format_num = ret;
                afhi_ptr = &afhi;
        }
+       munmap(map.data, map.size);
        if (pad->flags & ADD_FLAG_VERBOSE) {
-               ret = send_va_buffer(pad->fd, "adding %s\n", path);
-               if (ret < 0)
-                       goto out_unmap;
+               send_ret = send_va_buffer(pad->fd, "adding %s\n", path);
+               if (send_ret < 0)
+                       goto out_free;
        }
-       munmap(map.data, map.size);
        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) {
-               ret2 = send_va_buffer(pad->fd, "%s", (char *)result.data);
+               send_ret = send_va_buffer(pad->fd, "%s", (char *)result.data);
                free(result.data);
-               if (ret >= 0 && ret2 < 0)
-                       ret = ret2;
        }
        goto out_free;
 
 out_unmap:
        munmap(map.data, map.size);
 out_free:
-       if (ret < 0 && ret != -E_SEND)
-               send_va_buffer(pad->fd, "failed to add %s (%s)\n", path,
+       if (ret < 0 && send_ret >= 0)
+               send_ret = send_va_buffer(pad->fd, "failed to add %s (%s)\n", path,
                        PARA_STRERROR(-ret));
        free(obj.data);
        if (afhi_ptr)
                free(afhi_ptr->chunk_table);
-       /* it's not an error if not all files could be added */
-       return ret == -E_SEND? ret : 1;
+       /* Stop adding files only on send errors. */
+       return send_ret;
 }
 
 int com_add(int fd, int argc, char * const * const argv)