X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aft.c;h=7027e7f95d45104c559cd5720ebd377fc2d047a8;hp=db4c494d07bcd7c759de9708d1f2c30d4ba278aa;hb=e752cdeab213b329552e1eecd5687bca512217c5;hpb=6494f4bfddde1b9e06c4cb8bcd3acf7b9cc762f1 diff --git a/aft.c b/aft.c index db4c494d..7027e7f9 100644 --- a/aft.c +++ b/aft.c @@ -24,6 +24,7 @@ #include "portable_io.h" static struct osl_table *audio_file_table; +static char *current_status_items; /** The different sorting methods of the ls command. */ enum ls_sorting_method { @@ -352,23 +353,29 @@ enum afhi_offsets { CHUNK_TV_TV_USEC_OFFSET = 36, /** Number of channels is stored here. (1 byte) */ AFHI_CHANNELS_OFFSET = 40, - /** EOF timeout in ms. (2 byte) */ - AFHI_EOF_OFFSET = 41, /** The tag info position. */ - AFHI_INFO_STRING_OFFSET = 43, + AFHI_INFO_STRING_OFFSET = 41, /** Minimal on-disk size of a valid afhi struct. */ - MIN_AFHI_SIZE = 44 + MIN_AFHI_SIZE = 47, /* at least 6 null bytes for techinfo/tags */ }; static unsigned sizeof_afhi_buf(const struct afh_info *afhi) { if (!afhi) return 0; - return strlen(afhi->info_string) + MIN_AFHI_SIZE; + return MIN_AFHI_SIZE + + strlen(afhi->techinfo) + + strlen(afhi->tags.artist) + + strlen(afhi->tags.title) + + strlen(afhi->tags.year) + + strlen(afhi->tags.album) + + strlen(afhi->tags.comment); } static void save_afhi(struct afh_info *afhi, char *buf) { + char *p; + if (!afhi) return; write_u32(buf + AFHI_SECONDS_TOTAL_OFFSET, afhi->seconds_total); @@ -382,8 +389,14 @@ static void save_afhi(struct afh_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_OFFSET, afhi->chunk_tv.tv_usec); - write_u16(buf + AFHI_EOF_OFFSET, tv2ms(&afhi->eof_tv)); - strcpy(buf + AFHI_INFO_STRING_OFFSET, afhi->info_string); /* OK */ + p = buf + AFHI_INFO_STRING_OFFSET; + /* The sprintf's below are OK as our caller made sure that buf is large enough */ + p += sprintf(p, "%s", afhi->techinfo) + 1; + p += sprintf(p, "%s", afhi->tags.artist) + 1; + p += sprintf(p, "%s", afhi->tags.title) + 1; + p += sprintf(p, "%s", afhi->tags.year) + 1; + p += sprintf(p, "%s", afhi->tags.album) + 1; + sprintf(p, "%s", afhi->tags.comment); } static void load_afhi(const char *buf, struct afh_info *afhi) @@ -399,8 +412,12 @@ static void load_afhi(const char *buf, struct afh_info *afhi) afhi->header_offset = read_u32(buf + HEADER_OFFSET_OFFSET); afhi->chunk_tv.tv_sec = read_u32(buf + CHUNK_TV_TV_SEC_OFFSET); afhi->chunk_tv.tv_usec = read_u32(buf + CHUNK_TV_TV_USEC_OFFSET); - ms2tv(read_u16(buf + AFHI_EOF_OFFSET), &afhi->eof_tv); - afhi->info_string = para_strdup(buf + AFHI_INFO_STRING_OFFSET); + afhi->techinfo = buf + AFHI_INFO_STRING_OFFSET; + afhi->tags.artist = afhi->techinfo + strlen(afhi->techinfo) + 1; + afhi->tags.title = afhi->tags.artist + strlen(afhi->tags.artist) + 1; + afhi->tags.year = afhi->tags.title + strlen(afhi->tags.title) + 1; + afhi->tags.album = afhi->tags.year + strlen(afhi->tags.year) + 1; + afhi->tags.comment = afhi->tags.album + strlen(afhi->tags.album) + 1; } static unsigned sizeof_chunk_table(struct afh_info *afhi) @@ -446,7 +463,7 @@ int aft_get_row_of_path(const char *path, struct osl_row **row) * Get the row of the audio file table corresponding to the given hash value. * * \param hash The hash value of the desired audio file. - * \param row resul pointer. + * \param row Result pointer. * * \return Standard. */ @@ -891,10 +908,15 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, "%s: %lu\n" /* seconds total */ "%s: %s\n" /* last played time */ "%s: %d\n" /* num_played */ - "%s: %u\n" /* ampplification */ - "%s" /* tag info */ + "%s: %u\n" /* amplification */ "%s: %lu\n" /* chunk time */ - "%s: %lu\n", /* num chunks */ + "%s: %lu\n" /* num chunks */ + "%s: %s\n" /* techinfo */ + "%s: %s\n" /* artist */ + "%s: %s\n" /* title */ + "%s: %s\n" /* year */ + "%s: %s\n" /* album */ + "%s: %s\n", /* comment */ filename_lines, have_score? status_item_list[SI_SCORE] : "", have_score? ": " : "", @@ -913,9 +935,14 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, status_item_list[SI_LAST_PLAYED], last_played_time, status_item_list[SI_NUM_PLAYED], afsi->num_played, status_item_list[SI_AMPLIFICATION], afsi->amp, - afhi->info_string, status_item_list[SI_CHUNK_TIME], tv2ms(&afhi->chunk_tv), - status_item_list[SI_NUM_CHUNKS], afhi->chunks_total + status_item_list[SI_NUM_CHUNKS], afhi->chunks_total, + status_item_list[SI_TECHINFO], afhi->techinfo, + status_item_list[SI_ARTIST], afhi->tags.artist, + status_item_list[SI_TITLE], afhi->tags.title, + status_item_list[SI_YEAR], afhi->tags.year, + status_item_list[SI_ALBUM], afhi->tags.album, + status_item_list[SI_COMMENT], afhi->tags.comment ); if (ret < 0) goto out; @@ -933,124 +960,9 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, free(image_lines); free(filename_lines); out: - free(afhi->info_string); return ret; } -/** - * Write a list of audio-file related status items with empty values. - * - * \param buf Result pointer. - * - * This is used by vss when currently no audio file is open. - */ -void make_empty_status_items(char *buf) -{ - sprintf(buf, - "%s: \n" /* path */ - "%s: \n" /* dirname */ - "%s: \n" /* basename */ - "%s: \n" /* score */ - "%s: \n" /* attributes bitmap */ - "%s: \n" /* attributes txt */ - "%s: \n" /* hash */ - "%s: \n" /* image id */ - "%s: \n" /* image name */ - "%s: \n" /* lyrics id */ - "%s: \n" /* lyrics name */ - "%s: \n" /* bitrate */ - "%s: \n" /* format */ - "%s: \n" /* frequency */ - "%s: \n" /* channels */ - "%s: \n" /* duration */ - "%s: \n" /* seconds total */ - "%s: \n" /* num played */ - "%s: \n" /* last played */ - "%s: \n" /* audio file info */ - "%s: \n" /* taginfo1 */ - "%s: \n" /* taginfo2 */ - "%s: \n" /* amplification */ - , - status_item_list[SI_PATH], - status_item_list[SI_DIRECTORY], - status_item_list[SI_BASENAME], - status_item_list[SI_SCORE], - status_item_list[SI_ATTRIBUTES_BITMAP], - status_item_list[SI_ATTRIBUTES_TXT], - status_item_list[SI_HASH], - status_item_list[SI_IMAGE_ID], - status_item_list[SI_IMAGE_NAME], - status_item_list[SI_LYRICS_ID], - status_item_list[SI_LYRICS_NAME], - status_item_list[SI_BITRATE], - status_item_list[SI_FORMAT], - status_item_list[SI_FREQUENCY], - status_item_list[SI_CHANNELS], - status_item_list[SI_DURATION], - status_item_list[SI_SECONDS_TOTAL], - status_item_list[SI_NUM_PLAYED], - status_item_list[SI_LAST_PLAYED], - status_item_list[SI_AUDIO_FILE_INFO], - status_item_list[SI_TAGINFO1], - status_item_list[SI_TAGINFO2], - status_item_list[SI_AMPLIFICATION] - ); -} - -static void fixup_taginfo(char *begin, char *end) -{ - char *p = begin; - - for (;;) { - p = strchr(p, '\n'); - if (!p) - break; - if (p >= end - 1) - break; - *p = ' '; - p++; - } -} - -/* crap, remove this ASAP. */ -static int fixup_info_string(char *info_string) -{ - char *t1, *t2, *end; - - if (strncmp(info_string, "audio_file_info:", 16)) - return -ERRNO_TO_PARA_ERROR(EINVAL); - t1 = strstr(info_string, "\ntaginfo1:"); - if (!t1) - return -ERRNO_TO_PARA_ERROR(EINVAL); - t2 = strstr(info_string, "\ntaginfo2: "); - if (!t2) - return -ERRNO_TO_PARA_ERROR(EINVAL); - - end = t2 + strlen(t2) + 1; - fixup_taginfo(info_string + 16, t1); - fixup_taginfo(t1 + 10, t2); - fixup_taginfo(t2 + 10, end); - - if (t1 - info_string < 80 && t2 - t1 < 80 && end - t2 < 80) - return 0; - if (t1 - info_string >= 80) { - memmove(info_string + 80, t1, end - t1); - t1 = info_string + 80; - t2 -= t1 - info_string - 80; - end -= t1 - info_string - 80; - } - if (t2 - t1 >= 80) { - memmove(t1 + 80, t2, end - t2); - end -= t2 - t1 - 80; - t2 = t1 + 80; - } - if (end - t2 >= 80) { - t2[78] = '\n'; - t2[79] = '\0'; - } - return 1; -} - static int make_status_items(struct audio_file_data *afd, struct afs_info *afsi, char *path, long score, HASH_TYPE *hash) @@ -1066,26 +978,17 @@ static int make_status_items(struct audio_file_data *afd, .flags = LS_FLAG_FULL_PATH | LS_FLAG_ADMISSIBLE_ONLY, .mode = LS_MODE_VERBOSE, }; - struct para_buffer pb = {.max_size = VERBOSE_LS_OUTPUT_SIZE - 1}; + struct para_buffer pb = {.max_size = SHMMAX - 1}; time_t current_time; int ret; - ret = fixup_info_string(afd->afhi.info_string); - if (ret < 0) { - PARA_WARNING_LOG("ignoring invalid tag info\n"); - afd->afhi.info_string[0] = '\0'; - } else if (ret) - PARA_NOTICE_LOG("truncated overlong tag info\n"); time(¤t_time); - ret = print_list_item(&d, &opts, &pb, current_time); /* frees info string */ - afd->afhi.info_string = NULL; + ret = print_list_item(&d, &opts, &pb, current_time); if (ret < 0) - goto out; - strncpy(afd->verbose_ls_output, pb.buf, VERBOSE_LS_OUTPUT_SIZE); - afd->verbose_ls_output[VERBOSE_LS_OUTPUT_SIZE - 1] = '\0'; -out: - free(pb.buf); - return ret; + return ret; + free(current_status_items); + current_status_items = pb.buf; + return 1; } /** @@ -1157,7 +1060,6 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score, ret = save_afd(afd); err: free(afd->afhi.chunk_table); - free(afd->afhi.info_string); osl_close_disk_object(&chunk_table_obj); return ret; } @@ -1360,7 +1262,6 @@ static int prepare_ls_row(struct osl_row *row, void *ls_opts) } return 1; err: - free(d->afhi.info_string); return ret; } @@ -1924,7 +1825,12 @@ out_free: free(obj.data); if (afhi_ptr) { free(afhi_ptr->chunk_table); - free(afhi_ptr->info_string); + free(afhi_ptr->techinfo); + free(afhi_ptr->tags.artist); + free(afhi_ptr->tags.title); + free(afhi_ptr->tags.year); + free(afhi_ptr->tags.album); + free(afhi_ptr->tags.comment); } /* Stop adding files only on send errors. */ return send_ret; @@ -2471,6 +2377,18 @@ int com_cpsi(int fd, int argc, char * const * const argv) return ret; } +void afs_stat_callback(int fd, __a_unused const struct osl_object *query) +{ + if (current_status_items) + pass_buffer_as_shm(current_status_items, + strlen(current_status_items), &fd); +} + +int send_afs_status(int fd) +{ + return send_callback_request(afs_stat_callback, NULL, send_result, &fd); +} + /* TODO: optionally fix problems by removing offending rows */ static int check_audio_file(struct osl_row *row, void *data) { @@ -2549,6 +2467,8 @@ static void aft_close(void) { osl_close_table(audio_file_table, OSL_MARK_CLEAN); audio_file_table = NULL; + free(current_status_items); + current_status_items = NULL; } /** @@ -2574,7 +2494,7 @@ static int aft_open(const char *dir) } PARA_INFO_LOG("failed to open audio file table\n"); audio_file_table = NULL; - if (ret >= 0 || is_errno(-ret, ENOENT)) + if (ret >= 0 || ret == -OSL_ERRNO_TO_PARA_ERROR(E_OSL_NOENT)) return 1; return ret; }