X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aft.c;h=ff2691f90d127901c77579cdb58aed0b00b82583;hp=46d6729280cf8b90ce47c5d9194c2cace22c2f81;hb=61250cf03241bf73662dac3753e44660a572fa2a;hpb=c2ac39f76d245816a919d94790672fb66e9a7253 diff --git a/aft.c b/aft.c index 46d67292..ff2691f9 100644 --- a/aft.c +++ b/aft.c @@ -6,6 +6,7 @@ /** \file aft.c Audio file table functions. */ +#include /* readdir() */ #include "para.h" #include "error.h" #include "string.h" @@ -15,6 +16,8 @@ #include "afs.h" #include "net.h" #include "vss.h" +#include "fd.h" +#include "ipc.h" static struct osl_table *audio_file_table; @@ -138,8 +141,10 @@ enum afsi_offsets { AFSI_LYRICS_ID_OFFSET = 24, /** Storage position of the .audio_format_id field. */ AFSI_AUDIO_FORMAT_ID_OFFSET = 28, + /** 3 bytes reserved space for future usage. */ + AFSI_AUDIO_FORMAT_UNUSED_OFFSET = 29, /** On-disk storage space needed. */ - AFSI_SIZE = 29 + AFSI_SIZE = 32 }; /** @@ -161,6 +166,7 @@ void save_afsi(struct afs_info *afsi, struct osl_object *obj) write_u32(buf + AFSI_LYRICS_ID_OFFSET, afsi->lyrics_id); write_u8(buf + AFSI_AUDIO_FORMAT_ID_OFFSET, afsi->audio_format_id); + memset(buf + AFSI_AUDIO_FORMAT_UNUSED_OFFSET, 0, 3); } /** @@ -367,11 +373,23 @@ enum chunk_info_offsets{ CHUNK_TABLE_OFFSET = 20, }; -/* TODO: audio format handlers could just produce this */ -static void save_chunk_info(struct audio_format_info *afhi, char *buf) +static void save_chunk_table(struct audio_format_info *afhi, char *buf) +{ + int i; + for (i = 0; i < afhi->chunks_total; i++) + write_u32(buf + 4 * i, afhi->chunk_table[i]); +} + +static void load_chunk_table(struct audio_format_info *afhi, char *buf) { int i; + for (i = 0; i < afhi->chunks_total; i++) + afhi->chunk_table[i] = read_u32(buf + 4 * i); +} +/* TODO: audio format handlers could just produce this */ +static void save_chunk_info(struct audio_format_info *afhi, char *buf) +{ if (!afhi) return; write_u32(buf + CHUNKS_TOTAL_OFFSET, afhi->chunks_total); @@ -379,14 +397,12 @@ static void save_chunk_info(struct audio_format_info *afhi, char *buf) write_u32(buf + HEADER_OFFSET_OFFSET, afhi->header_offset); write_u32(buf + CHUNK_TV_TV_SEC_OFFSET, afhi->chunk_tv.tv_sec); write_u32(buf + CHUNK_TV_TV_USEC, afhi->chunk_tv.tv_usec); - for (i = 0; i < afhi->chunks_total; i++) - write_u32(buf + CHUNK_TABLE_OFFSET + 4 * i, afhi->chunk_table[i]); + save_chunk_table(afhi, buf + CHUNK_TABLE_OFFSET); } static int load_chunk_info(struct osl_object *obj, struct audio_format_info *afhi) { char *buf = obj->data; - int i; if (obj->size < CHUNK_TABLE_OFFSET) return -E_BAD_DATA_SIZE; @@ -400,8 +416,7 @@ static int load_chunk_info(struct osl_object *obj, struct audio_format_info *afh if (afhi->chunks_total * 4 + CHUNK_TABLE_OFFSET > obj->size) return -E_BAD_DATA_SIZE; afhi->chunk_table = para_malloc(afhi->chunks_total * sizeof(size_t)); - for (i = 0; i < afhi->chunks_total; i++) - afhi->chunk_table[i] = read_u32(buf + CHUNK_TABLE_OFFSET + 4 * i); + load_chunk_table(afhi, buf + CHUNK_TABLE_OFFSET); return 1; } @@ -576,6 +591,7 @@ int get_afhi_of_row(const struct osl_row *row, struct audio_format_info *afhi) return 1; } +#if 0 /** * Get the chunk table of an audio file, given a row of the audio file table. * @@ -597,6 +613,58 @@ static int get_chunk_table_of_row(const struct osl_row *row, struct audio_format osl_close_disk_object(&obj); return ret; } +#endif + +/* returns shmid on success */ +static int save_afd(struct audio_file_data *afd) +{ + size_t path_size = strlen(afd->path) + 1; + size_t size = sizeof(*afd) + path_size + + 4 * afd->afhi.chunks_total; + + PARA_NOTICE_LOG("size: %zu\n", size); + int shmid, ret = shm_new(size); + void *shm_afd; + char *buf; + + if (ret < 0) + return ret; + shmid = ret; + ret = shm_attach(shmid, ATTACH_RW, &shm_afd); + if (ret < 0) + goto err; + *(struct audio_file_data *)shm_afd = *afd; + buf = shm_afd; + buf += sizeof(*afd); + strcpy(buf, afd->path); + buf += path_size; + save_chunk_table(&afd->afhi, buf); + shm_detach(shm_afd); + return shmid; +err: + shm_destroy(shmid); + return ret; +} + +int load_afd(int shmid, struct audio_file_data *afd) +{ + void *shm_afd; + char *buf; + int ret; + + ret = shm_attach(shmid, ATTACH_RO, &shm_afd); + if (ret < 0) + return ret; + *afd = *(struct audio_file_data *)shm_afd; + buf = shm_afd; + buf += sizeof(*afd); + afd->path = para_strdup(buf); + buf += strlen(buf) + 1; + afd->afhi.chunk_table = para_malloc(afd->afhi.chunks_total * sizeof(size_t)); + load_chunk_table(&afd->afhi, buf); + shm_detach(shm_afd); + return 1; +} /** * Mmap the given audio file and update statistics. @@ -616,6 +684,8 @@ int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data * struct osl_object afsi_obj; struct afs_info new_afsi; int ret = get_hash_of_row(aft_row, &aft_hash); + struct afsi_change_event_data aced; + struct osl_object map, chunk_table_obj; if (ret < 0) return ret; @@ -631,30 +701,39 @@ int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data * ret = get_afhi_of_row(aft_row, &afd->afhi); if (ret < 0) return ret; - ret = get_chunk_table_of_row(aft_row, &afd->afhi); + ret = osl_open_disk_object(audio_file_table, aft_row, + AFTCOL_CHUNKS, &chunk_table_obj); if (ret < 0) return ret; - ret = mmap_full_file(afd->path, O_RDONLY, &afd->map); + ret = mmap_full_file(afd->path, O_RDONLY, &map.data, + &map.size, &afd->fd); if (ret < 0) goto err; - hash_function(afd->map.data, afd->map.size, file_hash); - ret = -E_HASH_MISMATCH; - if (hash_compare(file_hash, aft_hash)) + hash_function(map.data, map.size, file_hash); + ret = hash_compare(file_hash, aft_hash); + para_munmap(map.data, map.size); + if (ret) { + ret = -E_HASH_MISMATCH; goto err; + } new_afsi = afd->afsi; new_afsi.num_played++; new_afsi.last_played = time(NULL); save_afsi(&new_afsi, &afsi_obj); /* in-place update */ - if (afd->current_play_mode == PLAY_MODE_PLAYLIST) - ret = playlist_update_audio_file(aft_row); - else { - struct afsi_change_event_data aced = {.aft_row = aft_row, - .old_afsi = &afd->afsi}; - afs_event(AFSI_CHANGE, NULL, &aced); - } - return ret; -err: + + ret = load_chunk_info(&chunk_table_obj, &afd->afhi); + if (ret < 0) + goto err; + + aced.aft_row = aft_row; + aced.old_afsi = &afd->afsi; + afs_event(AFSI_CHANGE, NULL, &aced); + ret = save_afd(afd); + if (ret < 0) + goto err; free(afd->afhi.chunk_table); +err: + osl_close_disk_object(&chunk_table_obj); return ret; } @@ -1500,8 +1579,8 @@ out: return 0; result->data = msg.buf; result->size = msg.size; + afs_event(AUDIO_FILE_ADD, &msg, aft_row); return 1; - // mood_update_audio_file(aft_row, NULL); } struct private_add_data { @@ -1545,7 +1624,7 @@ static int add_one_audio_file(const char *path, const void *private_data) const struct private_add_data *pad = private_data; struct audio_format_info afhi, *afhi_ptr = NULL; struct osl_row *pb = NULL, *hs = NULL; /* path brother/hash sister */ - struct osl_object map, obj = {.data = NULL}, query, result; + struct osl_object map, obj = {.data = NULL}, query, result = {.data = NULL}; HASH_TYPE hash[HASH_SIZE]; afhi.header_offset = 0; @@ -1569,7 +1648,7 @@ static int add_one_audio_file(const char *path, const void *private_data) goto out_free; } /* We still want to add this file. Compute its hash. */ - ret = mmap_full_file(path, O_RDONLY, &map); + ret = mmap_full_file(path, O_RDONLY, &map.data, &map.size, NULL); if (ret < 0) goto out_free; hash_function(map.data, map.size, hash); @@ -1612,7 +1691,7 @@ static int add_one_audio_file(const char *path, const void *private_data) save_audio_file_info(hash, path, afhi_ptr, pad->flags, format_num, &obj); /* Ask afs to consider this entry for adding. */ ret = send_callback_request(com_add_callback, &obj, &result); - if (result.data && result.size) { + if (ret >= 0 && result.data && result.size) { ret2 = send_va_buffer(pad->fd, "%s", (char *)result.data); free(result.data); if (ret >= 0 && ret2 < 0) @@ -1965,7 +2044,7 @@ int com_afs_rm(int fd, int argc, char * const * const argv) if (ret > 0) { send_buffer(fd, (char *)result.data); free(result.data); - } else + } else if (ret < 0) send_va_buffer(fd, "%s\n", PARA_STRERROR(-ret)); return ret; }