diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am
index 7c82edb0a47df84b4b3639d1c845142e38afbceb..5bd7d1ab1e1a6d3b1a9a745093f728730d39d846 100644
--- a/src/audio/Makefile.am
+++ b/src/audio/Makefile.am
@@ -3,21 +3,13 @@ SUBDIRS = gsm pacpp
 noinst_LTLIBRARIES = libaudio.la
 
 
-libaudio_la_SOURCES = \
-	alaw.cpp alaw.h \
-	audiocodec.cpp audiocodec.h \
-	audiolayer.cpp audiolayer.h \
-	audiortp.cpp audiortp.h \
-	codecDescriptor.cpp codecDescriptor.h \
-	common.h \
-	dtmf.cpp dtmf.h \
-	dtmfgenerator.cpp dtmfgenerator.h \
-	g711.cpp g711.h \
-	gsmcodec.cpp gsmcodec.h \
-	ringbuffer.cpp ringbuffer.h \
-	tonegenerator.cpp tonegenerator.h \
-	ulaw.cpp ulaw.h 
+libaudio_la_SOURCES = alaw.cpp alaw.h 	audiocodec.cpp audiocodec.h \
+		audiolayer.cpp audiolayer.h 	audiortp.cpp audiortp.h 	codecDescriptor.cpp \
+	codecDescriptor.h 	common.h 	dtmf.cpp dtmf.h 	dtmfgenerator.cpp dtmfgenerator.h 	g711.cpp \
+	g711.h 	gsmcodec.cpp gsmcodec.h 	ringbuffer.cpp ringbuffer.h \
+		tonegenerator.cpp tonegenerator.h 	ulaw.cpp ulaw.h tone.cpp tonelist.cpp
 
 AM_CXXFLAGS = -I$(top_srcdir) -I$(srcdir)/pacpp/include/ $(libccext2_CFLAGS) $(libccrtp1_CFLAGS) $(portaudio_CFLAGS)
 libaudio_la_LIBADD = gsm/libgsm.la pacpp/source/portaudiocpp/libportaudiocpp.la
 
+noinst_HEADERS = tone.h tonelist.h
diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp
index f66e73072f02fea48008efb37f2b143ba1879b61..4140947d18457f898f7fa930df5dba87e8dea3e5 100644
--- a/src/audio/audiolayer.cpp
+++ b/src/audio/audiolayer.cpp
@@ -88,9 +88,9 @@ AudioLayer::openDevice (int index)
 	     NULL);
 
 	
-  // we could put 0 instead of FRAME_PER_BUFFER to be variable
+  // we could put paFramesPerBufferUnspecified instead of FRAME_PER_BUFFER to be variable
   portaudio::StreamParameters const params(inParams, outParams, 
-					   SAMPLING_RATE, paFramesPerBufferUnspecified, paPrimeOutputBuffersUsingStreamCallback | paNeverDropInput /*paNoFlag*/);
+					   SAMPLING_RATE, paFramesPerBufferUnspecified, paNoFlag /*paPrimeOutputBuffersUsingStreamCallback | paNeverDropInput*/);
 		  
   // Create (and open) a new Stream, using the AudioLayer::audioCallback
   _stream = new portaudio::MemFunCallbackStream<AudioLayer>(params, 
@@ -102,25 +102,21 @@ void
 AudioLayer::startStream(void) 
 {
   ost::MutexLock guard(_mutex);
-  if (Manager::instance().isDriverLoaded()) {
-    if (_stream && !_stream->isActive()) {
-      _debug("Thread: start audiolayer stream\n");
-      _stream->start();
-    }
-  } 
+  if (_stream && !_stream->isActive()) {
+    _debug("Thread: start audiolayer stream\n");
+    _stream->start();
+  }
 }
 	
 void
 AudioLayer::stopStream(void) 
 {
   ost::MutexLock guard(_mutex);
-  if (Manager::instance().isDriverLoaded()) {
-    if (_stream && !_stream->isStopped()) {
-      _debug("Thread: stop audiolayer stream\n");
-       _stream->stop();
-      _mainSndRingBuffer.flush();
-    }
-  } 
+  if (_stream && !_stream->isStopped()) {
+    _debug("Thread: stop audiolayer stream\n");
+      _stream->stop();
+    _mainSndRingBuffer.flush();
+  }
 }
 
 void
@@ -145,7 +141,12 @@ void
 AudioLayer::putMain(void* buffer, int toCopy)
 {
   ost::MutexLock guard(_mutex);
-  _mainSndRingBuffer.Put(buffer, toCopy);
+  int a = _mainSndRingBuffer.AvailForPut();
+  if ( a >= toCopy ) {
+    _mainSndRingBuffer.Put(buffer, toCopy);
+  } else {
+    _mainSndRingBuffer.Put(buffer, a);
+  }
 }
 
 void
@@ -159,7 +160,12 @@ void
 AudioLayer::putUrgent(void* buffer, int toCopy)
 {
   ost::MutexLock guard(_mutex);
-  _urgentRingBuffer.Put(buffer, toCopy);
+  int a = _mainSndRingBuffer.AvailForPut();
+  if ( a >= toCopy ) {
+    _urgentRingBuffer.Put(buffer, toCopy);
+  } else {
+    _urgentRingBuffer.Put(buffer, a);
+  }
 }
 
 void
@@ -195,38 +201,43 @@ AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer,
   int urgentAvail, // number of int16 right and int16 left
       normalAvail, // number of int16 right and int16 left
       micAvailPut;
-  unsigned short spkrVolume = Manager::instance().getSpkrVolume();
-  unsigned short micVolume  = Manager::instance().getMicVolume();
+  ManagerImpl& _manager = Manager::instance();
+  unsigned short spkrVolume = _manager.getSpkrVolume();
+  unsigned short micVolume  = _manager.getMicVolume();
 
   // AvailForGet tell the number of chars inside the buffer
   // framePerBuffer are the number of int16 for one channel (left)
-  framesPerBuffer *= NBCHARFORTWOINT16;
 	urgentAvail = _urgentRingBuffer.AvailForGet();
 	if (urgentAvail > 0) {  
 	// Urgent data (dtmf, incoming call signal) come first.		
-		toGet = (urgentAvail < (int)framesPerBuffer) ? urgentAvail : framesPerBuffer;
+		toGet = (urgentAvail < (int)framesPerBuffer * NBCHARFORTWOINT16) ? urgentAvail : framesPerBuffer * NBCHARFORTWOINT16;
 		_urgentRingBuffer.Get(out, toGet, spkrVolume);
 		
 		// Consume the regular one as well (same amount of bytes)
 		_mainSndRingBuffer.Discard(toGet);
 	}  
 	else {
-	// If nothing urgent, play the regular sound samples
-		normalAvail = _mainSndRingBuffer.AvailForGet();
-		toGet = (normalAvail < (int)framesPerBuffer) ? normalAvail : framesPerBuffer;
-
-   if (toGet) {
-		  _mainSndRingBuffer.Get(out, toGet, spkrVolume);
+    Tone* tone = _manager.getTelephoneTone();
+    if ( tone != 0) {
+      tone->getNext(out, framesPerBuffer, spkrVolume);
     } else {
-      toGet = framesPerBuffer;
-      _mainSndRingBuffer.PutZero(toGet);
-      _mainSndRingBuffer.Get(out, toGet, 100);
-    }
+      // If nothing urgent, play the regular sound samples
+      normalAvail = _mainSndRingBuffer.AvailForGet();
+      toGet = (normalAvail < (int)framesPerBuffer * NBCHARFORTWOINT16) ? normalAvail : framesPerBuffer * NBCHARFORTWOINT16;
+
+      if (toGet) {
+          _mainSndRingBuffer.Get(out, toGet, spkrVolume);
+        } else {
+          toGet = framesPerBuffer;
+          _mainSndRingBuffer.PutZero(toGet);
+          _mainSndRingBuffer.Get(out, toGet, 100);
+        }
+      }
 	}
 
 	// Additionally handle the mic's audio stream 
   micAvailPut = _micRingBuffer.AvailForPut();
-  toPut = (micAvailPut <= (int)framesPerBuffer) ? micAvailPut : framesPerBuffer;
+  toPut = (micAvailPut <= (int)framesPerBuffer) ? micAvailPut : framesPerBuffer * NBCHARFORTWOINT16;
   _micRingBuffer.Put(in, toPut, micVolume );
 
 	return paContinue;
diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h
index f04d53c9336a0432e8eb22b39f567c034755443d..3c0cdab7592940fe816c13a1b8a5f432ed933a72 100644
--- a/src/audio/audiolayer.h
+++ b/src/audio/audiolayer.h
@@ -29,7 +29,6 @@
 #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
diff --git a/src/audio/tone.cpp b/src/audio/tone.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fba483d5dc8f1b47614038c9aaa16b206f7483d4
--- /dev/null
+++ b/src/audio/tone.cpp
@@ -0,0 +1,169 @@
+/**
+ *  Copyright (C) 2005 Savoir-Faire Linux inc.
+ *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
+ *
+ *  Inspired by tonegenerator of 
+ *   Laurielle Lea <laurielle.lea@savoirfairelinux.com> (2004)
+ *  Inspired by ringbuffer of Audacity Project
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "tone.h"
+#include <math.h>
+
+int INT16_AMPLITUDE = 32767;
+
+Tone::Tone(const std::string& definition) 
+{
+  _buffer = 0;
+  _pos    = 0;
+  _size   = 0;
+  genBuffer(definition); // allocate memory with definition parameter
+}
+
+Tone::~Tone()
+{
+  delete _buffer; _buffer = 0;
+}
+
+void 
+Tone::genBuffer(const std::string& definition)
+{
+  _size = 0;
+
+  int16 *buffer = new int16[SIZEBUF]; //1kb
+  int16 *bufferPos = buffer;
+
+  // Number of format sections 
+  unsigned int posStart = 0; // position of precedent comma
+  unsigned int posEnd = 0; // position of the next comma
+
+  std::string s; // portion of frequency
+  int count; // number of int for one sequence
+
+  unsigned int deflen = definition.length();
+  do {
+    posEnd = definition.find(',', posStart);
+    if (posEnd == std::string::npos) {
+      posEnd = deflen;
+    }
+
+    {
+      // Sample string: "350+440" or "350+440/2000,244+655/2000"
+      int freq1, freq2, time;
+      s = definition.substr(posStart, posEnd-posStart);
+
+      // The 1st frequency is before the first + or the /
+      unsigned int pos_plus = s.find('+');
+      unsigned int pos_slash = s.find('/');
+      unsigned int len = s.length();
+      unsigned int endfrequency = 0;
+
+      if ( pos_slash == std::string::npos ) {
+        time = 0;
+        endfrequency = len;
+      } else {
+        time = atoi((s.substr(pos_slash+1,len-pos_slash-1)).data());
+        endfrequency = pos_slash;
+      }
+
+      // without a plus = 1 frequency
+      if (pos_plus == std::string::npos ) {
+        freq1 = atoi((s.substr(0,endfrequency)).data());
+        freq2 = 0;
+      } else {
+        freq1 = atoi((s.substr(0,pos_plus)).data());
+        freq2 = atoi((s.substr(pos_plus+1, endfrequency-pos_plus-1)).data());
+      }
+
+      // If there is time or if it's unlimited
+      if (time == 0) {
+        count = SAMPLING_RATE;
+      } else {
+        count = (SAMPLING_RATE * time) / 1000;
+      }
+      // Generate SAMPLING_RATE samples of sinus, buffer is the result
+      genSin(bufferPos, freq1, freq2, count);
+
+      // To concatenate the different buffers for each section.
+      _size += (count<<1); 
+      bufferPos += (count<<1);
+    }
+
+    posStart = posEnd+1;
+  } while (posStart < deflen);
+
+  _buffer = new int16[_size];
+  // src, dest, tocopy
+  bcopy(buffer, _buffer, _size<<1); // copy char, not int16..
+  delete[] buffer; buffer=0; bufferPos=0;
+}
+
+void
+Tone::genSin(int16 *buffer, int frequency1, int frequency2, int nb) 
+{
+  double var1 = (double)2 * (double)M_PI * (double)frequency1 / (double)SAMPLING_RATE; 
+  double var2 = (double)2 * (double)M_PI * (double)frequency2 / (double)SAMPLING_RATE;
+
+  double amp = (double)(INT16_AMPLITUDE >> 2);
+  int k = 0;
+  for(int t = 0; t < nb; t++) {
+    k = t << 1; // double channel : left/right
+    buffer[k] = buffer[k+1] = (int16)(amp * ((sin(var1 * t) + sin(var2 * t))));
+  }
+}
+
+int
+Tone::getNext(int16* output, int nb, short volume)
+{
+  int copied = 0;
+  int block;
+  int pos = _pos;
+  nb<<=1; // double the number of int16 (stereo)
+  while(nb) {
+    block = nb;
+    if ( block > (_size-pos) ) {
+      block = _size-pos;
+    }
+    // src, dest, len
+    bcopy(_buffer+pos, output, block<<1); // short>char conversion
+    if (volume!=100) {
+      for (int i=0;i<block;i++) {
+        *output = (*output * volume)/100;
+        output++;
+      }
+    } else {
+      output += block; // this is the destination...
+    }
+    // should adjust sound here, in output???
+    pos = (pos + block ) % _size;
+    nb -= block;
+    copied += block;
+  }
+  _pos = pos;
+  return copied;
+}
+
+int
+Tone::contains (const std::string& str, char c)
+{
+  int nb = 0;
+  unsigned int pos = str.find(c);
+  while (pos != std::string::npos ) {
+    nb++;
+    pos = str.find(c, pos+1);
+  }
+  return nb;
+}
diff --git a/src/audio/tone.h b/src/audio/tone.h
new file mode 100644
index 0000000000000000000000000000000000000000..7335844579e9308d7af46d81e0eadd693ce678fa
--- /dev/null
+++ b/src/audio/tone.h
@@ -0,0 +1,73 @@
+/**
+ *  Copyright (C) 2005 Savoir-Faire Linux inc.
+ *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
+ *
+ *  Inspired by tonegenerator of 
+ *   Laurielle Lea <laurielle.lea@savoirfairelinux.com> (2004)
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __TONE_H__
+#define __TONE_H__
+
+#include <string>
+#include "../global.h" // for int16 declaration and SAMPLING_RATE
+#define TONE_NBTONE 4
+#define TONE_NBCOUNTRY 7
+
+/**
+ * @author Yan Morin <yan.morin@savoirfairelinux.com>
+ */
+class Tone {
+public:
+  Tone(const std::string& definition);
+  ~Tone();
+  enum TONEID {
+    TONE_DIALTONE = 0,
+    TONE_BUSY,
+    TONE_RINGTONE,
+    TONE_CONGESTION,
+    TONE_NULL
+  };
+
+  /**
+   * get the next fragment of the tone
+   * the function change the intern position, and will loop
+   * @param nb of int16 (mono) to send
+   * @return the number of int16 sent (nb*2)
+   */
+  int getNext(int16* output, int nb, short volume=100);
+
+private:
+  /**
+   * add a simple or double sin to the buffer, it double the sin in stereo 
+   * @param nb are the number of int16 (mono) to generate
+   * by example nb=5 generate 10 int16, 5 for the left, 5 for the right
+   */
+  void genSin(int16 *buffer, int frequency1, int frequency2, int nb);
+
+  /**
+   * allocate the memory with the definition
+   */
+  void genBuffer(const std::string& definition);
+
+  int contains (const std::string& str, char c);
+  int16* _buffer;
+  int _size; // number of int16 inside the buffer, not the delay
+  int _pos; // current position, set to 0, when initialize
+};
+
+#endif // __TONE_H__
+
diff --git a/src/audio/tonegenerator.cpp b/src/audio/tonegenerator.cpp
index af84b27c2b9b0117dbd2f3bbba48a5c95f9c2a54..ef865aa1f7abed2de1beba8f1d0f89524c317576 100644
--- a/src/audio/tonegenerator.cpp
+++ b/src/audio/tonegenerator.cpp
@@ -337,7 +337,7 @@ ToneGenerator::toneHandle (unsigned int idr, const std::string& zone) {
 
 void
 ToneGenerator::stopTone() {
-  _currentTone = ZT_TONE_NULL;
+  //_currentTone = ZT_TONE_NULL;
 
   //_debug("Thread: delete tonethread\n");
   delete tonethread; tonethread = NULL;
diff --git a/src/audio/tonegenerator.h b/src/audio/tonegenerator.h
index dd9ae6c54f73a6f06335372079f40b82fbae9971..a857b9df8fe35cb75e8ee4ad35af1a9305a362ab 100644
--- a/src/audio/tonegenerator.h
+++ b/src/audio/tonegenerator.h
@@ -18,8 +18,8 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef __TONE_GENRATOR_H__
-#define __TONE_GENRATOR_H__
+#ifndef __TONE_GENERATOR_H__
+#define __TONE_GENERATOR_H__
 
 #include <string>
 
diff --git a/src/audio/tonelist.cpp b/src/audio/tonelist.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..40087c6ca9cbd6377849c546285cbb2b2ec7d08a
--- /dev/null
+++ b/src/audio/tonelist.cpp
@@ -0,0 +1,143 @@
+/**
+ *  Copyright (C) 2005 Savoir-Faire Linux inc.
+ *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
+ *
+ *  Inspired by tonegenerator of 
+ *   Laurielle Lea <laurielle.lea@savoirfairelinux.com> (2004)
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "tonelist.h"
+
+ToneList::ToneList() {
+  _nbTone = TONE_NBTONE; // could be dynamic
+  _nbCountry = TONE_NBCOUNTRY; // could be dynamic
+
+  _defaultCountryId = ZID_NORTH_AMERICA;
+  initToneDefinition();
+}
+
+ToneList::~ToneList() {
+}
+
+void 
+ToneList::initToneDefinition() 
+{
+  _toneZone[ZID_NORTH_AMERICA][Tone::TONE_DIALTONE] = "350+440";
+  _toneZone[ZID_NORTH_AMERICA][Tone::TONE_BUSY] = "480+620/500,0/500";
+  _toneZone[ZID_NORTH_AMERICA][Tone::TONE_RINGTONE] = "440+480/2000,0/4000";
+  _toneZone[ZID_NORTH_AMERICA][Tone::TONE_CONGESTION] = "480+620/250,0/250"; 
+
+  _toneZone[ZID_FRANCE][Tone::TONE_DIALTONE] = "440";
+  _toneZone[ZID_FRANCE][Tone::TONE_BUSY] = "440/500,0/500";
+  _toneZone[ZID_FRANCE][Tone::TONE_RINGTONE] = "440/1500,0/3500";
+  _toneZone[ZID_FRANCE][Tone::TONE_CONGESTION] = "440/250,0/250";
+
+  _toneZone[ZID_AUSTRALIA][Tone::TONE_DIALTONE] = "413+438";
+  _toneZone[ZID_AUSTRALIA][Tone::TONE_BUSY] = "425/375,0/375";
+  _toneZone[ZID_AUSTRALIA][Tone::TONE_RINGTONE] = 
+    "413+438/400,0/200,413+438/400,0/2000";
+  _toneZone[ZID_AUSTRALIA][Tone::TONE_CONGESTION] = "425/375,0/375,420/375,8/375"; 
+
+  _toneZone[ZID_UNITED_KINGDOM][Tone::TONE_DIALTONE] = "350+440";
+  _toneZone[ZID_UNITED_KINGDOM][Tone::TONE_BUSY] = "400/375,0/375";
+  _toneZone[ZID_UNITED_KINGDOM][Tone::TONE_RINGTONE] = 
+    "400+450/400,0/200,400+450/400,0/2000";
+  _toneZone[ZID_UNITED_KINGDOM][Tone::TONE_CONGESTION] = 
+    "400/400,0/350,400/225,0/525";
+
+  _toneZone[ZID_SPAIN][Tone::TONE_DIALTONE] = "425";
+  _toneZone[ZID_SPAIN][Tone::TONE_BUSY] = "425/200,0/200";
+  _toneZone[ZID_SPAIN][Tone::TONE_RINGTONE] = "425/1500,0/3000";
+  _toneZone[ZID_SPAIN][Tone::TONE_CONGESTION] = 
+    "425/200,0/200,425/200,0/200,425/200,0/600";
+
+  _toneZone[ZID_ITALY][Tone::TONE_DIALTONE] = "425/600,0/1000,425/200,0/200";
+  _toneZone[ZID_ITALY][Tone::TONE_BUSY] = "425/500,0/500";
+  _toneZone[ZID_ITALY][Tone::TONE_RINGTONE] = "425/1000,0/4000";
+  _toneZone[ZID_ITALY][Tone::TONE_CONGESTION] = "425/200,0/200";
+
+  _toneZone[ZID_JAPAN][Tone::TONE_DIALTONE] = "400";
+  _toneZone[ZID_JAPAN][Tone::TONE_BUSY] = "400/500,0/500";
+  _toneZone[ZID_JAPAN][Tone::TONE_RINGTONE] = "400+15/1000,0/2000";
+  _toneZone[ZID_JAPAN][Tone::TONE_CONGESTION] = "400/500,0/500";
+}
+
+std::string
+ToneList::getDefinition(COUNTRYID countryId, Tone::TONEID toneId) 
+{
+  if (toneId == Tone::TONE_NULL) { return ""; }
+  return _toneZone[countryId][toneId];
+}
+
+ToneList::COUNTRYID 
+ToneList::getCountryId(const std::string& countryName) 
+{
+  if (countryName.compare("North America") == 0) {
+    return ZID_NORTH_AMERICA;
+  } else if (countryName.compare("France") == 0) {
+    return ZID_FRANCE;
+  } else if (countryName.compare("Australia") == 0) {
+    return ZID_AUSTRALIA;
+  } else if (countryName.compare("United Kingdom") == 0) {
+    return ZID_UNITED_KINGDOM;
+  } else if (countryName.compare("Spain") == 0) {
+    return ZID_SPAIN;
+  } else if (countryName.compare("Italy") == 0) {
+    return ZID_ITALY;
+  } else if (countryName.compare("Japan") == 0) {
+    return ZID_JAPAN;
+  } else {
+    return _defaultCountryId; // default, we don't want segmentation fault
+  }
+}
+
+TelephoneTone::TelephoneTone(const std::string& countryName) {
+  ToneList::COUNTRYID countryId = _toneList.getCountryId(countryName);
+  _tone[Tone::TONE_DIALTONE] = new Tone(_toneList.getDefinition(countryId, Tone::TONE_DIALTONE));
+  _tone[Tone::TONE_BUSY] = new Tone(_toneList.getDefinition(countryId, Tone::TONE_BUSY));
+  _tone[Tone::TONE_RINGTONE] = new Tone(_toneList.getDefinition(countryId, Tone::TONE_RINGTONE));
+  _tone[Tone::TONE_CONGESTION] = new Tone(_toneList.getDefinition(countryId, Tone::TONE_CONGESTION));
+}
+
+TelephoneTone::~TelephoneTone() 
+{
+  for (int i=0; i<_toneList.getNbTone(); i++) {
+    delete _tone[i]; _tone[i] = 0;
+  }
+}
+
+void
+TelephoneTone::setCurrentTone(Tone::TONEID toneId)
+{
+  _currentTone = toneId;
+}
+
+Tone*
+TelephoneTone::getCurrentTone()
+{
+  if ( _currentTone == Tone::TONE_NULL ) {
+    return 0;
+  }
+  return _tone[_currentTone];
+}
+
+bool
+TelephoneTone::shouldPlay()
+{
+  return (( _currentTone != Tone::TONE_NULL ) ? true : false );
+}
+
+
diff --git a/src/audio/tonelist.h b/src/audio/tonelist.h
new file mode 100644
index 0000000000000000000000000000000000000000..b522fbac2bda7455b0868ce6bfe86ec145ab9aa4
--- /dev/null
+++ b/src/audio/tonelist.h
@@ -0,0 +1,97 @@
+/**
+ *  Copyright (C) 2005 Savoir-Faire Linux inc.
+ *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
+ *
+ *  Inspired by tonegenerator of 
+ *   Laurielle Lea <laurielle.lea@savoirfairelinux.com> (2004)
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __TONELIST_H__
+#define __TONELIST_H__
+
+#include "tone.h"
+
+/**
+ * @author Yan Morin <yan.morin@savoirfairelinux.com>
+ */
+class ToneList {
+public:
+  ToneList();
+  ~ToneList();
+
+  enum COUNTRYID {
+    ZID_NORTH_AMERICA = 0,
+    ZID_FRANCE,
+    ZID_AUSTRALIA,
+    ZID_UNITED_KINGDOM,
+    ZID_SPAIN,
+    ZID_ITALY,
+    ZID_JAPAN
+  };
+
+  /**
+    * get the string definition of a tone
+    * return the default country or default tone if id are invalid
+    * @param country the country Id, see ToneList constructor for the list
+    * @param toneId  toneId
+    * @return a string definition of the tone
+    */
+  std::string getDefinition(COUNTRYID countryId, Tone::TONEID toneId);
+  /**
+   * get the country id associate to a country name
+   * return the default country id if not found
+   * The default tone/country are set inside the ToneList constructor
+   * @param countryName countryName, see the ToneList constructor list
+   * @return Country Id or default Id
+   */
+  COUNTRYID getCountryId(const std::string& countryName);
+  int getNbTone() { return _nbTone; }
+private:
+  void initToneDefinition();
+  std::string _toneZone[TONE_NBCOUNTRY][TONE_NBTONE];
+  int _nbTone;
+  int _nbCountry;
+  COUNTRYID _defaultCountryId;
+};
+
+/**
+ * @author Yan Morin <yan.morin@savoirfairelinux.com>
+ */
+class TelephoneTone {
+public:
+  /** Initialize the toneList and set the current tone to null */
+  TelephoneTone(const std::string& countryName);
+  ~TelephoneTone();
+
+  /** send TONE::ZT_TONE_NULL to stop the playing */
+  void setCurrentTone(Tone::TONEID toneId);
+
+  /** 
+    * @return the currentTone after setting it with setCurrentTone 
+    *         0 if the current tone is null
+    */
+  Tone* getCurrentTone();
+
+  /** @return true if you should play the tone (CurrentTone is not NULL) */
+  bool shouldPlay();
+
+private:
+  Tone* _tone[TONE_NBTONE];
+  Tone::TONEID _currentTone;
+  ToneList _toneList;
+};
+
+#endif
diff --git a/src/gui/server/requestconfig.cpp b/src/gui/server/requestconfig.cpp
index 00983277d79855cf5515a8d0f7b7fcc5f2f2212a..3bfa954b5154c44fb872fd915f2740e1d610e963 100644
--- a/src/gui/server/requestconfig.cpp
+++ b/src/gui/server/requestconfig.cpp
@@ -137,6 +137,9 @@ RequestConfigSet::RequestConfigSet(const std::string &sequenceId, const TokenLis
         _value = *iter;
         _argList.pop_front();
         argsAreValid = true;
+      } else {
+        _value = "";
+        argsAreValid = true;
       }
     }
   }
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index ea70495b04f55cee9a5214198d83af427cb126a4..149d63d89d3fbc3cedfe802c15b0ad9bbd9d0104 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -39,6 +39,8 @@
 #include "audio/audiolayer.h"
 #include "audio/ringbuffer.h"
 #include "audio/tonegenerator.h"
+#include "audio/tonelist.h"
+
 #include "call.h"
 #include "error.h"
 #include "user_cfg.h"
@@ -65,6 +67,7 @@ ManagerImpl::ManagerImpl (void)
   // Init private variables 
   _error = new Error();
   _tone = new ToneGenerator();	
+
   _hasZeroconf = false;
 #ifdef USE_ZEROCONF
   _hasZeroconf = true;
@@ -78,7 +81,6 @@ ManagerImpl::ManagerImpl (void)
   _path = ""; 
   _exist = 0;
   _setupLoaded = false;
-  _loaded = false;
   _gui = NULL;
   _audiodriverPA = NULL;
 
@@ -123,7 +125,6 @@ ManagerImpl::init()
   try {
     _debugInit("Audio Driver Selection");
     selectAudioDriver();
-    loaded(true);
   }
   catch (const portaudio::PaException &e)
     {
@@ -156,10 +157,15 @@ ManagerImpl::init()
   // the stun detection is long, so it's a better idea to do it after getEvents
 
   initZeroconf();
+
+  std::string country = getConfigString(PREFERENCES, ZONE_TONE);
+  _telephoneTone = new TelephoneTone(country);
 }
 
 void ManagerImpl::terminate()
 {
+  delete _telephoneTone; _telephoneTone = 0;
+
   for(VoIPLinkVector::iterator pos = _voIPLinkVector.begin();
       pos != _voIPLinkVector.end();
       pos++) {
@@ -574,7 +580,11 @@ ManagerImpl::playDtmf(char code)
     // put the size in bytes...
     // so size * CHANNELS * 2 (bytes for the int16)
     int nbInt16InChar = sizeof(int16)/sizeof(char);
-    audiolayer->urgentRingBuffer().Put(buf_ctrl_vol, size * CHANNELS * nbInt16InChar);
+    int toSend = audiolayer->urgentRingBuffer().AvailForPut();
+    if (toSend > size * CHANNELS * nbInt16InChar ) {
+      toSend = size * CHANNELS * nbInt16InChar;
+    }
+    audiolayer->urgentRingBuffer().Put(buf_ctrl_vol, toSend);
 
     // We activate the stream if it's not active yet.
     if (!audiolayer->isStreamActive()) {
@@ -846,14 +856,13 @@ ManagerImpl::stopVoiceMessageNotification (void)
  * Multi Thread
  */
 bool 
-ManagerImpl::playATone(unsigned int tone) {
-  if (isDriverLoaded()) {
-    ost::MutexLock m(_toneMutex); 
-    _toneType = tone;
-    _tone->toneHandle(_toneType, getConfigString(PREFERENCES, ZONE_TONE));
-    return true;
-  }
-  return false;
+ManagerImpl::playATone(Tone::TONEID toneId) {
+  ost::MutexLock m(_toneMutex); 
+  //_toneType = tone;
+  //_tone->toneHandle(_toneType, getConfigString(PREFERENCES, ZONE_TONE));
+  _telephoneTone->setCurrentTone(toneId);
+  getAudioDriver()->startStream();
+  return true;
 }
 
 /**
@@ -861,15 +870,14 @@ ManagerImpl::playATone(unsigned int tone) {
  */
 void 
 ManagerImpl::stopTone() {
-  if (isDriverLoaded()) {
-    _toneMutex.enterMutex();
-    if ( _toneType != ZT_TONE_NULL ) {
-      _toneType = ZT_TONE_NULL;
-      _tone->stopTone();
-    }
-    _toneMutex.leaveMutex();
-    getAudioDriver()->stopStream();
-  }
+  _toneMutex.enterMutex();
+  _telephoneTone->setCurrentTone(Tone::TONE_NULL);
+//  if ( _toneType != ZT_TONE_NULL ) {
+//    _toneType = ZT_TONE_NULL;
+//    _tone->stopTone();
+//  }
+  _toneMutex.leaveMutex();
+  getAudioDriver()->stopStream();
 }
 
 /**
@@ -878,7 +886,7 @@ ManagerImpl::stopTone() {
 bool
 ManagerImpl::playTone()
 {
-  return playATone(ZT_TONE_DIALTONE);
+  return playATone(Tone::TONE_DIALTONE);
 }
 
 /**
@@ -886,7 +894,7 @@ ManagerImpl::playTone()
  */
 void
 ManagerImpl::congestion () {
-  playATone(ZT_TONE_CONGESTION);
+  playATone(Tone::TONE_CONGESTION);
 }
 
 /**
@@ -894,7 +902,7 @@ ManagerImpl::congestion () {
  */
 void
 ManagerImpl::ringback () {
-  playATone(ZT_TONE_RINGTONE);
+  playATone(Tone::TONE_RINGTONE);
 }
 
 /**
@@ -902,7 +910,7 @@ ManagerImpl::ringback () {
  */
 void
 ManagerImpl::callBusy(CALLID id) {
-  playATone(ZT_TONE_BUSY);
+  playATone(Tone::TONE_BUSY);
   Call* call = getCall(id);
   if (call != NULL) {
     call->setState(Call::Busy);
@@ -914,7 +922,7 @@ ManagerImpl::callBusy(CALLID id) {
  */
 void
 ManagerImpl::callFailure(CALLID id) {
-  playATone(ZT_TONE_BUSY);
+  playATone(Tone::TONE_BUSY);
   Call* call = getCall(id);
   if (call != NULL) {
     getCall(id)->setState(Call::Error);
@@ -930,21 +938,19 @@ ManagerImpl::callFailure(CALLID id) {
  */
 void
 ManagerImpl::ringtone() 
-{ 
-  if (isDriverLoaded()) {
-    _toneMutex.enterMutex(); 
-    _toneType = ZT_TONE_FILE;
-    std::string ringchoice = getConfigString(AUDIO, RING_CHOICE);
-    // if there is no / inside the path
-    if ( ringchoice.find(DIR_SEPARATOR_CH) == std::string::npos ) {
-      // check inside global share directory
-      ringchoice = std::string(PROGSHAREDIR) + DIR_SEPARATOR_STR + RINGDIR + DIR_SEPARATOR_STR + ringchoice; 
-    }
-    int play = _tone->playRingtone(ringchoice.c_str());
-    _toneMutex.leaveMutex();
-    if (play!=1) {
-      ringback();
-    }
+{
+  _toneMutex.enterMutex(); 
+  _toneType = ZT_TONE_FILE;
+  std::string ringchoice = getConfigString(AUDIO, RING_CHOICE);
+  // if there is no / inside the path
+  if ( ringchoice.find(DIR_SEPARATOR_CH) == std::string::npos ) {
+    // check inside global share directory
+    ringchoice = std::string(PROGSHAREDIR) + DIR_SEPARATOR_STR + RINGDIR + DIR_SEPARATOR_STR + ringchoice; 
+  }
+  int play = _tone->playRingtone(ringchoice.c_str());
+  _toneMutex.leaveMutex();
+  if (play!=1) {
+    ringback();
   }
 }
 
diff --git a/src/managerimpl.h b/src/managerimpl.h
index 8ac3a53fd344a17a8614bd98de81420e1ded879a..d5786c0b642a305d5538566d22203e0d562ec900 100644
--- a/src/managerimpl.h
+++ b/src/managerimpl.h
@@ -25,6 +25,7 @@
 #include <string>
 #include <vector>
 
+#include "audio/tonelist.h" // for Tone::TONEID declaration
 #include "../stund/stun.h"
 #include "call.h"
 #include "audio/audiodevice.h"
@@ -38,6 +39,9 @@ class CodecDescriptor;
 class Error;
 class GuiFramework;
 class ToneGenerator;
+
+class TelephoneTone;
+
 class VoIPLink;
 #ifdef USE_ZEROCONF
 class DNSService;
@@ -70,14 +74,6 @@ typedef std::vector< VoIPLink* > VoIPLinkVector;
  */
 typedef std::vector< CodecDescriptor* > CodecDescriptorVector;
 
-/*
- * Structure for audio device
- */
-//struct device_t{
-//	const char* hostApiName;
-//	const char* deviceName;
-//};
-
 /**
  * To send multiple string
  */
@@ -206,6 +202,9 @@ name);
   void callBusy(CALLID id);
   void callFailure(CALLID id);
 
+  // return 0 if no tone (init before calling this function)
+  Tone* getTelephoneTone() { return _telephoneTone->getCurrentTone(); };
+
   /**
    * @return true is there is one or many incoming call waiting
    * new call, not anwsered or refused
@@ -250,12 +249,6 @@ name);
 	inline void setFirewallPort 	(int port) 	{ _firewallPort = port; }
 	inline std::string getFirewallAddress (void) 	{ return _firewallAddr; }
 
-	/*
-	 * Manage information about audio driver
-	 */
-	inline bool isDriverLoaded (void) const { return _loaded; }
-	inline void loaded (bool l) { _loaded = l; }
-
 	/*
 	 * Init default values for the different fields
 	 */
@@ -327,12 +320,14 @@ private:
    * Play one tone
    * @return false if the driver is uninitialize
    */
-  bool playATone(unsigned int tone);
+  bool playATone(Tone::TONEID toneId);
+  //bool playATone(unsigned int tone);
   
 	/////////////////////
 	// Private variables
 	/////////////////////
 	ToneGenerator* _tone;
+  TelephoneTone* _telephoneTone;
   ost::Mutex _toneMutex;
   int _toneType;
 
@@ -398,9 +393,6 @@ private:
 	int			_firewallPort;
 	std::string		_firewallAddr;
 
-	// Variables used in exception
-	bool 		_loaded;
-
   // true if we tried to register Once
   void initRegisterVoIPLink();
   bool    _hasTriedToRegister;
diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp
index cd395eff1a5e3dad8d47afdcee47191a9bb470d7..56f384ba9e6c9f9c9a3c23af76e5fd67be86afd8 100644
--- a/src/sipvoiplink.cpp
+++ b/src/sipvoiplink.cpp
@@ -290,8 +290,11 @@ SipVoIPLink::outgoingInvite (CALLID id, const std::string& to_url)
   // TODO: should be inside account settings
   ManagerImpl& manager = Manager::instance();
   // Form the From header field basis on configuration panel
-  from = fromHeader(manager.getConfigString(SIGNALISATION, USER_PART),
-		    manager.getConfigString(SIGNALISATION, HOST_PART));
+  std::string host = manager.getConfigString(SIGNALISATION, HOST_PART);
+  if ( host.empty() ) {
+    host = getLocalIpAddress();
+  }
+  from = fromHeader(manager.getConfigString(SIGNALISATION, USER_PART), host);
 	
   to = toHeader(to_url);
 
@@ -783,6 +786,11 @@ SipVoIPLink::getEvent (void)
     }	
     break;
   case EXOSIP_CALL_RELEASED:
+    id = findCallId(event);
+    if (id!=0) {
+      Manager::instance().peerHungupCall(id);
+      deleteSipCall(id);
+    }
     break;
   case EXOSIP_CALL_REQUESTFAILURE:
     id = findCallId(event);