diff --git a/sflphone-common/src/audio/audiostream.cpp b/sflphone-common/src/audio/audiostream.cpp index 4af1e26c0416bed42f3663bb3ef61f19d7446578..877c1327b98e525e99142ffb24fb77604e9875a5 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 2314d31670ac28fede04fb0036e9b605210e1a57..692ed623799620d7955a79c4ec340c65de29835b 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 39d3ba887d32ab28d818043428f879ea55078013..09d8bcad8a66eff9a47d18b8440f948aa49bbb94 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; }