fix multiple simultaneous writers
authorAndre <maan@p133.(none)>
Mon, 5 Jun 2006 23:13:11 +0000 (01:13 +0200)
committerAndre <maan@p133.(none)>
Mon, 5 Jun 2006 23:13:11 +0000 (01:13 +0200)
This broke during the integration of the writers into para_audiod
was was noticed only recently.

alsa_writer.c
file_writer.c
write.h
write_common.c

index 7dab458..da02ac2 100644 (file)
@@ -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)
index 4a2e048..1ea9503 100644 (file)
@@ -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 1c4a65f..79531b5 100644 (file)
--- 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 */
index d647202..acf1d29 100644 (file)
@@ -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;