X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=afs.c;h=41ef1e21b126968dd7d7fe9bdf8a11f964a28782;hp=bbd68d2fc2f1f42e4d0944d800f94405db862128;hb=f3ebfd3dcb117f1c4a91c2c9f08d8ed710ee3907;hpb=b2917b2a0a68f84da34e7435ad697d798a0260da diff --git a/afs.c b/afs.c index bbd68d2f..41ef1e21 100644 --- a/afs.c +++ b/afs.c @@ -18,14 +18,15 @@ /** \file afs.c audio file sending functions * - * This contains the audio sending part of para_server which is independent - * of the current audio format, database tool and of the activated senders. + * This contains the audio sending part of para_server which is independent of + * the current audio format, audio file selector and of the activated senders. */ +#include "server.h" #include /* gettimeofday */ #include "server.cmdline.h" #include "db.h" -#include "server.h" +#include "afh.h" #include "afs.h" #include "send.h" #include "error.h" @@ -38,24 +39,27 @@ static struct timeval data_send_barrier; static struct timeval eof_barrier; extern struct misc_meta_data *mmd; -extern struct audio_file_selector dblist[]; +extern struct audio_file_selector selectors[]; extern struct sender senders[]; extern struct gengetopt_args_info conf; static FILE *audio_file = NULL; #if 1 - void mp3_init(void *); + void mp3_init(struct audio_format_handler *); #endif #ifdef HAVE_OGGVORBIS - void ogg_init(void *); + void ogg_init(struct audio_format_handler *); +#endif +#ifdef HAVE_FAAD + void aac_afh_init(struct audio_format_handler *); #endif /** * the list of supported audio formats */ -struct audio_format afl[] = { +static struct audio_format_handler afl[] = { #if 1 { .name = "mp3", @@ -67,12 +71,18 @@ struct audio_format afl[] = { .name = "ogg", .init = ogg_init, }, +#endif +#ifdef HAVE_FAAD + { + .name = "aac", + .init = aac_afh_init, + }, #endif { .name = NULL, } }; - +#define FOR_EACH_AUDIO_FORMAT(i) for (i = 0; afl[i].name; i++) /** * check if audio file sender is playing @@ -150,7 +160,7 @@ void afs_init(void) afl[i].init(&afl[i]); } ms2tv(conf.announce_time_arg, &announce_tv); - PARA_INFO_LOG("announce timeval: %lu:%lu\n", announce_tv.tv_sec, announce_tv.tv_usec); + PARA_INFO_LOG("announce timeval: %lums\n", tv2ms(&announce_tv)); for (i = 0; senders[i].name; i++) { PARA_NOTICE_LOG("initializing %s sender\n", senders[i].name); senders[i].init(&senders[i]); @@ -165,25 +175,30 @@ static int get_file_info(int i) &mmd->chunks_total, &mmd->seconds_total); } -/* +/** * guess the audio format judging from filename + * * \param name the filename * * \return This function returns -1 if it has no idea what kind of audio * file this might be. Otherwise the (non-negative) number of the audio format * is returned. */ -static int guess_audio_format(const char *name) +int guess_audio_format(const char *name) { - - int i, len1 = strlen(name), len2; - - for (i = 0; afl[i].name; i++) { - len2 = strlen(afl[i].name); - if (len1 < len2) - continue; - if (!strncasecmp(name + (len1 - len2), afl[i].name, len2)) { - PARA_DEBUG_LOG("might be %s\n", afl[i].name); + int i,j, len = strlen(name); + + FOR_EACH_AUDIO_FORMAT(i) { + for (j = 0; afl[i].suffixes[j]; j++) { + const char *p = afl[i].suffixes[j]; + int plen = strlen(p); + if (len < plen + 1) + continue; + if (name[len - plen - 1] != '.') + continue; + if (strcasecmp(name + len - plen, p)) + continue; + PARA_DEBUG_LOG("might be %s\n", audio_format_name(i)); return i; } } @@ -194,7 +209,7 @@ static int get_audio_format(int omit) { int i; - for (i = 0; afl[i].name; i++) { + FOR_EACH_AUDIO_FORMAT(i) { if (i == omit || !afl[i].get_file_info) continue; rewind(audio_file); @@ -233,7 +248,7 @@ static int update_mmd(void) static void get_song(void) { - char **sl = dblist[mmd->dbt_num].get_audio_file_list(10); + char **sl = selectors[mmd->selector_num].get_audio_file_list(10); int i; if (!sl) @@ -253,8 +268,8 @@ static void get_song(void) continue; } mmd->num_played++; - if (dblist[mmd->dbt_num].update_audio_file) - dblist[mmd->dbt_num].update_audio_file(sl[i]); + if (selectors[mmd->selector_num].update_audio_file) + selectors[mmd->selector_num].update_audio_file(sl[i]); PARA_DEBUG_LOG("%s", "success\n"); mmd->new_afs_status_flags &= (~AFS_NEXT); gettimeofday(&now, NULL); @@ -313,7 +328,7 @@ static struct timeval *afs_compute_timeout(void) if (chk_barrier("eof", &now, &eof_barrier, &the_timeout, 1) < 0) return &the_timeout; if (chk_barrier("data send", &now, &data_send_barrier, - &the_timeout, 1) < 0) + &the_timeout, 1) < 0) return &the_timeout; if (mmd->audio_format < 0 || !afs_playing() || !audio_file) return NULL; @@ -327,7 +342,7 @@ static struct timeval *afs_compute_timeout(void) return &the_timeout; } -static void afs_eof(struct audio_format *af) +static void afs_eof(struct audio_format_handler *af) { struct timeval now; int i; @@ -353,13 +368,50 @@ static void afs_eof(struct audio_format *af) free(tmp); tmp = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_DBINFO1], status_item_list[SI_DBINFO2], status_item_list[SI_DBINFO3]); - strcpy(mmd->dbinfo, tmp); + strcpy(mmd->selector_info, tmp); free(tmp); mmd->filename[0] = '\0'; mmd->size = 0; mmd->events++; } +/** + * get the header and of the current audio file + * + * \param header_len the length of the header is stored here + * + * \return a pointer to a buffer containing the header, or NULL, if no audio + * file is selected or if the current audio format does not need special header + * treamtment. + * + */ +char *afs_get_header(int *header_len) +{ + *header_len = 0; + if (mmd->audio_format < 0) + return NULL; + if (!afl[mmd->audio_format].get_header_info) + return NULL; + return afl[mmd->audio_format].get_header_info(header_len); +} +const char *supported_audio_formats(void) +{ + return SUPPORTED_AUDIO_FORMATS; +} + +/** + * get the chunk time of the current audio file + * + * \return a pointer to a struct containing the chunk time, or NULL, + * if currently no audio file is selected. + */ +struct timeval *afs_chunk_time(void) +{ + if (mmd->audio_format < 0) + return NULL; + return &afl[mmd->audio_format].chunk_tv; +} + /** * compute the timeout for para_server's main select-loop * @@ -379,7 +431,7 @@ static void afs_eof(struct audio_format *af) */ struct timeval *afs_preselect(void) { - struct audio_format *af = NULL; + struct audio_format_handler *af = NULL; int i, format; struct timeval *ret; again: @@ -398,10 +450,9 @@ again: senders[i].shutdown_clients(); if (af) { struct timeval now; - if (!afs_paused() || mmd->chunks_sent) { - gettimeofday(&now, NULL); + gettimeofday(&now, NULL); + if (!afs_paused() || mmd->chunks_sent) tv_add(&af->eof_tv, &now, &eof_barrier); - } if (afs_repos()) tv_add(&now, &announce_tv, &data_send_barrier); if (mmd->new_afs_status_flags & AFS_NOMORE) @@ -415,7 +466,7 @@ again: mmd->new_afs_status_flags &= ~(AFS_REPOS); mmd->current_chunk = mmd->repos_request; } - ret = afs_compute_timeout(); + ret = afs_compute_timeout(); if (!ret && !audio_file && afs_playing() && !(mmd->new_afs_status_flags & AFS_NOMORE)) { PARA_DEBUG_LOG("%s", "ready and playing, but no audio file\n"); @@ -441,7 +492,7 @@ again: void afs_send_chunk(void) { int i; - struct audio_format *af; + struct audio_format_handler *af; char *buf; ssize_t ret; struct timeval now, due; @@ -453,8 +504,13 @@ void afs_send_chunk(void) afs_next_chunk_time(&due); if (tv_diff(&due, &now, NULL) > 0) return; + if (chk_barrier("eof", &now, &eof_barrier, &due, 1) < 0) + return; + if (chk_barrier("data send", &now, &data_send_barrier, + &due, 1) < 0) + return; buf = af->read_chunk(mmd->current_chunk, &ret); - mmd->new_afs_status_flags &= ~(AFS_NEXT | AFS_REPOS); + mmd->new_afs_status_flags &= ~AFS_REPOS; if (!buf) { if (ret < 0) mmd->new_afs_status_flags = AFS_NEXT; @@ -471,8 +527,7 @@ void afs_send_chunk(void) mmd->events++; } for (i = 0; senders[i].name; i++) - senders[i].send(af, mmd->current_chunk, - mmd->chunks_sent, buf, ret); + senders[i].send(mmd->current_chunk, mmd->chunks_sent, buf, ret); mmd->new_afs_status_flags |= AFS_PLAYING; mmd->chunks_sent++; mmd->current_chunk++;