From 8e4fac6cf1cdb54a82906269a02aeece213c639a Mon Sep 17 00:00:00 2001
From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
Date: Fri, 15 Feb 2008 17:25:57 -0500
Subject: [PATCH] Remove totally portaudio. alsa playback implemented

---
 src/audio/audiolayer.cpp | 547 +++++++++++++++------------------------
 src/audio/audiolayer.h   | 239 +++++++++--------
 src/managerimpl.cpp      |  12 +-
 3 files changed, 337 insertions(+), 461 deletions(-)

diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp
index f1d990ff78..d892214c50 100644
--- a/src/audio/audiolayer.cpp
+++ b/src/audio/audiolayer.cpp
@@ -20,50 +20,35 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
 
 #include "audiolayer.h"
 #include "../global.h"
 #include "../manager.h"
 #include "../user_cfg.h"
 
-//#define SFL_TEST
-//#define SFL_TEST_SINE
+#define PCM_NAME_DEFAULT  "plughw:0,0"
 
 #ifdef SFL_TEST_SINE
 #include <cmath>
 #endif
 
-AudioLayer::AudioLayer(ManagerImpl* manager)
+  AudioLayer::AudioLayer(ManagerImpl* manager)
   : _urgentRingBuffer(SIZEBUF)
   , _mainSndRingBuffer(SIZEBUF)
   , _micRingBuffer(SIZEBUF)
-  , _defaultVolume(100)
-  , _stream(NULL)
+    , _defaultVolume(100)
   , _errorMessage("")
-  , _manager(manager)
+    , _manager(manager)
 {
   _sampleRate = 8000;
-  
+
   _inChannel  = 1; // don't put in stereo
   _outChannel = 1; // don't put in stereo
   _echoTesting = false;
 
-  try {
-     portaudio::AutoSystem autoSys;
-     portaudio::System::initialize();
-  }
-  catch (const portaudio::PaException &e) {
-    setErrorMessage(e.paErrorText());
-  }
-  catch (const portaudio::PaCppException &e) {
-    setErrorMessage(e.what());
-  } // std::runtime_error &e     (e.what())
-  catch (...) {
-    setErrorMessage("Unknown type error in portaudio initialization");
-  }
-
 #ifdef SFL_TEST_SINE
   leftPhase_ = 0;
   tableSize_ = 200;
@@ -80,343 +65,247 @@ AudioLayer::AudioLayer(ManagerImpl* manager)
 // Destructor
 AudioLayer::~AudioLayer (void) 
 { 
-  stopStream();
-  closeStream();
-
-  try {
-    portaudio::System::terminate();
-  } catch (const portaudio::PaException &e) {
-    _debug("! AL: Catch an exception when portaudio tried to terminate\n");
+  if(_playback_handle != NULL) {
+    close_alsa();
+    _playback_handle = NULL ;
   }
 #ifdef SFL_TEST_SINE
   delete [] table_;
 #endif
 }
 
-void
-AudioLayer::closeStream (void) 
+  void
+AudioLayer::close_alsa (void) 
 {
-  ost::MutexLock guard(_mutex);
-  if(_stream) {
-    _stream->close();
-    delete _stream; _stream = NULL;
-  }
+  _debug(" Alsa close stream \n");
+  //ost::MutexLock guard(_mutex);
+  snd_pcm_close(_playback_handle);
 }
 
 bool
 AudioLayer::hasStream(void) {
   ost::MutexLock guard(_mutex);
-  return (_stream!=0 ? true : false); 
+  return (_playback_handle!=0 ? true : false); 
 }
 
-
-void
+  void
 AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize) 
 {
-  closeStream();
 
   _indexIn = indexIn;
   _indexOut = indexOut;
   _sampleRate = sampleRate;
   _frameSize = frameSize;	
-  int portaudioFramePerBuffer = FRAME_PER_BUFFER; //=FRAME_PER_BUFFER; //= paFramesPerBufferUnspecified;
-  //int portaudioFramePerBuffer = (int) (8000 * frameSize / 1000); 	//= paFramesPerBufferUnspecified;
-  
-  // Select default audio API
-//  selectPreferedApi(paALSA, _indexIn, _indexOut);
-  
-  int nbDevice = getDeviceCount();
-	_debug("Nb of audio devices: %i\n",nbDevice);
-  if (nbDevice == 0) {
-    _debug("Portaudio detect no sound card.");
-    return;
-  } else {
-    _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, SFLPortaudioFormatString);
-    _debug("                   : frame per buffer=%d\n", portaudioFramePerBuffer);
+
+  _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, SFLPortaudioFormatString);
+  _debug("                   : frame per buffer=%d\n", FRAME_PER_BUFFER);
+
+  // Name of the PCM device
+  // TODO: Must be dynamic
+
+  // TODO: capture
+  // Capture stream
+  snd_pcm_stream_t capture_stream = SND_PCM_STREAM_CAPTURE;
+
+  // Open the playback device
+  open_playback_device(PCM_NAME_DEFAULT);
+
+  // Set up the parameters required to open a device:
+  init_hw_parameters();
+
+  device_info();
+
+  //ost::MutexLock guard(_mutex);
+}
+
+void 
+AudioLayer::open_playback_device(std::string pcm_name)
+{
+  // Playback stream
+  snd_pcm_stream_t playback_stream = SND_PCM_STREAM_PLAYBACK;
+
+  if(snd_pcm_open(&_playback_handle, pcm_name.c_str(),  playback_stream, SND_PCM_NONBLOCK) < 0){
+    _debug(" Error while opening PCM device %s\n", pcm_name.c_str());
   }
+  else
+    _debug(" Device %s successfully opened. \n", pcm_name.c_str());
+}
 
-  try {
-    // Set up the parameters required to open a (Callback)Stream:
-    portaudio::DirectionSpecificStreamParameters 
-      inParams(portaudio::System::instance().deviceByIndex(_indexIn), 
-	     _inChannel, SFLPortaudioFormat, true, 
-	     portaudio::System::instance().deviceByIndex(_indexIn).defaultLowInputLatency(), 
-	     NULL);
-
-     portaudio::DirectionSpecificStreamParameters outParams(
-                portaudio::System::instance().deviceByIndex(_indexOut), 
-	        _outChannel, SFLPortaudioFormat, true, 
-	        portaudio::System::instance().deviceByIndex(_indexOut).defaultLowOutputLatency(), 
-	        NULL);
-
-    // like audacity
-    // DON'T USE paFramesPerBufferUnspecified, it's 32, instead of 160 for FRAME_PER_BUFFER
-    // DON'T USE paDitherOff or paClipOff, 
-    // FRAME_PER_BUFFER | paFramesPerBufferUnspecified
-    // paNoFlag | paClipOff || paDitherOff | paPrimeOutputBuffersUsingStreamCallback | paNeverDropInput
-     
-    portaudio::StreamParameters const params(
-		inParams,
-		outParams, 
-		_sampleRate, portaudioFramePerBuffer, paClipOff);
-		
-    // Create (and open) a new Stream, using the AudioLayer::audioCallback
-    ost::MutexLock guard(_mutex);
-#ifdef SFL_TEST
-    _stream = new portaudio::MemFunCallbackStream<AudioLayer>(params, *this, &AudioLayer::miniAudioCallback);
-#else
-    _stream = new portaudio::MemFunCallbackStream<AudioLayer>(params,*this, &AudioLayer::audioCallback);
-#endif
- 
+void
+AudioLayer::init_hw_parameters(  )
+{
+  int periods = 2;
+  snd_pcm_uframes_t periodSize = 8192;
+  unsigned int sr = 44100; //(unsigned int)sampleRate;
+
+  // Information about the hardware
+  snd_pcm_hw_params_t *hwparams;
+  // Allocate the struct on the stack
+  snd_pcm_hw_params_alloca( &hwparams );
+  // Allocate memory space
+  if(snd_pcm_hw_params_malloc( &hwparams) < 0)
+    _debug(" can not allocate hardware paramater structure. \n");
+  // Init hwparams with full configuration space
+  if(snd_pcm_hw_params_any(_playback_handle, hwparams) < 0){
+    _debug(" Can not configure this PCM device .\n");  
+  }
+  // Set access type
+  if(snd_pcm_hw_params_set_access( _playback_handle , hwparams , SND_PCM_ACCESS_RW_INTERLEAVED ) <0){
+    _debug(" Error setting access. \n");
   }
-  catch (const portaudio::PaException &e) {
-    setErrorMessage(e.paErrorText());
-    _debug("Portaudio openDevice error: %s\n", e.paErrorText());
+  // Set sample format 
+  if(snd_pcm_hw_params_set_format( _playback_handle, hwparams , SND_PCM_FORMAT_S16_LE) < 0 ){
+    _debug(" Error setting format. \n");
   }
-  catch (const portaudio::PaCppException &e) {
-    setErrorMessage(e.what());
-    _debug("Portaudio openDevice error: %s\n", e.what());
-  } // std::runtime_error &e     (e.what())
-  catch (...) {
-    setErrorMessage("Unknown type error in portaudio openDevice");
-    _debug("Portaudio openDevice: unknown error\n");
+  // Set sample rate
+  if(snd_pcm_hw_params_set_rate_near( _playback_handle, hwparams, &sr, 0 ) <0 ) {
+    _debug(" Error setting sample rate. \n");
   }
+  if(_sampleRate != sr)
+    _debug(" The rate %i Hz is not supported by your hardware.\n ==> Using %i Hz instead. \n", _sampleRate, sr);
+  // Set number of channels
+  if (snd_pcm_hw_params_set_channels( _playback_handle, hwparams, _inChannel) < 0) 
+    _debug(" Error setting channels. \n");
+  // Set number of periods
+  if (snd_pcm_hw_params_set_periods( _playback_handle, hwparams, periods, 0) < 0)
+    _debug(" Error setting periods. \n ");
+  // Set buffer size
+  if(snd_pcm_hw_params_set_buffer_size( _playback_handle, hwparams,  (periodSize * periods) >>2) < 0 )
+    _debug(" Error setting buffer size. \n ");
+  // Apply hardware parameters to the device
+  if(snd_pcm_hw_params( _playback_handle, hwparams) < 0 )
+    _debug(" Error setting HW params. \n ");
 
 }
 
 int
-AudioLayer::getDeviceCount()
+AudioLayer::device_info( void )
 {
-  return portaudio::System::instance().deviceCount();
+  /*snd_pcm_info_t *info;
+  if(snd_pcm_info( _playback_handle , info) <0 ) {
+    _debug(" Can not gather infos on opened device. \n");  
+    return 0;
+  }
+  else{*/
+      return 1;
+ // }    
 }
 
-/**
- * Checks if ALSA is supported and selects compatible devices
- * Write changes to configuration file if necessary
- */
-void
-AudioLayer::selectPreferedApi(PaHostApiTypeId apiTypeID, int& outputDeviceIndex, int& inputDeviceIndex)
-{
-	// Create iterators
-	portaudio::System::HostApiIterator hostApiIter, hostApiIterEnd;
-	hostApiIter = portaudio::System::instance().hostApisBegin();
-	hostApiIterEnd = portaudio::System::instance().hostApisEnd();
-	
-	// Loop all Api
-	for(; hostApiIter != hostApiIterEnd; hostApiIter++)
-	{
-		// If prefered Api is found, see if devices are compatible
-		if(hostApiIter->typeId() == apiTypeID)
-		{
-			bool compatibleInputDevice = false;
-			bool compatibleOutputDevice = false;
-			
-			// Create device iterators
-			portaudio::System::DeviceIterator deviceIter, deviceIterEnd;
-			deviceIter = hostApiIter->devicesBegin();
-			deviceIterEnd = hostApiIter->devicesEnd();
-			
-			// Loop all devices
-			for(; deviceIter != deviceIterEnd; deviceIter++)
-			{
-				// If we found our input device and it is not only an output device
-				if(deviceIter->index() == inputDeviceIndex && !deviceIter->isOutputOnlyDevice())
-					compatibleInputDevice = true;
-				// If we found our output device and it is not only an input device
-				if(deviceIter->index() == outputDeviceIndex && !deviceIter->isInputOnlyDevice())
-					compatibleOutputDevice = true;
-			}
-			
-			// Select default device of prefered API if compatible device was not found
-			// and write changes to configuration file
-			if(!compatibleOutputDevice)
-			{
-				outputDeviceIndex = hostApiIter->defaultOutputDevice().index();
-				_manager->setConfig(AUDIO, DRIVER_NAME_OUT, outputDeviceIndex);
-			}
-			if(!compatibleInputDevice)
-			{
-				inputDeviceIndex = hostApiIter->defaultInputDevice().index();
-				_manager->setConfig(AUDIO, DRIVER_NAME_IN, inputDeviceIndex);
-			}
-		}
-	}
-}
 
-/**
- * Get list of audio devices index supported by api
- * and corresponding to IO device type
- */
-std::vector<std::string>
-AudioLayer::getAudioDeviceList(PaHostApiTypeId apiTypeID, int ioDeviceMask)
+  int
+AudioLayer::getDeviceCount()
 {
-	std::vector<std::string> v;
-	
-	// Create api iterators
-	portaudio::System::HostApiIterator hostApiIter, hostApiIterEnd;
-	hostApiIter = portaudio::System::instance().hostApisBegin();
-	hostApiIterEnd = portaudio::System::instance().hostApisEnd();
-	
-	// Loop all Api
-	for(; hostApiIter != hostApiIterEnd; hostApiIter++)
-	{
-		// If prefered Api is found, use this one
-		if(hostApiIter->typeId() == apiTypeID)
-			break;
-	}
-	// If none was found, use first api
-	if(hostApiIter == hostApiIterEnd)
-		hostApiIter = portaudio::System::instance().hostApisBegin();
-
-	// Create device iterators
-	portaudio::System::DeviceIterator deviceIter, deviceIterEnd;
-	deviceIter = hostApiIter->devicesBegin();
-	deviceIterEnd = hostApiIter->devicesEnd();
-	
-	// For each device supported by api
-	for(; deviceIter != deviceIterEnd; deviceIter++)
-	{
-		// Check for input or output capabality
-		if (	(ioDeviceMask == InputDevice && !deviceIter->isOutputOnlyDevice()) ||
-				(ioDeviceMask == OutputDevice && !deviceIter->isInputOnlyDevice()) ||
-				deviceIter->isFullDuplexDevice())
-		{
-			char id[10];
-			sprintf(id, "%d", deviceIter->index());
-			v.push_back(id);
-		}
-	}
-	return v;
+  // TODO: everything
+  return 1;
 }
 
-/**
- * Get audio device by index if it supports input output device mask
- */
-AudioDevice*
-AudioLayer::getAudioDeviceInfo(int index, int ioDeviceMask)
+  void
+AudioLayer::startStream(void) 
 {
 
-  try {
-    portaudio::System& sys = portaudio::System::instance();
-    portaudio::Device& device = sys.deviceByIndex(index);
-    int deviceIsSupported = false;
-
-    if (ioDeviceMask == InputDevice && !device.isOutputOnlyDevice()) {
-      deviceIsSupported = true;
-    } else if (ioDeviceMask == OutputDevice && !device.isInputOnlyDevice()) {
-      deviceIsSupported = true;
-    } else if (device.isFullDuplexDevice()) {
-      deviceIsSupported = true;
-    }
-
-    if (deviceIsSupported) {
-      AudioDevice* audiodevice = new AudioDevice(index, device.hostApi().name(), device.name());
-      if (audiodevice) {
-        audiodevice->setRate(device.defaultSampleRate());
-      }
-      return audiodevice;
-    }
-  } catch (...) {
-    return 0;
-  }
-  return 0;
+  snd_pcm_prepare( _playback_handle );
+  _debug(" ALSA start stream. \n");
+  if( snd_pcm_state( _playback_handle ) == SND_PCM_STATE_PREPARED )
+    snd_pcm_start( _playback_handle );
+  else
+    _debug(" Device not ready to start. \n");
+  //playSinusWave();
 }
 
 
-
-void
-AudioLayer::startStream(void) 
+  void
+AudioLayer::stopStream(void) 
 {
-  try {
-    ost::MutexLock guard(_mutex);
-    if (_stream && !_stream->isActive()) {
-        _debug("- AL Action: Starting sound stream\n");
-        _stream->start();
-    } else { 
-      _debug ("* AL Info: Stream doesn't exist or is already active\n");
-    }
-  } catch (const portaudio::PaException &e) {
-    _debugException("! AL: Portaudio error: error on starting audiolayer stream");
-    throw;
-  } catch(...) {
-    _debugException("! AL: Stream start error");
-    throw;
+  _debug(" Alsa stop stream. \n");
+  ost::MutexLock guard(_mutex);
+  if( isStreamActive() ){
+    // tells the device to stop reading 
+    snd_pcm_drop(_playback_handle);
+    _mainSndRingBuffer.flush();
+    _urgentRingBuffer.flush();
+    _micRingBuffer.flush();
   }
+  else
+    _debug(" Device not running. \n" );
 }
-	
-void
-AudioLayer::stopStream(void) 
+
+  void
+AudioLayer::playSinusWave( void )
 {
-  _debug("- AL Action: Stopping sound stream\n");
-  try {
-    ost::MutexLock guard(_mutex);
-    if (_stream && !_stream->isStopped()) {
-      _stream->stop();
-      _mainSndRingBuffer.flush();
-      _urgentRingBuffer.flush();
-      _micRingBuffer.flush();
+  unsigned char* data;
+  int pcmreturn, l1, l2;
+  short s1, s2;
+  int frames;
+
+  data = (unsigned char*)malloc(8192);
+  frames = 8192 >> 2;
+  for(l1 = 0; l1 < 100; l1++) {
+    for(l2 = 0; l2 < frames; l2++) {
+      s1 = (l2 % 128) * 100 - 5000;
+      s2 = (l2 % 256) * 100 - 5000;
+      data[4*l2] = (unsigned char)s1;
+      data[4*l2+1] = s1 >> 8;
+      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);
+      _debug("<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
     }
-  } catch (const portaudio::PaException &e) {
-    _debugException("! AL: Portaudio error: stoping audiolayer stream failed");
-    throw;
-  } catch(...) {
-    _debugException("! AL: Stream stop error");
-    throw;
   }
 }
 
-void
+
+
+//TODO
+  void
 AudioLayer::sleep(int msec) 
 {
-  if (_stream) {
-    portaudio::System::instance().sleep(msec);
-  }
 }
 
-bool
+//TODO
+  bool
 AudioLayer::isStreamActive (void) 
 {
   ost::MutexLock guard(_mutex);
-  try {
-    if(_stream && _stream->isActive()) {
-      return true;
-    }
-  } catch (const portaudio::PaException &e) {
-      _debugException("! AL: Portaudio error: isActive returned an error");
-  }
-  return false;
+  if(snd_pcm_state(_playback_handle) == SND_PCM_STATE_RUNNING)
+    return true;
+  else
+    return false;
 }
 
-int 
+  int 
 AudioLayer::putMain(void* buffer, int toCopy)
 {
-  ost::MutexLock guard(_mutex);
-  if (_stream) {
-    int a = _mainSndRingBuffer.AvailForPut();
-    if ( a >= toCopy ) {
-      return _mainSndRingBuffer.Put(buffer, toCopy, _defaultVolume);
-    } else {
-      _debug("Chopping sound, Ouch! RingBuffer full ?\n");
-      return _mainSndRingBuffer.Put(buffer, a, _defaultVolume);
-    }
-  }
+  play_alsa(buffer, toCopy);
+  //ost::MutexLock guard(_mutex);
+  /*int a = _mainSndRingBuffer.AvailForPut();
+  if ( a >= toCopy ) {
+    return _mainSndRingBuffer.Put(buffer, toCopy, _defaultVolume);
+  } else {
+    _debug("Chopping sound, Ouch! RingBuffer full ?\n");
+    return _mainSndRingBuffer.Put(buffer, a, _defaultVolume);
+  }*/
   return 0;
 }
 
-void
+  void
 AudioLayer::flushMain()
 {
   ost::MutexLock guard(_mutex);
   _mainSndRingBuffer.flush();
 }
 
-int
+  int
 AudioLayer::putUrgent(void* buffer, int toCopy)
 {
   ost::MutexLock guard(_mutex);
-  if (_stream) {
+  if ( hasStream() ) {
     int a = _urgentRingBuffer.AvailForPut();
     if ( a >= toCopy ) {
       return _urgentRingBuffer.Put(buffer, toCopy, _defaultVolume);
@@ -427,44 +316,40 @@ AudioLayer::putUrgent(void* buffer, int toCopy)
   return 0;
 }
 
-int
+  int
 AudioLayer::canGetMic()
 {
-  if (_stream) {
+  if ( hasStream() ) {
     return _micRingBuffer.AvailForGet();
   } else {
     return 0;
   }
 }
 
-int 
+  int 
 AudioLayer::getMic(void *buffer, int toCopy)
 {
-  if(_stream) {
+  if( hasStream() ) {
     return _micRingBuffer.Get(buffer, toCopy, 100);
   } else {
     return 0;
   }
 }
 
-void
+  void
 AudioLayer::flushMic()
 {
   _micRingBuffer.flush();
 }
 
-bool
+  bool
 AudioLayer::isStreamStopped (void) 
 {
   ost::MutexLock guard(_mutex);
-  try {
-    if(_stream && _stream->isStopped()) {
-      return true;
-    }
-  } catch (const portaudio::PaException &e) {
-      _debugException("! AL: Portaudio error: isStopped returned an exception");
-  }
-  return false;
+  if(snd_pcm_state( _playback_handle ) == SND_PCM_STATE_XRUN)
+    return true;
+  else
+    return false;
 }
 
 void
@@ -475,19 +360,14 @@ AudioLayer::toggleEchoTesting() {
 
 int 
 AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer, 
-			   unsigned long framesPerBuffer, 
-			   const PaStreamCallbackTimeInfo *timeInfo, 
-			   PaStreamCallbackFlags statusFlags) {
+    unsigned long framesPerBuffer){ 
 
-  (void) timeInfo;
-  (void) statusFlags;
-	
   SFLDataFormat *in  = (SFLDataFormat *) inputBuffer;
   SFLDataFormat *out = (SFLDataFormat *) outputBuffer;
 
   if (_echoTesting) {
     memcpy(out, in, framesPerBuffer*sizeof(SFLDataFormat));
-    return paContinue;
+    return framesPerBuffer*sizeof(SFLDataFormat);
   }
 
   int toGet; 
@@ -519,9 +399,9 @@ AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer,
       toGet = (normalAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof(SFLDataFormat);
 
       if (toGet) {
-        _mainSndRingBuffer.Get(out, toGet, spkrVolume);
+	_mainSndRingBuffer.Get(out, toGet, spkrVolume);
       } else {
-        bzero(out, framesPerBuffer * sizeof(SFLDataFormat));
+	bzero(out, framesPerBuffer * sizeof(SFLDataFormat));
       }
     }
   }
@@ -532,37 +412,24 @@ AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer,
   //_debug("AL: Nb sample: %d char, [0]=%f [1]=%f [2]=%f\n", toPut, in[0], in[1], in[2]);
   _micRingBuffer.Put(in, toPut, micVolume);
 
-  return paContinue;
+  return toPut;
 }
 
-int 
-AudioLayer::miniAudioCallback (const void *inputBuffer, void *outputBuffer, 
-			   unsigned long framesPerBuffer, 
-			   const PaStreamCallbackTimeInfo *timeInfo, 
-			   PaStreamCallbackFlags statusFlags) {
-  (void) timeInfo;
-  (void) statusFlags;
-	
- _debug("mini audio callback!!\n");
-#ifdef SFL_TEST_SINE
-  assert(outputBuffer != NULL);
-
-  float *out = static_cast<float *>(outputBuffer);
-  for (unsigned int i = 0; i < framesPerBuffer; ++i) {
-    out[i] = table_[leftPhase_];
-    leftPhase_ += 1;
-    if (leftPhase_ >= tableSize_) {
-      leftPhase_ -= tableSize_;
-    }
-  }
-#else
-  SFLDataFormat *out = (SFLDataFormat *) outputBuffer;
-  AudioLoop* tone = _manager->getTelephoneTone();
-  if ( tone != 0) {
-    //_debug("Frames Per Buffer: %d\n", framesPerBuffer);
-    tone->getNext(out, framesPerBuffer, 100);
-  }
-#endif
 
-  return paContinue;
+
+  int
+AudioLayer::play_alsa(void* buffer, int length)
+{
+  if(_playback_handle == NULL)
+    return 0;
+
+  snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames( _playback_handle, length);
+  snd_pcm_prepare( _playback_handle );
+  if( snd_pcm_writei( _playback_handle, buffer, frames) < 0){
+    snd_pcm_prepare( _playback_handle );
+    _debug(" Buffer underrun!!!\n");
+    return 0;
+  }
+  return 1;
 }
+
diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h
index 667b6eee5e..973eb6856f 100644
--- a/src/audio/audiolayer.h
+++ b/src/audio/audiolayer.h
@@ -25,13 +25,12 @@
 
 #include <cc++/thread.h> // for ost::Mutex
 
-#include "portaudiocpp/PortAudioCpp.hxx"
-
 #include "../global.h"
 #include "ringbuffer.h"
 #include "audiodevice.h"
 
 #include <vector>
+#include <alsa/asoundlib.h>
 
 #define FRAME_PER_BUFFER	160
 
@@ -39,119 +38,129 @@ class RingBuffer;
 class ManagerImpl;
 
 class AudioLayer {
-	public:
-		AudioLayer(ManagerImpl* manager);
-		~AudioLayer(void);
-
-		/*
-		 * @param indexIn
-		 * @param indexOut
-		 * @param sampleRate
-		 * @param frameSize
-		 */
-		void openDevice(int, int, int, int);
-		void startStream(void);
-		void stopStream(void);
-		void sleep(int);
-		bool hasStream(void);
-		bool isStreamActive(void);
-		bool isStreamStopped(void);
-
-		void flushMain();
-		int putMain(void* buffer, int toCopy);
-		int putUrgent(void* buffer, int toCopy);
-		int canGetMic();
-		int getMic(void *, int);
-		void flushMic();
-
-		int audioCallback (const void *, void *, unsigned long,
-				const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags);
-		int miniAudioCallback (const void *, void *, unsigned long,
-				const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags);
-
-		void setErrorMessage(const std::string& error) { _errorMessage = error; }
-		std::string getErrorMessage() { return _errorMessage; }
-
-		/**
-		 * Get the sample rate of audiolayer
-		 * accessor only
-		 */
-		int getIndexIn() { return _indexIn; }
-		int getIndexOut() { return _indexOut; }
-		unsigned int getSampleRate() { return _sampleRate; }
-		unsigned int getFrameSize() { return _frameSize; }
-		int getDeviceCount();
-		
-		
-		// NOW
-		void selectPreferedApi(PaHostApiTypeId apiTypeID, int& outputDeviceIndex, int& inputDeviceIndex);
-		
-		std::vector<std::string> getAudioDeviceList(PaHostApiTypeId apiTypeID, int ioDeviceMask);
-
-
-		AudioDevice* getAudioDeviceInfo(int index, int ioDeviceMask);
-
-		enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 };
-
-		/**
-		 * Toggle echo testing on/off
-		 */
-		void toggleEchoTesting();
-
-	private:
-		void closeStream (void);
-		RingBuffer _urgentRingBuffer;
-		RingBuffer _mainSndRingBuffer;
-		RingBuffer _micRingBuffer;
-		ManagerImpl* _manager; // augment coupling, reduce indirect access
-		// a audiolayer can't live without manager
-
-		portaudio::MemFunCallbackStream<AudioLayer> *_stream;
-
-		/**
-		 * Portaudio indexes of audio devices on which stream has been opened 
-		 */
-		int _indexIn;
-		int _indexOut;
-		
-		/**
-		 * Sample Rate SFLphone should send sound data to the sound card 
-		 * The value can be set in the user config file- now: 44100HZ
-		 */
-		unsigned int _sampleRate;
-		
-		/**
- 		 * Length of the sound frame we capture or read in ms
- 		 * The value can be set in the user config file - now: 20ms
- 		 */	 		
-		unsigned int _frameSize;
-		
-		/**
-		 * Input channel (mic) should be 1 mono
-		 */
-		unsigned int _inChannel; // mic
-
-		/**
-		 * Output channel (stereo) should be 1 mono
-		 */
-		unsigned int _outChannel; // speaker
-
-		/**
-		 * Default volume for incoming RTP and Urgent sounds.
-		 */
-		unsigned short _defaultVolume; // 100
-
-		/**
-		 * Echo testing or not
-		 */
-		bool _echoTesting;
-
-		std::string _errorMessage;
-		ost::Mutex _mutex;
-
-		float *table_;
-		int tableSize_;
-		int leftPhase_;
+  public:
+    AudioLayer(ManagerImpl* manager);
+    ~AudioLayer(void);
+
+    /*
+     * @param indexIn
+     * @param indexOut
+     * @param sampleRate
+     * @param frameSize
+     */
+    void openDevice(int, int, int, int);
+    void startStream(void);
+    void stopStream(void);
+    void sleep(int);
+    bool hasStream(void);
+    bool isStreamActive(void);
+    bool isStreamStopped(void);
+
+    void flushMain();
+    int putMain(void* buffer, int toCopy);
+    int putUrgent(void* buffer, int toCopy);
+    int canGetMic();
+    int getMic(void *, int);
+    void flushMic();
+
+    int audioCallback (const void *, void *, unsigned long);
+    //int miniAudioCallback (const void *, void *, unsigned long,
+    //const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags);
+
+    void setErrorMessage(const std::string& error) { _errorMessage = error; }
+    std::string getErrorMessage() { return _errorMessage; }
+
+    /**
+     * Get the sample rate of audiolayer
+     * accessor only
+     */
+    int getIndexIn() { return _indexIn; }
+    int getIndexOut() { return _indexOut; }
+    unsigned int getSampleRate() { return _sampleRate; }
+    unsigned int getFrameSize() { return _frameSize; }
+    int getDeviceCount();
+
+    void playSinusWave();
+
+
+    // NOW
+    //void selectPreferedApi(PaHostApiTypeId apiTypeID, int& outputDeviceIndex, int& inputDeviceIndex);
+
+    //std::vector<std::string> getAudioDeviceList(PaHostApiTypeId apiTypeID, int ioDeviceMask);
+
+
+    //AudioDevice* getAudioDeviceInfo(int index, int ioDeviceMask);
+
+    enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 };
+
+    /**
+     * Toggle echo testing on/off
+     */
+    void toggleEchoTesting();
+
+  private:
+    void close_alsa (void);
+    int play_alsa( void* , int );
+    int device_info( void );
+    void init_hw_parameters( void );
+    void open_playback_device( std::string ); 
+    RingBuffer _urgentRingBuffer;
+    RingBuffer _mainSndRingBuffer;
+    RingBuffer _micRingBuffer;
+    ManagerImpl* _manager; // augment coupling, reduce indirect access
+    // a audiolayer can't live without manager
+
+    //portaudio::MemFunCallbackStream<AudioLayer> *_stream;
+
+    snd_pcm_t* _playback_handle;
+    snd_pcm_state_t* playback_state;
+    snd_pcm_t* _capture_handle;
+
+    int playback_callback(snd_pcm_sframes_t nframes);
+    /**
+     * Portaudio indexes of audio devices on which stream has been opened 
+     */
+    int _indexIn;
+    int _indexOut;
+
+    /**
+     * Sample Rate SFLphone should send sound data to the sound card 
+     * The value can be set in the user config file- now: 44100HZ
+     */
+    unsigned int _sampleRate;
+
+    /**
+     * Length of the sound frame we capture or read in ms
+     * The value can be set in the user config file - now: 20ms
+     */	 		
+    unsigned int _frameSize;
+
+    /**
+     * Input channel (mic) should be 1 mono
+     */
+    unsigned int _inChannel; // mic
+
+    /**
+     * Output channel (stereo) should be 1 mono
+     */
+    unsigned int _outChannel; // speaker
+
+    /**
+     * Default volume for incoming RTP and Urgent sounds.
+     */
+    unsigned short _defaultVolume; // 100
+
+    /**
+     * Echo testing or not
+     */
+    bool _echoTesting;
+
+    std::string _errorMessage;
+    ost::Mutex _mutex;
+
+    float *table_;
+    int tableSize_;
+    int leftPhase_;
 };
 
 #endif // _AUDIO_LAYER_H_
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index ecad7b0880..9f9d8baf1a 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -1236,7 +1236,7 @@ std::vector<std::string>
 ManagerImpl::getAudioOutputDeviceList(void)
 {
 	_debug("Get audio output device list");
-	return _audiodriver->getAudioDeviceList(paALSA, _audiodriver->OutputDevice);
+	//return _audiodriver->getAudioDeviceList(paALSA, _audiodriver->OutputDevice);
 }
 
 /**
@@ -1257,7 +1257,7 @@ std::vector<std::string>
 ManagerImpl::getAudioInputDeviceList(void)
 {
 	_debug("Get audio input device list");
-	return _audiodriver->getAudioDeviceList(paALSA, _audiodriver->InputDevice);
+	//return _audiodriver->getAudioDeviceList(paALSA, _audiodriver->InputDevice);
 }
 
 /**
@@ -1296,7 +1296,7 @@ std::vector<std::string>
 ManagerImpl::getAudioDeviceDetails(const int index)
 {
 	_debug("Get audio input device list");
-	std::vector<std::string> v;
+	/*std::vector<std::string> v;
 
 	try
 	{
@@ -1313,7 +1313,7 @@ ManagerImpl::getAudioDeviceDetails(const int index)
 		v.push_back(answer);
 	}
 	catch (...) {}
-	return v;
+	return v;*/
 }
 
 
@@ -1684,7 +1684,7 @@ ManagerImpl::getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask)
   TokenList tk;
   AudioDevice* device = 0;
   int nbDevice = audiolayer->getDeviceCount();
-  
+ /* 
   for (int index = 0; index < nbDevice; index++ ) {
     device = audiolayer->getAudioDeviceInfo(index, ioDeviceMask);
     if (device != 0) {
@@ -1698,7 +1698,7 @@ ManagerImpl::getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask)
       // don't forget to delete it after
       delete device; device = 0;
     }
-  }
+  }*/
   returnValue = true;
   
   std::ostringstream rate; 
-- 
GitLab