From 6160a51e4ca6094656e3d25802c988c466c8d049 Mon Sep 17 00:00:00 2001 From: pierre-luc <pierre-luc@aqra.ca> Date: Fri, 17 Jul 2009 16:23:31 -0400 Subject: [PATCH] [#1805] Remove the old flawed signal mechanism which was failing in some cases. The PulseLayer is now closed after the playback stream was drained. This step is however optional and might be removed if wanted. This step shouldn't be noticeable as the stream is probably already empty when the draining is performed. --- sflphone-common/src/audio/audiostream.cpp | 37 +++++++++++++++++++++-- sflphone-common/src/audio/audiostream.h | 5 +++ sflphone-common/src/audio/pulselayer.cpp | 25 ++++++++++----- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/sflphone-common/src/audio/audiostream.cpp b/sflphone-common/src/audio/audiostream.cpp index 4af1e26c04..877c1327b9 100644 --- a/sflphone-common/src/audio/audiostream.cpp +++ b/sflphone-common/src/audio/audiostream.cpp @@ -56,11 +56,43 @@ AudioStream::connectStream() return true; } +static void success_cb(pa_stream *s, int success, void *userdata) { + + assert(s); + + pa_threaded_mainloop * mainloop = (pa_threaded_mainloop *) userdata; + + pa_threaded_mainloop_signal(mainloop, 0); +} + + +bool +AudioStream::drainStream(void) { + if (_audiostream) { + _debug("Draining stream\n"); + pa_operation * operation; + + pa_threaded_mainloop_lock(_mainloop); + + if ((operation = pa_stream_drain(_audiostream, success_cb, _mainloop))) { + while (pa_operation_get_state(operation) != PA_OPERATION_DONE) { + if (!_context || pa_context_get_state(_context) != PA_CONTEXT_READY || !_audiostream || pa_stream_get_state(_audiostream) != PA_STREAM_READY) { + _debug("Connection died: %s\n", _context ? pa_strerror(pa_context_errno(_context)) : "NULL"); + pa_operation_unref(operation); + break; + } else { + pa_threaded_mainloop_wait(_mainloop); + } + } + } + + pa_threaded_mainloop_unlock(_mainloop); + } +} + bool AudioStream::disconnectStream (void) { - ost::MutexLock guard (_mutex); - _debug ("Destroy audio streams\n"); pa_threaded_mainloop_lock(_mainloop); @@ -95,7 +127,6 @@ AudioStream::stream_state_callback (pa_stream* s, void* user_data) case PA_STREAM_TERMINATED: _debug ("Stream is terminating...\n"); - pa_threaded_mainloop_signal(m, 0); break; case PA_STREAM_READY: diff --git a/sflphone-common/src/audio/audiostream.h b/sflphone-common/src/audio/audiostream.h index 2314d31670..692ed62379 100644 --- a/sflphone-common/src/audio/audiostream.h +++ b/sflphone-common/src/audio/audiostream.h @@ -83,6 +83,11 @@ class AudioStream { */ bool connectStream(); + /** + * Drain the given stream. + */ + bool drainStream(void); + /** * Disconnect the pulseaudio stream */ diff --git a/sflphone-common/src/audio/pulselayer.cpp b/sflphone-common/src/audio/pulselayer.cpp index 39d3ba887d..09d8bcad8a 100644 --- a/sflphone-common/src/audio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulselayer.cpp @@ -51,19 +51,30 @@ bool PulseLayer::closeLayer (void) { _debug ("PulseLayer::closeLayer :: Destroy pulselayer\n"); + + // Commenting the line below will make the + // PulseLayer to close immediately, not + // waiting for the playback buffer to be + // emptied. It should not hurt. + playback->drainStream(); + if(m) { + pa_threaded_mainloop_stop(m); + } + playback->disconnectStream(); record->disconnectStream(); - - pa_threaded_mainloop_lock (m); - pa_threaded_mainloop_wait(m); - if(m) { + + if(context) { pa_context_disconnect (context); pa_context_unref (context); + context = NULL; + } + + if(m) { + pa_threaded_mainloop_free (m); + m = NULL; } - pa_threaded_mainloop_unlock (m); - - pa_threaded_mainloop_free (m); return true; } -- GitLab