diff --git a/src/audio/audiostream.cpp b/src/audio/audiostream.cpp index 263347a010732e28203a092d51f26937a924ae30..778192643d5ee2ad3b2e2ba8540e2266a8cb370f 100644 --- a/src/audio/audiostream.cpp +++ b/src/audio/audiostream.cpp @@ -79,6 +79,8 @@ AudioStream::stream_state_callback( pa_stream* s, void* user_data UNUSED ) } + + pa_stream* AudioStream::createStream( pa_context* c ) { @@ -100,7 +102,7 @@ AudioStream::createStream( pa_context* c ) attributes->prebuf = 10000; attributes->minreq = 940; pa_stream_connect_playback( s , NULL , attributes, - PA_STREAM_INTERPOLATE_TIMING, + PA_STREAM_START_CORKED, &_volume, NULL); } else if( _streamType == CAPTURE_STREAM ){ diff --git a/src/audio/pulselayer.cpp b/src/audio/pulselayer.cpp index 87d31d988b1ba426103373535fd36d99042f844e..40de7e886fa86a6282b40e5870c402d3af0b4a18 100644 --- a/src/audio/pulselayer.cpp +++ b/src/audio/pulselayer.cpp @@ -30,6 +30,8 @@ static void audioCallback ( pa_stream* s, size_t bytes, void* userdata ) static_cast<PulseLayer*>(userdata)->processData(); } + + PulseLayer::PulseLayer(ManagerImpl* manager) : AudioLayer( manager , PULSEAUDIO ) , context(NULL) @@ -106,7 +108,8 @@ void PulseLayer::context_state_callback( pa_context* c, void* user_data ) break; case PA_CONTEXT_READY: pulse->createStreams( c ); - _debug("Connection to PulseAudio server established\n"); + _debug("Connection to PulseAudio server established\n"); + break; case PA_CONTEXT_TERMINATED: _debug("Context terminated\n"); @@ -130,22 +133,27 @@ void PulseLayer::disconnectPulseAudioServer( void ) delete record; record=NULL; } - void -PulseLayer::createStreams( pa_context* c ) + +void PulseLayer::createStreams( pa_context* c ) { _debug("PulseLayer::createStreams \n"); + playback = new AudioStream(c, PLAYBACK_STREAM, PLAYBACK_STREAM_NAME, _manager->getSpkrVolume()); - pa_stream_set_write_callback( playback->pulseStream() , audioCallback, this); + pa_stream_set_write_callback( playback->pulseStream(), audioCallback, this); //pa_stream_set_overflow_callback( playback->pulseStream() , overflow , this); + // pa_stream_set_suspended_callback( playback->pulseStream(), stream_suspended_callback, this); + record = new AudioStream(c, CAPTURE_STREAM, CAPTURE_STREAM_NAME , _manager->getMicVolume()); pa_stream_set_read_callback( record->pulseStream() , audioCallback, this); //pa_stream_set_underflow_callback( record->pulseStream() , underflow , this); + // pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this); + pa_threaded_mainloop_signal(m , 0); } - bool -PulseLayer::openDevice(int indexIn UNUSED, int indexOut UNUSED, int sampleRate, int frameSize , int stream UNUSED, std::string plugin UNUSED) + +bool PulseLayer::openDevice(int indexIn UNUSED, int indexOut UNUSED, int sampleRate, int frameSize , int stream UNUSED, std::string plugin UNUSED) { _debug("PulseLayer::openDevice \n"); _sampleRate = sampleRate; @@ -170,18 +178,15 @@ PulseLayer::openDevice(int indexIn UNUSED, int indexOut UNUSED, int sampleRate, return true; } - void -PulseLayer::closeCaptureStream( void ) +void PulseLayer::closeCaptureStream( void ) { } - void -PulseLayer::closePlaybackStream( void ) +void PulseLayer::closePlaybackStream( void ) { } - int -PulseLayer::canGetMic() +int PulseLayer::canGetMic() { if( record ) return _micRingBuffer.AvailForGet(); @@ -189,8 +194,7 @@ PulseLayer::canGetMic() return 0; } - int -PulseLayer::getMic(void *buffer, int toCopy) +int PulseLayer::getMic(void *buffer, int toCopy) { if( record ){ return _micRingBuffer.Get(buffer, toCopy, 100); @@ -199,15 +203,14 @@ PulseLayer::getMic(void *buffer, int toCopy) return 0; } - void -PulseLayer::startStream (void) +void PulseLayer::startStream (void) { flushMic(); _debug("PulseLayer::Start stream\n"); pa_threaded_mainloop_lock(m); - pa_stream_cork( playback->pulseStream(), NULL, NULL, NULL); - pa_stream_cork( record->pulseStream(), NULL, NULL, NULL); + pa_stream_cork( playback->pulseStream(), 0, NULL, NULL); + pa_stream_cork( record->pulseStream(), 0, NULL, NULL); pa_threaded_mainloop_unlock(m); @@ -220,8 +223,8 @@ PulseLayer::stopStream (void) pa_stream_flush( playback->pulseStream(), NULL, NULL ); pa_stream_flush( record->pulseStream(), NULL, NULL ); - pa_stream_cork( playback->pulseStream(), NULL, NULL, NULL); - pa_stream_cork( record->pulseStream(), NULL, NULL, NULL); + pa_stream_cork( playback->pulseStream(), 1, NULL, NULL); + pa_stream_cork( record->pulseStream(), 1, NULL, NULL); flushMic(); flushMain(); @@ -230,44 +233,48 @@ PulseLayer::stopStream (void) - void -PulseLayer::underflow ( pa_stream* s UNUSED, void* userdata UNUSED ) +void PulseLayer::underflow ( pa_stream* s UNUSED, void* userdata UNUSED ) { _debug("PulseLayer::Buffer Underflow\n"); } - void -PulseLayer::overflow ( pa_stream* s, void* userdata UNUSED ) +void PulseLayer::overflow ( pa_stream* s, void* userdata UNUSED ) { //PulseLayer* pulse = (PulseLayer*) userdata; pa_stream_drop( s ); pa_stream_trigger( s, NULL, NULL); } - void -PulseLayer::processData( void ) +void PulseLayer::stream_suspended_callback(pa_stream *s, void *userdata UNUSED ) { - // Handle the mic - // We check if the stream is ready - if( (record->pulseStream()) && (pa_stream_get_state( record->pulseStream()) == PA_STREAM_READY) && record) - // _debug("PulseLayer::processData() readFromMic() \n"); - readFromMic(); + +} - // Handle the data for the speakers - if( (playback->pulseStream()) && (pa_stream_get_state( playback->pulseStream()) == PA_STREAM_READY) && playback){ +void PulseLayer::processData( void ) +{ + + _debug("PulseLayer::processData() \n"); + + // 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 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 ) return; - // _debug("PulseLayer::processData() writeToSpeaker()\n"); writeToSpeaker(); } } - void -PulseLayer::writeToSpeaker( void ) +void PulseLayer::writeToSpeaker( void ) { /** Bytes available in the urgent ringbuffer ( reserved for DTMF ) */ int urgentAvail; @@ -316,6 +323,7 @@ PulseLayer::writeToSpeaker( void ) else { bzero(out, framesPerBuffer * sizeof(SFLDataFormat)); } + pa_stream_write( playback->pulseStream() , out , toGet , NULL, 0 , PA_SEEK_RELATIVE); pa_xfree(out); } diff --git a/src/audio/pulselayer.h b/src/audio/pulselayer.h index 7476d6052ec41fe04013e9068c2f863ef82e6109..ce2bc2e6af79d49dd5d049f952896c2b03956c44 100644 --- a/src/audio/pulselayer.h +++ b/src/audio/pulselayer.h @@ -24,6 +24,7 @@ #include "audiostream.h" #include <pulse/pulseaudio.h> +#include <pulse/stream.h> #define PLAYBACK_STREAM_NAME "SFLphone out" #define CAPTURE_STREAM_NAME "SFLphone in" @@ -74,7 +75,8 @@ class PulseLayer : public AudioLayer { static void overflow ( pa_stream* s, void* userdata ); 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 context_state_callback( pa_context* c, void* user_data ); + static void stream_suspended_callback ( pa_stream* s, void* userdata ); bool isCaptureActive (void){return true;} @@ -127,6 +129,7 @@ class PulseLayer : public AudioLayer { void setMicVolume( int value ) { micVolume = value; } void processData( void ); + private: // Copy Constructor PulseLayer(const PulseLayer& rh);