aft: Update status items on afs events.
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index 517c972..0e86b12 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1040,7 +1040,10 @@ out:
        return ret;
 }
 
-static int make_status_items(struct ls_data *d)
+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,
@@ -1051,7 +1054,7 @@ static int make_status_items(struct ls_data *d)
        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);
@@ -1059,7 +1062,7 @@ static int make_status_items(struct ls_data *d)
        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;
@@ -1083,70 +1086,70 @@ static int make_status_items(struct ls_data *d)
  */
 int open_and_update_audio_file(struct audio_file_data *afd)
 {
-       struct osl_row *aft_row;
        unsigned char file_hash[HASH_SIZE];
        struct osl_object afsi_obj;
        struct afs_info new_afsi;
        int ret;
        struct afsi_change_event_data aced;
        struct osl_object map, chunk_table_obj;
-       struct ls_data d;
+       struct ls_data *d = &status_item_ls_data;
 again:
-       ret = score_get_best(&aft_row, &d.score);
+       ret = score_get_best(&current_aft_row, &d->score);
        if (ret < 0)
                return ret;
-       ret = get_hash_of_row(aft_row, &d.hash);
+       ret = get_hash_of_row(current_aft_row, &d->hash);
        if (ret < 0)
                return ret;
-       ret = get_audio_file_path_of_row(aft_row, &d.path);
+       ret = get_audio_file_path_of_row(current_aft_row, &d->path);
        if (ret < 0)
                return ret;
-       PARA_NOTICE_LOG("%s\n", d.path);
-       ret = get_afsi_object_of_row(aft_row, &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 = load_afsi(&d.afsi, &afsi_obj);
+       ret = load_afsi(&d->afsi, &afsi_obj);
        if (ret < 0)
                return ret;
-       ret = get_afhi_of_row(aft_row, &afd->afhi);
+       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, aft_row,
+       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(d.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, d.hash);
+       ret = hash_compare(file_hash, d->hash);
        para_munmap(map.data, map.size);
        if (ret) {
                ret = -E_HASH_MISMATCH;
                goto err;
        }
-       new_afsi = d.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 = d.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(&d);
-       if (ret < 0)
-               goto err;
-       aced.aft_row = aft_row;
-       aced.old_afsi = &d.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", d.path, para_strerror(-ret));
-               ret = score_delete(aft_row);
+               PARA_ERROR_LOG("%s: %s\n", d->path, para_strerror(-ret));
+               ret = score_delete(current_aft_row);
                if (ret >= 0)
                        goto again;
        }
@@ -2765,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;
        }
 }