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