From 517f7355d8bd904aaa6d75693d2344c54a323df7 Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandre.savard@savoirfairelinux.net>
Date: Mon, 19 Oct 2009 10:23:48 -0400
Subject: [PATCH] [#2309] Open/close pulseaudio connections in
 startStream/stopStream

The connection to pulseaudio are established only when Tone, DTMF, or a new call is active
---
 .../src/audio/pulseaudio/pulselayer.cpp       | 111 ++++++++++++------
 .../src/audio/pulseaudio/pulselayer.h         |   2 +-
 sflphone-common/src/managerimpl.cpp           |   4 +-
 3 files changed, 79 insertions(+), 38 deletions(-)

diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
index 88569e918d..43656b34d5 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
@@ -100,9 +100,11 @@ PulseLayer::closeLayer (void)
         pa_threaded_mainloop_stop (m);
     }
 
-    playback->disconnectStream();
+    // playback->disconnectStream();
+    closePlaybackStream();
 
-    record->disconnectStream();
+    // record->disconnectStream();
+    closeCaptureStream();
 
     if (context) {
         pa_context_disconnect (context);
@@ -166,7 +168,6 @@ void PulseLayer::context_state_callback (pa_context* c, void* user_data)
         case PA_CONTEXT_READY:
             pulse->createStreams (c);
             _debug ("Connection to PulseAudio server established\n");
-
             break;
 
         case PA_CONTEXT_TERMINATED:
@@ -187,17 +188,9 @@ bool PulseLayer::disconnectPulseAudioServer (void)
 {
     _debug (" PulseLayer::disconnectPulseAudioServer( void ) \n");
 
-    if (playback) {
-        // playback->disconnectStream();
-        delete playback;
-        playback=NULL;
-    }
-
-    if (record) {
-        // record->disconnectStream();
-        delete record;
-        record=NULL;
-    }
+    closePlaybackStream();
+    
+    closeCaptureStream();
 
     if (!playback && !record)
         return true;
@@ -208,7 +201,7 @@ bool PulseLayer::disconnectPulseAudioServer (void)
 
 bool PulseLayer::createStreams (pa_context* c)
 {
-    _debug ("PulseLayer::createStreams \n");
+    _debug ("--------------------------------- PulseLayer::createStreams ---------------------\n");
 
     PulseLayerType * playbackParam = new PulseLayerType();
     playbackParam->context = c;
@@ -221,9 +214,9 @@ bool PulseLayer::createStreams (pa_context* c)
     playback->connectStream();
     pa_stream_set_write_callback(playback->pulseStream(), audioCallback, this);
     pa_stream_set_overflow_callback(playback->pulseStream(), playback_overflow_callback, this);
-    pa_stream_set_underflow_callback(playback->pulseStream(), playback_underflow_callback, this);
-    pa_stream_set_suspended_callback(playback->pulseStream(), stream_suspended_callback, this);
-    pa_stream_set_moved_callback(playback->pulseStream(), stream_moved_callback, this);
+    // pa_stream_set_underflow_callback(playback->pulseStream(), playback_underflow_callback, this);
+    // pa_stream_set_suspended_callback(playback->pulseStream(), stream_suspended_callback, this);
+    // pa_stream_set_moved_callback(playback->pulseStream(), stream_moved_callback, this);
     delete playbackParam;
 
     PulseLayerType * recordParam = new PulseLayerType();
@@ -236,8 +229,8 @@ bool PulseLayer::createStreams (pa_context* c)
     record = new AudioStream (recordParam);
     record->connectStream();
     pa_stream_set_read_callback (record->pulseStream() , audioCallback, this);
-    pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this);
-    pa_stream_set_moved_callback(record->pulseStream(), stream_moved_callback, this);
+    // pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this);
+    // pa_stream_set_moved_callback(record->pulseStream(), stream_moved_callback, this);
     delete recordParam;
 
     pa_threaded_mainloop_signal (m , 0);
@@ -254,20 +247,23 @@ bool PulseLayer::openDevice (int indexIn UNUSED, int indexOut UNUSED, int sample
     _audioSampleRate = sampleRate;
     _frameSize = frameSize;
 
+    /*
     m = pa_threaded_mainloop_new();
     assert (m);
-
     if (pa_threaded_mainloop_start (m) < 0) {
         _debug ("Failed starting the mainloop\n");
     }
+    */
 
+    /*
     // Instanciate a context
     if (! (context = pa_context_new (pa_threaded_mainloop_get_api (m) , "SFLphone")))
         _debug ("Error while creating the context\n");
 
     assert (context);
+    */
 
-    connectPulseAudioServer();
+    // connectPulseAudioServer();
 
     // startStream();
 
@@ -280,10 +276,18 @@ bool PulseLayer::openDevice (int indexIn UNUSED, int indexOut UNUSED, int sample
 
 void PulseLayer::closeCaptureStream (void)
 {
+    if (record) {
+	delete record;
+	record=NULL;
+    }
 }
 
 void PulseLayer::closePlaybackStream (void)
 {
+    if (playback) {
+	delete playback;
+	playback=NULL;
+    }
 }
 
 int PulseLayer::canGetMic()
@@ -304,16 +308,36 @@ int PulseLayer::getMic (void *buffer, int toCopy)
 
 void PulseLayer::startStream (void)
 {
-   
+    // connectPulseAudioServer();
 
     if(!is_started) {
 
 	_debug ("------------------------ PulseLayer::Start stream ---------------\n");
 
+	if (!m) {
+	    m = pa_threaded_mainloop_new();
+	    assert (m);
+	
+	    if (pa_threaded_mainloop_start (m) < 0) {
+		_debug ("Failed starting the mainloop\n");
+	    }
+	}
+
+	if (!context) {
+
+	    // Instanciate a context
+	    if (! (context = pa_context_new (pa_threaded_mainloop_get_api (m) , "SFLphone")))
+		_debug ("Error while creating the context\n");
+	    
+	    assert (context);
+	}
+
 	_urgentRingBuffer.flush();
 
 	_mainBuffer.flushAllBuffers();
 
+	connectPulseAudioServer();
+
 	// pa_threaded_mainloop_lock (m);
 
 	// pa_stream_cork (playback->pulseStream(), 0, NULL, NULL);
@@ -321,6 +345,8 @@ void PulseLayer::startStream (void)
 
 	// pa_threaded_mainloop_unlock (m);
 
+	// createStreams(context);
+
 	is_started = true;
     }
 
@@ -340,6 +366,11 @@ PulseLayer::stopStream (void)
 	flushMain();
 	flushUrgent();
 
+	// closeCaptureStream();
+	// closePlaybackStream();
+
+	disconnectPulseAudioServer();
+
 	// pa_threaded_mainloop_lock (m);
 	
 	// pa_stream_cork (playback->pulseStream(), 1, NULL, NULL);
@@ -347,6 +378,18 @@ PulseLayer::stopStream (void)
 
 	// pa_threaded_mainloop_unlock (m);
 
+	if (context) {
+	    pa_context_disconnect (context);
+	    pa_context_unref (context);
+	    context = NULL;
+	}
+
+	if (m) {
+	    pa_threaded_mainloop_free (m);
+	    m = NULL;
+	}
+	
+
 	is_started = false;
 
     }
@@ -368,23 +411,11 @@ void PulseLayer::overflow (pa_stream* s, void* userdata UNUSED)
     pa_stream_trigger (s, NULL, NULL);
 }
 
-void PulseLayer::stream_suspended_callback (pa_stream *s, void *userdata UNUSED)
-{
-
-}
 
 void PulseLayer::processData (void)
 {
-
-    // Handle the mic
-    // We check if the stream is ready
-    if ( (record->pulseStream()) && (pa_stream_get_state (record->pulseStream()) == PA_STREAM_READY))
-        readFromMic();
-
-    // _debug("PulseLayer::processData() playback->pulseStream() \n");
-
     // Handle the data for the speakers
-    if ( (playback->pulseStream()) && (pa_stream_get_state (playback->pulseStream()) == PA_STREAM_READY)) {
+    if ( playback &&(playback->pulseStream()) && (pa_stream_get_state (playback->pulseStream()) == PA_STREAM_READY)) {
 
         // If the playback buffer is full, we don't overflow it; wait for it to have free space
         if (pa_stream_writable_size (playback->pulseStream()) == 0)
@@ -392,6 +423,14 @@ void PulseLayer::processData (void)
 
         writeToSpeaker();
     }
+
+
+    // Handle the mic
+    // We check if the stream is ready
+    if ( record &&(record->pulseStream()) && (pa_stream_get_state (record->pulseStream()) == PA_STREAM_READY))
+        readFromMic();
+
+
 }
 
 void PulseLayer::writeToSpeaker (void)
diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.h b/sflphone-common/src/audio/pulseaudio/pulselayer.h
index cdd3096b8c..5056b8231e 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.h
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.h
@@ -78,7 +78,7 @@ class PulseLayer : public AudioLayer {
     static void underflow ( pa_stream* s, void* userdata );
     static void stream_state_callback( pa_stream* s, void* user_data );	
     static void context_state_callback( pa_context* c, void* user_data );
-    static void stream_suspended_callback ( pa_stream* s, void* userdata );	
+    // static void stream_suspended_callback ( pa_stream* s, void* userdata );	
 
     bool isCaptureActive (void){return true;}
 
diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp
index ce0ec378ea..4055a143f1 100644
--- a/sflphone-common/src/managerimpl.cpp
+++ b/sflphone-common/src/managerimpl.cpp
@@ -428,7 +428,8 @@ ManagerImpl::hangupCall (const CallID& call_id)
     int nbCalls = getCallList().size();
 
     audiolayer = getAudioDriver();
-    // stop streamx
+
+    // stop streams
     if (! (nbCalls >= 1))
     {
 	_debug("    hangupCall: stop audio stream, ther is only %i call(s) remaining\n", nbCalls);
@@ -3149,6 +3150,7 @@ void ManagerImpl::switchAudioManager (void)
 
         default:
             _debug ("Error: audio layer unknown\n");
+	    break;
     }
 
     _audiodriver->setErrorMessage (-1);
-- 
GitLab