From bb92402464a61c03616ff23397e753a9dca98d6d Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Mon, 22 Dec 2014 18:05:38 +0000 Subject: [PATCH] aft: Update status items on afs events. When a paraslash command changes the afs or afh info structures of the current audio file, for example by re-adding the file with modified meta tags, the stat output still reports the old values. With this patch applied, the status items are updated immediately. This is achieved by letting aft.c honor the AFSI_CHANGE and AFHI_CHANGE events. If the audio file which triggered the event is the one currently being streamed, the event handler recreates the status items. We need two new global static variables in aft.c to track the row of the audio file table which corresponds to the current file. --- aft.c | 77 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/aft.c b/aft.c index 517c972c..0e86b12d 100644 --- 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(¤t_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(¤t_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; } } -- 2.39.5