From 9337bed6e84a4068e750fb6597646b45778eeba7 Mon Sep 17 00:00:00 2001 From: Andre Date: Mon, 5 Jun 2006 22:51:43 +0200 Subject: [PATCH 1/1] simplify writer node group It's not neccessary to register a task for each writer in the wng. So use only one task for the wng that calls the writer's pre_select() and post_select(). --- alsa_writer.c | 26 +++++------- audiod.c | 1 - file_writer.c | 30 ++++++------- write.c | 2 - write.h | 111 ++++++++++++++++++++++++------------------------- write_common.c | 33 ++++++++------- 6 files changed, 97 insertions(+), 106 deletions(-) diff --git a/alsa_writer.c b/alsa_writer.c index d13ea3a8..7dab4585 100644 --- a/alsa_writer.c +++ b/alsa_writer.c @@ -146,16 +146,15 @@ static int alsa_open(struct writer_node *w) PARA_ERROR_LOG("%s\n", "failed to set nonblock mode"); return period_size * pad->bytes_per_frame; } -static void alsa_write_pre_select(struct sched *s, struct task *t) + +static int alsa_write_pre_select(struct sched *s, struct writer_node *wn) { - struct writer_node *wn = t->private_data; struct private_alsa_data *pad = wn->private_data; struct writer_node_group *wng = wn->wng; struct timeval diff; - t->ret = 1; if (*wng->loaded < pad->bytes_per_frame) - return; + return 1; if (tv_diff(&s->now, &pad->next_chunk, &diff) < 0) { if (tv_diff(&s->timeout, &diff, NULL) > 0) s->timeout = diff; @@ -163,12 +162,12 @@ static void alsa_write_pre_select(struct sched *s, struct task *t) s->timeout.tv_sec = 0; s->timeout.tv_usec = 1; } + return 1; // PARA_INFO_LOG("timeout: %lu\n", tv2ms(&s->timeout)); } -static void alsa_write_post_select(struct sched *s, struct task *t) +static int alsa_write_post_select(struct sched *s, struct writer_node *wn) { - struct writer_node *wn = t->private_data; struct private_alsa_data *pad = wn->private_data; struct writer_node_group *wng = wn->wng; size_t frames = *wng->loaded / pad->bytes_per_frame; @@ -176,31 +175,28 @@ static void alsa_write_post_select(struct sched *s, struct task *t) unsigned char *data = (unsigned char*)wng->buf; struct timeval tv; - t->ret = 0; // PARA_INFO_LOG("%zd frames\n", frames); if (!frames) { if (*wng->input_eof) - t->ret = *wng->loaded; - return; + ret = *wng->loaded; + return 0; } if (tv_diff(&s->now, &pad->next_chunk, NULL) < 0) - return; + return 0; ret = snd_pcm_writei(pad->handle, data, frames); if (ret == -EPIPE) { PARA_WARNING_LOG("%s", "EPIPE\n"); snd_pcm_prepare(pad->handle); - return; + return 0; } if (ret < 0) { PARA_WARNING_LOG("%s", "ALSA ERROR\n"); - t->ret = -E_ALSA_WRITE; - return; + return -E_ALSA_WRITE; } ms2tv(pad->buffer_time / 4000, &tv); // ms2tv(1, &tv); tv_add(&s->now, &tv, &pad->next_chunk); - t->ret = ret * pad->bytes_per_frame; -// PARA_INFO_LOG("ret: %d, frames: %zd\n", t->ret, frames); + return ret * pad->bytes_per_frame; } static void alsa_close(struct writer_node *wn) diff --git a/audiod.c b/audiod.c index 54863cb6..0f8fb1a7 100644 --- a/audiod.c +++ b/audiod.c @@ -737,7 +737,6 @@ static void open_writers(int slot_num) for (i = 0; i < a->num_writers; i++) { s->wng->writer_nodes[i].conf = a->writer_conf[i]; s->wng->writer_nodes[i].writer = a->writers[i]; - sprintf(s->wng->writer_nodes[i].task.status, "writer_node"); } ret = wng_open(s->wng); if (ret < 0) { diff --git a/file_writer.c b/file_writer.c index 9145ef9f..4a2e0481 100644 --- a/file_writer.c +++ b/file_writer.c @@ -68,42 +68,38 @@ static int file_writer_write(char *data, size_t nbytes, struct writer_node *wn) return ret; } -static void file_writer_pre_select(struct sched *s, struct task *t) +static int file_writer_pre_select(struct sched *s, struct writer_node *wn) { - struct writer_node *wn = t->private_data; struct private_file_writer_data *pfwd = wn->private_data; struct writer_node_group *wng = wn->wng; -// PARA_INFO_LOG("task %p check_fd: %d\n", t, pfwd->check_fd); pfwd->check_fd = 0; - t->ret = -E_FW_NO_FILE; if (pfwd->fd <= 0) - return; - t->ret = 0; + return -E_FW_NO_FILE; if (!*wng->loaded) - return; - t->ret = 1; + return 1; para_fd_set(pfwd->fd, &s->wfds, &s->max_fileno); pfwd->check_fd = 1; + return 1; } -static void file_writer_post_select(struct sched *s, struct task *t) +static int file_writer_post_select(struct sched *s, struct writer_node *wn) { - struct writer_node *wn = t->private_data; struct private_file_writer_data *pfwd = wn->private_data; struct writer_node_group *wng = wn->wng; + int ret = 0; - t->ret = 0; if (!pfwd->check_fd) - return; + return 0; if (!*wng->loaded) - return; + return 0; if (!FD_ISSET(pfwd->fd, &s->wfds)) - return; + return 0; // PARA_INFO_LOG("writing %zd\n", *wng->loaded); - t->ret = write(pfwd->fd, wng->buf, *wng->loaded); - if (t->ret < 0) - t->ret = -E_FW_WRITE; + ret = write(pfwd->fd, wng->buf, *wng->loaded); + if (ret < 0) + ret = -E_FW_WRITE; + return ret; } static void file_writer_close(struct writer_node *wn) diff --git a/write.c b/write.c index fc50040a..89d79d13 100644 --- a/write.c +++ b/write.c @@ -150,8 +150,6 @@ static struct writer_node_group *check_args(void) if (!wng->writer_nodes[i].conf) goto out; wng->writer_nodes[i].writer = &writers[writer_num]; - sprintf(wng->writer_nodes[i].task.status, "%s", - writer_names[writer_num]); } ret = 1; out: diff --git a/write.h b/write.h index cc24d359..1c4a65fc 100644 --- a/write.h +++ b/write.h @@ -26,12 +26,11 @@ enum writer_enum {WRITER_ENUM}; */ struct writer_node { /** points to the writer structure associated with this node */ - struct writer *writer; + struct writer *writer; /* FIXME: Should better be only the number */ /** writer-specific data */ void *private_data; /** send that many bytes in one go */ int chunk_bytes; - struct task task; struct writer_node_group *wng; /** the writer-specific configuration of this node */ void *conf; @@ -39,60 +38,60 @@ struct writer_node { /** describes one supported writer */ struct writer { -/** - * the init function of the writer - * - * It must fill in all other function pointers of the given - * writer structure. - * - */ -void (*init)(struct writer *w); -/** - * - * - * the command line parser of the writer - * - * It should check whether the command line options given by \a options are - * valid. On success, it should return a pointer to the writer-specific - * configuration data determined by \a options. Note that this might be called - * more than once with different values of \a options. - * - */ - void * (*parse_config)(char *options); -/** - * - * open one instance of this writer - * - * This function should perform any work necessary to write the incoming - * stream. If To this aim, it may allocate its private data structure and store - * a pointer to that structure via the given writer_node paramenter. - */ -int (*open)(struct writer_node *); -/** - * - * write a chunk of audio data - * - * This is called from the driving application whenever a data block of \a - * chunk_bytes is available. It must return the number of bytes consumed from - * \a data on success, and negative on errors. - * - */ -int (*write)(char *data, size_t nbytes, struct writer_node *); -void (*pre_select)(struct sched *s, struct task *t); -void (*post_select)(struct sched *s, struct task *t); -/** - * close one instance of the writer - * - * This function is assumed to succeed. - */ -void (*close)(struct writer_node *); -/** - * shutdown the writer - * - * This is a optional function pointer used for cleaning - * up. - */ -void (*shutdown)(struct writer_node *); + /** + * the init function of the writer + * + * It must fill in all other function pointers of the given + * writer structure. + * + */ + void (*init)(struct writer *w); + /** + * + * + * the command line parser of the writer + * + * It should check whether the command line options given by \a options are + * valid. On success, it should return a pointer to the writer-specific + * configuration data determined by \a options. Note that this might be called + * more than once with different values of \a options. + * + */ + void * (*parse_config)(char *options); + /** + * + * open one instance of this writer + * + * This function should perform any work necessary to write the incoming + * stream. If To this aim, it may allocate its private data structure and store + * a pointer to that structure via the given writer_node paramenter. + */ + int (*open)(struct writer_node *); + /** + * + * write a chunk of audio data + * + * This is called from the driving application whenever a data block of \a + * chunk_bytes is available. It must return the number of bytes consumed from + * \a data on success, and negative on errors. + * + */ + int (*write)(char *data, size_t nbytes, struct writer_node *); + int (*pre_select)(struct sched *s, struct writer_node *wn); + int (*post_select)(struct sched *s, struct writer_node *wn); + /** + * close one instance of the writer + * + * This function is assumed to succeed. + */ + void (*close)(struct writer_node *); + /** + * shutdown the writer + * + * This is a optional function pointer used for cleaning + * up. + */ + void (*shutdown)(struct writer_node *); }; /** diff --git a/write_common.c b/write_common.c index 4350c9f1..d6472027 100644 --- a/write_common.c +++ b/write_common.c @@ -28,7 +28,22 @@ const char *writer_names[] ={WRITER_NAMES}; struct writer writers[NUM_SUPPORTED_WRITERS] = {WRITER_ARRAY}; -static void wng_post_select(__a_unused struct sched *s, struct task *t) +static void wng_pre_select(__a_unused struct sched *s, struct task *t) +{ + struct writer_node_group *g = t->private_data; + int i; + + FOR_EACH_WRITER_NODE(i, g) { + struct writer_node *wn = &g->writer_nodes[i]; + t->ret = wn->writer->pre_select(s, wn); + if (t->ret < 0) { + g->eof = 1; + return; + } + } +} + +static void wng_post_select(struct sched *s, struct task *t) { struct writer_node_group *g = t->private_data; int i; @@ -36,7 +51,7 @@ static void wng_post_select(__a_unused struct sched *s, struct task *t) FOR_EACH_WRITER_NODE(i, g) { struct writer_node *wn = &g->writer_nodes[i]; - t->ret = wn->task.ret; + t->ret = wn->writer->post_select(s, wn); if (t->ret < 0) { g->eof = 1; return; @@ -70,10 +85,6 @@ int wng_open(struct writer_node_group *g) goto err_out; wn->chunk_bytes = ret; g->max_chunk_bytes = PARA_MAX(g->max_chunk_bytes, ret); - wn->task.pre_select = wn->writer->pre_select; - wn->task.post_select = wn->writer->post_select; - wn->task.private_data = wn; - register_task(&wn->task); } sprintf(g->task.status, "%s", "writer node group"); g->eof = 0; @@ -82,7 +93,6 @@ err_out: unregister_task(&g->task); while (i > 0) { struct writer_node *wn = &g->writer_nodes[--i]; - unregister_task(&wn->task); wn->writer->close(wn); } g->num_writers = 0; @@ -92,12 +102,6 @@ err_out: void wng_unregister(struct writer_node_group *g) { - int i; - - FOR_EACH_WRITER_NODE(i, g) { - struct writer_node *wn = &g->writer_nodes[i]; - unregister_task(&wn->task); - } unregister_task(&g->task); g->eof = 1; } @@ -127,6 +131,7 @@ struct writer_node_group *wng_new(unsigned num_writers) g->written = para_calloc(num_writers * sizeof(size_t)); g->task.private_data = g; g->task.post_select = wng_post_select; + g->task.pre_select = wng_pre_select; return g; } @@ -174,8 +179,6 @@ struct writer_node_group *setup_default_wng(void) else default_writer = 1; wng->writer_nodes[0].writer = &writers[default_writer]; - sprintf(wng->writer_nodes[0].task.status, "%s", - writer_names[default_writer]); PARA_INFO_LOG("using default writer: %s %p\n", writer_names[default_writer], writers[default_writer].parse_config); wng->writer_nodes[0].conf = writers[default_writer].parse_config(""); -- 2.30.2