diff --git a/src/audio/tonegenerator.cpp b/src/audio/tonegenerator.cpp
index 9bbc64327b55e6b5b3b0dd07f80786e984a699da..ea21beeecaa999d2ffe0c2e1fb890107d1026251 100644
--- a/src/audio/tonegenerator.cpp
+++ b/src/audio/tonegenerator.cpp
@@ -364,6 +364,7 @@ ToneGenerator::playRingtone (const char *fileName) {
 	
  	// read data as a block:
  	file.read (_src,length);
+	file.close();
 	
 	// Decode file.ul
 	expandedsize = _ulaw->codecDecode (_dst, (unsigned char *)_src, length);
@@ -373,7 +374,6 @@ ToneGenerator::playRingtone (const char *fileName) {
 		tonethread->start();
 	}
 	
-	file.close();
 	return 1;
 }
 
diff --git a/src/gui/guiframework.cpp b/src/gui/guiframework.cpp
index e2f11ed328a9ceec46238a5d3b338e79d0ac83b7..06baf09a9608340adbd8cb2899cfa53a9c5f48bd 100644
--- a/src/gui/guiframework.cpp
+++ b/src/gui/guiframework.cpp
@@ -24,7 +24,6 @@ using namespace std;
 #include "guiframework.h"
 #include "../manager.h"
 
-
 GuiFramework::GuiFramework ()
 {}
 
@@ -217,9 +216,9 @@ GuiFramework::getZeroconf(const std::string& sequenceId)
 }
 
 bool 
-GuiFramework::attachZeroconfEvents(const std::string& sequenceId)
+GuiFramework::attachZeroconfEvents(const std::string& sequenceId, Observer& observer)
 {
-  return Manager::instance().attachZeroconfEvents(sequenceId, *this);
+  return Manager::instance().attachZeroconfEvents(sequenceId, observer);
 }
 
 bool 
diff --git a/src/gui/guiframework.h b/src/gui/guiframework.h
index 7690eb071e613874fa16890d72b0a34e8b2fa344..725b40c7cc741c701197602702752f2e3cad1698 100644
--- a/src/gui/guiframework.h
+++ b/src/gui/guiframework.h
@@ -25,9 +25,8 @@
 
 #include <string>
 #include "server/argtokenizer.h"
-#include "../observer.h"
 
-class GuiFramework : public Pattern::Observer {
+class GuiFramework {
 public:
 	GuiFramework ();
 	virtual ~GuiFramework (void);
@@ -82,7 +81,7 @@ public:
 
   // config
   bool getZeroconf(const std::string& sequenceId);
-  bool attachZeroconfEvents(const std::string& sequenceId);
+  bool attachZeroconfEvents(const std::string& sequenceId, Observer& observer);
   bool getCallStatus(const std::string& sequenceId);
   bool getConfigAll(const std::string& sequenceId);
   bool getConfig(const std::string& section,  const std::string& name, TokenList& arg);
diff --git a/src/gui/server/requestconfig.cpp b/src/gui/server/requestconfig.cpp
index 1fde8987e9498298d4d9c4727732b95589114489..358a7e35be8324eb6979b651b28ff87b661593bd 100644
--- a/src/gui/server/requestconfig.cpp
+++ b/src/gui/server/requestconfig.cpp
@@ -41,13 +41,24 @@ RequestZeroconf::execute()
 ResponseMessage
 RequestZeroconfEvent::execute()
 {
-  if (GUIServer::instance().attachZeroconfEvents(_sequenceId)) {
+  if (GUIServer::instance().attachZeroconfEvents(_sequenceId, *this)) {
     return message("200", "OK");
   } else {
     return message("501","Zeroconf not enabled or activated");
   }
 }
 
+RequestZeroconfEvent::~RequestZeroconfEvent() 
+{
+  GUIServer::instance.removeZeroconfEvents(*this);
+}
+
+ResponseMessage
+RequestZeroconfEvent::update()
+{
+  return message("100", "New Zeroconf events - Not Implemented");
+}
+
 ResponseMessage
 RequestCallStatus::execute()
 {
diff --git a/src/gui/server/requestconfig.h b/src/gui/server/requestconfig.h
index 8566453c2471cb258e5c275aca48d7ba7ad9508d..5a5a577d7f00be167438d007843975079f96d93e 100644
--- a/src/gui/server/requestconfig.h
+++ b/src/gui/server/requestconfig.h
@@ -21,7 +21,7 @@
 #define __REQUESTCONFIG_H__
 
 #include "request.h"
-
+#include "../../observer.h"
 
 class RequestGetEvents : public RequestGlobal {
 public:
@@ -36,9 +36,10 @@ public:
 };
 
 
-class RequestZeroconfEvent : public RequestGlobal {
+class RequestZeroconfEvent : public RequestGlobal, public Pattern::Observer {
 public:
   RequestZeroconfEvent(const std::string &sequenceId, const TokenList& argList) : RequestGlobal(sequenceId,argList) {}
+  ~RequestZeroconfEvent();
   ResponseMessage execute();
 };
 
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index f58af4d59b61686217c3427d0a8132537f9ee541..c8c8424150e81392e53fdfc45d4aa92427ecb7dd 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -1038,7 +1038,7 @@ ManagerImpl::getStunInfo (StunAddress4& stunSvrAddr) {
         _debug("Opened a stun socket pair FAILED\n");
     }
 }
-
+/*
 AudioDevice
 ManagerImpl::deviceList (int index)
 {
@@ -1073,6 +1073,7 @@ ManagerImpl::defaultDevice (int index)
 	}
 	return defaultDisplayed;
 }
+*/
 
 bool
 ManagerImpl::useStun (void) {
@@ -1252,11 +1253,11 @@ ManagerImpl::selectAudioDriver (void)
 void 
 ManagerImpl::initZeroconf(void) 
 {
-  _useZeroconf = getConfigInt(PREFERENCES, CONFIG_ZEROCONF);
+  int useZeroconf = getConfigInt(PREFERENCES, CONFIG_ZEROCONF);
 
 #ifdef USE_ZEROCONF
-  if (_useZeroconf) {
-    _DNSService->scanServices();
+  if (useZeroconf) {
+    _DNSService->startScanServices();
   }
 #endif
 }
@@ -1281,28 +1282,30 @@ ManagerImpl::getZeroconf(const std::string& sequenceId)
 {
   bool returnValue = false;
 #ifdef USE_ZEROCONF
-  if (_useZeroconf && _gui != NULL) {
+  int useZeroconf = getConfigInt(PREFERENCES, CONFIG_ZEROCONF);
+  if (useZeroconf && _gui != NULL) {
     TokenList arg;
     TokenList argTXT;
     std::string newService = "new service";
     std::string newTXT = "new txt record";
+    if (!_DNSService->isStart()) { _DNSService->startScanServices(); }
     DNSServiceMap services = _DNSService->getServices();
     DNSServiceMap::iterator iter = services.begin();
     arg.push_back(newService);
     while(iter!=services.end()) {
-      arg.push_first(iter->first);
-      _gui.sendMessage("100",sequenceId,arg);
-      arg.pop_first(); // remove the first, the name
+      arg.push_front(iter->first);
+      _gui->sendMessage("100",sequenceId,arg);
+      arg.pop_front(); // remove the first, the name
 
       TXTRecordMap record = iter->second.getTXTRecords();
       TXTRecordMap::iterator iterTXT = record.begin();
       while(iterTXT!=record.end()) {
-        argTXT.flush();
+        argTXT.clear();
         argTXT.push_back(iter->first);
         argTXT.push_back(iterTXT->first);
         argTXT.push_back(iterTXT->second);
         argTXT.push_back(newTXT);
-        _gui.sendMessage("101",sequenceId,arg);
+        _gui->sendMessage("101",sequenceId,argTXT);
         iterTXT++;
       }
       iter++;
@@ -1317,20 +1320,31 @@ ManagerImpl::getZeroconf(const std::string& sequenceId)
  * Main Thread
  */
 bool 
-ManagerImpl::attachZeroconfEvents(const std::string& sequenceId, const Pattern::Observer &observer)
+ManagerImpl::attachZeroconfEvents(const std::string& sequenceId, Pattern::Observer& observer)
 {
   bool returnValue = false;
   // don't need the _gui like getZeroconf function
   // because Observer is here
 #ifdef USE_ZEROCONF
-  if (_useZeroconf) {
-    _DNSService->attach(sequenceId,observer);
+  int useZeroconf = getConfigInt(PREFERENCES, CONFIG_ZEROCONF);
+  if (useZeroconf) {
+    if (!_DNSService->isStart()) { _DNSService->startScanServices(); }
+    _DNSService->attach(observer);
     returnValue = true;
   }
 #endif
   return returnValue;
 }
-
+bool
+ManagerImpl::detachZeroconfEvents(Pattern::Observer& observer)
+{
+  bool returnValue = false;
+#ifdef USE_ZEROCONF
+  _DNSService->detach(observer);
+  returnValue = true;
+#endif
+  return returnValue;
+}
 /**
  * Main Thread
  */
@@ -1476,10 +1490,10 @@ bool
 ManagerImpl::getConfigList(const std::string& sequenceId, const std::string& name)
 {
   bool returnValue = false;
+  TokenList tk;
   if (name=="codecdescriptor") {
-    TokenList tk;
+
     CodecMap::iterator iter = _codecMap.begin();
-    
     while( iter != _codecMap.end() ) {
       tk.clear();
       std::ostringstream strType;
@@ -1492,24 +1506,13 @@ ManagerImpl::getConfigList(const std::string& sequenceId, const std::string& nam
     returnValue = true;
   } else if (name=="ringtones") {
     std::string path = std::string(PROGSHAREDIR) + "/" + RINGDIR;
-    try {
-      ost::Dir dir(path.c_str());
-      const char *cFileName = NULL;
-      std::string fileName;
-      std::string filePathName;
-      while ( (cFileName=dir++) != NULL ) {
-        fileName = cFileName;
-        filePathName = path + "/" + cFileName;
-        if (fileName.length() && fileName[0]!='.' && !ost::isDir(fileName.c_str())) {
-          _debug("Filename: %s\n", fileName.c_str());
-        }
-      }
-      returnValue = true;
-    } catch (...) {
-      // error to open file dir
-    }
-  } else if (name=="") {
-    returnValue = true;
+    int nbFile = 0;
+    returnValue = getDirListing(sequenceId, path, &nbFile);
+
+    path = std::string(HOMEDIR) + "/." + PROGNAME + "/" + RINGDIR;
+    getDirListing(sequenceId, path, &nbFile);
+  } else if (name=="audiodevice") {
+    returnValue = getAudioDeviceList(sequenceId);
   } else if (name=="") {
     returnValue = true;
   } else if (name=="") {
@@ -1518,6 +1521,63 @@ ManagerImpl::getConfigList(const std::string& sequenceId, const std::string& nam
   return returnValue;
 }
 
+/**
+ * User request Main Thread (list)
+ */
+bool 
+ManagerImpl::getAudioDeviceList(const std::string& sequenceId) 
+{
+  TokenList tk;
+  portaudio::AutoSystem autoSys;
+  portaudio::System& sys = portaudio::System::instance();
+
+  const char *hostApiName;
+  const char *deviceName;
+
+  for (int index = 0; index < sys.deviceCount(); index++ ) {
+    portaudio::Device& device = sys.deviceByIndex(index);
+    hostApiName = device.hostApi().name();
+    deviceName  = device.name();
+
+    tk.clear();
+    std::ostringstream str; str << index; tk.push_back(str.str());
+    tk.push_back(std::string(hostApiName) + " (device #" + str.str() + ")");
+    _gui->sendMessage("100", sequenceId, tk);
+  }
+  return true;
+}
+
+/**
+ * User action : main thread
+ */
+bool
+ManagerImpl::getDirListing(const std::string& sequenceId, const std::string& path, int *nbFile) {
+  TokenList tk;
+  try {
+    ost::Dir dir(path.c_str());
+    const char *cFileName = NULL;
+    std::string fileName;
+    std::string filePathName;
+    while ( (cFileName=dir++) != NULL ) {
+      fileName = cFileName;
+      filePathName = path + "/" + cFileName;
+      if (fileName.length() && fileName[0]!='.' && !ost::isDir(filePathName.c_str())) {
+        tk.clear();
+        std::ostringstream str;
+        str << (*nbFile);
+        tk.push_back(str.str());
+        tk.push_back(filePathName);
+        _gui->sendMessage("100", sequenceId, tk);
+        (*nbFile)++;
+      }
+    }
+    return true;
+  } catch (...) {
+    // error to open file dir
+    return false;
+  }
+}
+
 /**
  * Multi Thread
  */
diff --git a/src/managerimpl.h b/src/managerimpl.h
index 3b0dff412a1915b8e8b400a3fc07b04261fa2e5f..853b9d720f1ada70c46b7d2c70a989f4cafa6802 100644
--- a/src/managerimpl.h
+++ b/src/managerimpl.h
@@ -191,7 +191,8 @@ public:
 
   // configuration function requests
   bool getZeroconf(const std::string& sequenceId);
-  bool attachZeroconfEvents(const std::string& sequenceId, const Pattern::Observer &observer);
+  bool attachZeroconfEvents(const std::string& sequenceId, Pattern::Observer& observer);
+  bool removeZeroconfEvents(Pattern::Observer& observer);
   bool getCallStatus(const std::string& sequenceId);
   bool getConfigAll(const std::string& sequenceId);
   bool getConfig(const std::string& section, const std::string& name, TokenList& arg);
@@ -261,10 +262,11 @@ name);
 	/* 
 	 * Functions about audio device
 	 */
+/*
 	AudioDevice deviceList (int);
 	int deviceCount (void);
 	bool defaultDevice (int);
-	
+*/	
 	/*
 	 * Init default values for the different fields
 	 */
@@ -314,6 +316,13 @@ private:
    */ 
   void initVolume();
 
+  /**
+   * Configuration
+   */
+  bool getDirListing(const std::string& sequenceId, const std::string& path, int *nbFile);
+  bool getAudioDeviceList(const std::string& sequenceId);
+  Conf::ConfigTree _config;
+
   /*
    * Play one tone
    * @return false if the driver is uninitialize
@@ -394,13 +403,9 @@ private:
 	// Variables used in exception
 	bool 		_loaded;
 
-  // look if zeroconf scanning should run or not
-  int _useZeroconf;
-  // tell if we have zeroconf d'enable
+  // tell if we have zeroconf is enabled
   int _hasZeroconf;
 
-  Conf::ConfigTree _config;
-
   void switchCall(short id);
 
 #ifdef USE_ZEROCONF
diff --git a/src/zeroconf/DNSService.cpp b/src/zeroconf/DNSService.cpp
index b5b5a80d45a9776b8688ed6baeae0c5a44e1297b..63df7c517afb4113c1e3a29b095575f387a32035 100644
--- a/src/zeroconf/DNSService.cpp
+++ b/src/zeroconf/DNSService.cpp
@@ -33,11 +33,12 @@
  */
 DNSService::DNSService()
 {
+  _start = false;
   _regtypeList.push_back("_sip._udp");
 #ifdef USE_IAX2
   _regtypeList.push_back("_iax._udp");
 #endif
-  
+
   // for the thread, the ifdef add a dynamic _regtypeList problem
   for (std::list<std::string>::iterator iterThread=_regtypeList.begin();
        iterThread!=_regtypeList.end();
@@ -62,11 +63,12 @@ DNSService::~DNSService()
  * Look for zeroconf services and add them to _services
  */
 void
-DNSService::scanServices() 
+DNSService::startScanServices() 
 {
   for (std::vector<DNSQueryThread *>::iterator iter = _queryThread.begin();iter!=_queryThread.end();iter++) {
     (*iter)->start();
   }
+  _start = true;
 }
 
 /**
@@ -81,6 +83,7 @@ void DNSService::addService(const std::string &service)
   // we leave before the queryService since, each 
   // thread will modify a DNSServiceTXTRecord of a difference services
   _mutex.leaveMutex();
+  notify();
   queryService(service);
 }
 
@@ -90,8 +93,10 @@ void DNSService::addService(const std::string &service)
  */
 void DNSService::removeService(const std::string &service) 
 {
-  ost::MutexLock(_mutex);
+  _mutex.enterMutex();
   _services.erase(service);
+  _mutex.leaveMutex();
+  notify();
 }
 
 /**
@@ -116,7 +121,7 @@ DNSService::listServices()
 DNSServiceMap
 DNSService::getServices() 
 {
-  ost::MutexLock(_mutex);
+  ost::MutexLock m(_mutex);
   return _services;
 }
 
@@ -192,9 +197,7 @@ DNSService::addTXTRecord(const char *fullname, uint16_t rdlen, const void *rdata
     }
   }
 
-  // TODO: remove this call, when we do not debug..
-  // addTXTRecord is a good function to know changes... 
-  listServices();
+  notify();
 }
 
 void 
diff --git a/src/zeroconf/DNSService.h b/src/zeroconf/DNSService.h
index cd6b2f0bd85c8282461b834830a7289a37336efa..a721173686c3fff1b6283f7744576fecc9f9927d 100644
--- a/src/zeroconf/DNSService.h
+++ b/src/zeroconf/DNSService.h
@@ -38,7 +38,7 @@ public:
   DNSService();
   ~DNSService();
   
-  void scanServices(); // looking for services
+  void startScanServices(); // looking for services
   void addService(const std::string &service); // adding every services
   void removeService(const std::string &service); // remove a service
   void listServices(); // listing services (call addService before)
@@ -50,6 +50,8 @@ public:
   void addTXTRecord(const char *fullname, uint16_t rdlen, const void *rdata);
   //void removeTXTRecord(const char *fullname);
 
+  bool isStart() const { return _start; }
+
 private:
   DNSServiceMap _services; //map
 
@@ -63,6 +65,8 @@ private:
    * It will be use to initialize the DNSQueryThread
    */
   std::list<std::string> _regtypeList;
+
+  bool _start;
 };
 
 void DNSServiceAddServicesCallback(DNSServiceRef sdRef,
diff --git a/src/zeroconf/INSTALL b/src/zeroconf/INSTALL
index 85a836c46b76e2d9eda0fafdaadc60fe999891be..31bb0e60143e8e5c930f8c31e88b6cd425979351 100644
--- a/src/zeroconf/INSTALL
+++ b/src/zeroconf/INSTALL
@@ -9,6 +9,7 @@ Howl's one is named 'mDNSResponder'.
  - or you can get tarball from: http://helios.et.put.poznan.pl/~jstachow/pub/mDNSResponder-98.tar.gz
     (for those who don't like registration)
  - you can also use the last mDNSResponder
+   like http://helios.et.put.poznan.pl/~jstachow/pub/mDNSResponder-107.1.tar.gz
 
 2) compile and install
  Build system for mDNSResponder is quite weird so here are instructions: