From b680e18c069fef1a03b83a5f906c994e1ab063a1 Mon Sep 17 00:00:00 2001 From: Andre Date: Tue, 6 Jun 2006 01:13:11 +0200 Subject: [PATCH] fix multiple simultaneous writers This broke during the integration of the writers into para_audiod was was noticed only recently. --- alsa_writer.c | 15 ++++++++------- file_writer.c | 18 ++++++++++-------- write.h | 5 +++-- write_common.c | 22 ++++++++++++++-------- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/alsa_writer.c b/alsa_writer.c index 7dab4585..da02ac28 100644 --- a/alsa_writer.c +++ b/alsa_writer.c @@ -170,24 +170,24 @@ static int alsa_write_post_select(struct sched *s, struct writer_node *wn) { struct private_alsa_data *pad = wn->private_data; struct writer_node_group *wng = wn->wng; - size_t frames = *wng->loaded / pad->bytes_per_frame; + size_t frames = (*wng->loaded - wn->written) / pad->bytes_per_frame; snd_pcm_sframes_t ret; - unsigned char *data = (unsigned char*)wng->buf; + unsigned char *data = (unsigned char*)wng->buf + wn->written; struct timeval tv; // PARA_INFO_LOG("%zd frames\n", frames); if (!frames) { if (*wng->input_eof) - ret = *wng->loaded; - return 0; + wn->written = *wng->loaded; + return 1; } if (tv_diff(&s->now, &pad->next_chunk, NULL) < 0) - return 0; + return 1; ret = snd_pcm_writei(pad->handle, data, frames); if (ret == -EPIPE) { PARA_WARNING_LOG("%s", "EPIPE\n"); snd_pcm_prepare(pad->handle); - return 0; + return 1; } if (ret < 0) { PARA_WARNING_LOG("%s", "ALSA ERROR\n"); @@ -196,7 +196,8 @@ static int alsa_write_post_select(struct sched *s, struct writer_node *wn) ms2tv(pad->buffer_time / 4000, &tv); // ms2tv(1, &tv); tv_add(&s->now, &tv, &pad->next_chunk); - return ret * pad->bytes_per_frame; + wn->written += ret * pad->bytes_per_frame; + return 1; } static void alsa_close(struct writer_node *wn) diff --git a/file_writer.c b/file_writer.c index 4a2e0481..1ea95032 100644 --- a/file_writer.c +++ b/file_writer.c @@ -87,19 +87,21 @@ static int file_writer_post_select(struct sched *s, struct writer_node *wn) { struct private_file_writer_data *pfwd = wn->private_data; struct writer_node_group *wng = wn->wng; - int ret = 0; + int ret; if (!pfwd->check_fd) - return 0; - if (!*wng->loaded) - return 0; + return 1; + if (*wng->loaded <= wn->written) + return 1; if (!FD_ISSET(pfwd->fd, &s->wfds)) - return 0; + return 1; // PARA_INFO_LOG("writing %zd\n", *wng->loaded); - ret = write(pfwd->fd, wng->buf, *wng->loaded); + ret = write(pfwd->fd, wng->buf + wn->written, + *wng->loaded - wn->written); if (ret < 0) - ret = -E_FW_WRITE; - return ret; + return -E_FW_WRITE; + wn->written += ret; + return 1; } static void file_writer_close(struct writer_node *wn) diff --git a/write.h b/write.h index 1c4a65fc..79531b50 100644 --- a/write.h +++ b/write.h @@ -31,9 +31,12 @@ struct writer_node { void *private_data; /** send that many bytes in one go */ int chunk_bytes; + /** pointer to the group this node belongs to */ struct writer_node_group *wng; /** the writer-specific configuration of this node */ void *conf; + /** how much of the wng's buffer is already written */ + size_t written; }; /** describes one supported writer */ @@ -102,8 +105,6 @@ struct writer_node_group { unsigned num_writers; /** array of pointers to the corresponding writer nodes */ struct writer_node *writer_nodes; - /** keeps track of how many bytes have been written by each node */ - int *written; /** the maximum of the chunk_bytes values of the writer nodes in this group */ size_t max_chunk_bytes; /** non-zero if end of file was encountered */ diff --git a/write_common.c b/write_common.c index d6472027..acf1d292 100644 --- a/write_common.c +++ b/write_common.c @@ -57,18 +57,26 @@ static void wng_post_select(struct sched *s, struct task *t) return; } if (!i) - min_written = t->ret; + min_written = wn->written; else - min_written = PARA_MIN(min_written, t->ret); + min_written = PARA_MIN(min_written, wn->written); + } +// PARA_INFO_LOG("loaded: %zd, min_written: %zd bytes\n", *g->loaded, min_written); + if (min_written) { + *g->loaded -= min_written; + FOR_EACH_WRITER_NODE(i, g) + g->writer_nodes[i].written -= min_written; } - *g->loaded -= min_written; if (!*g->loaded && *g->input_eof) { g->eof = 1; t->ret = -E_WNG_EOF; - } else - t->ret = 1; - if (*g->loaded && min_written) + return; + } + t->ret = 1; + if (*g->loaded && min_written) { +// PARA_INFO_LOG("moving %zd bytes\n", *g->loaded); memmove(g->buf, g->buf + min_written, *g->loaded); + } } int wng_open(struct writer_node_group *g) @@ -117,7 +125,6 @@ void wng_close(struct writer_node_group *g) struct writer_node *wn = &g->writer_nodes[i]; wn->writer->close(wn); } - free(g->written); free(g->writer_nodes); free(g); } @@ -128,7 +135,6 @@ struct writer_node_group *wng_new(unsigned num_writers) g->num_writers = num_writers; g->writer_nodes = para_calloc(num_writers * sizeof(struct writer_node)); - 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; -- 2.39.5