afs: Simplify open_next_audio_file().
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index 5204ce0ce47c8d81df9fb8d8865338e45d3b33a3..8a633298ead4d05d6c11b8a7a429b0ec7974ed80 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2014 Andre Noll <maan@tuebingen.mpg.de>
+ * Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -72,6 +72,20 @@ enum ls_listing_mode {
        LS_MODE_PARSER,
 };
 
+/* Data about one audio file. Needed for ls and stat output. */
+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 hash value of the audio file data. */
+       unsigned char *hash;
+};
+
 /** The flags accepted by the ls command. */
 enum ls_flags {
        /** -p */
@@ -87,10 +101,9 @@ enum ls_flags {
 /**
  * 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.
+ * These depend on the content being listed. For example, if each listed file
+ * is shorter than an hour, the duration format is set to mm:ss. Otherwise it
+ * is set to hh:mm:ss.
  */
 struct ls_widths {
        /** size of the score field. */
@@ -830,8 +843,8 @@ static int print_chunk_table(struct ls_data *d, struct para_buffer *b)
        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);
+       ret = osl(osl_open_disk_object(audio_file_table, aft_row,
+               AFTCOL_CHUNKS, &chunk_table_obj));
        if (ret < 0)
                return ret;
        ret = para_printf(b, "%s\n"
@@ -1067,10 +1080,8 @@ static int make_status_items(struct audio_file_data *afd,
 }
 
 /**
- * Mmap the given audio file and update statistics.
+ * Open the audio file with highest score and set up an afd structure.
  *
- * \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
@@ -1079,17 +1090,22 @@ static int make_status_items(struct audio_file_data *afd,
  *
  * \return Positive shmid on success, negative on errors.
  */
-int open_and_update_audio_file(struct osl_row *aft_row, long score,
-       struct audio_file_data *afd)
+int open_and_update_audio_file(struct audio_file_data *afd)
 {
+       struct osl_row *aft_row;
+       long score;
        unsigned char *aft_hash, file_hash[HASH_SIZE];
        struct osl_object afsi_obj;
        struct afs_info old_afsi, new_afsi;
-       int ret = get_hash_of_row(aft_row, &aft_hash);
+       int ret;
        struct afsi_change_event_data aced;
        struct osl_object map, chunk_table_obj;
        char *path;
-
+again:
+       ret = score_get_best(&aft_row, &score);
+       if (ret < 0)
+               return ret;
+       ret = get_hash_of_row(aft_row, &aft_hash);
        if (ret < 0)
                return ret;
        ret = get_audio_file_path_of_row(aft_row, &path);
@@ -1106,10 +1122,10 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
        if (ret < 0)
                return ret;
        afd->afhi.chunk_table = NULL;
-       ret = osl_open_disk_object(audio_file_table, aft_row,
-               AFTCOL_CHUNKS, &chunk_table_obj);
+       ret = osl(osl_open_disk_object(audio_file_table, aft_row,
+               AFTCOL_CHUNKS, &chunk_table_obj));
        if (ret < 0)
-               goto err;
+               return ret;
        ret = mmap_full_file(path, O_RDONLY, &map.data, &map.size, &afd->fd);
        if (ret < 0)
                goto err;
@@ -1137,8 +1153,12 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
 err:
        free(afd->afhi.chunk_table);
        osl_close_disk_object(&chunk_table_obj);
-       if (ret < 0)
+       if (ret < 0) {
                PARA_ERROR_LOG("%s: %s\n", path, para_strerror(-ret));
+               ret = score_delete(aft_row);
+               if (ret >= 0)
+                       goto again;
+       }
        return ret;
 }
 
@@ -1717,10 +1737,11 @@ static void com_add_callback(int fd, const struct osl_object *query)
                struct osl_object obj;
                if (pb) { /* hs trumps pb, remove pb */
                        if (flags & ADD_FLAG_VERBOSE) {
-                               ret = para_printf(&msg, "removing path brother\n");
+                               ret = para_printf(&msg, "removing %s\n", path);
                                if (ret < 0)
                                        goto out;
                        }
+                       afs_event(AUDIO_FILE_REMOVE, &msg, pb);
                        ret = osl(osl_del_row(audio_file_table, pb));
                        if (ret < 0)
                                goto out;
@@ -2593,7 +2614,7 @@ static void afs_stat_callback(int fd, const struct osl_object *query)
  * is used to pass the status items from the afs process to the command handler
  * via a shared memory area and a pipe.
  *
- * \return The return value of the underyling call to \ref send_callback_request().
+ * \return The return value of the underlying call to \ref send_callback_request().
  */
 int send_afs_status(struct command_context *cc, int parser_friendly)
 {