[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-dev] supernova: crash on /quit



actually this one
From 7576b4c82243abfc003d20ce78832ee2527c429f Mon Sep 17 00:00:00 2001
Message-Id: <7576b4c82243abfc003d20ce78832ee2527c429f.1356604888.git.tim@xxxxxxxxxx>
From: Tim Blechmann <tim@xxxxxxxxxx>
Date: Thu, 27 Dec 2012 11:37:19 +0100
Subject: [PATCH] supernova: portaudio backend - deactivate_audio should wait
 for stream to finish

Signed-off-by: Tim Blechmann <tim@xxxxxxxxxx>
---
 .../supernova/audio_backend/portaudio_backend.hpp  |   26 +++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/server/supernova/audio_backend/portaudio_backend.hpp b/server/supernova/audio_backend/portaudio_backend.hpp
index b61d9e1..d1dfee9 100644
--- a/server/supernova/audio_backend/portaudio_backend.hpp
+++ b/server/supernova/audio_backend/portaudio_backend.hpp
@@ -20,6 +20,7 @@
 #define _PORTAUDIO_HPP
 
 #include <cstdio>
+#include <boost/thread/barrier.hpp>
 
 #include "portaudio.h"
 #ifdef HAVE_PORTAUDIO_CONFIG_H
@@ -47,7 +48,7 @@ class portaudio_backend:
 
 public:
     portaudio_backend(void):
-        stream(NULL), blocksize_(0)
+        stream(NULL), blocksize_(0), finish_barrier(2)
     {
         int err = Pa_Initialize();
         report_error(err, true);
@@ -166,6 +167,12 @@ public:
         if (opened != paNoError)
             return false;
 
+        PaError finish_cb_set = Pa_SetStreamFinishedCallback(&portaudio_backend::pa_stream_finished, this);
+
+        report_error(finish_cb_set);
+        if (finish_cb_set != paNoError)
+            return false;
+
         input_channels = inchans;
         super::input_samples.resize(inchans);
         output_channels = outchans;
@@ -183,6 +190,9 @@ public:
 
         int err = Pa_CloseStream(stream);
         report_error(err);
+
+        close_condition.wait();
+
         stream = NULL;
     }
 
@@ -210,6 +220,7 @@ public:
         if (audio_is_active()) {
             PaError err = Pa_StopStream(stream);
             report_error(err);
+            finish_barrier.wait();
         }
     }
 
@@ -266,10 +277,23 @@ private:
         return self->perform(input, output, frame_count, time_info, status_flags);
     }
 
+    void stream_finished()
+    {
+        finish_barrier.wait();
+    }
+
+    static void pa_stream_finished(void * user_data)
+    {
+        portaudio_backend * self = static_cast<portaudio_backend*>(user_data);
+        return self->stream_finished();
+    }
+
     PaStream *stream;
     uint32_t blocksize_;
     bool callback_initialized;
     cpu_time_info cpu_time_accumulator;
+
+    boost::barrier finish_barrier;
 };
 
 } /* namespace nova */
-- 
1.7.10.4