osx_write fixes.
authorAndre Noll <maan@systemlinux.org>
Thu, 22 Apr 2010 16:01:34 +0000 (18:01 +0200)
committerAndre Noll <maan@systemlinux.org>
Thu, 22 Apr 2010 16:01:34 +0000 (18:01 +0200)
Boy, that was broken since the switch to the buffer tree API
and hasn't obviously seen any testing since then.

That code is rather strange and full of braindead crap. It
should be rewritten eventually. For now, this patch beats it
a little bit into the direction of sanitity.

ggo/osx_write.ggo
osx_write.c

index c73ad2a..33c495a 100644 (file)
@@ -30,5 +30,5 @@ option "numbuffers" n
 you get buffer underruns)"
 
        int typestr="num"
-       default="5"
+       default="20"
        optional
index f3917f6..bcff09f 100644 (file)
@@ -98,8 +98,7 @@ static void fill_buffer(struct osx_buffer *b, short *source, long size)
 {
        float *dest;
 
-       if (b->remaining) /* Non empty buffer, must still be playing */
-               return;
+       assert(b->remaining == 0 || size > 0);
        if (b->size != size) {
                b->buffer = para_realloc(b->buffer, size * sizeof(float));
                b->size = size;
@@ -129,9 +128,14 @@ static OSStatus osx_callback(void * inClientData,
                m = outOutputData->mBuffers[i].mDataByteSize / sizeof(float);
                dest = outOutputData->mBuffers[i].mData;
                while (m > 0) {
-                       if ((n = powd->from->remaining) <= 0) {
-                               PARA_INFO_LOG("buffer underrun\n");
-                               return 0;
+                       n = powd->from->remaining;
+                       if (n <= 0) {
+                               n = powd->from->next->remaining;
+                               if (n <= 0) {
+                                       PARA_INFO_LOG("buffer underrun\n");
+                                       return 0;
+                               }
+                               powd->from = powd->from->next;
                        }
 //                     PARA_INFO_LOG("buf %p: n = %ld, m= %ld\n", powd->from->buffer, n, m);
                        /*
@@ -276,17 +280,6 @@ static void osx_write_close(struct writer_node *wn)
        free(powd);
 }
 
-static int need_new_buffer(struct writer_node *wn)
-{
-       struct private_osx_write_data *powd = wn->private_data;
-
-       if (wn->min_iqs > btr_get_input_queue_size(wn->btrn))
-               return 0;
-       if (powd->to->remaining) /* Non empty buffer, must still be playing */
-               return 0;
-       return 1;
-}
-
 static void osx_write_post_select(__a_unused struct sched *s, struct task *t)
 {
        struct writer_node *wn = container_of(t, struct writer_node, task);
@@ -294,25 +287,25 @@ static void osx_write_post_select(__a_unused struct sched *s, struct task *t)
        struct btr_node *btrn = wn->btrn;
        char *data;
        size_t bytes;
-       int ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+       int ret = 0;
 
-       if (ret <= 0)
-               goto out;
-       if (!need_new_buffer(wn))
-               goto out;
-       btr_merge(btrn, wn->min_iqs);
-       bytes = btr_next_buffer(btrn, &data);
-       fill_buffer(powd->to, (short *)data, bytes / sizeof(short));
-       btr_consume(btrn, bytes);
-       powd->to = powd->to->next;
-       if (!powd->play) {
-               ret = -E_UNIT_START;
-               if (AudioOutputUnitStart(powd->audio_unit))
-                       goto out;
-               powd->play = 1;
+       while (powd->to->remaining <= 0) {
+               ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+               if (ret <= 0)
+                       break;
+               btr_merge(btrn, 8192);
+               bytes = btr_next_buffer(btrn, &data);
+               //PARA_CRIT_LOG("have: %zu\n", bytes);
+               fill_buffer(powd->to, (short *)data, bytes / sizeof(short));
+               btr_consume(btrn, bytes);
+               if (!powd->play) {
+                       ret = -E_UNIT_START;
+                       if (AudioOutputUnitStart(powd->audio_unit))
+                               break;
+                       powd->play = 1;
+               }
+               powd->to = powd->to->next;
        }
-       ret = 1;
-out:
        if (ret < 0)
                btr_remove_node(btrn);
        t->error = ret;