diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp index 937faabdfcad4fa2a97f285e8796cbf8dc54590e..48d60a2b0d3e5caba12852d59aac78087ebac96d 100644 --- a/src/audio/audiolayer.cpp +++ b/src/audio/audiolayer.cpp @@ -39,10 +39,9 @@ : _defaultVolume(100) , _errorMessage("") , _manager(manager) - , _playback_handle( NULL ) - , _capture_handle( NULL ) + , _PlaybackHandle( NULL ) + , _CaptureHandle( NULL ) , deviceClosed( true ) - , _mainBuffer( SIZEBUF ) , _urgentBuffer( SIZEBUF ) { @@ -55,17 +54,10 @@ // Destructor AudioLayer::~AudioLayer (void) { + closeCaptureStream(); + closePlaybackStream(); deviceClosed = true; - if(_capture_handle){ - snd_pcm_drop( _capture_handle ); - snd_pcm_close( _capture_handle ); - _capture_handle = 0; - } - if(_playback_handle){ - snd_pcm_drop( _playback_handle ); - snd_pcm_close( _playback_handle ); - _playback_handle = 0; - } + _urgentBuffer.flush(); } @@ -75,22 +67,18 @@ AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize if(deviceClosed == false) { - if( stream == SFL_PCM_CAPTURE ){ - if(_capture_handle) - { - _debugAlsa(" Close the current capture device\n"); - snd_pcm_drop( _capture_handle ); - snd_pcm_close( _capture_handle ); - _capture_handle = 0; - } + if( stream == SFL_PCM_CAPTURE ) + { + closeCaptureStream(); } - else if( stream == SFL_PCM_PLAYBACK){ - if(_playback_handle){ - _debugAlsa(" Close the current playback device\n"); - snd_pcm_drop( _playback_handle ); - snd_pcm_close( _playback_handle ); - _playback_handle = 0; - } + else if( stream == SFL_PCM_PLAYBACK) + { + closePlaybackStream(); + } + else + { + closeCaptureStream(); + closePlaybackStream(); } } @@ -100,20 +88,43 @@ AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize _frameSize = frameSize; _audioPlugin = plugin; - _debug(" Setting audiolayer: device in=%2d, out=%2d\n", _indexIn, _indexOut); - _debug(" : nb channel in=%2d, out=%2d\n", _inChannel, _outChannel); - _debug(" : sample rate=%5d, format=%s\n", _sampleRate, SFLDataFormatString); - _debug(" : frame per buffer=%d\n", FRAME_PER_BUFFER); + _debugAlsa(" Setting audiolayer: device in=%2d, out=%2d\n", _indexIn, _indexOut); + _debugAlsa(" : alsa plugin=%s\n", _audioPlugin.c_str()); + _debugAlsa(" : nb channel in=%2d, out=%2d\n", _inChannel, _outChannel); + _debugAlsa(" : sample rate=%5d, format=%s\n", _sampleRate, SFLDataFormatString); - ost::MutexLock guard( _mutex ); + ost::MutexLock lock( _mutex ); - //std::string plugin = PCM_DEFAULT; - //std::string plugout = PCM_DEFAULT; std::string pcmp = buildDeviceTopo( plugin , indexOut , 0); std::string pcmc = buildDeviceTopo(PCM_SURROUND40 , indexIn , 0); return open_device( pcmp , pcmc , stream); } + void +AudioLayer::startStream(void) +{ + _debugAlsa(" Start stream\n"); + int err; + ost::MutexLock lock( _mutex ); + snd_pcm_prepare( _CaptureHandle ); + snd_pcm_start( _CaptureHandle ) ; + + snd_pcm_prepare( _PlaybackHandle ); + if( err = snd_pcm_start( _PlaybackHandle) < 0 ) _debugAlsa(" Cannot start (%s)\n", snd_strerror(err)); +} + + void +AudioLayer::stopStream(void) +{ + ost::MutexLock lock( _mutex ); + _talk = false; + snd_pcm_drop( _CaptureHandle ); + snd_pcm_prepare( _CaptureHandle ); + snd_pcm_drop( _PlaybackHandle ); + snd_pcm_prepare( _PlaybackHandle ); + _urgentBuffer.flush(); +} + int AudioLayer::getDeviceCount() { @@ -123,7 +134,7 @@ AudioLayer::getDeviceCount() void AudioLayer::AlsaCallBack( snd_async_handler_t* pcm_callback ) { - ( ( AudioLayer *)snd_async_handler_get_callback_private( pcm_callback )) -> updateBuffers(); + ( ( AudioLayer *)snd_async_handler_get_callback_private( pcm_callback )) -> playUrgent(); } void @@ -132,11 +143,10 @@ AudioLayer::fillHWBuffer( void) unsigned char* data; int pcmreturn, l1, l2; short s1, s2; - int frames; - int periodSize = 1024 * 2; + int periodSize = 128 ; + int frames = periodSize >> 2 ; data = (unsigned char*)malloc(periodSize); - frames = periodSize >> 2; for(l1 = 0; l1 < 100; l1++) { for(l2 = 0; l2 < frames; l2++) { s1 = 0; @@ -146,53 +156,18 @@ AudioLayer::fillHWBuffer( void) data[4*l2+2] = (unsigned char)s2; data[4*l2+3] = s2 >> 8; } - /* Write num_frames frames from buffer data to the PCM device pointed to by pcm_handle */ - /* writei for interleaved */ - /* writen for non-interleaved */ - while ((pcmreturn = snd_pcm_writei(_playback_handle, data, frames)) < 0) { - snd_pcm_prepare(_playback_handle); + while ((pcmreturn = snd_pcm_writei(_PlaybackHandle, data, frames)) < 0) { + snd_pcm_prepare(_PlaybackHandle); fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n"); } } -} - - void -AudioLayer::startStream(void) -{ - _debug(" Start stream\n"); - int err; - ost::MutexLock guard( _mutex ); - snd_pcm_prepare( _capture_handle ); - snd_pcm_start( _capture_handle ) ; - - snd_pcm_prepare( _playback_handle ); - - //if( err = snd_pcm_start( _playback_handle) < 0 ) _debugAlsa(" Cannot start (%s)\n", snd_strerror(err)); -} - - - void -AudioLayer::stopStream(void) -{ - ost::MutexLock guard( _mutex ); - snd_pcm_drop( _capture_handle ); - snd_pcm_prepare( _capture_handle ); - snd_pcm_drop( _playback_handle ); - snd_pcm_prepare( _playback_handle ); -} - - - void -AudioLayer::sleep(int msec) -{ - //snd_pcm_wait(_playback_handle, msec); } bool AudioLayer::isStreamActive (void) { - ost::MutexLock guard( _mutex ); + ost::MutexLock lock( _mutex ); return (isPlaybackActive() && isCaptureActive()); } @@ -200,26 +175,20 @@ AudioLayer::isStreamActive (void) int AudioLayer::playSamples(void* buffer, int toCopy) { - //_debug(" Write %d bytes in the main buffer \n ", toCopy); - ost::MutexLock guard( _mutex ); - if ( _playback_handle ){ + ost::MutexLock lock( _mutex ); + _talk = true; + if ( _PlaybackHandle ){ write(buffer, toCopy); } - /* int a = _mainBuffer.AvailForPut(); - if( a >= toCopy ){ - return _mainBuffer.Put( buffer , toCopy , _defaultVolume ); - } else { - return _mainBuffer.Put( buffer , a , _defaultVolume ) ; - }*/ return 0; } int AudioLayer::putUrgent(void* buffer, int toCopy) { + snd_pcm_avail_update( _PlaybackHandle ); fillHWBuffer(); - ost::MutexLock guard( _mutex ); - if ( _playback_handle ) + if ( _PlaybackHandle ) { int a = _urgentBuffer.AvailForPut(); if( a >= toCopy ){ @@ -231,23 +200,12 @@ AudioLayer::putUrgent(void* buffer, int toCopy) return 0; } - void -AudioLayer::stopPlaybackStream( void ) -{ - ost::MutexLock guard( _mutex ); - if( _playback_handle ) - { - snd_pcm_drop( _playback_handle ); - snd_pcm_prepare( _playback_handle ); - } -} - int AudioLayer::canGetMic() { int avail; - if ( _capture_handle ) { - avail = snd_pcm_avail_update( _capture_handle ); + if ( _CaptureHandle ) { + avail = snd_pcm_avail_update( _CaptureHandle ); //printf("%d\n", avail ); if(avail > 0) return avail; @@ -261,7 +219,7 @@ AudioLayer::canGetMic() int AudioLayer::getMic(void *buffer, int toCopy) { - if( _capture_handle ) + if( _CaptureHandle ) return read(buffer, toCopy); else return 0; @@ -271,13 +229,13 @@ AudioLayer::getMic(void *buffer, int toCopy) bool AudioLayer::isStreamStopped (void) { - ost::MutexLock guard( _mutex ); + ost::MutexLock lock( _mutex ); return !(isStreamActive()); } void AudioLayer::toggleEchoTesting() { - ost::MutexLock guard( _mutex ); + ost::MutexLock lock( _mutex ); _echoTesting = (_echoTesting == true) ? false : true; } @@ -289,22 +247,22 @@ AudioLayer::toggleEchoTesting() { void -AudioLayer::updateBuffers( void ) +AudioLayer::playUrgent( void ) { - int toGet; - int urgentAvail; - int bytes = 882 * sizeof(SFLDataFormat); - SFLDataFormat* toWrite[bytes]; - snd_pcm_uframes_t avail = 0; - avail = snd_pcm_avail_update( _playback_handle ); - if( avail ) { - //_debug("%i\n", avail); + int bytes = 1024 * sizeof(SFLDataFormat); + SFLDataFormat toWrite[bytes]; + int urgentAvail = _urgentBuffer.AvailForGet(); + if( _talk ) { + _urgentBuffer.Discard( urgentAvail ); + } + else{ + //_debugAlsa("Callback !!!!!!!!\n"); urgentAvail = _urgentBuffer.AvailForGet(); - if( urgentAvail > 0 ){ + if(urgentAvail > bytes ){ toGet = ( urgentAvail < bytes ) ? urgentAvail : bytes; _urgentBuffer.Get( toWrite , toGet , 100 ); - //write( toWrite , toGet ); + write( toWrite , bytes ); } } } @@ -312,8 +270,8 @@ AudioLayer::updateBuffers( void ) bool AudioLayer::isPlaybackActive(void) { ost::MutexLock guard( _mutex ); - if( _playback_handle ) - return (snd_pcm_state(_playback_handle) == SND_PCM_STATE_RUNNING ? true : false); + if( _PlaybackHandle ) + return (snd_pcm_state(_PlaybackHandle) == SND_PCM_STATE_RUNNING ? true : false); else return false; } @@ -321,8 +279,8 @@ AudioLayer::isPlaybackActive(void) { bool AudioLayer::isCaptureActive(void) { ost::MutexLock guard( _mutex ); - if( _capture_handle ) - return (snd_pcm_state( _capture_handle) == SND_PCM_STATE_RUNNING ? true : false); + if( _CaptureHandle ) + return (snd_pcm_state( _CaptureHandle) == SND_PCM_STATE_RUNNING ? true : false); else return false; } @@ -340,82 +298,73 @@ AudioLayer::open_device(std::string pcm_p, std::string pcm_c, int flag) snd_pcm_uframes_t buffer_size_in = 4096; snd_pcm_uframes_t threshold = getFrameSize() * getSampleRate() / 1000 ; snd_pcm_uframes_t period_size_out = 1024 ; + unsigned int period_time = 20; snd_pcm_uframes_t buffer_size_out = 4096 ; snd_pcm_sw_params_t *swparams = NULL; if(flag == SFL_PCM_BOTH || flag == SFL_PCM_CAPTURE) { - _debug(" Opening capture device %s\n", pcm_c.c_str()); - if(err = snd_pcm_open(&_capture_handle, pcm_c.c_str(), SND_PCM_STREAM_CAPTURE, 0) < 0){ - _debug(" Error while opening capture device %s (%s)\n", pcm_c.c_str(), snd_strerror(err)); + _debugAlsa(" Opening capture device %s\n", pcm_c.c_str()); + if(err = snd_pcm_open(&_CaptureHandle, pcm_c.c_str(), SND_PCM_STREAM_CAPTURE, 0) < 0){ + _debugAlsa(" Error while opening capture device %s (%s)\n", pcm_c.c_str(), snd_strerror(err)); return false; } if( err = snd_pcm_hw_params_malloc( &hwparams ) < 0 ) { - _debug(" Cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); + _debugAlsa(" Cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); return false; } - if( err = snd_pcm_hw_params_any(_capture_handle, hwparams) < 0) _debug(" Cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_access( _capture_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) _debug(" Cannot set access type (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_format( _capture_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) _debug(" Cannot set sample format (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_rate_near( _capture_handle, hwparams, &rate_in, &dir) < 0) _debug(" Cannot set sample rate (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_channels( _capture_handle, hwparams, 1) < 0) _debug(" Cannot set channel count (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_period_size_near( _capture_handle, hwparams, &period_size_in , &dir) < 0) _debug(" Cannot set period size (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_buffer_size_near( _capture_handle, hwparams, &buffer_size_in ) < 0) _debug(" Cannot set buffer size (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params( _capture_handle, hwparams ) < 0) _debug(" Cannot set hw parameters (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_any(_CaptureHandle, hwparams) < 0) _debugAlsa(" Cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_access( _CaptureHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) _debugAlsa(" Cannot set access type (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_format( _CaptureHandle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) _debugAlsa(" Cannot set sample format (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_rate_near( _CaptureHandle, hwparams, &rate_in, &dir) < 0) _debugAlsa(" Cannot set sample rate (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_channels( _CaptureHandle, hwparams, 1) < 0) _debugAlsa(" Cannot set channel count (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_period_size_near( _CaptureHandle, hwparams, &period_size_in , &dir) < 0) _debugAlsa(" Cannot set period size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_buffer_size_near( _CaptureHandle, hwparams, &buffer_size_in ) < 0) _debugAlsa(" Cannot set buffer size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params( _CaptureHandle, hwparams ) < 0) _debugAlsa(" Cannot set hw parameters (%s)\n", snd_strerror(err)); snd_pcm_hw_params_free( hwparams ); - //snd_pcm_sw_params_malloc( &swparams ); - //snd_pcm_sw_params_current( _capture_handle, swparams ); - - //if( err = snd_pcm_sw_params_set_start_threshold( _capture_handle, swparams, 1 ) < 0 ) _debug(" Cannot set start threshold (%s)\n", snd_strerror(err)); - //if( err = snd_pcm_sw_params_set_stop_threshold( _capture_handle, swparams, buffer_size_in ) < 0 ) _debug(" Cannot get stop threshold (%s)\n", snd_strerror(err)); - //if( err = snd_pcm_sw_params( _capture_handle, swparams ) < 0 ) _debug(" Cannot set sw parameters (%s)\n", snd_strerror(err)); deviceClosed = false; - //snd_pcm_sw_params_free( swparams ); } if(flag == SFL_PCM_BOTH || flag == SFL_PCM_PLAYBACK) { - _debug(" Opening playback device %s\n", pcm_p.c_str()); - if(err = snd_pcm_open(&_playback_handle, pcm_p.c_str(), SND_PCM_STREAM_PLAYBACK, 0 ) < 0){ - _debug(" Error while opening playback device %s (%s)\n", pcm_p.c_str(), snd_strerror(err)); + _debugAlsa(" Opening playback device %s\n", pcm_p.c_str()); + if(err = snd_pcm_open(&_PlaybackHandle, pcm_p.c_str(), SND_PCM_STREAM_PLAYBACK, 0 ) < 0){ + _debugAlsa(" Error while opening playback device %s (%s)\n", pcm_p.c_str(), snd_strerror(err)); return false; } if( err = snd_pcm_hw_params_malloc( &hwparams ) < 0 ) { - _debug(" Cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); + _debugAlsa(" Cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); return false; } - if( err = snd_pcm_hw_params_any( _playback_handle, hwparams) < 0) _debug(" Cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_access( _playback_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) _debug(" Cannot set access type (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_format( _playback_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) _debug(" Cannot set sample format (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_rate_near( _playback_handle, hwparams, &rate_out, &dir) < 0) _debug(" Cannot set sample rate (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_channels( _playback_handle, hwparams, 1) < 0) _debug(" Cannot set channel count (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_period_size_near( _playback_handle, hwparams, &period_size_out , &dir) < 0) _debug(" Cannot set period size (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params_set_buffer_size_near( _playback_handle, hwparams, &buffer_size_out ) < 0) _debug(" Cannot set buffer size (%s)\n", snd_strerror(err)); - if( err = snd_pcm_hw_params( _playback_handle, hwparams ) < 0) _debug(" Cannot set hw parameters (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_any( _PlaybackHandle, hwparams) < 0) _debugAlsa(" Cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_access( _PlaybackHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) _debugAlsa(" Cannot set access type (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_format( _PlaybackHandle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) _debugAlsa(" Cannot set sample format (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_rate_near( _PlaybackHandle, hwparams, &rate_out, &dir) < 0) _debugAlsa(" Cannot set sample rate (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_channels( _PlaybackHandle, hwparams, 1) < 0) _debugAlsa(" Cannot set channel count (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_period_size_near( _PlaybackHandle, hwparams, &period_size_out , &dir) < 0) _debugAlsa(" Cannot set period size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_period_time_min( _PlaybackHandle, hwparams, &period_time , &dir) < 0) _debugAlsa(" Cannot set period time (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_buffer_size_near( _PlaybackHandle, hwparams, &buffer_size_out ) < 0) _debugAlsa(" Cannot set buffer size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params( _PlaybackHandle, hwparams ) < 0) _debugAlsa(" Cannot set hw parameters (%s)\n", snd_strerror(err)); snd_pcm_hw_params_free( hwparams ); snd_pcm_uframes_t val = 1024 ; snd_pcm_sw_params_malloc( &swparams ); - snd_pcm_sw_params_current( _playback_handle, swparams ); + snd_pcm_sw_params_current( _PlaybackHandle, swparams ); - if( err = snd_pcm_sw_params_set_start_threshold( _playback_handle, swparams, period_size_out ) < 0 ) _debug(" Cannot set start threshold (%s)\n", snd_strerror(err)); - //if( err = snd_pcm_sw_params_set_stop_threshold( _playback_handle, swparams, buffer_size_out ) < 0 ) _debug(" Cannot set stop threshold (%s)\n", snd_strerror(err)); - if( err = snd_pcm_sw_params_set_avail_min( _playback_handle, swparams, period_size_out) < 0) _debug(" Cannot set min avail (%s)\n" , snd_strerror(err)); - if( err = snd_pcm_sw_params_set_xfer_align( _playback_handle , swparams , 1 ) < 0) _debug( "Cannot align transfer (%s)\n", snd_strerror(err)); - if( err = snd_pcm_sw_params( _playback_handle, swparams ) < 0 ) _debug(" Cannot set sw parameters (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params_set_start_threshold( _PlaybackHandle, swparams, 1024 ) < 0 ) _debugAlsa(" Cannot set start threshold (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params_set_start_mode( _PlaybackHandle, swparams, SND_PCM_START_DATA ) < 0 ) _debugAlsa(" Cannot set start mode (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params_set_avail_min( _PlaybackHandle, swparams, 1) < 0) _debugAlsa(" Cannot set min avail (%s)\n" , snd_strerror(err)); + if( err = snd_pcm_sw_params_set_xfer_align( _PlaybackHandle , swparams , 1 ) < 0) _debugAlsa( "Cannot align transfer (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params( _PlaybackHandle, swparams ) < 0 ) _debugAlsa(" Cannot set sw parameters (%s)\n", snd_strerror(err)); snd_pcm_sw_params_free( swparams ); - if ( err = snd_async_add_pcm_handler( &_AsyncHandler, _playback_handle , AlsaCallBack, this ) < 0) _debugAlsa(" Unable to install the async callback handler (%s)\n", snd_strerror(err)); + if ( err = snd_async_add_pcm_handler( &_AsyncHandler, _PlaybackHandle , AlsaCallBack, this ) < 0) _debugAlsa(" Unable to install the async callback handler (%s)\n", snd_strerror(err)); deviceClosed = false; - - //fillHWBuffer(); - - //if( err = snd_pcm_start(_playback_handle ) < 0 ) _debug(" Cannot start\n"); - } + _talk = false; return true; } @@ -425,32 +374,14 @@ AudioLayer::open_device(std::string pcm_p, std::string pcm_c, int flag) AudioLayer::write(void* buffer, int length) { int bytes; - /* if(deviceClosed || _playback_handle == NULL) - return 0; - int framesPerBuffer = 882; - bool playUrgent = false; - SFLDataFormat ringtone[ framesPerBuffer ]; - AudioLoop* tone = _manager->getTelephoneTone(); - if( tone != 0){ - _debug("Play tone \n"); - tone->getNext(ringtone, framesPerBuffer , _manager->getSpkrVolume()); - playUrgent = true; - } - else if( (tone=_manager->getTelephoneFile()) != 0 ){ - _debug("Play tone also \n"); - tone->getNext(ringtone, framesPerBuffer , _manager->getSpkrVolume()); - playUrgent = true; - } - - int bytes;*/ - snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames( _playback_handle, length); - - bytes = snd_pcm_writei( _playback_handle, buffer, frames); + snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames( _PlaybackHandle, length); + + bytes = snd_pcm_writei( _PlaybackHandle, buffer, frames); if( bytes == -EAGAIN) { _debugAlsa(" (%s)\n", snd_strerror( bytes )); - snd_pcm_resume( _playback_handle ); + snd_pcm_resume( _PlaybackHandle ); } else if(bytes >=0 && bytes < frames) { @@ -458,22 +389,19 @@ AudioLayer::write(void* buffer, int length) } else if( bytes == -EPIPE ) { - _debugAlsa(" %d Alsa error from writei (%s)\n", bytes, snd_strerror(bytes)); - snd_pcm_prepare( _playback_handle ); - snd_pcm_writei( _playback_handle , buffer , frames ); + //_debugAlsa(" %d Alsa error from writei (%s)\n", bytes, snd_strerror(bytes)); + snd_pcm_prepare( _PlaybackHandle ); + snd_pcm_writei( _PlaybackHandle , buffer , frames ); } else if( bytes == -ESTRPIPE ) { _debugAlsa(" Playback suspend (%s)\n", snd_strerror(bytes)); - snd_pcm_resume( _playback_handle ); + snd_pcm_resume( _PlaybackHandle ); } else if( bytes == -EBADFD) { _debugAlsa(" PCM is not in the right state (%s)\n", snd_strerror( bytes )); } - snd_pcm_sframes_t delay; - //snd_pcm_delay( _playback_handle, &delay); - //snd_pcm_avail_update( _playback_handle ); return 0; } @@ -482,31 +410,31 @@ AudioLayer::write(void* buffer, int length) AudioLayer::read( void* buffer, int toCopy) { - if(deviceClosed || _capture_handle == NULL) + if(deviceClosed || _CaptureHandle == NULL) return 0; int err; - if(snd_pcm_state( _capture_handle ) == SND_PCM_STATE_XRUN) - snd_pcm_prepare( _capture_handle ); - snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames( _capture_handle, toCopy ); - if( err = snd_pcm_readi( _capture_handle, buffer, frames) < 0 ) { + if(snd_pcm_state( _CaptureHandle ) == SND_PCM_STATE_XRUN) + snd_pcm_prepare( _CaptureHandle ); + snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames( _CaptureHandle, toCopy ); + if( err = snd_pcm_readi( _CaptureHandle, buffer, frames) < 0 ) { switch(err){ case EPERM: - _debug(" Capture EPERM (%s)\n", snd_strerror(err)); + _debugAlsa(" Capture EPERM (%s)\n", snd_strerror(err)); //handle_xrun_state(); - snd_pcm_prepare( _capture_handle); + snd_pcm_prepare( _CaptureHandle); break; case -ESTRPIPE: - _debug(" Capture ESTRPIPE (%s)\n", snd_strerror(err)); - snd_pcm_resume( _capture_handle); + _debugAlsa(" Capture ESTRPIPE (%s)\n", snd_strerror(err)); + snd_pcm_resume( _CaptureHandle); break; case -EAGAIN: - _debug(" Capture EAGAIN (%s)\n", snd_strerror(err)); + _debugAlsa(" Capture EAGAIN (%s)\n", snd_strerror(err)); break; case -EBADFD: - _debug(" Capture EBADFD (%s)\n", snd_strerror(err)); + _debugAlsa(" Capture EBADFD (%s)\n", snd_strerror(err)); break; case -EPIPE: - _debug(" Capture EPIPE (%s)\n", snd_strerror(err)); + _debugAlsa(" Capture EPIPE (%s)\n", snd_strerror(err)); handle_xrun_state(); break; } @@ -523,16 +451,16 @@ AudioLayer::handle_xrun_state( void ) snd_pcm_status_t* status; snd_pcm_status_alloca( &status ); - int res = snd_pcm_status( _capture_handle, status ); + int res = snd_pcm_status( _CaptureHandle, status ); if( res <= 0){ if(snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN ){ - snd_pcm_drop( _capture_handle ); - snd_pcm_prepare( _capture_handle ); - snd_pcm_start( _capture_handle ); + snd_pcm_drop( _CaptureHandle ); + snd_pcm_prepare( _CaptureHandle ); + snd_pcm_start( _CaptureHandle ); } } else - _debug(" Get status failed\n"); + _debugAlsa(" Get status failed\n"); } std::string @@ -583,9 +511,9 @@ AudioLayer::getSoundCardsInfo( int flag ) else snd_pcm_info_set_stream( pcminfo, SND_PCM_STREAM_PLAYBACK ); - if( snd_ctl_pcm_info ( handle ,pcminfo ) < 0) _debug(" Cannot get info\n"); + if( snd_ctl_pcm_info ( handle ,pcminfo ) < 0) _debugAlsa(" Cannot get info\n"); else{ - _debug("card %i : %s [%s]- device %i : %s [%s] \n - driver %s - dir %i\n", + _debugAlsa("card %i : %s [%s]- device %i : %s [%s] \n - driver %s - dir %i\n", numCard, snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_name( info ), @@ -610,3 +538,27 @@ AudioLayer::getSoundCardsInfo( int flag ) return cards_id; } +void +AudioLayer::closeCaptureStream( void) +{ + if(_CaptureHandle){ + _debugAlsa(" Close the current capture device\n"); + snd_pcm_drop( _CaptureHandle ); + snd_pcm_close( _CaptureHandle ); + _CaptureHandle = 0; + } +} + +void +AudioLayer::closePlaybackStream( void) +{ + if(_PlaybackHandle){ + _debugAlsa(" Close the current playback device\n"); + snd_pcm_drop( _PlaybackHandle ); + snd_pcm_close( _PlaybackHandle ); + _PlaybackHandle = 0; + } +} + + + diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h index d60e4fe95fb2b701bc08c47f79a37a9933224bbd..9de4610cab846d15c8bb4370db07d55bc6a82845 100644 --- a/src/audio/audiolayer.h +++ b/src/audio/audiolayer.h @@ -53,30 +53,28 @@ class AudioLayer { * @param indexOut The number of the card choosen for playback * @param sampleRate The sample rate * @param frameSize The frame size - * @param flag To indicate which kind of stream you want to open + * @param stream To indicate which kind of stream you want to open * SFL_PCM_CAPTURE * SFL_PCM_PLAYBACK * SFL_PCM_BOTH + * @param plugin The alsa plugin ( dmix , default , front , surround , ...) */ bool openDevice(int, int, int, int, int, std::string); /* - * Start the capture stream. The playback starts according th its threshold + * Start the capture stream and prepare the playback stream. + * The playback starts accordingly to its threshold * ALSA Library API */ void startStream(void); /* - * Stop the capture stream. The playback stops according to its threshold - * Drops the pending frames and put the capture handle to PREPARED state + * Stop the playback and capture streams. + * Drops the pending frames and put the capture and playback handles to PREPARED state * ALSA Library API */ void stopStream(void); - void fillHWBuffer( void) ; - - void sleep(int); - /* * Check if the playback is running * @return true if the state of the playback handle equals SND_PCM_STATE_RUNNING @@ -106,18 +104,24 @@ class AudioLayer { bool isStreamStopped(void); /* - * Send samples to the audio device - * @params buffer The buffer containing the data to be played + * Send samples to the audio device. + * @params buffer The buffer containing the data to be played ( voice and DTMF ) * @params toCopy The number of samples, in bytes * @return int The number of bytes played */ int playSamples(void* buffer, int toCopy); - int putUrgent(void* buffer, int toCopy); - void stopPlaybackStream( void ); + /* + * Send a chunk of data to the hardware buffer to start the playback + * Copy data in the urgent buffer. + * @params buffer The buffer containing the data to be played ( ringtones ) + * @params toCopy The size of the buffer + * @return int The number of bytes copied in the urgent buffer + */ + int putUrgent(void* buffer, int toCopy); /* - * Query the audio devices for number of bytes available in the hardware ring buffer + * Query the capture device for number of bytes available in the hardware ring buffer * @return int The number of bytes available */ int canGetMic(); @@ -149,11 +153,9 @@ class AudioLayer { */ std::vector<std::string> getSoundCardsInfo( int flag ); - void setErrorMessage(const std::string& error) { _errorMessage = error; } std::string getErrorMessage() { return _errorMessage; } - /* * Get the index of the audio card for capture * @return _indexIn The index of the card used for capture @@ -182,8 +184,19 @@ class AudioLayer { */ unsigned int getFrameSize() { return _frameSize; } + /* + * Get the current audio plugin. + * @return std::string The name of the audio plugin + */ std::string getAudioPlugin( void ) { return _audioPlugin; } + /* + * Get the current state. Conversation or not + * @return bool true if playSamples has been called + * false otherwise + */ + bool getCurrentState( void ) { return _talk; } + int getDeviceCount(); /** @@ -194,13 +207,34 @@ class AudioLayer { private: + /* + * Drop the pending frames and close the capture device + * ALSA Library API + */ + void closeCaptureStream( void ); + + /* + * Drop the pending frames and close the playback device + * ALSA Library API + */ + void closePlaybackStream( void ); + + /* + * Fill the alsa internal ring buffer with chunks of data + */ + void fillHWBuffer( void) ; + + /* + * Callback used for asynchronous playback. + * Called when a certain amount of data is written ot the device + */ static void AlsaCallBack( snd_async_handler_t* ); - snd_async_handler_t *_AsyncHandler; - snd_pcm_t* _playback_handle; - snd_pcm_t* _capture_handle; - RingBuffer _urgentBuffer; - RingBuffer _mainBuffer; - void updateBuffers( void ); + + /* + * Callback used for asynchronous playback. + * Write the urgent buffer to the alsa internal ring buffer + */ + void playUrgent( void ); /* * Open the specified device. @@ -241,14 +275,31 @@ class AudioLayer { void handle_xrun_state( void ); ManagerImpl* _manager; // augment coupling, reduce indirect access - // a audiolayer can't live without manager /* * Handle to manipulate capture and playback streams * ALSA Library API */ - + snd_pcm_t* _PlaybackHandle; + snd_pcm_t* _CaptureHandle; + /* + * Handle on asynchronous event + */ + snd_async_handler_t *_AsyncHandler; + + /* + * Urgent ring buffer used for ringtones + */ + RingBuffer _urgentBuffer; + + /* + * Determine if both endpoints hang up. + * true if conversation is running + * false otherwise + */ + bool _talk; + /* * Enable to determine if the devices are opened or not * true if the devices are closed @@ -274,6 +325,9 @@ class AudioLayer { */ unsigned int _frameSize; + /* + * name of the alsa audio plugin used + */ std::string _audioPlugin; /** diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp index e98012be65a914ffcc36f9ccc599c104d9950e1b..eaf4706d6d2af18b8d6afafb8bc34f4256a901f0 100644 --- a/src/managerimpl.cpp +++ b/src/managerimpl.cpp @@ -554,12 +554,12 @@ ManagerImpl::playDtmf(char code) //audiolayer->putUrgent(_buf, size * sizeof(SFLDataFormat)); // We activate the stream if it's not active yet. - if (!audiolayer->isStreamActive()) { + //if (!audiolayer->isStreamActive()) { //audiolayer->startStream(); - } else { - _debugAlsa("send dtmf - sleep\n"); - audiolayer->sleep(pulselen); // in milliseconds - } + //} else { + //_debugAlsa("send dtmf - sleep\n"); + //audiolayer->sleep(pulselen); // in milliseconds + //} } returnValue = true; @@ -817,7 +817,7 @@ ManagerImpl::playATone(Tone::TONEID toneId) { SFLDataFormat buf[nbSampling]; audioloop->getNext(buf, (int) nbSampling); if ( audiolayer ) { - //audiolayer->putUrgent( buf, sizeof(SFLDataFormat)*nbSampling ); + audiolayer->putUrgent( buf, sizeof(SFLDataFormat)*nbSampling ); } else return false; @@ -905,9 +905,8 @@ ManagerImpl::ringtone() _toneMutex.leaveMutex(); int size = _audiofile.getSize(); SFLDataFormat output[ size ]; - _debugAlsa("Size = %i\n", size); _audiofile.getNext(output, size , 100); - audiolayer->playSamples( output , size ); + audiolayer->putUrgent( output , size ); } else { ringback(); } @@ -2057,9 +2056,9 @@ ManagerImpl::setSwitch(const std::string& switchName, std::string& message) { message = _("Change with success"); playDtmf('9'); - getAudioDriver()->sleep(300); // in milliseconds + //getAudioDriver()->sleep(300); // in milliseconds playDtmf('1'); - getAudioDriver()->sleep(300); // in milliseconds + //getAudioDriver()->sleep(300); // in milliseconds playDtmf('1'); return true; }