diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp
index c5ba9570e5289fe37b6b150be333ea1264199bc3..b179db8002f26f7d6fff5c19b5911b7199e40828 100644
--- a/src/audio/audiolayer.cpp
+++ b/src/audio/audiolayer.cpp
@@ -28,11 +28,11 @@
 #include "../global.h"
 #include "../manager.h"
 
-AudioLayer::AudioLayer () 
+AudioLayer::AudioLayer(ManagerImpl& manager)
   : _urgentRingBuffer(SIZEBUF)
   , _mainSndRingBuffer(SIZEBUF)
   , _micRingBuffer(SIZEBUF)
-  , _stream(NULL)
+  , _stream(NULL), _manager(manager)
 {
   portaudio::System::initialize();
   listDevices();
@@ -98,7 +98,7 @@ void
 AudioLayer::startStream(void) 
 {
   ost::MutexLock guard(_mutex);
-  if (Manager::instance().isDriverLoaded()) {
+  if (_manager.isDriverLoaded()) {
     if (_stream && !_stream->isActive()) {
       _debug("Thread: start audiolayer stream\n");
       _stream->start();
@@ -110,10 +110,11 @@ void
 AudioLayer::stopStream(void) 
 {
   ost::MutexLock guard(_mutex);
-  if (Manager::instance().isDriverLoaded()) {
+  if (_manager.isDriverLoaded()) {
     if (_stream && !_stream->isStopped()) {
       _debug("Thread: stop audiolayer stream\n");
       _stream->stop();
+      _mainSndRingBuffer.flush();
     }
   } 
 }
@@ -142,6 +143,14 @@ AudioLayer::putMain(void* buffer, int toCopy)
   ost::MutexLock guard(_mutex);
   _mainSndRingBuffer.Put(buffer, toCopy);
 }
+
+void
+AudioLayer::flushMain()
+{
+  ost::MutexLock guard(_mutex);
+  _mainSndRingBuffer.flush();
+}
+
 void
 AudioLayer::putUrgent(void* buffer, int toCopy)
 {
@@ -165,13 +174,14 @@ AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer,
 			   unsigned long framesPerBuffer, 
 			   const PaStreamCallbackTimeInfo *timeInfo, 
 			   PaStreamCallbackFlags statusFlags) {
-   	(void) timeInfo;
-	(void) statusFlags;
+
+  (void) timeInfo;
+  (void) statusFlags;
 	
 	int16 *in  = (int16 *) inputBuffer;
 	int16 *out = (int16 *) outputBuffer;
 	int toGet, toPut, urgentAvail, normalAvail, micAvailPut;
-	
+
 	urgentAvail = _urgentRingBuffer.AvailForGet();
 	if (urgentAvail > 0) {  
 	// Urgent data (dtmf, incoming call signal) come first.		
@@ -180,11 +190,10 @@ AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer,
 		} else {
 			toGet = framesPerBuffer;
 		}
-		_urgentRingBuffer.Get(out, SAMPLES_SIZE(toGet));
+		_urgentRingBuffer.Get(out, SAMPLES_SIZE(toGet), _manager.getSpkrVolume());
 		
 		// Consume the regular one as well (same amount of bytes)
 		_mainSndRingBuffer.Discard(SAMPLES_SIZE(toGet));
-		
 	}  
 	else {
 	// If nothing urgent, play the regular sound samples
@@ -194,19 +203,18 @@ AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer,
 
     //_debug("%d vs %d : %d\t", normalAvail, (int)framesPerBuffer, toGet);
     if (toGet) {
-		  _mainSndRingBuffer.Get(out, SAMPLES_SIZE(toGet));
+		  _mainSndRingBuffer.Get(out, SAMPLES_SIZE(toGet), _manager.getSpkrVolume());
     } else {
       toGet = SAMPLES_SIZE(framesPerBuffer);
       _mainSndRingBuffer.PutZero(toGet);
-      _mainSndRingBuffer.Get(out, toGet);
+      _mainSndRingBuffer.Get(out, toGet, 0);
     }
 	}
 
 	// Additionally handle the mike's audio stream 
 	micAvailPut = _micRingBuffer.AvailForPut();
-	toPut = (micAvailPut <= (int)framesPerBuffer) ? micAvailPut : 
-			framesPerBuffer;
-	_micRingBuffer.Put(in, SAMPLES_SIZE(toPut));
+	toPut = (micAvailPut <= (int)framesPerBuffer) ? micAvailPut : framesPerBuffer;
+	_micRingBuffer.Put(in, SAMPLES_SIZE(toPut), _manager.getMicVolume());
 
 	return paContinue;
 }
diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h
index 69a0d4db36fd64adeda82491c324e156a1e74452..9ed53488a7cbbbd7f06ee88155ea572dbf2962c7 100644
--- a/src/audio/audiolayer.h
+++ b/src/audio/audiolayer.h
@@ -29,6 +29,7 @@
 #include "../global.h"
 #include "ringbuffer.h"
 #include <cc++/thread.h>
+#include "../manager.h"
 
 #define FRAME_PER_BUFFER	160
 #define MIC_CHANNELS 		2 // 1=mono 2=stereo
@@ -38,10 +39,9 @@
 
 class RingBuffer;
 
-
 class AudioLayer {
 public:
-	AudioLayer();
+	AudioLayer(ManagerImpl& manager);
 	~AudioLayer (void);
 
 	void listDevices();
@@ -52,6 +52,7 @@ public:
 	bool    isStreamActive	        (void);
 	bool    isStreamStopped	        (void);
 
+  void flushMain();
   void putMain(void* buffer, int toCopy);
   void putUrgent(void* buffer, int toCopy);
 
@@ -59,7 +60,6 @@ public:
 			   const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags);
 
 	inline RingBuffer &urgentRingBuffer(void) { return _urgentRingBuffer; }
-	inline RingBuffer &mainSndRingBuffer(void) { return _mainSndRingBuffer; }
 	inline RingBuffer &micRingBuffer(void) { return _micRingBuffer; }
 
 private:
@@ -71,6 +71,7 @@ private:
 	portaudio::MemFunCallbackStream<AudioLayer> *_stream;
 	portaudio::AutoSystem autoSys;
   ost::Mutex _mutex;
+  ManagerImpl& _manager;
 };
 
 #endif // _AUDIO_LAYER_H_
diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp
index 03e1e7607afdbe9a2d17a960f5190c623574ab74..55f7f3bc270fe99e1785c438abae58ec1d224f01 100644
--- a/src/audio/audiortp.cpp
+++ b/src/audio/audiortp.cpp
@@ -29,7 +29,6 @@
 #include "audiocodec.h"
 #include "audiortp.h"
 #include "audiolayer.h"
-#include "codecDescriptor.h"
 #include "ringbuffer.h"
 #include "../user_cfg.h"
 #include "../sipcall.h"
@@ -73,29 +72,16 @@ AudioRtp::createNewSession (SipCall *ca) {
 
 	
 void
-AudioRtp::closeRtpSession (SipCall *ca) {
-	// This will make RTP threads finish.
-	if (ca) {
-    if (ca->enable_audio > 0) {
-      ca->enable_audio = -1;
-
-      if (_RTXThread != NULL) {
-        _debug("Thread: stop AudioRTP for sipcall: %d\n", ca->getId());
-        delete _RTXThread; _RTXThread = NULL;
-      }
-  	}
-  } else {
-    _debug("Thread: stop AudioRTP for no sipcall\n");
-    delete _RTXThread; _RTXThread = NULL;
-  }
+AudioRtp::closeRtpSession () {
+  // This will make RTP threads finish.
+  delete _RTXThread; _RTXThread = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AudioRtpRTX Class                                                          //
 ////////////////////////////////////////////////////////////////////////////////
-AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, 
-			  AudioLayer* driver, 
-			  bool sym) {
+AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioLayer* driver, 
+			  bool sym) : _codecBuilder(0) {
 	time = new ost::Time();
 	_ca = sipcall;
 	_sym = sym;
@@ -123,6 +109,7 @@ AudioRtpRTX::~AudioRtpRTX () {
   } catch (...) {
     _debug("AudioRtpRTX: try to terminate, but catch an exception...\n");
   }
+  _ca = NULL;
   _debug("Thread: AudioRtpRTX stop session\n");
   if (!_sym) {
     delete _sessionRecv; _sessionRecv = NULL;
@@ -189,7 +176,8 @@ AudioRtpRTX::initAudioRtpSession (void)
 }
 
 void
-AudioRtpRTX::sendSessionFromMic (unsigned char* data_to_send, int16* data_from_mic, int16* data_from_mic_tmp, int timestamp, int micVolume)
+// AudioRtpRTX::sendSessionFromMic (unsigned char* data_to_send, int16* data_from_mic, int16* data_from_mic_tmp, int timestamp, int micVolume)
+AudioRtpRTX::sendSessionFromMic (unsigned char* data_to_send, int16* data_from_mic, int16* data_from_mic_tmp, int timestamp)
 {
 	int k; 
 	int compSize; 
@@ -204,34 +192,34 @@ AudioRtpRTX::sendSessionFromMic (unsigned char* data_to_send, int16* data_from_m
   }
 
   // Get bytes from micRingBuffer to data_from_mic
-  Manager::instance().getAudioDriver()->micRingBuffer().Get(data_from_mic, 
-      SAMPLES_SIZE(bytesAvail));
+  Manager::instance().getAudioDriver()->micRingBuffer().Get(data_from_mic, SAMPLES_SIZE(bytesAvail), 0);
   // control volume and stereo->mono
   for (int j = 0; j < RTP_FRAMES2SEND; j++) {
-    k = j*2;
-    data_from_mic_tmp[j] = (int16)(0.5f*(data_from_mic[k] +
-                      data_from_mic[k+1]) * 
-                      micVolume/100); 
+    k = j<<1;
+    data_from_mic_tmp[j] = (int16)(0.5f*(data_from_mic[k] + data_from_mic[k+1]));
+    //micVolume/100);
   }
 
-	// Encode acquired audio sample
-	compSize = _ca->getAudioCodec()->codecEncode (data_to_send,
-												  data_from_mic_tmp, 
-												  RTP_FRAMES2SEND*2);
-	// Send encoded audio sample over the network
-	if (!_sym) {
-		_sessionSend->putData(timestamp, data_to_send, compSize);
-	} else {
-		_session->putData(timestamp, data_to_send, compSize);
-	}
-
+  if ( _ca != NULL ) {
+    // Encode acquired audio sample
+    AudioCodec* ac = _ca->getAudioCodec();
+    if ( ac != NULL ) {
+      compSize =  ac->codecEncode (data_to_send, data_from_mic_tmp, RTP_FRAMES2SEND*2);
+      // Send encoded audio sample over the network
+      if (!_sym) {
+        _sessionSend->putData(timestamp, data_to_send, compSize);
+      } else {
+        _session->putData(timestamp, data_to_send, compSize);
+      }
+    }
+  }
 }
 
 void
 AudioRtpRTX::receiveSessionForSpkr (int16* data_for_speakers, 
-		int16* data_for_speakers_tmp, int spkrVolume, int& countTime)
+//		int16* data_for_speakers_tmp, int spkrVolume, int& countTime)
+     int16* data_for_speakers_tmp, int& countTime)
 {
-	int expandedSize;
 	int k;
 	const ost::AppDataUnit* adu = NULL;
 
@@ -242,31 +230,33 @@ AudioRtpRTX::receiveSessionForSpkr (int16* data_for_speakers,
     adu = _session->getData(_session->getFirstTimestamp());
   }
   if (adu == NULL) {
-//    Manager::instance().getAudioDriver()->mainSndRingBuffer().flush();
-//    Manager::instance().getAudioDriver()->stopStream();
+    Manager::instance().getAudioDriver()->flushMain();
     return;
   }
 
-	// Decode data with relevant codec
-	CodecDescriptor* cd = new CodecDescriptor (adu->getType());
-	
-	AudioCodec* ac = cd->alloc(adu->getType(), "");
+  int payload = adu->getType();
+  unsigned char* data  = (unsigned char*)adu->getData();
+  unsigned int size    = adu->getSize();
 
-	expandedSize = ac->codecDecode (data_for_speakers,
-									(unsigned char*) adu->getData(),
-									adu->getSize());
-		
-	// control volume for speakers and mono->stereo
-	for (int j = 0; j < expandedSize; j++) {
-		k = j*2;
-		data_for_speakers_tmp[k] = data_for_speakers_tmp[k+1]= 
-			data_for_speakers[j] * spkrVolume/100;
+	// Decode data with relevant codec
+	int expandedSize = 0;
+	AudioCodec* ac = _codecBuilder.alloc(payload, "");
+  if (ac != NULL) {
+    expandedSize = ac->codecDecode (data_for_speakers, data, size);
 	}
+  ac = NULL;
+
+  // control volume for speakers and mono->stereo
+  for (int j = 0; j < expandedSize; j++) {
+    k = j<<1; // fast multiply by two
+    data_for_speakers_tmp[k] = data_for_speakers_tmp[k+1] = data_for_speakers[j];
+    // * spkrVolume/100;
+  }
 
-	// If the current call is the call which is answered
-		// Set decoded data to sound device
-		Manager::instance().getAudioDriver()->putMain(data_for_speakers_tmp, SAMPLES_SIZE(RTP_FRAMES2SEND));
-	//}
+  // If the current call is the call which is answered
+  // Set decoded data to sound device
+  Manager::instance().getAudioDriver()->putMain(data_for_speakers_tmp, SAMPLES_SIZE(RTP_FRAMES2SEND));
+  //}
 	
 	// Notify (with a beep) an incoming call when there is already a call 
 	countTime += time->getSecond();
@@ -279,15 +269,13 @@ AudioRtpRTX::receiveSessionForSpkr (int16* data_for_speakers,
 
 	Manager::instance().getAudioDriver()->startStream();
 	
-  delete ac;  ac = NULL;
-	delete cd;  cd = NULL;
 	delete adu; adu = NULL;
 }
 
 void
 AudioRtpRTX::run (void) {
-	int micVolume;
-	int spkrVolume;
+//	int micVolume;
+//	int spkrVolume;
 	unsigned char	*data_to_send;
 	int16			*data_from_mic;
 	int16			*data_from_mic_tmp;
@@ -314,7 +302,6 @@ AudioRtpRTX::run (void) {
   // flush stream:
   ManagerImpl& manager = Manager::instance();
   AudioLayer *audiolayer = manager.getAudioDriver();
-  audiolayer->mainSndRingBuffer().flush();
   audiolayer->urgentRingBuffer().flush();
 
 	// start running the packet queue scheduler.
@@ -326,23 +313,23 @@ AudioRtpRTX::run (void) {
 		_session->startRunning();
 	}
 
-	while (!testCancel() && _ca->enable_audio != -1) {
-		micVolume = manager.getMicVolume();
-	  spkrVolume = manager.getSpkrVolume();
+	while (!testCancel() && _ca != NULL && _ca->enable_audio != -1) {
+		//micVolume = manager.getMicVolume();
+	  //spkrVolume = manager.getSpkrVolume();
 
 		////////////////////////////
 		// Send session
 		////////////////////////////
-		sendSessionFromMic(data_to_send, data_from_mic, data_from_mic_tmp,
-				timestamp, micVolume);
+    //sendSessionFromMic(data_to_send, data_from_mic, data_from_mic_tmp, timestamp, micVolume);
+		sendSessionFromMic(data_to_send, data_from_mic, data_from_mic_tmp, timestamp);
 		
 		timestamp += RTP_FRAMES2SEND;
 
 		////////////////////////////
 		// Recv session
 		////////////////////////////
-		receiveSessionForSpkr(data_for_speakers, data_for_speakers_tmp,
-				spkrVolume, countTime);
+    //receiveSessionForSpkr(data_for_speakers, data_for_speakers_tmp, spkrVolume, countTime);
+    receiveSessionForSpkr(data_for_speakers, data_for_speakers_tmp, countTime);
 		
 		// Let's wait for the next transmit cycle
 		Thread::sleep(TimerPort::getTimer());
@@ -356,8 +343,6 @@ AudioRtpRTX::run (void) {
 	delete [] data_from_mic;         data_from_mic         = 0;
 
   audiolayer->stopStream();
-  audiolayer->mainSndRingBuffer().flush();
-  //audiolayer->urgentRingBuffer().flush();
 }
 
 
diff --git a/src/audio/audiortp.h b/src/audio/audiortp.h
index 273136cdd6ae72ed4e0297f79bf7492632c6e1c5..716296f5eb1b9a8be0f1c649d91bb1f62c683559 100644
--- a/src/audio/audiortp.h
+++ b/src/audio/audiortp.h
@@ -25,6 +25,7 @@
 
 #include <ccrtp/rtp.h>
 #include <cc++/numbers.h>
+#include "codecDescriptor.h"
 
 
 #define RTP_FRAMES2SEND	160
@@ -52,9 +53,14 @@ private:
 	ost::SymmetricRTPSession *_session;
 	bool _sym;
 
+  // build codec...
+  CodecDescriptor _codecBuilder;
+
 	void initAudioRtpSession (void);
-	void sendSessionFromMic (unsigned char*, int16*, int16*, int, int);
-	void receiveSessionForSpkr (int16*, int16*, int, int&);
+//  void sendSessionFromMic (unsigned char*, int16*, int16*, int, int);
+  void sendSessionFromMic (unsigned char*, int16*, int16*, int);
+//	void receiveSessionForSpkr (int16*, int16*, int, int&);
+  void receiveSessionForSpkr (int16*, int16*, int&);
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -66,7 +72,7 @@ public:
 	~AudioRtp();
 
 	int 			createNewSession (SipCall *);
-	void			closeRtpSession	 (SipCall *);
+	void			closeRtpSession	 ();
 
 private:
 	AudioRtpRTX*	_RTXThread;
diff --git a/src/audio/codecDescriptor.cpp b/src/audio/codecDescriptor.cpp
index 7c64f397a793ca191011af361b13e62ec35efd5e..9e5feae22bb35eebff797bf9934da20a62119a47 100644
--- a/src/audio/codecDescriptor.cpp
+++ b/src/audio/codecDescriptor.cpp
@@ -46,36 +46,63 @@ CodecDescriptor::CodecDescriptor (int payload)
 {
 	_payload = payload;
 	_codecName = rtpmapPayload(_payload);
+	initCache();
 }
 
 CodecDescriptor::CodecDescriptor (const std::string& name) 
 {
 	_codecName = name;
 	_payload = matchPayloadCodec(name);
+	initCache();
 }
 
 CodecDescriptor::CodecDescriptor (int payload, const std::string& name) 
 {
 	_payload = payload;
 	_codecName = name;
+	initCache();
 }
 
-CodecDescriptor::~CodecDescriptor (void)
+void CodecDescriptor::initCache() 
 {
+  _ac1 = NULL;  
+  _ac2 = NULL;
+  _ac3 = NULL;
+}
+
+
+CodecDescriptor::~CodecDescriptor (void)
+{	
+  delete _ac1;
+  delete _ac2;
+  delete _ac3;
 }
 
 AudioCodec*
 CodecDescriptor::alloc (int payload, const std::string& name)
 {
+	// _ac1, _ac2 and _ac3 are caching...
 	switch(payload) {
 	case PAYLOAD_CODEC_ULAW:
-		return new Ulaw(payload, name);
+		if ( _ac1 == NULL ) {
+			_ac1 = new Ulaw(payload, name);
+      //return new Ulaw(payload, name);
+		}
+		return _ac1;
 		break;
 	case PAYLOAD_CODEC_ALAW:
-		return new Alaw(payload, name);
+		if ( _ac2 == NULL ) {
+			_ac2 = new Alaw(payload, name);
+      //return new Alaw(payload, name);
+		}
+		return _ac2;
 		break;
 	case PAYLOAD_CODEC_GSM:
-		return new Gsm(payload, name);
+		if ( _ac3 == NULL ) {
+			_ac3 = new Gsm(payload, name);
+      //return new Gsm(payload, name);
+		}
+		return _ac3;
 		break;
 	default:
 		return NULL;
diff --git a/src/audio/codecDescriptor.h b/src/audio/codecDescriptor.h
index 4ca94aea42402656a83343789ac7829d654ead1b..db8e6a96dd3710f3f667bea7c891ecde70815d51 100644
--- a/src/audio/codecDescriptor.h
+++ b/src/audio/codecDescriptor.h
@@ -77,8 +77,13 @@ public:
 	std::string rtpmapPayload (int);
 
 private:
+	void initCache();
 	int _payload;
 	std::string _codecName;
+
+	AudioCodec* _ac1;
+	AudioCodec* _ac2;
+	AudioCodec* _ac3;
 };
 
 #endif // __CODEC_DESCRIPTOR_H__
diff --git a/src/audio/gsmcodec.cpp b/src/audio/gsmcodec.cpp
index 36767d1c410c18f8e7fb6bd99c8ad1273e20481b..60d54eda887faf917524db2bd74780476aaec9ae 100644
--- a/src/audio/gsmcodec.cpp
+++ b/src/audio/gsmcodec.cpp
@@ -36,7 +36,6 @@ Gsm::~Gsm (void)
 {
 	gsm_destroy(_decode_gsmhandle);
 	gsm_destroy(_encode_gsmhandle);
-
 }
 
 int
diff --git a/src/audio/ringbuffer.cpp b/src/audio/ringbuffer.cpp
index 54168f31dce3783f25e9ced2738a75f4d596a225..c7825b35ff7271c41cd16b63f0f18960b5859d17 100644
--- a/src/audio/ringbuffer.cpp
+++ b/src/audio/ringbuffer.cpp
@@ -50,10 +50,8 @@ RingBuffer::~RingBuffer() {
  
 void
 RingBuffer::flush (void) {
-	mMutex.enterMutex();
 	mStart = 0; 
 	mEnd = 0;
-	mMutex.leaveMutex();
 } 
 
 int 
@@ -78,19 +76,19 @@ RingBuffer::PutZero(int toZero)
 }
 
 // This one puts some data inside the ring buffer.
+// Change the volume if it's not 0
 int 
-RingBuffer::Put(void* buffer, int toCopy) {
+RingBuffer::Put(void* buffer, int toCopy, unsigned short volume) {
    samplePtr src;
    int block;
    int copied;
    int pos;
    int len = Len();
 
-   mMutex.enterMutex();
    if (toCopy > (mBufferSize-4) - len)
       toCopy = (mBufferSize-4) - len;
 
-   src = (samplePtr) buffer; 
+   src = (samplePtr) buffer;
 
    copied = 0;
    pos = mEnd;
@@ -98,9 +96,15 @@ RingBuffer::Put(void* buffer, int toCopy) {
    while(toCopy) {
       block = toCopy;
       if (block > mBufferSize - pos) // from current pos. to end of buffer
-         block = mBufferSize - pos; 
+         block = mBufferSize - pos;
 
       // put the data inside the buffer.
+      if (volume) {
+        int16* src16 = (int16*)src;
+        int int16len = (block >> 1);
+        for (int i=0; i< int16len; i++) { src16[i] = src16[i] * volume / 100; }
+      }
+      // bcopy(src, dest, len)
       bcopy (src, mBuffer + pos, block);
 
       src += block;
@@ -110,7 +114,6 @@ RingBuffer::Put(void* buffer, int toCopy) {
    }
 
    mEnd = pos;
-   mMutex.leaveMutex();
 
    // How many items copied.
    return copied;
@@ -128,13 +131,14 @@ RingBuffer::AvailForGet() const {
 
 // Get will move 'toCopy' bytes from the internal FIFO to 'buffer'
 int 
-RingBuffer::Get(void *buffer, int toCopy) {
+RingBuffer::Get(void *buffer, int toCopy, unsigned short volume) {
    samplePtr dest;
    int block;
    int copied;
    int len = Len();
-	
-   mMutex.enterMutex();
+   int int16len;
+   int16* start;
+
    if (toCopy > len)
       toCopy = len;
 
@@ -146,14 +150,17 @@ RingBuffer::Get(void *buffer, int toCopy) {
       if (block > (mBufferSize - mStart))
          block = mBufferSize - mStart;
 
-      bcopy (mBuffer + mStart, dest, block);
+      start = (int16*)(mBuffer + mStart);
+      int16len = (block >> 1);
+      for (int i=0; i<int16len; i++) { start[i] = start[i] * volume / 100; }
+      // bcopy(src, dest, len)
+      bcopy (start, dest, block);
       dest += block;
       mStart = (mStart + block) % mBufferSize;
       toCopy -= block;
       copied += block;
    }
 	
-   mMutex.leaveMutex();
    return copied;
 }
 
@@ -169,10 +176,3 @@ RingBuffer::Discard(int toDiscard) {
 
    return toDiscard;
 }
-
-/*
-T
-RingBuffer::getNextItem (void) {
-   return (T) 0;
-}
-*/
diff --git a/src/audio/ringbuffer.h b/src/audio/ringbuffer.h
index c18f82b08f614608ecc41018bee594c44ae0bfeb..9e1ef6bef4177f45a0f92e7ef5e9d59982fcc411 100644
--- a/src/audio/ringbuffer.h
+++ b/src/audio/ringbuffer.h
@@ -42,14 +42,14 @@ class RingBuffer {
    // For the writer only:
    //
    int AvailForPut (void) const;
-   int Put (void*, int);
+   int Put (void*, int, unsigned short = 0);
    void PutZero(int);
 
    //
    // For the reader only:
    //
    int AvailForGet (void) const;
-   int Get (void *, int);
+   int Get (void *, int, unsigned short);
    int Discard(int);
 
    int Len() const;
@@ -57,7 +57,6 @@ class RingBuffer {
  private:
  //  T getNextSample(void);
 
-   ost::Mutex  		 mMutex;
    int           mStart;
    int           mEnd;
    int           mBufferSize;
diff --git a/src/audio/tonegenerator.cpp b/src/audio/tonegenerator.cpp
index c7b1488e4a2833b6e139fb3bb837941d4154d8ff..7a430f38179c90e1ec9f3355a75af7a76ff5061c 100644
--- a/src/audio/tonegenerator.cpp
+++ b/src/audio/tonegenerator.cpp
@@ -56,7 +56,7 @@ ToneThread::~ToneThread (void) {
 void
 ToneThread::run (void) {
 	int k;
-	int spkrVolume;
+	//int spkrVolume;
 	bool started = false;
 
 	// How long do 'size' samples play ?
@@ -64,14 +64,16 @@ ToneThread::run (void) {
   unsigned int pause = (size * 1000) / SAMPLING_RATE - 100;
 
   ManagerImpl& manager = Manager::instance();
-  manager.getAudioDriver()->mainSndRingBuffer().flush();
+  manager.getAudioDriver()->flushMain();
 
 	while (!testCancel()) {
 		// Create a new stereo buffer with the volume adjusted
-		spkrVolume = manager.getSpkrVolume();
+		//spkrVolume = manager.getSpkrVolume();
 		for (int j = 0; j < size; j++) {
-			k = j*2; // channels is 2 (global.h)
-			buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = buffer[j] * spkrVolume/100;
+			k = j<<1; // channels is 2 (global.h)
+                // split in two
+			buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = buffer[j];
+      // * spkrVolume/100;
 		}
 
 		// Push the tone to the audio FIFO
diff --git a/src/call.cpp b/src/call.cpp
index 3804e160d325db2c497c8c13d0f714c192bc4dfc..e1b74afc2c8419b589d48bf72f831590fdf37e51 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -185,7 +185,7 @@ Call::isAnswered (void)
 bool 
 Call::isNotAnswered (void)
 {
-	return (_state == Error || _state == NotExist ) ? true : false;
+	return (_state == Error || _state == NotExist || _state == Busy) ? true : false;
 }
 
 bool 
diff --git a/src/gui/server/tcpstreampool.h b/src/gui/server/tcpstreampool.h
index 46f8e90af0d61e9389f48879652d0c59d8fe3d98..6bec3bd783f1fec6ae55c9071bbace7356084457 100644
--- a/src/gui/server/tcpstreampool.h
+++ b/src/gui/server/tcpstreampool.h
@@ -43,6 +43,7 @@ public:
   {
     setCancel(cancelDeferred);
   }
+  TCPStreamPool::~TCPStreamPool() {terminate();}
 
   void run();
   void send(const std::string& response);
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index 3656c65cd71578dbea9ab7958fb76a9a4764d098..7716a8e8e894de15f0ec1c75899867e0351087dc 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -336,7 +336,7 @@ ManagerImpl::onHoldCall (CALLID id)
   if (call == NULL) {
     return -1;
   }
-  if ( call->getState() == Call::OnHold) {
+  if ( call->getState() == Call::OnHold || call->isNotAnswered()) {
     return 1;
   }
   return call->onHold();
@@ -349,6 +349,7 @@ ManagerImpl::onHoldCall (CALLID id)
 int 
 ManagerImpl::offHoldCall (CALLID id)
 {
+  stopTone();
   ost::MutexLock m(_mutex);
   Call* call = getCall(id);
   if (call == NULL) {
@@ -480,6 +481,7 @@ ManagerImpl::sendDtmf (CALLID id, char code)
   int returnValue = false;
   switch (sendType) {
   case 0: // SIP INFO
+    playDtmf(code);
     _voIPLinkVector.at(DFT_VOIP_LINK)->carryingDTMFdigits(id, code);
     returnValue = true;
     break;
@@ -509,7 +511,8 @@ ManagerImpl::playDtmf(char code)
   _key.startTone(code);
   if ( _key.generateDTMF(_buf, SAMPLING_RATE) ) {
 
-    int k, spkrVolume;
+    int k;
+    //int spkrVolume;
     int16* buf_ctrl_vol;
 
     // Determine dtmf pulse length
@@ -517,12 +520,13 @@ ManagerImpl::playDtmf(char code)
     int size = pulselen * (OCTETS /1000);
 
     buf_ctrl_vol = new int16[size*CHANNELS];
-    spkrVolume = getSpkrVolume();
+    //spkrVolume = getSpkrVolume();
 
     // Control volume and format mono->stereo
     for (int j = 0; j < size; j++) {
-      k = j*2;
-      buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = _buf[j] * spkrVolume/100;
+      k = j<<1; // fast multiply by two
+      buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = _buf[j];
+      // * spkrVolume/100;
     }
 
     AudioLayer *audiolayer = getAudioDriver();
@@ -815,7 +819,6 @@ ManagerImpl::stopTone() {
       _tone->stopTone();
     }
     _toneMutex.leaveMutex();
-    getAudioDriver()->mainSndRingBuffer().flush();
     getAudioDriver()->stopStream();
   }
 }
@@ -899,16 +902,18 @@ ManagerImpl::notificationIncomingCall (void) {
   int16* buf_ctrl_vol;
   int16* buffer = new int16[SAMPLING_RATE];
   int size = SAMPLES_SIZE(FRAME_PER_BUFFER);//SAMPLING_RATE/2;
-  int k, spkrVolume;
+  int k;
+  //int spkrVolume;
 
   _tone->generateSin(440, 0, buffer);
 
   // Volume Control 
   buf_ctrl_vol = new int16[size*CHANNELS];
-  spkrVolume = getSpkrVolume();
+  // spkrVolume = getSpkrVolume();
   for (int j = 0; j < size; j++) {
-    k = j*2;
-    buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = buffer[j] * spkrVolume/100;
+    k = j<<1; // fast multiply by two
+    buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = buffer[j];
+    // * spkrVolume/100;
   }
   getAudioDriver()->putUrgent(buf_ctrl_vol, SAMPLES_SIZE(FRAME_PER_BUFFER));
 
@@ -1083,7 +1088,7 @@ ManagerImpl::selectAudioDriver (void)
 {
 #if defined(AUDIO_PORTAUDIO)
   try {
-    _audiodriverPA = new AudioLayer();
+    _audiodriverPA = new AudioLayer(*this);
     _audiodriverPA->openDevice(getConfigInt(AUDIO, DRIVER_NAME));
   } catch(...) {
     throw;
diff --git a/src/managerimpl.h b/src/managerimpl.h
index 3a631a9b24e7cf824e9869af74085817dddba93d..cc5050bbf1b7d0fa52007c37c26d1e02591f97e5 100644
--- a/src/managerimpl.h
+++ b/src/managerimpl.h
@@ -222,13 +222,27 @@ name);
 	void getStunInfo (StunAddress4& stunSvrAddr);
 	bool useStun (void);
 	
-	/*
-	 * Inline functions to manage volume control
-	 */
-	inline int getSpkrVolume 	(void) 			{ ost::MutexLock m(_mutex); return _spkr_volume; }
-	inline void setSpkrVolume 	(int spkr_vol) 	{ ost::MutexLock m(_mutex); _spkr_volume = spkr_vol; }
-	inline int getMicVolume 	(void) 			{ ost::MutexLock m(_mutex); return _mic_volume; }
-	inline void setMicVolume 	(int mic_vol) 	{ ost::MutexLock m(_mutex); _mic_volume = _mic_volume_before_mute = mic_vol; }
+  /*
+   * Inline functions to manage volume control
+   * Read by main thread and AudioLayer thread
+   * Write by main thread only
+   */
+  unsigned short getSpkrVolume(void) { 
+    //ost::MutexLock m(_mutex); 
+    return _spkr_volume; 
+  }
+  void setSpkrVolume(unsigned short spkr_vol) { 
+    //ost::MutexLock m(_mutex); 
+    _spkr_volume = spkr_vol;
+  }
+  unsigned short getMicVolume(void) { 
+    //ost::MutexLock m(_mutex); 
+    return _mic_volume;
+  }
+  void setMicVolume(unsigned short mic_vol) { 
+    //ost::MutexLock m(_mutex); 
+    _mic_volume = _mic_volume_before_mute = mic_vol; 
+  }
 
   bool hasLoadedSetup() { return _setupLoaded; }
 	
@@ -378,10 +392,10 @@ private:
 
 	unsigned int _nCodecs;
 
-	// To handle volume control
-	int 		_spkr_volume;
-	int 		_mic_volume;
-  int 		_mic_volume_before_mute;
+  // To handle volume control
+  short _spkr_volume;
+  short _mic_volume;
+  short _mic_volume_before_mute;
 
 	// To handle firewall
 	int			_firewallPort;
diff --git a/src/sipcall.cpp b/src/sipcall.cpp
index 2028c1481fb2a02a3445ba30b1cda76e87ee30f0..02ce78d86b61823d1dd78e30dc7a7a35e278d71b 100644
--- a/src/sipcall.cpp
+++ b/src/sipcall.cpp
@@ -44,7 +44,7 @@ SipCall::SipCall (CALLID id, CodecDescriptorVector* cdv) : _localIp("127.0.0.1")
   alloc(); // char* allocation
   _cdv = cdv;
   _audiocodec = NULL;
-  enable_audio = -1;
+  enable_audio = false;
 
   _state = 0;
   _local_audio_port = 0;
@@ -57,7 +57,8 @@ SipCall::SipCall (CALLID id, CodecDescriptorVector* cdv) : _localIp("127.0.0.1")
 SipCall::~SipCall (void) 
 {
 	dealloc();
-  delete _audiocodec; _audiocodec = NULL;
+  //delete _audiocodec;  don't delete it, the Manager will do it...
+  _audiocodec = NULL;
 }
 
 void
@@ -142,7 +143,8 @@ void
 SipCall::setAudioCodec (AudioCodec* ac)
 {
   // it use a new!
-  delete _audiocodec; _audiocodec = ac;
+  // delete _audiocodec;
+ _audiocodec = ac;
 }
 
 // newIncomingCall is called when the IP-Phone user receives a new call.
@@ -253,10 +255,10 @@ SipCall::newIncomingCall (eXosip_event_t *event) {
               	eXosip_call_send_answer (_tid, 415, NULL);
           	} else {
               	/* start sending audio */
-              	if (enable_audio > 0) {
-                  	enable_audio = -1;
+              	if (enable_audio == true) {
+                  	enable_audio = false;
                 }
-              	if (enable_audio != 1)        /* audio is started */ {
+              	if (enable_audio == false)        /* audio is started */ {
                   	sdp_message_t *local_sdp;
                   	local_sdp = eXosip_get_sdp_info (answer);
                   	if (remote_sdp != NULL && local_sdp != NULL) {
@@ -284,12 +286,12 @@ SipCall::newIncomingCall (eXosip_event_t *event) {
                           && local_med != NULL) {
                           	tmp = (char *) osip_list_get (local_med->m_payloads, 0);
                         }
-                      	if (tmp != NULL) {
-                          	payload = atoi (tmp);
-    						_debug("SipCall::newIncomingCall: For incoming payload = %d\n", payload);
-    						setAudioCodec(_cdv->at(0)->alloc(payload, ""));
-                        }
-						if (tmp != NULL
+                      if (tmp != NULL) {
+                            payload = atoi (tmp);
+                            _debug("SipCall::newIncomingCall: For incoming payload = %d\n", payload);
+                            setAudioCodec(_cdv->at(0)->alloc(payload, "")); // codec builder for the mic
+                      }
+                    if (tmp != NULL
                           && audio_port > 0
                           && _remote_sdp_audio_port > 0
                           && _remote_sdp_audio_ip[0] != '\0') {
@@ -353,64 +355,6 @@ SipCall::ringingCall (eXosip_event_t *event) {
       osip_free (tmp);
     }
   }
-/*
-    sdp_message_t *remote_sdp;
-    sdp_message_t *local_sdp;
-
-    local_sdp = eXosip_get_sdp_info (event->request);
-    remote_sdp = eXosip_get_sdp_info (event->response);
-    if (remote_sdp == NULL) {
-    	_debug("SipCall::ringingCall: No remote SDP body found for call\n");
-          // TODO: remote_sdp = retreive from ack above
-    }
-    if (local_sdp == NULL) {
-    	_debug("SipCall::ringingCall: SDP body was probably in the ACK (TODO)\n");
-    }
-    if (remote_sdp != NULL && local_sdp != NULL) {
-        sdp_connection_t *conn;
-        sdp_media_t *local_med;
-        sdp_media_t *remote_med;
-        char *tmp = NULL;
-        int audio_port = 0;
-
-        conn = eXosip_get_audio_connection (remote_sdp);
-        if (conn != NULL && conn->c_addr != NULL) {
-        	snprintf (_remote_sdp_audio_ip, 49, "%s", conn->c_addr);
-        }
-        remote_med = eXosip_get_audio_media (remote_sdp);
-        if (remote_med != NULL && remote_med->m_port != NULL) {
-        	_remote_sdp_audio_port = atoi (remote_med->m_port);
-        }
-        local_med = eXosip_get_audio_media (local_sdp);
-        if (local_med != NULL && local_med->m_port != NULL) {
-            audio_port = atoi (local_med->m_port);
-        }
-        if (_remote_sdp_audio_port > 0 && _remote_sdp_audio_ip[0] != '\0' 
-				&& remote_med != NULL) {
-            tmp = (char *) osip_list_get (remote_med->m_payloads, 0);
-        }
-        if (tmp != NULL) {
-            ca->payload = atoi (tmp);
-        }
-        if (tmp != NULL
-              && audio_port > 0
-              && _remote_sdp_audio_port > 0
-              && _remote_sdp_audio_ip[0] != '\0') {
-			// search if stream is sendonly or recvonly
-            _remote_sendrecv =
-               	sdp_analyse_attribute (remote_sdp, remote_med);
-            _local_sendrecv = sdp_analyse_attribute (local_sdp, local_med);
-            if (_local_sendrecv == _SENDRECV) {
-               	if (_remote_sendrecv == _SENDONLY)
-                   	_local_sendrecv = _RECVONLY;
-               	else if (_remote_sendrecv == _RECVONLY)
-                   	_local_sendrecv = _SENDONLY;
-            }
-		}
-	}
-    sdp_message_free (local_sdp);
-    sdp_message_free (remote_sdp);
-*/
   	this->_state = event->type;;
   	return 0;
 }
@@ -420,74 +364,6 @@ SipCall::receivedAck (eXosip_event_t *event)
 {
   _cid = event->cid;
   _did = event->did;
-/*
-  	if (event->ack != NULL) {
-      	sdp_message_t *remote_sdp;
-      	remote_sdp = eXosip_get_sdp_info (event->ack);
-      	if (remote_sdp != NULL) {
-	  		_debug("SipCall::receivedAck: SDP detected in ACK!\n");
-		} else {
-	  		_debug("SipCall::receivedAck: no SDP detected in ACK!\n");
-		}
-    }
-
-  	if (enable_audio != 1) {   // audio is started
-      	sdp_message_t *remote_sdp;
-      	sdp_message_t *local_sdp;
-
-      	remote_sdp = eXosip_get_remote_sdp (_did);
-      	local_sdp = eXosip_get_local_sdp (_did);
-      	if (remote_sdp == NULL) {
-          	_debug("SipCall::receivedAck: No remote SDP body found for call\n");
-        }
-      	if (remote_sdp != NULL && local_sdp != NULL) {
-          	sdp_connection_t *conn;
-          	sdp_media_t *local_med;
-          	sdp_media_t *remote_med;
-          	char *tmp = NULL;
-          	int audio_port = 0;
-
-          	conn = eXosip_get_audio_connection (remote_sdp);
-          	if (conn != NULL && conn->c_addr != NULL) {
-              	snprintf (_remote_sdp_audio_ip, 49, "%s", conn->c_addr);
-            }
-          	remote_med = eXosip_get_audio_media (remote_sdp);
-          	if (remote_med != NULL && remote_med->m_port != NULL) {
-              	_remote_sdp_audio_port = atoi (remote_med->m_port);
-            }
-          	local_med = eXosip_get_audio_media (local_sdp);
-          	if (local_med != NULL && local_med->m_port != NULL) {
-              	audio_port = atoi (local_med->m_port);
-            }
-
-          	if (_remote_sdp_audio_port > 0
-              && _remote_sdp_audio_ip[0] != '\0' && local_med != NULL) {
-              	tmp = (char *) osip_list_get (local_med->m_payloads, 0);
-            }
-          	if (tmp != NULL) {
-              ca->payload = atoi (tmp);
-            }
-          	if (tmp != NULL
-              && audio_port > 0
-              && _remote_sdp_audio_port > 0
-              && _remote_sdp_audio_ip[0] != '\0') {
-
-              	// search if stream is sendonly or recvonly
-              	_remote_sendrecv =
-                	sdp_analyse_attribute (remote_sdp, remote_med);
-              	_local_sendrecv = sdp_analyse_attribute (local_sdp, local_med);
-              	if (_local_sendrecv == _SENDRECV) {
-                  	if (_remote_sendrecv == _SENDONLY)
-                    	_local_sendrecv = _RECVONLY;
-                  	else if (_remote_sendrecv == _RECVONLY)
-                    	_local_sendrecv = _SENDONLY;
-                }
-            }
-        }
-      sdp_message_free (local_sdp);
-      sdp_message_free (remote_sdp);
-    }
-*/
   _state = event->type;
   return 0;
 }
@@ -557,16 +433,16 @@ SipCall::answeredCall(eXosip_event_t *event) {
 void
 SipCall::answeredCall_without_hold (eXosip_event_t *event) 
 {
-  if (enable_audio == 1 && event->response != NULL) {
+  if (enable_audio == true && event->response != NULL) {
     sdp_message_t *sdp = eXosip_get_sdp_info (event->response);
     if (sdp != NULL) {
         /* audio is started and session has just been modified */
-      enable_audio = -1;
+      enable_audio = false;
       sdp_message_free (sdp);
     }
   }
 
-  if (enable_audio != 1 && 
+  if (enable_audio == false && 
       event->request  != NULL && 
       event->response != NULL) {   /* audio is started */ 
 
diff --git a/src/sipcall.h b/src/sipcall.h
index 18cb3864ae54fbde343acc1ec2f2bf92089a903a..95626bc9636b5dfd5c0d8d666229247f599028b8 100644
--- a/src/sipcall.h
+++ b/src/sipcall.h
@@ -44,7 +44,7 @@ public:
 	~SipCall (void);
 
   int payload;
-  int enable_audio; /* 1 started, -1 stopped */
+  bool enable_audio; /* true = started, false = stopped */
 	
 	/*
 	 * Store information about incoming call and negociate payload
diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp
index e187dea7728c22e32c9e7b1a3164317fba070bab..b74a707a4ace39f86bee46d20828ce55a599b60d 100644
--- a/src/sipvoiplink.cpp
+++ b/src/sipvoiplink.cpp
@@ -379,11 +379,16 @@ SipVoIPLink::answer (CALLID id)
   return i;
 }
 
+
+/**
+ * @return > 0 is good, -1 is bad
+ */
 int
 SipVoIPLink::hangup (CALLID id) 
 {
   int i = 0;
   SipCall* sipcall = getSipCall(id);
+  if (sipcall == NULL) { return -1; }
   _debug("Hang up call [id = %d, cid = %d, did = %d]\n", 
     id, sipcall->getCid(), sipcall->getDid());	
   // Release SIP stack.
@@ -392,7 +397,8 @@ SipVoIPLink::hangup (CALLID id)
   eXosip_unlock();
 
   // Release RTP channels
-  _audiortp.closeRtpSession(sipcall);
+  sipcall->enable_audio = false;
+  _audiortp.closeRtpSession();
 
   deleteSipCall(id);
   return i;
@@ -413,6 +419,9 @@ SipVoIPLink::cancel (CALLID id)
   return i;
 }
 
+/*
+ * @return -1 = sipcall not present
+ */
 int
 SipVoIPLink::onhold (CALLID id) 
 {
@@ -422,12 +431,15 @@ SipVoIPLink::onhold (CALLID id)
 
   sdp_message_t *local_sdp = NULL;
 
-  did = getSipCall(id)->getDid();
-	
+  SipCall *sipcall = getSipCall(id);
+  if ( sipcall == NULL ) { return -1; }
+
+  did = sipcall->getDid();
+
   eXosip_lock ();
   local_sdp = eXosip_get_local_sdp (did);
   eXosip_unlock ();
-	
+
   if (local_sdp == NULL) {
     return -1;
   }
@@ -445,7 +457,7 @@ SipVoIPLink::onhold (CALLID id)
   /* add sdp body */
   {
     char *tmp = NULL;
-    
+
     i = sdp_hold_call (local_sdp);
     if (i != 0) {
       sdp_message_free (local_sdp);
@@ -471,7 +483,8 @@ SipVoIPLink::onhold (CALLID id)
   eXosip_unlock ();
   
   // Disable audio
-  _audiortp.closeRtpSession(getSipCall(id));
+  sipcall->enable_audio = false;
+  _audiortp.closeRtpSession();
   return i;
 }
 
@@ -740,7 +753,9 @@ SipVoIPLink::getEvent (void)
     _debug("Call is closed [id = %d, cid = %d, did = %d]\n", id, event->cid, event->did);	
     if (id != 0) {
       if (Manager::instance().callCanBeClosed(id)) {
-	       _audiortp.closeRtpSession(getSipCall(id));
+         SipCall* sipcall = getSipCall(id);
+         if ( sipcall != NULL ) { sipcall->enable_audio = false; }
+         _audiortp.closeRtpSession();
       }
       Manager::instance().peerHungupCall(id);
       deleteSipCall(id);
@@ -1005,7 +1020,7 @@ SipVoIPLink::endSipCalls()
       eXosip_unlock();
 
       // Release RTP channels
-      _audiortp.closeRtpSession(*iter);
+      _audiortp.closeRtpSession();
       delete *iter; *iter = NULL;
     }
     iter++;