]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - aft.c
aft: Update status items on afs events.
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index a73537c74446b3cdb49e405f7918701d837a8e8f..0e86b12d6c13ea1992c0c751dae61df43f78b226 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1040,17 +1040,11 @@ out:
        return ret;
 }
 
-static int make_status_items(struct audio_file_data *afd,
-               struct afs_info *afsi, char *path, long score,
-               unsigned char *hash)
-{
-       struct ls_data d = {
-               .afhi = afd->afhi,
-               .afsi = *afsi,
-               .path = path,
-               .score = score,
-               .hash = hash
-       };
+static struct ls_data status_item_ls_data;
+static struct osl_row *current_aft_row;
+
+static int make_status_items(void)
+{
        struct ls_options opts = {
                .flags = LS_FLAG_FULL_PATH | LS_FLAG_ADMISSIBLE_ONLY,
                .mode = LS_MODE_VERBOSE,
@@ -1060,7 +1054,7 @@ static int make_status_items(struct audio_file_data *afd,
        int ret;
 
        time(&current_time);
-       ret = print_list_item(&d, &opts, &pb, current_time);
+       ret = print_list_item(&status_item_ls_data, &opts, &pb, current_time);
        if (ret < 0)
                return ret;
        free(status_items);
@@ -1068,7 +1062,7 @@ static int make_status_items(struct audio_file_data *afd,
        memset(&pb, 0, sizeof(pb));
        pb.max_size = shm_get_shmmax() - 1;
        pb.flags = PBF_SIZE_PREFIX;
-       ret = print_list_item(&d, &opts, &pb, current_time);
+       ret = print_list_item(&status_item_ls_data, &opts, &pb, current_time);
        if (ret < 0) {
                free(status_items);
                status_items = NULL;
@@ -1080,10 +1074,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
@@ -1092,66 +1084,75 @@ 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)
 {
-       unsigned char *aft_hash, file_hash[HASH_SIZE];
+       unsigned char 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);
+       struct afs_info new_afsi;
+       int ret;
        struct afsi_change_event_data aced;
        struct osl_object map, chunk_table_obj;
-       char *path;
-
+       struct ls_data *d = &status_item_ls_data;
+again:
+       ret = score_get_best(&current_aft_row, &d->score);
        if (ret < 0)
                return ret;
-       ret = get_audio_file_path_of_row(aft_row, &path);
+       ret = get_hash_of_row(current_aft_row, &d->hash);
        if (ret < 0)
                return ret;
-       PARA_NOTICE_LOG("%s\n", path);
-       ret = get_afsi_object_of_row(aft_row, &afsi_obj);
+       ret = get_audio_file_path_of_row(current_aft_row, &d->path);
        if (ret < 0)
                return ret;
-       ret = load_afsi(&old_afsi, &afsi_obj);
+       PARA_NOTICE_LOG("%s\n", d->path);
+       ret = get_afsi_object_of_row(current_aft_row, &afsi_obj);
        if (ret < 0)
                return ret;
-       ret = get_afhi_of_row(aft_row, &afd->afhi);
+       ret = load_afsi(&d->afsi, &afsi_obj);
        if (ret < 0)
                return ret;
-       afd->afhi.chunk_table = NULL;
-       ret = osl(osl_open_disk_object(audio_file_table, aft_row,
+       ret = get_afhi_of_row(current_aft_row, &afd->afhi);
+       if (ret < 0)
+               return ret;
+       d->afhi = afd->afhi;
+       d->afhi.chunk_table = afd->afhi.chunk_table = NULL;
+       ret = osl(osl_open_disk_object(audio_file_table, current_aft_row,
                AFTCOL_CHUNKS, &chunk_table_obj));
        if (ret < 0)
                return ret;
-       ret = mmap_full_file(path, O_RDONLY, &map.data, &map.size, &afd->fd);
+       ret = mmap_full_file(d->path, O_RDONLY, &map.data, &map.size, &afd->fd);
        if (ret < 0)
                goto err;
        hash_function(map.data, map.size, file_hash);
-       ret = hash_compare(file_hash, aft_hash);
+       ret = hash_compare(file_hash, d->hash);
        para_munmap(map.data, map.size);
        if (ret) {
                ret = -E_HASH_MISMATCH;
                goto err;
        }
-       new_afsi = old_afsi;
+       new_afsi = d->afsi;
        new_afsi.num_played++;
        new_afsi.last_played = time(NULL);
        save_afsi(&new_afsi, &afsi_obj); /* in-place update */
 
-       afd->audio_format_id = old_afsi.audio_format_id;
+       afd->audio_format_id = d->afsi.audio_format_id;
        load_chunk_table(&afd->afhi, chunk_table_obj.data);
-       ret = make_status_items(afd, &old_afsi, path, score, file_hash);
-       if (ret < 0)
-               goto err;
-       aced.aft_row = aft_row;
-       aced.old_afsi = &old_afsi;
+       aced.aft_row = current_aft_row;
+       aced.old_afsi = &d->afsi;
+       /*
+        * No need to update the status items as the AFSI_CHANGE event will
+        * recreate them.
+        */
        afs_event(AFSI_CHANGE, NULL, &aced);
        ret = save_afd(afd);
 err:
        free(afd->afhi.chunk_table);
        osl_close_disk_object(&chunk_table_obj);
-       if (ret < 0)
-               PARA_ERROR_LOG("%s: %s\n", path, para_strerror(-ret));
+       if (ret < 0) {
+               PARA_ERROR_LOG("%s: %s\n", d->path, para_strerror(-ret));
+               ret = score_delete(current_aft_row);
+               if (ret >= 0)
+                       goto again;
+       }
        return ret;
 }
 
@@ -2767,9 +2768,27 @@ static int aft_event_handler(enum afs_events event, struct para_buffer *pb,
                if (ret < 0)
                        return ret;
                return audio_file_loop(data, clear_attribute);
-               }
-       default:
+       } case AFSI_CHANGE: {
+               struct afsi_change_event_data *aced = data;
+               uint64_t old_last_played = status_item_ls_data.afsi.last_played;
+               if (aced->aft_row != current_aft_row)
+                       return 0;
+               ret = get_afsi_of_row(aced->aft_row, &status_item_ls_data.afsi);
+               if (ret < 0)
+                       return ret;
+               status_item_ls_data.afsi.last_played = old_last_played;
+               make_status_items();
                return 1;
+       } case AFHI_CHANGE: {
+               if (data != current_aft_row)
+                       return 0;
+               ret = get_afhi_of_row(data, &status_item_ls_data.afhi);
+               if (ret < 0)
+                       return ret;
+               make_status_items();
+               return 1;
+       } default:
+               return 0;
        }
 }