diff --git a/CHANGES b/CHANGES
index 6f1eb920e70a0d4caa52b72b09939417ab874873..99fdef7f2d90318578c5591a96b194bb29e73f35 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,7 @@ SFLphoned/SFLphone (0.6)  / 2005-11-04
 	* accept reinvite call
 	* cleaning headers
 	* improving bash launcher script
+        * select audio input and output device
 
 SFLphoned/SFLphone (0.5a) / 2005-10-17
 	* sflphoned
diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp
index f24cb1ef58eff3c63bf29ac5d5019152b74f0d96..0d39679dfc46881bd3a6fe1f37bb8a9d293ba511 100644
--- a/src/audio/audiolayer.cpp
+++ b/src/audio/audiolayer.cpp
@@ -59,23 +59,30 @@ AudioLayer::closeStream (void)
   }
 }
 
+bool
+AudioLayer::hasStream(void) {
+  ost::MutexLock guard(_mutex);
+  return (_stream!=0 ? true : false); 
+}
+
+
 void
-AudioLayer::openDevice (int index) 
+AudioLayer::openDevice (int indexIn, int indexOut) 
 {
   closeStream();
 
   try {
   // Set up the parameters required to open a (Callback)Stream:
   portaudio::DirectionSpecificStreamParameters 
-    outParams(portaudio::System::instance().deviceByIndex(index), 
+    outParams(portaudio::System::instance().deviceByIndex(indexOut), 
 	      2, portaudio::INT16, true, 
-	      portaudio::System::instance().deviceByIndex(index).defaultLowOutputLatency(), 
+	      portaudio::System::instance().deviceByIndex(indexOut).defaultLowOutputLatency(), 
 	      NULL);
 	
   portaudio::DirectionSpecificStreamParameters 
-    inParams(portaudio::System::instance().deviceByIndex(index), 
+    inParams(portaudio::System::instance().deviceByIndex(indexIn), 
 	     2, portaudio::INT16, true, 
-	     portaudio::System::instance().deviceByIndex(index).defaultLowInputLatency(), 
+	     portaudio::System::instance().deviceByIndex(indexIn).defaultLowInputLatency(), 
 	     NULL);
 	
   // we could put paFramesPerBufferUnspecified instead of FRAME_PER_BUFFER to be variable
diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h
index 8ba2d343709d74738da4ede2a1e3c756a538a3fd..2fe4632e0a71643bc9d065caef911f4e24f09dc2 100644
--- a/src/audio/audiolayer.h
+++ b/src/audio/audiolayer.h
@@ -43,10 +43,11 @@ public:
   AudioLayer();
   ~AudioLayer(void);
 
-  void openDevice(int);
+  void openDevice(int, int);
   void startStream(void);
   void stopStream(void);
   void sleep(int);
+  bool hasStream(void);
   bool isStreamActive(void);
   bool isStreamStopped(void);
 
@@ -63,6 +64,8 @@ public:
   void setErrorMessage(const std::string& error) { _errorMessage = error; }
   std::string getErrorMessage() { return _errorMessage; }
 
+  enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 };
+
 private:
   void	closeStream	(void);
   RingBuffer _urgentRingBuffer;
diff --git a/src/gui/guiframework.cpp b/src/gui/guiframework.cpp
index aea606107032d80d7ae3e37bf87edade213aaae8..8fb60f27a8d7013ba1d2379e63a791d791884b02 100644
--- a/src/gui/guiframework.cpp
+++ b/src/gui/guiframework.cpp
@@ -280,3 +280,9 @@ GuiFramework::getRegistrationState(std::string& stateCode, std::string& stateMes
   }
   return returnValue;
 }
+
+bool 
+GuiFramework::setSwitch(const std::string& switchName)
+{
+  return Manager::instance().setSwitch(switchName);
+}
diff --git a/src/gui/guiframework.h b/src/gui/guiframework.h
index a823eb3e56e47c55abead6615f6f53c6cb62cd01..06047252f3896ffb21e0f0968bb813fd0a40db15 100644
--- a/src/gui/guiframework.h
+++ b/src/gui/guiframework.h
@@ -88,6 +88,7 @@ public:
   bool setMicVolume(int volume);
   int getSpkrVolume();
   int getMicVolume();
+  bool setSwitch(const std::string& switchName);
 
   bool hasLoadedSetup();
   CALLID getCurrentId();
diff --git a/src/gui/server/requestconfig.cpp b/src/gui/server/requestconfig.cpp
index 6b75a34ad6248f779ce9b6b54fb11002b973de1f..08eff1ce4738be5c738b601871bca43c647218ba 100644
--- a/src/gui/server/requestconfig.cpp
+++ b/src/gui/server/requestconfig.cpp
@@ -261,4 +261,24 @@ RequestUnregister::execute()
   }
 }
 
+RequestSwitch::RequestSwitch(const std::string &sequenceId, const TokenList& argList) : RequestGlobal(sequenceId,argList)
+{
+  TokenList::iterator iter = _argList.begin();
+  if (iter != _argList.end()) {
+    _switchName = *iter;
+  } else {
+    throw RequestConstructorException();
+  }
+}
+
+ResponseMessage
+RequestSwitch::execute()
+{
+  if (GUIServer::instance().setSwitch(_switchName)) {
+    return message("200", "OK");
+  } else {
+    return message("500","Server Error");
+  }
+}
+
 
diff --git a/src/gui/server/requestconfig.h b/src/gui/server/requestconfig.h
index db50c74b77afaa427729d776227599343890b611..ad0581e6180064c927f414a8be433affb58fe192 100644
--- a/src/gui/server/requestconfig.h
+++ b/src/gui/server/requestconfig.h
@@ -121,5 +121,13 @@ public:
   RequestUnregister(const std::string &sequenceId, const TokenList& argList) : RequestGlobal(sequenceId, argList) {}
   ResponseMessage execute();
 };
+class RequestSwitch : public RequestGlobal {
+public:
+  RequestSwitch(const std::string &sequenceId, const TokenList& argList);
+  ResponseMessage execute();
+private:
+  std::string _switchName;
+};
+
 
 #endif // __REQUESTCONFIG_H__
diff --git a/src/gui/server/requestfactory.cpp b/src/gui/server/requestfactory.cpp
index 6bbbf03c48704a3937ea7cf672813331a11d7b23..5ebd8d09b7f370600984183ac15c7b58685b0ac9 100644
--- a/src/gui/server/requestfactory.cpp
+++ b/src/gui/server/requestfactory.cpp
@@ -130,4 +130,6 @@ RequestFactory::registerAll() {
   registerRequest<RequestVolumeMic>   ("setmicvolume");
   registerRequest<RequestRegister>    ("register");
   registerRequest<RequestUnregister>  ("unregister");
+
+  registerRequest<RequestSwitch>      ("switch");
 }
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index cd9affdf9750ae7ef449affd71a04b9f0810d958..b6246dfa64675684be784d40fdff73b56650763c 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -118,16 +118,20 @@ ManagerImpl::init()
   _telephoneTone = new TelephoneTone(country);
 
   try {
+    initAudioDriver();
     selectAudioDriver();
   }
   catch (const portaudio::PaException &e) {
       getAudioDriver()->setErrorMessage(e.paErrorText());
+      _debug("Portaudio exception: %s\n", e.paErrorText());
   }
   catch (const portaudio::PaCppException &e) {
       getAudioDriver()->setErrorMessage(e.what());
+      _debug("Portaudio exception: %s\n", e.what());
   }
   catch (const std::runtime_error &e) {
       getAudioDriver()->setErrorMessage(e.what());
+      _debug("Portaudio exception: %s\n", e.what());
   }
   catch (...) {
       displayError("An unknown exception occured while selecting audio driver.");
@@ -1211,6 +1215,8 @@ ManagerImpl::initConfigFile (void)
 
   section = AUDIO;
   fill_config_int(DRIVER_NAME, DFT_DRIVER_STR);
+  fill_config_int(DRIVER_NAME_IN, DFT_DRIVER_STR);
+  fill_config_int(DRIVER_NAME_OUT, DFT_DRIVER_STR);
   fill_config_str(CODEC1, DFT_CODEC);
   fill_config_str(CODEC2, DFT_CODEC);
   fill_config_str(CODEC3, DFT_CODEC);
@@ -1263,24 +1269,56 @@ ManagerImpl::unloadAudioCodec()
  * Initialization: Main Thread
  */
 void
-ManagerImpl::selectAudioDriver (void)
+ManagerImpl::initAudioDriver(void) 
 {
 #if defined(AUDIO_PORTAUDIO)
   try {
     _debugInit("AudioLayer Creation");
     _audiodriverPA = new AudioLayer();
-    int noDevice = getConfigInt(AUDIO, DRIVER_NAME);
+  } catch(...) {
+    throw;
+  }
+#else
+# error You must define one AUDIO driver to use.
+#endif
+}
+
+/**
+ * Initialization: Main Thread and gui
+ */
+void
+ManagerImpl::selectAudioDriver (void)
+{
+#if defined(AUDIO_PORTAUDIO)
+  try {
+    int noDevice    = getConfigInt(AUDIO, DRIVER_NAME);
+    int noDeviceIn  = getConfigInt(AUDIO, DRIVER_NAME_IN);
+    int noDeviceOut = getConfigInt(AUDIO, DRIVER_NAME_OUT);
+
+    // this is when no audio device in/out are set
+    // or the audio device in/out are set to 0
+    // we take the nodevice instead
+    if (noDeviceIn == 0 && noDeviceOut == 0) {
+      noDeviceIn = noDeviceOut = noDevice;
+    }
     _debugInit(" AudioLayer Device Count");
     int nbDevice = portaudio::System::instance().deviceCount();
     if (nbDevice == 0) {
       throw std::runtime_error("Portaudio detect no sound card.");
-    } else if (noDevice >= nbDevice) {
-      _debug(" Portaudio auto-select device #0 because device #%d is not found\n", noDevice);
-      _setupLoaded = false;
-      noDevice = 0;
+    } else {
+      if (noDeviceIn >= nbDevice) {
+        _debug(" Portaudio auto-select device #0 for input because device #%d is not found\n", noDeviceIn);
+        _setupLoaded = false;
+        noDeviceIn = 0;
+      }
+      if (noDeviceOut >= nbDevice) {
+        _debug(" Portaudio auto-select device #0 for output because device #%d is not found\n", noDeviceOut);
+        _setupLoaded = false;
+        noDeviceOut = 0;
+      }
     }
     _debugInit(" AudioLayer Opening Device");
-    _audiodriverPA->openDevice(noDevice);
+    _audiodriverPA->openDevice(noDeviceIn, noDeviceOut);
   } catch(...) {
     throw;
   }
@@ -1358,6 +1396,8 @@ ManagerImpl::getZeroconf(const std::string& sequenceId)
     }
     returnValue = true;
   }
+#else
+  (void)sequenceId;
 #endif
   return returnValue;
 }
@@ -1378,6 +1418,9 @@ ManagerImpl::attachZeroconfEvents(const std::string& sequenceId, Pattern::Observ
     _DNSService->attach(observer);
     returnValue = true;
   }
+#else
+  (void)sequenceId;
+  (void)observer;
 #endif
   return returnValue;
 }
@@ -1390,6 +1433,8 @@ ManagerImpl::detachZeroconfEvents(Pattern::Observer& observer)
     _DNSService->detach(observer);
     returnValue = true;
   }
+#else
+  (void)observer;
 #endif
   return returnValue;
 }
@@ -1559,7 +1604,11 @@ ManagerImpl::getConfigList(const std::string& sequenceId, const std::string& nam
     path = std::string(HOMEDIR) + DIR_SEPARATOR_STR + "." + PROGDIR + DIR_SEPARATOR_STR + RINGDIR;
     getDirListing(sequenceId, path, &nbFile);
   } else if (name=="audiodevice") {
-    returnValue = getAudioDeviceList(sequenceId);
+    returnValue = getAudioDeviceList(sequenceId, AudioLayer::InputDevice | AudioLayer::OutputDevice);
+  } else if (name=="audiodevicein") {
+    returnValue = getAudioDeviceList(sequenceId, AudioLayer::InputDevice);
+  } else if (name=="audiodeviceout") {
+    returnValue = getAudioDeviceList(sequenceId, AudioLayer::OutputDevice);
   } else if (name=="countrytones") {
     returnValue = getCountryTones(sequenceId);
   }
@@ -1570,7 +1619,7 @@ ManagerImpl::getConfigList(const std::string& sequenceId, const std::string& nam
  * User request Main Thread (list)
  */
 bool 
-ManagerImpl::getAudioDeviceList(const std::string& sequenceId) 
+ManagerImpl::getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask) 
 {
   bool returnValue = false;
   try {
@@ -1583,14 +1632,19 @@ ManagerImpl::getAudioDeviceList(const std::string& sequenceId)
 
     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(deviceName);
-      tk.push_back(std::string(hostApiName));
-      _gui->sendMessage("100", sequenceId, tk);
+      if ((ioDeviceMask == AudioLayer::InputDevice  && !device.isOutputOnlyDevice()) ||
+          (ioDeviceMask == AudioLayer::OutputDevice && !device.isInputOnlyDevice() ) ||
+           device.isFullDuplexDevice()) {
+        hostApiName = device.hostApi().name();
+        deviceName  = device.name();
+
+        tk.clear();
+        std::ostringstream str; str << index; tk.push_back(str.str());
+        tk.push_back(deviceName);
+        tk.push_back(std::string(hostApiName));
+        _gui->sendMessage("100", sequenceId, tk);
+      }
     }
     returnValue = true;
   } catch (...) {
@@ -1666,4 +1720,42 @@ ManagerImpl::switchCall(CALLID id)
   }
 }
 
-
+/**
+ * Main Thread - Gui
+ * Experimental...
+ */
+bool
+ManagerImpl::setSwitch(const std::string& switchName) {
+  if (switchName == "audiodriver" ) {
+    try 
+      {
+        selectAudioDriver();
+        return true;
+      }
+    catch (const portaudio::PaException &e) 
+      {
+        getAudioDriver()->setErrorMessage(e.paErrorText());
+        _debug("Portaudio exception: %s\n", e.paErrorText());
+        return false;
+      }
+    catch (const portaudio::PaCppException &e) 
+      {
+        getAudioDriver()->setErrorMessage(e.what());
+        _debug("Portaudio exception: %s\n", e.what());
+        return false;
+      }
+    catch (const std::runtime_error &e) 
+      {
+        getAudioDriver()->setErrorMessage(e.what());
+        _debug("Portaudio exception: %s\n", e.what());
+        return false;
+      } 
+    catch(...) 
+      {
+        _debug("Portaudio exception: <unknown>\n");
+        return false;
+      }
+  } else {
+    return false;
+  }
+}
diff --git a/src/managerimpl.h b/src/managerimpl.h
index 0cf41d603a96e778ad4f7db7278c9905e0e4a427..dbd7c1e677b5ae0fdabc583775ee92c42f32ad10 100644
--- a/src/managerimpl.h
+++ b/src/managerimpl.h
@@ -175,6 +175,8 @@ public:
   bool setConfig(const std::string& section, const std::string& name, const std::string& value);
   bool setConfig(const std::string& section, const std::string& name, int value);
   bool getConfigList(const std::string& sequenceId, const std::string& name);
+  void selectAudioDriver(void);
+  bool setSwitch(const std::string& switchName);
 
   // configuration function for extern
   // throw an Conf::ConfigTreeItemException if not found
@@ -269,7 +271,7 @@ private:
   /*
    * Initialize audiodriver
    */
-  void selectAudioDriver (void);
+  void initAudioDriver(void);
 
   /*
    * Initialize zeroconf module and scanning
@@ -290,7 +292,7 @@ private:
    * Configuration
    */
   bool getDirListing(const std::string& sequenceId, const std::string& path, int *nbFile);
-  bool getAudioDeviceList(const std::string& sequenceId);
+  bool getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask);
   Conf::ConfigTree _config;
   bool getCountryTones(const std::string& sequenceId);
   void sendCountryTone(const std::string& sequenceId, int index, const std::string& name);
diff --git a/src/user_cfg.h b/src/user_cfg.h
index 343e0c887e33e0ee1b97a5ef83f94878961ada94..49aed13606a689df426bea6140d8ba4f07ee8352 100644
--- a/src/user_cfg.h
+++ b/src/user_cfg.h
@@ -54,6 +54,8 @@
 #define STUN_SERVER		"STUN.STUNserver"
 #define USE_STUN		"STUN.useStun"
 #define DRIVER_NAME		"Drivers.driverName"
+#define DRIVER_NAME_IN		"Drivers.driverNameIn"
+#define DRIVER_NAME_OUT		"Drivers.driverNameOut"
 #define NB_CODEC		"Codecs.nbCodec"
 #define CODEC1			"Codecs.codec1"
 #define CODEC2			"Codecs.codec2"