From: Andre Noll Date: Mon, 22 Dec 2014 18:05:38 +0000 (+0000) Subject: aft: Update status items on afs events. X-Git-Tag: v0.5.5~40^2~2 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=bb92402464a61c03616ff23397e753a9dca98d6d;hp=e0671caf7202075332964347dacd92ab6e18dcd4 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. --- 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; } }