]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 't/osx_writer_improvements'
authorAndre Noll <maan@systemlinux.org>
Sun, 25 Nov 2012 13:00:08 +0000 (14:00 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 25 Nov 2012 13:01:44 +0000 (14:01 +0100)
Cooking since 2012-10-30.

9eaa22 osx_write: Check return value of AudioOutputUnitStart().
831db3 osx_write: Be careful when dereferencing the private_data pointer.
97902a osx: Treat writer node as an internal buffer tree node.
1c6fa9 osx_write: Add big fat comment on callback btr node.

NEWS
osx_write.c

diff --git a/NEWS b/NEWS
index 2c05b8f90be044f7070ef5a2a08a589e4d46b58d..69372cc42c4ea40712fe6f5a337840875ddff04b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@
        - Overhaul of the build system: All generated files are now
          written to the "build" directory.
        - The modular mixer API and the alsa mixer.
+       - Minor fixes for the osx writer.
 
 --------------------------------------
 0.4.11 (2012-07-20) "mutual diversity"
index 8dcfb4cd1fcc32082abeae34bdff3a23214a2f20..2894f11eb6672dd5f06fa1f3166f6a77afad7ae0 100644 (file)
@@ -43,9 +43,28 @@ struct private_osx_write_data {
        unsigned sample_format;
        /** Number of channels of the current audio stream. */
        unsigned channels;
-       /** Serializes access to buffer tree nodes. */
+       /**
+        * Serializes access to buffer tree nodes between the writer and
+        * the callback which runs in a different thread.
+        */
        int mutex;
-       /** The btr node of the callback. */
+       /**
+        * The btr node of the callback.
+        *
+        * Although access to the btr node is serialized between the writer and
+        * the callback via the above mutex, this does not stop other buffer
+        * tree nodes, for example the decoder, to race against the osx
+        * callback.
+        *
+        * However, since all operations on buffer tree nodes are local in the
+        * sense that they only affect one level in the buffer tree (i.e.
+        * parent or child nodes, but not the grandparent or the
+        * grandchildren), we may work around this problem by using another
+        * buffer tree node for the callback.
+        *
+        * The writer grabs the mutex in its post_select method and pushes down
+        * the buffers to the callback node.
+        */
        struct btr_node *callback_btrn;
 };
 
@@ -59,10 +78,14 @@ static OSStatus osx_callback(void *cb_arg, __a_unused AudioUnitRenderActionFlags
 {
        int i;
        struct writer_node *wn = cb_arg;
-       struct private_osx_write_data *powd = wn->private_data;
+       struct private_osx_write_data *powd;
        size_t samples_have, samples_want = 0;
 
+       powd = wn->private_data;
        mutex_lock(powd->mutex);
+       powd = wn->private_data;
+       if (!powd || !wn->btrn)
+               goto out;
        /*
         * We fill with zeros if no data was yet written and we do not have
         * enough to fill all buffers.
@@ -266,7 +289,7 @@ static void osx_write_pre_select(struct sched *s, struct task *t)
        }
 
        mutex_lock(powd->mutex);
-       ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+       ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_INTERNAL);
        if (ret < 0)
                drain_delay_nec = need_drain_delay(powd);
        mutex_unlock(powd->mutex);
@@ -295,25 +318,32 @@ static void osx_write_post_select(__a_unused struct sched *s, struct task *t)
                if (ret < 0)
                        goto remove_btrn;
                powd = wn->private_data;
-               AudioOutputUnitStart(powd->audio_unit);
+               ret = -E_UNIT_START;
+               if (AudioOutputUnitStart(powd->audio_unit) != noErr) {
+                       AudioUnitUninitialize(powd->audio_unit);
+                       CloseComponent(powd->audio_unit);
+                       btr_remove_node(&powd->callback_btrn);
+                       goto remove_btrn;
+               }
        }
        mutex_lock(powd->mutex);
-       btr_pushdown(btrn);
-       ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
+       ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_INTERNAL);
+       if (ret > 0)
+               btr_pushdown(btrn);
        if (ret < 0 && need_drain_delay(powd))
                ret = 0;
-       mutex_unlock(powd->mutex);
-
-       if (ret >= 0)
-               goto out;
+       if (ret >= 0) {
+               mutex_unlock(powd->mutex);
+               return;
+       }
        AudioOutputUnitStop(powd->audio_unit);
        AudioUnitUninitialize(powd->audio_unit);
        CloseComponent(powd->audio_unit);
        btr_remove_node(&powd->callback_btrn);
+       mutex_unlock(powd->mutex);
 remove_btrn:
        btr_remove_node(&wn->btrn);
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
-out:
        t->error = ret;
 }