diff --git a/sflphone-common/src/audio/alsa/alsalayer.cpp b/sflphone-common/src/audio/alsa/alsalayer.cpp index 92f2fba69ae38af047b3890326e25b938f1b28a6..fcd22045b26058cafa629946837a5abface97557 100644 --- a/sflphone-common/src/audio/alsa/alsalayer.cpp +++ b/sflphone-common/src/audio/alsa/alsalayer.cpp @@ -37,14 +37,14 @@ AlsaLayer::AlsaLayer (ManagerImpl* manager) , _is_running_capture (false) , _is_open_playback (false) , _is_open_capture (false) - , _trigger_request (false) - , _converterSamplingRate(0) + , _trigger_request (false) + , _audioThread(NULL) { _debug (" Constructor of AlsaLayer called\n"); /* Instanciate the audio thread */ - _audioThread = new AudioThread (this); - + // _audioThread = new AudioThread (this); + // _audioThread = NULL; _urgentRingBuffer.createReadPointer(); dcblocker = new DcBlocker(); @@ -60,7 +60,9 @@ AlsaLayer::~AlsaLayer (void) delete _converter; _converter = NULL; } - delete dcblocker; dcblocker = NULL; + if(dcblocker) { + delete dcblocker; dcblocker = NULL; + } } bool @@ -71,6 +73,7 @@ AlsaLayer::closeLayer() try { /* Stop the audio thread first */ if (_audioThread) { + _debug("Stop Audio Thread\n"); delete _audioThread; _audioThread=NULL; } @@ -112,7 +115,7 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize, _frameSize = frameSize; - _audioPlugin = plugin; + _audioPlugin = std::string(plugin); _debugAlsa (" Setting AlsaLayer: device in=%2d, out=%2d\n", _indexIn, _indexOut); @@ -122,37 +125,76 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize, _debugAlsa (" : sample rate=%5d, format=%s\n", _audioSampleRate, SFLDataFormatString); + _audioThread = NULL; + ost::MutexLock lock (_mutex); std::string pcmp = buildDeviceTopo (plugin, indexOut, 0); - std::string pcmc = buildDeviceTopo (PCM_PLUGHW, indexIn, 0); + std::string pcmc = buildDeviceTopo (plugin, indexIn, 0); _converter = new SamplerateConverter (_audioSampleRate, _frameSize); - return open_device (pcmp, pcmc, stream); + // open_device (pcmp, pcmc, stream); + return true; // open_device (pcmp, pcmc, stream); } void AlsaLayer::startStream (void) { - _debug ("Start ALSA streams\n"); + _debug ("AlsaLayer:: startStream\n"); + + std::string pcmp = buildDeviceTopo (_audioPlugin, _indexOut, 0); + std::string pcmc = buildDeviceTopo (_audioPlugin, _indexIn, 0); + + if(!is_playback_open()){ + open_device (pcmp, pcmc, SFL_PCM_PLAYBACK); + } + + if(!is_capture_open()){ + open_device (pcmp, pcmc, SFL_PCM_CAPTURE); + } + prepareCaptureStream (); + preparePlaybackStream (); startCaptureStream (); startPlaybackStream (); _urgentRingBuffer.flush(); - _mainBuffer.flush(); + _mainBuffer.flushAllBuffers(); _mainBuffer.flushDefault(); + if(_audioThread == NULL) { + try { + _debug("Start Audio Thread\n"); + _audioThread = new AudioThread (this); + _audioThread->start(); + } catch (...) { + _debugException ("Fail to start audio thread\n"); + } + } + } void AlsaLayer::stopStream (void) { - _debug ("AlsaLayer::stopStream :: Stop ALSA streams\n"); - stopCaptureStream (); - //stopPlaybackStream (); + _debug ("AlsaLayer:: stopStream\n"); + + try { + /* Stop the audio thread first */ + if (_audioThread) { + _debug("Stop Audio Thread\n"); + delete _audioThread; + _audioThread=NULL; + } + } catch (...) { + _debugException ("! ARTP Exception: when stopping audiortp\n"); + throw; + } + + closeCaptureStream (); + closePlaybackStream (); /* Flush the ring buffers */ flushUrgent (); @@ -227,38 +269,52 @@ void AlsaLayer::stopCaptureStream (void) int err; if (_CaptureHandle) { - err = snd_pcm_drop (_CaptureHandle); - - stop_capture (); + _debug("AlsaLayer:: stop Alsa capture\n"); + if((err = snd_pcm_drop (_CaptureHandle)) < 0) + _debug("AlsaLayer:: Error stopping ALSA capture: %s\n", snd_strerror(err)); + else + stop_capture (); } } void AlsaLayer::closeCaptureStream (void) { + int err; + if (is_capture_prepared() == true && is_capture_running() == true) stopCaptureStream (); - if (is_capture_open()) - snd_pcm_close (_CaptureHandle); - - close_capture (); + if (is_capture_open()) { + _debug("AlsaLayer:: close ALSA capture\n"); + if ((err = snd_pcm_close (_CaptureHandle)) < 0) + _debug("Error closing ALSA capture: %s\n", snd_strerror(err)); + else + close_capture (); + } } void AlsaLayer::startCaptureStream (void) { - if (_CaptureHandle) { - _debug ("Start the capture\n"); - snd_pcm_start (_CaptureHandle); - start_capture(); + int err; + + if (_CaptureHandle && !is_capture_running()) { + _debug ("AlsaLayer:: start ALSA capture\n"); + if((err = snd_pcm_start (_CaptureHandle)) < 0) + _debug("Error starting ALSA capture: %s\n", snd_strerror(err)); + else + start_capture(); } } void AlsaLayer::prepareCaptureStream (void) { - if (is_capture_open()) { - if (snd_pcm_prepare (_CaptureHandle) < 0) - _debug (""); + int err; + + if (is_capture_open() && !is_capture_prepared()) { + _debug("AlsaLayer:: prepare ALSA capture\n"); + if ((err = snd_pcm_prepare (_CaptureHandle)) < 0) + _debug ("Error preparing ALSA capture: %s\n", snd_strerror(err)); else prepare_capture (); } @@ -266,38 +322,57 @@ void AlsaLayer::prepareCaptureStream (void) void AlsaLayer::stopPlaybackStream (void) { - if (_PlaybackHandle) { - snd_pcm_drop (_PlaybackHandle); - stop_playback (); + int err; + + if (_PlaybackHandle && is_playback_running()) { + _debug("AlsaLayer:: stop ALSA playback\n"); + if((err = snd_pcm_drop (_PlaybackHandle)) < 0) + _debug("Error stopping ALSA playback: %s\n", snd_strerror(err)); + else + stop_playback (); } } void AlsaLayer::closePlaybackStream (void) { + int err; + if (is_playback_prepared() == true && is_playback_running() == true) stopPlaybackStream (); - if (is_playback_open()) - snd_pcm_close (_PlaybackHandle); - - close_playback (); + if (is_playback_open()) { + _debug("AlsaLayer:: close ALSA playback\n"); + if ((err = snd_pcm_close (_PlaybackHandle)) < 0) + _debug("Error closing ALSA playback: %s\n", snd_strerror(err)); + else + close_playback (); + } } void AlsaLayer::startPlaybackStream (void) { - if (_PlaybackHandle) { - snd_pcm_start (_PlaybackHandle); - start_playback(); + int err; + + if (_PlaybackHandle && !is_playback_running()) { + _debug ("AlsaLayer:: start ALSA playback\n"); + if ((err = snd_pcm_start (_PlaybackHandle)) < 0) + _debug("Error starting ALSA playback: %s\n", snd_strerror(err)); + else + start_playback(); } } void AlsaLayer::preparePlaybackStream (void) { - if (is_playback_open()) { - if (snd_pcm_prepare (_PlaybackHandle) < 0) _debug ("Error preparing the device\n"); + int err; - prepare_playback (); + if (is_playback_open() && !is_playback_prepared()) { + _debug("AlsaLayer:: prepare playback stream\n"); + if ((err = snd_pcm_prepare (_PlaybackHandle)) < 0) + _debug ("Error preparing the device: %s\n", snd_strerror(err)); + else + prepare_playback (); } } @@ -431,6 +506,8 @@ AlsaLayer::open_device (std::string pcm_p, std::string pcm_c, int flag) int err; if (flag == SFL_PCM_BOTH || flag == SFL_PCM_PLAYBACK) { + + _debug("AlsaLayer:: open playback device\n"); // if((err = snd_pcm_open(&_PlaybackHandle, pcm_p.c_str(), SND_PCM_STREAM_PLAYBACK, 0 )) < 0){ if ( (err = snd_pcm_open (&_PlaybackHandle, pcm_p.c_str(), SND_PCM_STREAM_PLAYBACK, 0)) < 0) { _debugAlsa ("Error while opening playback device %s\n", pcm_p.c_str()); @@ -450,6 +527,8 @@ AlsaLayer::open_device (std::string pcm_p, std::string pcm_c, int flag) } if (flag == SFL_PCM_BOTH || flag == SFL_PCM_CAPTURE) { + + _debug("AlsaLayer:: open capture device\n"); if ( (err = snd_pcm_open (&_CaptureHandle, pcm_c.c_str(), SND_PCM_STREAM_CAPTURE, 0)) < 0) { _debugAlsa ("Error while opening capture device %s\n", pcm_c.c_str()); setErrorMessage (ALSA_CAPTURE_DEVICE); @@ -466,15 +545,17 @@ AlsaLayer::open_device (std::string pcm_p, std::string pcm_c, int flag) open_capture (); - prepare_capture (); + // prepare_capture (); } /* Start the secondary audio thread for callbacks */ + /* try { _audioThread->start(); } catch (...) { _debugException ("Fail to start audio thread\n"); } + */ return true; } @@ -570,6 +651,8 @@ AlsaLayer::read (void* buffer, int toCopy) void AlsaLayer::handle_xrun_capture (void) { + _debugAlsa("handle_xrun_capture\n"); + snd_pcm_status_t* status; snd_pcm_status_alloca (&status); @@ -588,6 +671,8 @@ AlsaLayer::handle_xrun_capture (void) void AlsaLayer::handle_xrun_playback (void) { + _debugAlsa("AlsaLayer:: handle_xrun_playback\n"); + int state; snd_pcm_status_t* status; snd_pcm_status_alloca (&status); @@ -729,6 +814,7 @@ void AlsaLayer::audioCallback (void) int toGet, urgentAvailBytes, normalAvailBytes, maxBytes; unsigned short spkrVolume, micVolume; AudioLoop *tone; + AudioLoop *file_tone; SFLDataFormat *out; SFLDataFormat *rsmpl_out; @@ -759,8 +845,10 @@ void AlsaLayer::audioCallback (void) } else { tone = _manager->getTelephoneTone(); - toGet = 940 ; - maxBytes = toGet * sizeof (SFLDataFormat) ; + file_tone = _manager->getTelephoneFile(); + + toGet = framesPerBufferAlsa; + maxBytes = toGet * sizeof (SFLDataFormat); if (tone != 0) { @@ -771,10 +859,10 @@ void AlsaLayer::audioCallback (void) free(out); out = 0; - } else if ( (tone=_manager->getTelephoneFile()) != 0) { + } else if (file_tone != 0) { out = (SFLDataFormat*) malloc (maxBytes * sizeof (SFLDataFormat)); - tone->getNext (out, toGet, spkrVolume); + file_tone->getNext(out, toGet, spkrVolume); write (out , maxBytes); free(out); @@ -822,7 +910,6 @@ void AlsaLayer::audioCallback (void) // Do sample rate conversion int nb_sample_down = toGet / sizeof(SFLDataFormat); - int nbSample = _converter->upsampleData((SFLDataFormat*)out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_down); @@ -840,7 +927,11 @@ void AlsaLayer::audioCallback (void) } else { - bzero (out, maxNbBytesToGet); + if((tone == 0) && (file_tone == 0)) { + + bzero (out, maxNbBytesToGet); + write (out, maxNbBytesToGet); + } } _urgentRingBuffer.Discard (toGet); @@ -865,11 +956,11 @@ void AlsaLayer::audioCallback (void) { micAvailBytes = snd_pcm_avail_update(_CaptureHandle); - + // _debug("micAvailBytes %i\n", micAvailBytes); if(micAvailBytes > 0) { micAvailPut = _mainBuffer.availForPut(); - toPut = (micAvailBytes <= micAvailPut) ? micAvailBytes : micAvailPut; + toPut = (micAvailBytes <= framesPerBufferAlsa) ? micAvailBytes : framesPerBufferAlsa; in = (SFLDataFormat*)malloc(toPut * sizeof(SFLDataFormat)); toPut = read (in, toPut* sizeof(SFLDataFormat)); @@ -886,6 +977,7 @@ void AlsaLayer::audioCallback (void) int nbSample = toPut / sizeof(SFLDataFormat); int nb_sample_up = nbSample; + // _debug("nb_sample_up %i\n", nb_sample_up); nbSample = _converter->downsampleData ((SFLDataFormat*)in, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_up); dcblocker->filter_signal(rsmpl_out, nbSample); diff --git a/sflphone-common/src/audio/alsa/alsalayer.h b/sflphone-common/src/audio/alsa/alsalayer.h index e1d4b189b78d3b79c7ae5194a3751e04fc4e7044..1f5167ede252b9516c55df316e10763c3dfcd036 100644 --- a/sflphone-common/src/audio/alsa/alsalayer.h +++ b/sflphone-common/src/audio/alsa/alsalayer.h @@ -265,13 +265,12 @@ class AlsaLayer : public AudioLayer { bool _is_open_capture; bool _trigger_request; - AudioThread *_audioThread; + AudioThread* _audioThread; /** Sample rate converter object */ - SamplerateConverter * _converter; - - int _converterSamplingRate; + SamplerateConverter* _converter; + // Allpass filter to remove DC offset DcBlocker* dcblocker; }; diff --git a/sflphone-common/src/audio/audiolayer.cpp b/sflphone-common/src/audio/audiolayer.cpp index 9f1119ff694baf871e77d9fa9c17b4b13818a667..8966eb6aba086a30183d9dfa048ec3d42f5350f8 100644 --- a/sflphone-common/src/audio/audiolayer.cpp +++ b/sflphone-common/src/audio/audiolayer.cpp @@ -24,13 +24,13 @@ void AudioLayer::flushMain (void) ost::MutexLock guard (_mutex); // should pass call id - _mainBuffer.flush(); + _mainBuffer.flushAllBuffers(); } void AudioLayer::flushUrgent (void) { ost::MutexLock guard (_mutex); - _urgentRingBuffer.flush(); + _urgentRingBuffer.flushAll(); } void AudioLayer::flushMic (void) diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h index bed84b1c3d3956e64170e2e2507f2dc14e0f9967..3ac8916b3aa4dbb20093b47d40500406647156ec 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h @@ -498,10 +498,12 @@ namespace sfl { } _ca->setRecordingSmplRate(_audiocodec->getClockRate()); - + _audiolayer->startStream(); static_cast<D*>(this)->startRunning(); + _audiolayer->flushUrgent(); + _debug ("Entering RTP mainloop for callid %s\n",_ca->getCallId().c_str()); while (!testCancel()) { diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.cpp b/sflphone-common/src/audio/pulseaudio/audiostream.cpp index e30f40f78b200cdf0845cc5394b8c709a2a7af6e..deaab30f5b545228952e237fd4ba8c52b43f8ead 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.cpp +++ b/sflphone-common/src/audio/pulseaudio/audiostream.cpp @@ -20,7 +20,7 @@ #include <audiostream.h> #include "pulselayer.h" -static pa_channel_map channel_map ; +static pa_channel_map channel_map; AudioStream::AudioStream (PulseLayerType * driver) @@ -31,7 +31,7 @@ AudioStream::AudioStream (PulseLayerType * driver) _volume(), flag (PA_STREAM_AUTO_TIMING_UPDATE), sample_spec(), - _mainloop (driver->mainloop) + _mainloop (driver->mainloop) { sample_spec.format = PA_SAMPLE_S16LE; sample_spec.rate = 44100; @@ -99,7 +99,7 @@ AudioStream::disconnectStream (void) { _debug ("Destroy audio streams\n"); - pa_threaded_mainloop_lock (_mainloop); + // pa_threaded_mainloop_lock (_mainloop); if (_audiostream) { pa_stream_disconnect (_audiostream); @@ -107,7 +107,7 @@ AudioStream::disconnectStream (void) _audiostream = NULL; } - pa_threaded_mainloop_unlock (_mainloop); + // pa_threaded_mainloop_unlock (_mainloop); return true; } @@ -136,7 +136,6 @@ AudioStream::stream_state_callback (pa_stream* s, void* user_data) break; case PA_STREAM_READY: - _debug ("Stream successfully created, connected to %s\n", pa_stream_get_device_name (s)); // pa_stream_cork( s, 0, NULL, NULL); break; @@ -187,9 +186,9 @@ AudioStream::createStream (pa_context* c) if (_streamType == PLAYBACK_STREAM) { attributes->maxlength = 16000; attributes->tlength = 2048; - attributes->prebuf = 1024; + attributes->prebuf = 2048; attributes->minreq = 1024; - attributes->fragsize = 1024; + attributes->fragsize = 4096; pa_stream_connect_playback( s , NULL , attributes, PA_STREAM_INTERPOLATE_TIMING, &_volume, NULL); // pa_stream_connect_playback (s , NULL , attributes, PA_STREAM_START_CORKED, &_volume, NULL); } else if (_streamType == CAPTURE_STREAM) { diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.h b/sflphone-common/src/audio/pulseaudio/audiostream.h index 3f6e25c66c27fb7221ea9740e4a1434432e121c0..40fa26e50e663300876f63478fcbe2d93c9941cc 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.h +++ b/sflphone-common/src/audio/pulseaudio/audiostream.h @@ -183,6 +183,8 @@ class AudioStream { ost::Mutex _mutex; + bool _stream_is_ready; + }; #endif // _AUDIO_STREAM_H diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index cea5e4eeccff50329d87b621a2f4eef1561f00da..2ce375a3ca788d6e4d486fe37dd178190b3ed6cf 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -25,7 +25,7 @@ int framesPerBuffer = 2048; static void playback_callback (pa_stream* s, size_t bytes, void* userdata) { - _debug("playback_callback\n"); + // _debug("playback_callback\n"); assert (s && bytes); assert (bytes > 0); @@ -112,10 +112,12 @@ PulseLayer::closeLayer (void) } // playback->disconnectStream(); - closePlaybackStream(); + // closePlaybackStream(); // record->disconnectStream(); - closeCaptureStream(); + // closeCaptureStream(); + + disconnectAudioStream(); if (context) { pa_context_disconnect (context); @@ -154,6 +156,8 @@ PulseLayer::connectPulseAudioServer (void) pa_threaded_mainloop_unlock (m); + _urgentRingBuffer.flushAll(); + //serverinfo(); //muteAudioApps(99); _debug ("Context creation done\n"); @@ -189,15 +193,15 @@ void PulseLayer::context_state_callback (pa_context* c, void* user_data) default: _debug (" Error : %s\n" , pa_strerror (pa_context_errno (c))); - pulse->disconnectPulseAudioServer(); + pulse->disconnectAudioStream(); exit (0); break; } } -bool PulseLayer::disconnectPulseAudioServer (void) +bool PulseLayer::disconnectAudioStream (void) { - _debug (" PulseLayer::disconnectPulseAudioServer( void ) \n"); + _debug (" PulseLayer::disconnectAudioStream( void ) \n"); closePlaybackStream(); @@ -212,7 +216,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; @@ -246,6 +250,8 @@ bool PulseLayer::createStreams (pa_context* c) pa_threaded_mainloop_signal (m , 0); + _urgentRingBuffer.flushAll(); + return true; } @@ -253,42 +259,23 @@ bool PulseLayer::createStreams (pa_context* c) bool PulseLayer::openDevice (int indexIn UNUSED, int indexOut UNUSED, int sampleRate, int frameSize , int stream UNUSED, std::string plugin UNUSED) { - - _debug ("PulseLayer::openDevice \n"); _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(); - - // startStream(); + _urgentRingBuffer.flushAll(); _converter = new SamplerateConverter (_audioSampleRate, _frameSize); - _debug ("Connection Done!! \n"); - return true; } void PulseLayer::closeCaptureStream (void) { if (record) { + + pa_threaded_mainloop_lock (m); delete record; + pa_threaded_mainloop_unlock (m); record=NULL; } } @@ -296,7 +283,10 @@ void PulseLayer::closeCaptureStream (void) void PulseLayer::closePlaybackStream (void) { if (playback) { + + pa_threaded_mainloop_lock (m); delete playback; + pa_threaded_mainloop_unlock (m); playback=NULL; } } @@ -323,9 +313,11 @@ void PulseLayer::startStream (void) if(!is_started) { - _debug ("------------------------ PulseLayer::Start stream ---------------\n"); + _debug ("PulseLayer::Start Stream\n"); if (!m) { + + _debug("Creating PulseAudio MainLoop\n"); m = pa_threaded_mainloop_new(); assert (m); @@ -336,28 +328,22 @@ void PulseLayer::startStream (void) if (!context) { + _debug("Creating new PulseAudio Context\n"); + pa_threaded_mainloop_lock (m); // Instanciate a context if (! (context = pa_context_new (pa_threaded_mainloop_get_api (m) , "SFLphone"))) _debug ("Error while creating the context\n"); + pa_threaded_mainloop_unlock (m); assert (context); } _urgentRingBuffer.flush(); - _mainBuffer.flushAllBuffers(); + // Create Streams connectPulseAudioServer(); - // pa_threaded_mainloop_lock (m); - - // pa_stream_cork (playback->pulseStream(), 0, NULL, NULL); - // pa_stream_cork (record->pulseStream(), 0, NULL, NULL); - - // pa_threaded_mainloop_unlock (m); - - // createStreams(context); - is_started = true; } @@ -369,32 +355,30 @@ PulseLayer::stopStream (void) if(is_started) { - _debug ("------------------------ PulseLayer::Stop stream ---------------\n"); + _debug ("PulseLayer::Stop Audio Stream\n"); pa_stream_flush (playback->pulseStream(), NULL, NULL); pa_stream_flush (record->pulseStream(), NULL, NULL); - flushMic(); - flushMain(); - flushUrgent(); - - // closeCaptureStream(); - // closePlaybackStream(); + disconnectAudioStream(); - disconnectPulseAudioServer(); + if (m) { + pa_threaded_mainloop_stop (m); + } - // pa_threaded_mainloop_lock (m); - - // pa_stream_cork (playback->pulseStream(), 1, NULL, NULL); - // pa_stream_cork (record->pulseStream(), 1, NULL, NULL); - // pa_threaded_mainloop_unlock (m); + _debug("Disconnecting PulseAudio context\n"); if (context) { + + pa_threaded_mainloop_lock (m); pa_context_disconnect (context); pa_context_unref (context); + pa_threaded_mainloop_unlock (m); context = NULL; } + _debug("Freeing Pulseaudio mainloop\n"); + if (m) { pa_threaded_mainloop_free (m); m = NULL; @@ -428,6 +412,8 @@ void PulseLayer::processPlaybackData (void) // Handle the data for the speakers if ( playback &&(playback->pulseStream()) && (pa_stream_get_state (playback->pulseStream()) == PA_STREAM_READY)) { + // _debug("PulseLayer::processPlaybackData()\n"); + // 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; @@ -462,12 +448,12 @@ void PulseLayer::writeToSpeaker (void) if (urgentAvailBytes > 0) { - // Urgent data (dtmf, incoming call signal) come first. - //_debug("Play urgent!: %i\e" , urgentAvail); + toGet = (urgentAvailBytes < (int) (framesPerBuffer * sizeof (SFLDataFormat))) ? urgentAvailBytes : framesPerBuffer * sizeof (SFLDataFormat); out = (SFLDataFormat*) pa_xmalloc (toGet * sizeof (SFLDataFormat)); _urgentRingBuffer.Get (out, toGet, 100); pa_stream_write (playback->pulseStream(), out, toGet, NULL, 0, PA_SEEK_RELATIVE); + // Consume the regular one as well (same amount of bytes) _mainBuffer.discard (toGet); @@ -476,26 +462,35 @@ void PulseLayer::writeToSpeaker (void) } else { AudioLoop* tone = _manager->getTelephoneTone(); + AudioLoop* file_tone = _manager->getTelephoneFile(); if (tone != 0) { - toGet = framesPerBuffer; - out = (SFLDataFormat*) pa_xmalloc (toGet * sizeof (SFLDataFormat)); - tone->getNext (out, toGet , 100); - pa_stream_write (playback->pulseStream(), out, toGet * sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE); + if (playback->getStreamState() == PA_STREAM_READY) + { + + toGet = framesPerBuffer; + out = (SFLDataFormat*) pa_xmalloc (toGet * sizeof (SFLDataFormat)); + tone->getNext (out, toGet , 100); + pa_stream_write (playback->pulseStream(), out, toGet * sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE); - pa_xfree (out); + pa_xfree (out); + } } - if ( (tone=_manager->getTelephoneFile()) != 0) { + if (file_tone != 0) { + + if (playback->getStreamState() == PA_STREAM_READY) + { - toGet = framesPerBuffer; - toPlay = ( (int) (toGet * sizeof (SFLDataFormat)) > framesPerBuffer) ? framesPerBuffer : toGet * sizeof (SFLDataFormat) ; - out = (SFLDataFormat*) pa_xmalloc (toPlay); - tone->getNext (out, toPlay/2 , 100); - pa_stream_write (playback->pulseStream(), out, toPlay, NULL, 0, PA_SEEK_RELATIVE); + toGet = framesPerBuffer; + toPlay = ( (int) (toGet * sizeof (SFLDataFormat)) > framesPerBuffer) ? framesPerBuffer : toGet * sizeof (SFLDataFormat); + out = (SFLDataFormat*) pa_xmalloc (toPlay); + file_tone->getNext(out, toPlay/2 , 100); + pa_stream_write (playback->pulseStream(), out, toPlay, NULL, 0, PA_SEEK_RELATIVE); - pa_xfree (out); + pa_xfree (out); + } } else { @@ -549,10 +544,11 @@ void PulseLayer::writeToSpeaker (void) } else { - _debug("send zeros......................\n"); + if((tone == 0) && (file_tone == 0)) { - bzero (out, maxNbBytesToGet); - pa_stream_write (playback->pulseStream(), out, maxNbBytesToGet, NULL, 0, PA_SEEK_RELATIVE); + bzero (out, maxNbBytesToGet); + pa_stream_write (playback->pulseStream(), out, maxNbBytesToGet, NULL, 0, PA_SEEK_RELATIVE); + } } _urgentRingBuffer.Discard(toGet); diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.h b/sflphone-common/src/audio/pulseaudio/pulselayer.h index 151fdec00591edae24a8bc1c52d408792663f4bc..e4a4981e570ff6af9a774e82e9a7b396082d270a 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.h +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.h @@ -172,7 +172,7 @@ class PulseLayer : public AudioLayer { /** * Close the connection with the local pulseaudio server */ - bool disconnectPulseAudioServer( void ); + bool disconnectAudioStream( void ); /** * Get some information about the pulseaudio server diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index 4055a143f154e96379c5d56054ac22e76aa11eed..5491f2fe9d44ecc3c7ad645ba6bda9daf1dc3a07 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -372,6 +372,7 @@ ManagerImpl::answerCall (const CallID& call_id) } + if (!getAccountLink (account_id)->answer (call_id)) { // error when receiving... removeCallAccount (call_id); @@ -427,10 +428,12 @@ ManagerImpl::hangupCall (const CallID& call_id) int nbCalls = getCallList().size(); + // _debug("nbCalls: %i\n", nbCalls); + audiolayer = getAudioDriver(); // stop streams - if (! (nbCalls >= 1)) + if (nbCalls <= 1) { _debug(" hangupCall: stop audio stream, ther is only %i call(s) remaining\n", nbCalls); audiolayer->stopStream(); @@ -775,7 +778,20 @@ ManagerImpl::refuseCall (const CallID& id) AccountID accountid; bool returnValue; - stopTone (true); + stopTone (false); + + + int nbCalls = getCallList().size(); + + // AudioLayer* audiolayer = getAudioDriver(); + + if (nbCalls <= 1) + { + _debug(" hangupCall: stop audio stream, ther is only %i call(s) remaining\n", nbCalls); + + AudioLayer* audiolayer = getAudioDriver(); + audiolayer->stopStream(); + } /* Direct IP to IP call */ @@ -807,6 +823,8 @@ ManagerImpl::refuseCall (const CallID& id) switchCall (""); } + + return returnValue; } @@ -1683,6 +1701,8 @@ ManagerImpl::playDtmf (char code, bool isTalking) // Put buffer to urgentRingBuffer // put the size in bytes... // so size * 1 channel (mono) * sizeof (bytes for the data) + audiolayer->flushUrgent(); + audiolayer->startStream(); audiolayer->putUrgent (buf, size * sizeof (SFLDataFormat)); } @@ -1895,6 +1915,18 @@ ManagerImpl::peerHungupCall (const CallID& call_id) if (isCurrentCall(call_id)) { stopTone (true); + + int nbCalls = getCallList().size(); + + // stop streams + if (nbCalls <= 1) + { + _debug(" hangupCall: stop audio stream, ther is only %i call(s) remaining\n", nbCalls); + + AudioLayer* audiolayer = getAudioDriver(); + audiolayer->stopStream(); + } + switchCall (""); } } @@ -1998,6 +2030,12 @@ bool ManagerImpl::playATone (Tone::TONEID toneId) audiolayer = getAudioDriver(); + + if (audiolayer) { + audiolayer->startStream(); + audiolayer->flushUrgent(); + } + if (_telephoneTone != 0) { _toneMutex.enterMutex(); _telephoneTone->setCurrentTone (toneId); @@ -2007,6 +2045,7 @@ bool ManagerImpl::playATone (Tone::TONEID toneId) nbSamples = audioloop->getSize(); SFLDataFormat buf[nbSamples]; + if (audiolayer) { audiolayer->putUrgent (buf, nbSamples); } else @@ -2130,12 +2169,8 @@ ManagerImpl::ringtone() _audiofile.start(); _toneMutex.leaveMutex(); - if (CHECK_INTERFACE (layer, ALSA)) { - //ringback(); - - } else { - audiolayer->startStream(); - } + audiolayer->startStream(); + } else { ringback(); } @@ -2186,6 +2221,7 @@ void ManagerImpl::notificationIncomingCall (void) SFLDataFormat buf[nbSampling]; tone.getNext (buf, tone.getSize()); /* Put the data in the urgent ring buffer */ + audiolayer->flushUrgent(); audiolayer->putUrgent (buf, sizeof (SFLDataFormat) *nbSampling); } } diff --git a/sflphone-common/test/audiolayerTest.cpp b/sflphone-common/test/audiolayerTest.cpp index 92648bc20166977365ad0d5b0a34b7954f9e575e..1cdb792598329c7cbf492b68d5bc4cd4435a89c3 100644 --- a/sflphone-common/test/audiolayerTest.cpp +++ b/sflphone-common/test/audiolayerTest.cpp @@ -169,7 +169,7 @@ void AudioLayerTest::testPulseConnect() CPPUNIT_ASSERT (_pulselayer->getRecordStream()->getStreamState() == 1); // usleep(1000000); - CPPUNIT_ASSERT (_pulselayer->disconnectPulseAudioServer() == true); + CPPUNIT_ASSERT (_pulselayer->disconnectAudioStream() == true); }