From 608ed45f1c2175a7b0e10c5c70da0fc22319d380 Mon Sep 17 00:00:00 2001 From: Alexandre Savard <alexandre.savard@savoirfairelinux.net> Date: Thu, 22 Oct 2009 13:39:16 -0400 Subject: [PATCH] [#2333] Change (again) Pulseaudio settings to fit logiteck usb hdw requirement --- sflphone-client-gnome/doc/C/sflphone.xml | 52 +++++++++++-------- .../src/audio/pulseaudio/audiostream.cpp | 22 ++++---- .../src/audio/pulseaudio/pulselayer.cpp | 43 +++++++++++++-- .../src/audio/pulseaudio/pulselayer.h | 2 + sflphone-common/src/managerimpl.cpp | 9 ++++ 5 files changed, 90 insertions(+), 38 deletions(-) diff --git a/sflphone-client-gnome/doc/C/sflphone.xml b/sflphone-client-gnome/doc/C/sflphone.xml index 00cb6a6d18..07f31faa79 100644 --- a/sflphone-client-gnome/doc/C/sflphone.xml +++ b/sflphone-client-gnome/doc/C/sflphone.xml @@ -99,8 +99,11 @@ <application>SFLphone</application> is a free software and is distributed under the GNU General Public License version 3. It is developed by Savoir-Faire Linux, a Canadian Linux consulting company, in partnership with the global community. </para> <para> - Among the many features we developed for you, we could highlight the high definition sound (wide-band audio codecs - speex, G722, Celt), audio recording, voicemail notification and call history. - More than a simple softphone, <application>SFLphone</application> supports advanced enterprise-class call features: unlimited number of calls, call transfer and on/off hold option. + Among the many features we developed for you, we could + highlight the high definition sound (wide-band audio + codecs - speex, G722, Celt), multiple conference call, + audio recording, voicemail notification, and call history. + More than a simple softphone, <application>SFLphone</application> supports advanced enterprise-class call features: unlimited number of calls, call transfer, and on/off hold option. </para> <para> This release also provides advanced security features (secure RTP and TLS). @@ -137,7 +140,8 @@ <sect1 id="accounts"> <title>Managing your accounts</title> <para> - <application>SFLphone</application> supports both IAX2 and SIP accounts. + <application>SFLphone</application> supports both IAX2 + and SIP accounts. </para> <sect2 id="accounts_basic"> @@ -507,36 +511,34 @@ </sect2> <sect2 id="conferencecall" label="Conference calls"> - <para>SFLphone now supports conference calling - integrating server like features in a simple - GUI.</para> + <para>SFLphone now supports conference call hosting + integrating server like features in a simple GUI. + </para> <para> <itemizedlist> <listitem> <guilabel>Create a conference</guilabel> - <para>To create a conference, drag and drop one call + <para>To host a conference, simply drag and drop one call on another. Additional participants are added the same way, dragging a call on the - conference icon. SFLphone automatically - includes into the newly created conference. + conference icon. </para> </listitem> <listitem> <guilabel>Leave a conference</guilabel> <para> - The Main Participant may leave at any time to - answer any other incoming communication or initiate - new ones. The conference is not interupted if Main - Participant left it. Double clicking the conference - let the Main Participant reintroduce - the conference. + SFLphone conference model let you leave a conference that + you are currently hosting to answer any other incoming + communication or even initiate new ones. The conference is + not interupted Double clicking the conference icon + let you reintroduce the conference. </para> </listitem> <listitem> <guilabel>Multiple conference</guilabel> <para> SFLphone supports multiple conferences running - simultaneously. Conferences may be joined the same way + simultaneously. Two conferences can be joined the same way they are created, dragging one on the other. </para> @@ -582,33 +584,39 @@ <para> <itemizedlist> <listitem> - <guilabel>PCMU</guilabel> + <guilabel>PCMU/PCMA</guilabel> <para> + ITU-T telefony standard PCM formats, 8kHz, 64 + kbit/s, using logarithmic byte compression algorithm. </para> </listitem> - <listitem> - <guilabel>PCMA</guilabel> - <para> - </para> - </listitem> <listitem> <guilabel>GSM</guilabel> <para> + Global System for Mobile communications (GSM) + narrowband 8kHz standard based on linear prediction encoding. </para> </listitem> <listitem> <guilabel>G722</guilabel> <para> + ITU-T standard wideband 16kHz standard based on linear prediction. </para> </listitem> <listitem> <guilabel>SPEEX</guilabel> <para> + High quality voice encoding/decoding available + in narrowband 8Khz, wideband 16khz (HD Voice), + and ultra-wideband 32 kHz. + Integrate additional features such as Variable Bit + Rate (VBR) and noise reduction. </para> </listitem> <listitem> <guilabel>CELT</guilabel> <para> + </para> </listitem> </itemizedlist> diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.cpp b/sflphone-common/src/audio/pulseaudio/audiostream.cpp index 54309276ec..5e10a6b91f 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.cpp +++ b/sflphone-common/src/audio/pulseaudio/audiostream.cpp @@ -184,27 +184,27 @@ AudioStream::createStream (pa_context* c) // parameters are defined as number of bytes // 2048 bytes (1024 int16) is 20 ms at 44100 Hz if (_streamType == PLAYBACK_STREAM) { - attributes->maxlength = 16000; - attributes->tlength = 8192; + attributes->maxlength = 88200; + attributes->tlength = 22050; attributes->prebuf = 4096; // Pulseaudio will not start if prebuffering is not reached - attributes->minreq = 2048; // The server side playback framesize - attributes->fragsize = 4096; // Fragment size at wich we receive an interupt - pa_stream_connect_playback( s , NULL , attributes, PA_STREAM_INTERPOLATE_TIMING, &_volume, NULL); + attributes->minreq = 2048; // The server side playback framesize + attributes->fragsize = 11025; // Fragment size at wich we receive an interupt + pa_stream_connect_playback( s , NULL , attributes, PA_STREAM_NOFLAGS, &_volume, NULL); // pa_stream_connect_playback (s , NULL , attributes, PA_STREAM_START_CORKED, &_volume, NULL); } else if (_streamType == CAPTURE_STREAM) { // attributes->maxlength = 66500; // attributes->fragsize = (uint32_t)-1; - attributes->maxlength = 32000; - attributes->tlength = (uint32_t)-1; - attributes->prebuf = (uint32_t)-1; - attributes->minreq = (uint32_t)-1; - attributes->fragsize = 4096; + attributes->maxlength = 88200; + attributes->tlength = 22050; + attributes->prebuf = 4096; + attributes->minreq = 2048; + attributes->fragsize = 11025; // pa_stream_connect_record (s , NULL , attributes , PA_STREAM_START_CORKED); // pa_stream_connect_record( s , NULL , attributes , PA_STREAM_INTERPOLATE_TIMING ); - pa_stream_connect_record( s, NULL, NULL, PA_STREAM_INTERPOLATE_TIMING ); + pa_stream_connect_record( s, NULL, NULL, PA_STREAM_NOFLAGS); } else if (_streamType == UPLOAD_STREAM) { pa_stream_connect_upload (s , 1024); } else { diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index e46e1e9524..7801582cb7 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -30,6 +30,7 @@ static void playback_callback (pa_stream* s, size_t bytes, void* userdata) assert (s && bytes); assert (bytes > 0); static_cast<PulseLayer*> (userdata)->processPlaybackData(); + // static_cast<PulseLayer*> (userdata)->processData(); } static void capture_callback (pa_stream* s, size_t bytes, void* userdata) @@ -39,6 +40,7 @@ static void capture_callback (pa_stream* s, size_t bytes, void* userdata) assert(s && bytes); assert(bytes > 0); static_cast<PulseLayer*> (userdata)->processCaptureData(); + // static_cast<PulseLayer*> (userdata)->processData(); } @@ -357,12 +359,15 @@ void PulseLayer::startStream (void) // Create Streams connectPulseAudioServer(); - _urgentRingBuffer.flushAll(); - _mainBuffer.flushAllBuffers(); + // _urgentRingBuffer.flushAll(); + // _mainBuffer.flushAllBuffers(); is_started = true; } + _urgentRingBuffer.flushAll(); + _mainBuffer.flushAllBuffers(); + } void @@ -451,6 +456,30 @@ void PulseLayer::processCaptureData(void) } + +void PulseLayer::processData(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; + + 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) { /** Bytes available in the urgent ringbuffer ( reserved for DTMF ) */ @@ -471,9 +500,9 @@ void PulseLayer::writeToSpeaker (void) urgentAvailBytes = _urgentRingBuffer.AvailForGet(); - if (urgentAvailBytes > 0) { + if (urgentAvailBytes > (framesPerBuffer*sizeof(SFLDataFormat))) { - // _debug("urgentAvailBytes: %i\n", urgentAvailBytes); + _debug("urgentAvailBytes: %i\n", urgentAvailBytes); toGet = (urgentAvailBytes < (int) (framesPerBuffer * sizeof (SFLDataFormat))) ? urgentAvailBytes : framesPerBuffer * sizeof (SFLDataFormat); out = (SFLDataFormat*) pa_xmalloc (toGet * sizeof (SFLDataFormat)); @@ -490,6 +519,8 @@ void PulseLayer::writeToSpeaker (void) AudioLoop* tone = _manager->getTelephoneTone(); AudioLoop* file_tone = _manager->getTelephoneFile(); + _urgentRingBuffer.flushAll(); + if (tone != 0) { if (playback->getStreamState() == PA_STREAM_READY) @@ -577,12 +608,14 @@ void PulseLayer::writeToSpeaker (void) if((tone == 0) && (file_tone == 0)) { // _debug("maxNbBytesToGet: %i\n", maxNbBytesToGet); + SFLDataFormat* zeros = (SFLDataFormat*)pa_xmalloc (framesPerBuffer*sizeof(SFLDataFormat)); bzero (zeros, framesPerBuffer*sizeof(SFLDataFormat)); pa_stream_write(playback->pulseStream(), zeros, framesPerBuffer*sizeof(SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE); pa_xfree (zeros); + } } @@ -603,7 +636,7 @@ void PulseLayer::readFromMic (void) size_t r; 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) )); + _debug("pa_stream_peek() failed: %s\n" , pa_strerror( pa_context_errno( context) )); } if (data != 0) { diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.h b/sflphone-common/src/audio/pulseaudio/pulselayer.h index e4a4981e57..4e7e30e816 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.h +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.h @@ -133,6 +133,8 @@ class PulseLayer : public AudioLayer { void processPlaybackData( void ); void processCaptureData( void ); + + void processData(void); private: // Copy Constructor diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index 95293f6dc5..21b400a822 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -1651,6 +1651,8 @@ ManagerImpl::playDtmf (char code, bool isTalking) AudioLayer *audiolayer; SFLDataFormat *buf; + _debug("ManagerImpl::playDtmf\n"); + stopTone (false); bool hasToPlayTone = getConfigBool (SIGNALISATION, PLAY_DTMF); @@ -1689,6 +1691,9 @@ ManagerImpl::playDtmf (char code, bool isTalking) // ms/s size = (int) ((pulselen * (float) audiolayer->getSampleRate()) / 1000); + _debug("DTMF pulselen: %i\n", pulselen); + _debug("DTMF size: %i\n", size); + // this buffer is for mono // TODO <-- this should be global and hide if same size buf = new SFLDataFormat[size]; @@ -2023,6 +2028,8 @@ bool ManagerImpl::playATone (Tone::TONEID toneId) AudioLayer *audiolayer; unsigned int nbSamples; + _debug("ManagerImpl::playATone\n"); + hasToPlayTone = getConfigBool (SIGNALISATION, PLAY_TONES); if (!hasToPlayTone) @@ -2213,6 +2220,8 @@ void ManagerImpl::notificationIncomingCall (void) audiolayer = getAudioDriver(); + _debug("ManagerImpl::notificationIncomingCall\n"); + if (audiolayer != 0) { samplerate = audiolayer->getSampleRate(); frequency << "440/" << FRAME_PER_BUFFER; -- GitLab