diff --git a/src/audio/audiostream.cpp b/src/audio/audiostream.cpp index 8b88009346f75726222af3597e2cd431fae04c11..b1c0fcfd3d781f38be74ef2885042addc7d21ea3 100644 --- a/src/audio/audiostream.cpp +++ b/src/audio/audiostream.cpp @@ -39,6 +39,7 @@ AudioStream::~AudioStream() { _debug("Destroy audio streams\n"); pa_stream_disconnect( pulseStream() ); + pa_stream_unref( pulseStream() ); } void @@ -63,7 +64,8 @@ AudioStream::stream_state_callback( pa_stream* s, void* user_data ) break; case PA_STREAM_FAILED: default: - _debug("Stream error: %s\n" , pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + _debug("Stream error - Sink/Source doesn't exists: %s\n" , pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + exit(0); break; } } diff --git a/src/audio/pulselayer.cpp b/src/audio/pulselayer.cpp index 862d74fbaf4c17e642524f7623356542ada46fc7..734a2dec9531ad6b49fa4f308373d2f59726e07f 100644 --- a/src/audio/pulselayer.cpp +++ b/src/audio/pulselayer.cpp @@ -39,7 +39,7 @@ PulseLayer::~PulseLayer (void) pa_context_disconnect(context); } -void + void PulseLayer::closeLayer( void ) { playback->disconnect(); @@ -48,7 +48,7 @@ PulseLayer::closeLayer( void ) } void -PulseLayer::connectPulseServer( void ) +PulseLayer::connectPulseAudioServer( void ) { pa_context_flags_t flag = PA_CONTEXT_NOAUTOSPAWN ; int ret = 1; @@ -56,7 +56,7 @@ PulseLayer::connectPulseServer( void ) pa_threaded_mainloop_lock( m ); _debug("Connect the context to the server\n"); - pa_context_connect( context, NULL , flag , NULL ); + pa_context_connect( context, NULL , flag , NULL ); pa_context_set_state_callback(context, context_state_callback, this); pa_threaded_mainloop_wait( m ); @@ -68,7 +68,7 @@ PulseLayer::connectPulseServer( void ) } pa_threaded_mainloop_unlock( m ); - serverinfo(); + //serverinfo(); //muteAudioApps(99); _debug("Context creation done\n"); } @@ -94,20 +94,31 @@ void PulseLayer::context_state_callback( pa_context* c, void* user_data ) break; case PA_CONTEXT_FAILED: default: - _debug(" Error : %n" , pa_strerror(pa_context_errno(c))); - exit(1); + _debug(" Error : %s\n" , pa_strerror(pa_context_errno(c))); + pulse->disconnectPulseAudioServer(); + exit(0); + break; } } +void PulseLayer::disconnectPulseAudioServer( void ) +{ + if( playback ) + delete playback; + + if( record ) + delete record; +} + void PulseLayer::createStreams( pa_context* c ) { playback = new AudioStream(c, PLAYBACK_STREAM, "SFLphone out", _manager->getSpkrVolume()); pa_stream_set_write_callback( playback->pulseStream() , audioCallback, this); - //pa_stream_set_overflow_callback( playback , overflow , this); + pa_stream_set_overflow_callback( playback->pulseStream() , overflow , this); record = new AudioStream(c, CAPTURE_STREAM, "SFLphone in", _manager->getMicVolume()); pa_stream_set_read_callback( record->pulseStream() , audioCallback, this); - //pa_stream_set_underflow_callback( record , underflow , this); + pa_stream_set_underflow_callback( record->pulseStream() , underflow , this); cache = new AudioStream(c, UPLOAD_STREAM, "Cache samples", _manager->getSpkrVolume()); pa_threaded_mainloop_signal(m , 0); @@ -132,7 +143,7 @@ PulseLayer::openDevice(int indexIn, int indexOut, int sampleRate, int frameSize assert(context); - connectPulseServer(); + connectPulseAudioServer(); _debug("Connection Done!! \n"); } @@ -251,7 +262,25 @@ PulseLayer::underflow ( pa_stream* s, void* userdata ) void PulseLayer::overflow ( pa_stream* s, void* userdata ) { - _debug("Buffer Overflow\n"); + PulseLayer* pulse = (PulseLayer*) userdata; + pa_stream_drop( s ); + pa_stream_trigger( s, NULL, NULL); + /* + AudioLoop* tone=pulse->_manager->getTelephoneTone(); + if( tone!= NULL ){ + _debug("Buffer Overflow\n"); + int toGet = 2048; + SFLDataFormat* out = (SFLDataFormat*)pa_xmalloc(toGet * sizeof(SFLDataFormat) * sizeof(SFLDataFormat)); + tone->getNext(out, toGet * sizeof(SFLDataFormat) , 100); + pa_stream_write( s , out , toGet * sizeof(SFLDataFormat) * sizeof(SFLDataFormat) , pa_xfree, 0 , PA_SEEK_RELATIVE); + //pa_threaded_mainloop_lock(pulse->m); + //pa_threaded_mainloop_unlock(pulse->m); + + if (pa_stream_drain(pulse->getPlaybackStream()->pulseStream(), NULL, NULL) < 0) { + fprintf(stderr, "pa_stream_drop() failed: %s\n", pa_strerror(pa_context_errno(pulse->context))); + return; + } + }*/ } void @@ -262,15 +291,15 @@ PulseLayer::processData( void ) int toGet; int urgentAvail; // number of data right and data left int normalAvail; // number of data right and data left + size_t maxsize; + int toPlay; - - - // Handle the mic also + // Handle the mic if( (record->pulseStream()) && pa_stream_get_state( record->pulseStream()) == PA_STREAM_READY) { if( pa_stream_peek( record->pulseStream() , (const void**)&data , &r ) < 0 || !data ){ _debug("pa_stream_peek() failed: %s\n" , pa_strerror( pa_context_errno( context) )); - return; + //return; } if( data != 0 ){ @@ -279,42 +308,60 @@ PulseLayer::processData( void ) if( pa_stream_drop( record->pulseStream() ) < 0 ) { _debug("pa_stream_drop() failed: %s\n" , pa_strerror( pa_context_errno( context) )); - return; + //return; } } + _debug("writable size = %d\n" , pa_stream_writable_size(playback->pulseStream())); + if( pa_stream_writable_size(playback->pulseStream()) == 0 ){ + _debug("flush it\n"); + return; + } - SFLDataFormat* out = (SFLDataFormat*)pa_xmalloc(framesPerBuffer * sizeof(SFLDataFormat)); - urgentAvail = _urgentRingBuffer.AvailForGet(); - if (urgentAvail > 0) { - // Urgent data (dtmf, incoming call signal) come first. - _debug("Play urgent!\n"); - toGet = (urgentAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? urgentAvail : framesPerBuffer * sizeof(SFLDataFormat); - _urgentRingBuffer.Get(out, toGet, 100); - // Consume the regular one as well (same amount of bytes) - _mainSndRingBuffer.Discard(toGet); - } - else - { - AudioLoop* tone = 0;//_manager->getTelephoneTone(); - if ( tone != 0) { - //tone->getNext(out, framesPerBuffer, 100); - toGet = framesPerBuffer; - } /*else if ( (tone=_manager->getTelephoneFile()) != 0 ) { - tone->getNext(out, framesPerBuffer, 100); + if( (playback->pulseStream()) && pa_stream_get_state( playback->pulseStream()) == PA_STREAM_READY || !(maxsize=pa_stream_writable_size(playback->pulseStream()))) { + maxsize = 2048; + SFLDataFormat* out; + urgentAvail = _urgentRingBuffer.AvailForGet(); + if (urgentAvail > 0) { + // Urgent data (dtmf, incoming call signal) come first. + _debug("Play urgent!: %i\n" , urgentAvail); + toGet = (urgentAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? urgentAvail : framesPerBuffer * sizeof(SFLDataFormat); + out = (SFLDataFormat*)pa_xmalloc(toGet * sizeof(SFLDataFormat) ); + _urgentRingBuffer.Get(out, toGet, 100); + // Consume the regular one as well (same amount of bytes) + _mainSndRingBuffer.Discard(toGet); + pa_stream_write( playback->pulseStream() , out , toGet , pa_xfree, 0 , PA_SEEK_RELATIVE); + } + else + { + AudioLoop* tone = _manager->getTelephoneTone(); + if ( tone != 0) { toGet = framesPerBuffer; - } */else { - normalAvail = _mainSndRingBuffer.AvailForGet(); - toGet = (normalAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof(SFLDataFormat); - if (toGet) { - _mainSndRingBuffer.Get(out, toGet, 100); - _debug("Write %i bytes\n" , toGet); - _mainSndRingBuffer.Discard(toGet); - } else { - bzero(out, framesPerBuffer * sizeof(SFLDataFormat)); - } + out = (SFLDataFormat*)pa_xmalloc(toGet * sizeof(SFLDataFormat) * sizeof(SFLDataFormat)); + tone->getNext(out, toGet * sizeof(SFLDataFormat) , 100); + pa_stream_write( playback->pulseStream() , out , toGet * sizeof(SFLDataFormat) * sizeof(SFLDataFormat) , pa_xfree, 0 , PA_SEEK_RELATIVE); + } else if ( (tone=_manager->getTelephoneFile()) != 0 ) { + toGet = framesPerBuffer; + toPlay = ( toGet * sizeof(SFLDataFormat) * sizeof(SFLDataFormat) > maxsize )? maxsize : toGet* sizeof(SFLDataFormat) * sizeof(SFLDataFormat); + out = (SFLDataFormat*)pa_xmalloc(toPlay); + tone->getNext(out, toPlay/2 , 100); + if( pa_stream_write( playback->pulseStream() , out , toPlay , pa_xfree, 0 , PA_SEEK_RELATIVE) < 0 ) + _debug("aie aie aie\n"); + } else { + out = (SFLDataFormat*)pa_xmalloc(framesPerBuffer * sizeof(SFLDataFormat)); + normalAvail = _mainSndRingBuffer.AvailForGet(); + toGet = (normalAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof(SFLDataFormat); + if (toGet) { + _mainSndRingBuffer.Get(out, toGet, 100); + //_debug("Write %i bytes\n" , toGet); + _mainSndRingBuffer.Discard(toGet); + } else { + bzero(out, framesPerBuffer * sizeof(SFLDataFormat)); } - } - pa_stream_write( playback->pulseStream() , out , toGet , pa_xfree, 0 , PA_SEEK_RELATIVE); + pa_stream_write( playback->pulseStream() , out , toGet , pa_xfree, 0 , PA_SEEK_RELATIVE); + } + } + } + //} } int @@ -374,19 +421,19 @@ static void restore_sink_list(pa_context *c, const pa_sink_input_info *i, int eo } } -void + void PulseLayer::reducePulseAppsVolume( void ) { pa_context_get_sink_input_info_list( context , reduce_sink_list , this ); } -void + void PulseLayer::restorePulseAppsVolume( void ) { pa_context_get_sink_input_info_list( context , restore_sink_list , this ); } -void + void PulseLayer::serverinfo( void ) { pa_context_get_server_info( context , retrieve_server_info , NULL ); @@ -397,30 +444,30 @@ static void on_success(pa_context *c, int success, void *userdata) _debug("Operation successfull \n"); } -void + void PulseLayer::reduceAppVolume( int index , int channels ) { pa_cvolume volume; pa_volume_t vol = PA_VOLUME_NORM; vol /= 10; - + pa_cvolume_set( &volume , channels , vol); _debug("Mute Index %i\n" , index); pa_context_set_sink_input_volume( context, index, &volume, on_success, this) ; } -void + void PulseLayer::restoreAppVolume( int index, int channels ) { pa_cvolume volume; pa_volume_t vol = PA_VOLUME_NORM; - + pa_cvolume_set( &volume , channels , vol); _debug("Restore Index %i\n" , index); pa_context_set_sink_input_volume( context, index, &volume, on_success, this) ; } -void + void PulseLayer::setPlaybackVolume( double volume ) { //value between 0 and 100 diff --git a/src/audio/pulselayer.h b/src/audio/pulselayer.h index 6265351f2e8bcbdf7559421a03b64bb7dd0398ae..5156591269151329a8c0d5c1c3b8919d3e47a293 100644 --- a/src/audio/pulselayer.h +++ b/src/audio/pulselayer.h @@ -196,7 +196,12 @@ class PulseLayer : public AudioLayer { /** * Establishes the connection with the local pulseaudio server */ - void connectPulseServer( void ); + void connectPulseAudioServer( void ); + + /** + * Close the connection with the local pulseaudio server + */ + void disconnectPulseAudioServer( void ); /** * Get some information about the pulseaudio server diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp index b7f595cab23c4aacf8a9700c06cf1d76fa15203a..817dfa51a12286ff0b809b3a169af9b96080d8f9 100644 --- a/src/managerimpl.cpp +++ b/src/managerimpl.cpp @@ -739,9 +739,10 @@ ManagerImpl::playATone(Tone::TONEID toneId) { int layer = audiolayer->getLayerType(); if(CHECK_INTERFACE( layer , ALSA ) ) audiolayer->putUrgent( buf, nbSampling ); - else{} + else{ + audiolayer->startStream(); + } // Pulseaudio code - // startStream()?;} } else return false; @@ -846,8 +847,7 @@ ManagerImpl::ringtone() _audiofile.getNext(output, size , 100); audiolayer->putUrgent( output , size );} else{ - // pulseaudio code - //audiolayer->startStream(); + audiolayer->startStream(); } } else { ringback(); @@ -1527,13 +1527,7 @@ ManagerImpl::getCurrentAudioOutputPlugin( void ) ManagerImpl::initAudioDriver(void) { _debugInit("AudioLayer Creation"); - //_audiodriver = new AlsaLayer( this ); - /*if( _audiodriver ){ - _debug("delete audiodriver\n"); - delete _audiodriver; _audiodriver = NULL; - } */ - if( getConfigInt( PREFERENCES , CONFIG_AUDIO ) == ALSA ) _audiodriver = new AlsaLayer( this ); else if( getConfigInt( PREFERENCES , CONFIG_AUDIO ) == PULSEAUDIO ) @@ -1549,6 +1543,7 @@ ManagerImpl::initAudioDriver(void) _debug("Init audio driver: %i\n", error); } } + } /**