From: Andre Date: Wed, 17 May 2006 19:22:59 +0000 (+0200) Subject: major afs cleanup X-Git-Tag: v0.2.14~108 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=8b2c02c8d6255583982e767374d39375b3380c4d;p=paraslash.git major afs cleanup This patch makes afs.c the only user of the audio format handler arry afl[] in order to completely separate audio format handling from audio file sending. This is achieved by providing the new helper functions afs_get_header() and afs_chunk_time(). audio file senders may call these functions without knowledge of struct audio_format. This allows to get rid of the "af" parameter for the pre_select and post_select functions of struct sender. Related to this cleanup is the removal of match_audio_file_name() from db.c which also depended on afl[]. This function was essentially identical to afs.c's guess_audio_format(), so make the latter public and use it from within db.c. --- diff --git a/afs.c b/afs.c index 918c5636..e3b0db55 100644 --- a/afs.c +++ b/afs.c @@ -58,7 +58,7 @@ static FILE *audio_file = NULL; /** * the list of supported audio formats */ -struct audio_format_handler afl[] = { +static struct audio_format_handler afl[] = { #if 1 { .name = "mp3", @@ -81,7 +81,7 @@ struct audio_format_handler afl[] = { .name = NULL, } }; - +#define FOR_EACH_AUDIO_FORMAT(i) for (i = 0; afl[i].name; i++) /** * check if audio file sender is playing @@ -174,25 +174,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; } } @@ -203,7 +208,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); @@ -369,6 +374,39 @@ static void afs_eof(struct audio_format_handler *af) 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); +} + +/** + * 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 * @@ -484,8 +522,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++; diff --git a/afs.h b/afs.h index c34f8817..3725ffa1 100644 --- a/afs.h +++ b/afs.h @@ -130,8 +130,6 @@ struct audio_format_handler { char * (*read_chunk)(long unsigned chunk_num, ssize_t *len); }; -extern struct audio_format_handler afl[]; -#define FOR_EACH_AUDIO_FORMAT(i) for (i = 0; afl[i].name; i++) void afs_init(void); void afs_send_chunk(void); @@ -141,4 +139,6 @@ unsigned int afs_playing(void); unsigned int afs_next(void); unsigned int afs_repos(void); unsigned int afs_paused(void); - +char *afs_get_header(int *header_len); +struct timeval *afs_chunk_time(void); +int guess_audio_format(const char *name); diff --git a/audiod.c b/audiod.c index 8d1d8eb8..e1551617 100644 --- a/audiod.c +++ b/audiod.c @@ -935,6 +935,7 @@ static void close_decoder_if_idle(int slot_num) return; } if (s->write_fd > 0) { + PARA_INFO_LOG("err: %d\n", s->fci->error); PARA_INFO_LOG("slot %d: closing write fd %d\n", slot_num, s->write_fd); close(s->write_fd); diff --git a/db.c b/db.c index cb6f692a..9db622bc 100644 --- a/db.c +++ b/db.c @@ -28,29 +28,6 @@ #include "error.h" #include "string.h" -/* - * return 1 if name matches any supported audio format - */ -static int match_audio_file_name(char *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; - return 1; - } - } - return 0; -} - /** * traverse the given directory recursively * @@ -103,7 +80,7 @@ int find_audio_files(const char *dirname, int (*f)(const char *, const char *)) if (!S_ISREG(m) && !S_ISDIR(m)) /* skip links, sockets, ... */ continue; if (S_ISREG(m)) { /* regular file */ - if (!match_audio_file_name(entry->d_name)) + if (guess_audio_format(entry->d_name) < 0) continue; if (f(dirname, entry->d_name) < 0) goto out; diff --git a/dccp_send.c b/dccp_send.c index 855780e6..546056a0 100644 --- a/dccp_send.c +++ b/dccp_send.c @@ -50,8 +50,8 @@ struct dccp_client { int header_sent; }; -static void dccp_pre_select(__a_unused struct audio_format_handler *af, - int *max_fileno, fd_set *rfds, __a_unused fd_set *wfds) +static void dccp_pre_select( int *max_fileno, fd_set *rfds, + __a_unused fd_set *wfds) { if (listen_fd < 0) return; @@ -59,8 +59,7 @@ static void dccp_pre_select(__a_unused struct audio_format_handler *af, *max_fileno = PARA_MAX(*max_fileno, listen_fd); } -static void dccp_post_select(__a_unused struct audio_format_handler *af, - fd_set *rfds, __a_unused fd_set *wfds) +static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds) { struct dccp_client *dc; int ret; @@ -133,8 +132,7 @@ err_out: return -E_DCCP_WRITE; } -static void dccp_send(__a_unused struct audio_format_handler *af, - long unsigned current_chunk, +static void dccp_send(long unsigned current_chunk, __a_unused long unsigned chunks_sent, const char *buf, size_t len) { struct dccp_client *dc, *tmp; @@ -152,8 +150,8 @@ static void dccp_send(__a_unused struct audio_format_handler *af, } if (!ret) continue; - if (!dc->header_sent && af->get_header_info && current_chunk) { - header_buf = af->get_header_info(&header_len); + if (!dc->header_sent && current_chunk) { + header_buf = afs_get_header(&header_len); if (!header_buf || header_len <= 0) continue; /* header not yet available */ ret = dccp_write(dc->fd, header_buf, header_len); diff --git a/http_send.c b/http_send.c index f9345ace..6aa82e44 100644 --- a/http_send.c +++ b/http_send.c @@ -206,9 +206,8 @@ static int send_queued_packets(struct http_client *hc) return 1; } -static void http_send(__a_unused struct audio_format_handler *af, - long unsigned current_chunk, - __a_unused long unsigned chunks_sent, const char *buf, size_t len) +static void http_send( long unsigned current_chunk, + __a_unused long unsigned chunks_sent, const char *buf, size_t len) { struct http_client *hc, *tmp; int ret; @@ -218,12 +217,10 @@ static void http_send(__a_unused struct audio_format_handler *af, hc->status != HTTP_READY_TO_STREAM) continue; if (hc->status == HTTP_READY_TO_STREAM) { - if (af->get_header_info && current_chunk) { + int hlen; + char *buf = afs_get_header(&hlen); + if (buf && hlen > 0 && current_chunk) { /* need to send header */ - int hlen; - char *buf = af->get_header_info(&hlen); - if (!buf || hlen <= 0) - continue; /* header not yet available */ PARA_INFO_LOG("queueing header: %d\n", hlen); if (queue_packet(hc, buf, hlen) < 0) continue; @@ -267,8 +264,7 @@ static int host_in_access_perm_list(struct http_client *hc) return 0; } -static void http_post_select(__a_unused struct audio_format_handler *af, fd_set *rfds, - fd_set *wfds) +static void http_post_select(fd_set *rfds, fd_set *wfds) { int i = -1, match; struct http_client *hc, *tmp; @@ -347,8 +343,7 @@ err_out: free(hc); } -static void http_pre_select(struct audio_format_handler *af, int *max_fileno, - fd_set *rfds, fd_set *wfds) +static void http_pre_select(int *max_fileno, fd_set *rfds, fd_set *wfds) { struct http_client *hc, *tmp; @@ -373,7 +368,7 @@ static void http_pre_select(struct audio_format_handler *af, int *max_fileno, hc->check_w = 1; break; case HTTP_SENT_OK_MSG: - if (!af || !afs_playing()) + if (!afs_playing()) break; /* wait until server starts playing */ para_fd_set(hc->fd, wfds, max_fileno); hc->check_w = 1; diff --git a/ortp_send.c b/ortp_send.c index 46b3ece7..9d244225 100644 --- a/ortp_send.c +++ b/ortp_send.c @@ -133,27 +133,36 @@ static void ortp_shutdown_targets(void) } } -static int need_extra_header(struct audio_format_handler *af, - long unsigned chunks_sent) +static int need_extra_header(long unsigned current_chunk) { - /* FIXME: No need to compute this on every run */ - int mod = conf.ortp_header_interval_arg / (tv2ms(&af->chunk_tv) + 1); - if (mod && (chunks_sent % mod)) + static struct timeval last_header; + struct timeval now, diff; + + if (!current_chunk) + return 0; + gettimeofday(&now, NULL); + tv_diff(&now, &last_header, &diff); + if (tv2ms(&diff) < conf.ortp_header_interval_arg) return 0; + last_header = now; return 1; } -static void ortp_send(struct audio_format_handler *af, long unsigned current_chunk, - long unsigned chunks_sent, const char *buf, size_t len) +static void ortp_send(long unsigned current_chunk, long unsigned chunks_sent, + const char *buf, size_t len) { struct ortp_target *ot, *tmp; size_t sendbuf_len; int header_len = 0; - int packet_type = ORTP_DATA, stream_type = af && af->get_header_info; /* header stream? */ + int packet_type = ORTP_DATA; char *sendbuf, *header_buf = NULL; + struct timeval *chunk_tv; if (self->status != SENDER_ON) return; + chunk_tv = afs_chunk_time(); + if (!chunk_tv) + return; list_for_each_entry_safe(ot, tmp, &targets, node) { if (!ot->session) { ortp_init_session(ot); @@ -162,18 +171,16 @@ static void ortp_send(struct audio_format_handler *af, long unsigned current_chu } if (!ot->chunk_ts) ot->chunk_ts = rtp_session_time_to_ts(ot->session, - tv2ms(&af->chunk_tv)); + tv2ms(chunk_tv)); // PARA_DEBUG_LOG("len: %d, ts: %lu, ts: %d\n", // len, ot->chunk_ts * chunks_sent, ot->chunk_ts); ot->streaming = 1; } if (list_empty(&targets)) return; - if (stream_type) { - header_buf = af->get_header_info(&header_len); - if (!need_extra_header(af, chunks_sent)) - header_len = 0; - } + header_buf = afs_get_header(&header_len); + if (!need_extra_header(current_chunk)) + header_len = 0; sendbuf_len = ORTP_AUDIO_HEADER_LEN + header_len + len; sendbuf = para_malloc(sendbuf_len); if (!current_chunk) @@ -181,8 +188,8 @@ static void ortp_send(struct audio_format_handler *af, long unsigned current_chu else if (header_len) packet_type = ORTP_HEADER; WRITE_PACKET_TYPE(sendbuf, packet_type); - WRITE_CHUNK_TIME(sendbuf, af->chunk_tv.tv_usec); - WRITE_STREAM_TYPE(sendbuf, stream_type); + WRITE_CHUNK_TIME(sendbuf, chunk_tv->tv_usec); + WRITE_STREAM_TYPE(sendbuf, header_buf? 1 : 0); WRITE_HEADER_LEN(sendbuf, header_len); if (header_len) memcpy(sendbuf + ORTP_AUDIO_HEADER_LEN, header_buf, @@ -290,8 +297,7 @@ success: } } -static void ortp_pre_select(__a_unused struct audio_format_handler *af, - __a_unused int *max_fileno, __a_unused fd_set *rfds, +static void ortp_pre_select(__a_unused int *max_fileno, __a_unused fd_set *rfds, __a_unused fd_set *wfds) { return; diff --git a/send.h b/send.h index f7198ed7..bf1ca111 100644 --- a/send.h +++ b/send.h @@ -45,8 +45,8 @@ struct sender { * command. Of course, \a buf is a pointer to the chunk of data which * should be sent, and \a len is the length of this buffer. */ - void (*send)(struct audio_format_handler *af, long unsigned current_chunk, - long unsigned chunks_sent, const char *buf, size_t len); + void (*send)(long unsigned current_chunk, long unsigned chunks_sent, + const char *buf, size_t len); /** add file descriptors to fd_sets * * The pre_select function of each supported sender is called just before @@ -58,8 +58,7 @@ struct sender { * * \sa select(2) */ - void (*pre_select)(struct audio_format_handler *af, int *max_fileno, fd_set *rfds, - fd_set *wfds); + void (*pre_select)(int *max_fileno, fd_set *rfds, fd_set *wfds); /** * handle the file descriptors which are ready for I/O * @@ -67,7 +66,7 @@ struct sender { * set, this is the hook to check the result and do any I/O on those descriptors * which are ready for reading/writing. */ - void (*post_select)(struct audio_format_handler *af, fd_set *rfds, fd_set *wfds); + void (*post_select)(fd_set *rfds, fd_set *wfds); /** * terminate all connected clients * diff --git a/server.c b/server.c index 56162735..2391e07c 100644 --- a/server.c +++ b/server.c @@ -449,10 +449,7 @@ repeat: continue; if (!senders[i].pre_select) continue; - senders[i].pre_select(mmd->audio_format >= 0? - &afl[mmd->audio_format] : NULL, - &max_fileno, - &rfds, &wfds); + senders[i].pre_select( &max_fileno, &rfds, &wfds); } if (selectors[mmd->selector_num].pre_select) { ret = selectors[mmd->selector_num].pre_select(&rfds, &wfds); @@ -472,9 +469,7 @@ repeat: continue; if (!senders[i].post_select) continue; - senders[i].post_select(mmd->audio_format >= 0? - &afl[mmd->audio_format] : NULL, - &rfds, &wfds); + senders[i].post_select(&rfds, &wfds); } afs_send_chunk(); status_refresh();