--- /tmp/sound_alsa.cxx_orig	2006-05-01 12:13:44.597706228 +0200
+++ /tmp/sound_alsa.cxx	2006-05-08 08:25:51.138362680 +0200
@@ -109,6 +109,7 @@
 
 #pragma implementation "sound_alsa.h"
 
+#define PTRACING 1
 #include "sound_alsa.h"
 
 
@@ -227,24 +228,45 @@
 PStringArray PSoundChannelALSA::GetDeviceNames (Directions dir)
 {
   PStringArray devices;
- 
+  snd_config_t *config;
+  PString* dev;
+
+
+  // Add real hardware to the dictionary 
   UpdateDictionary (dir);
+
+  // Read additional devices from config file
+  PConfig cfg("");
+  PINDEX i = 0;
+  PStringList devs_from_config = cfg.GetKeys("ALSA::Player");
+  while ( (dev = (PString*) devs_from_config.GetAt( i++ )) != 0 ) {
+    AddPcmDefinition( *dev, Player );
+    PTRACE(1, *dev + " added as Player");
+  }
+  
+  i = 0;
+  devs_from_config = cfg.GetKeys("ALSA::Recorder");
+  while ( (dev = (PString*) devs_from_config.GetAt( i++ )) != 0 ) {
+    AddPcmDefinition( *dev, Recorder );
+    PTRACE(1, *dev + " added as Recorder");
+  }
   
   if (dir == Recorder) {
     
     for (PINDEX j = 0 ; j < capture_devices.GetSize () ; j++) 
       devices += capture_devices.GetKeyAt (j);
+    devices += additional_capture_devices;
   }
   else {
 
     for (PINDEX j = 0 ; j < playback_devices.GetSize () ; j++) 
       devices += playback_devices.GetKeyAt (j);
+    devices += additional_playback_devices;
   }
 
+  if ( snd_config_search_definition(snd_config, "pcm", "default", &config) >= 0 )
+    devices += "default";
 
-  if (devices.GetSize () > 0)
-    devices += "Default";
-  
   return devices;
 }
 
@@ -267,6 +289,7 @@
   PString real_device_name;
   POrdinalKey *i = NULL;
   snd_pcm_stream_t stream;
+  int err;
 
   Close();
 
@@ -295,23 +318,43 @@
       || (_dir == Player && playback_devices.IsEmpty ()))
     UpdateDictionary (_dir);
 
+    snd_config_t* config;
+
     i = (_dir == Recorder) ? capture_devices.GetAt (_device) : playback_devices.GetAt (_device);
 
     if (i) {
 
-      real_device_name = "plughw:" + PString (*i);
+      // default + cardnumber works since alsa 1.0.8
+      real_device_name = "default:" + PString (*i);
+      err = snd_config_search_definition(snd_config, "pcm", real_device_name, &config);
+      if (err < 0) {
+        real_device_name = "plughw:" + PString (*i);
+        err = snd_config_search_definition(snd_config, "pcm", real_device_name, &config);
+        if (err < 0) {
+          PTRACE (1, "ALSA\tDevice " + real_device_name + " not defined");
+          return FALSE;
+        }
+      }
       card_nr = *i;
     }
-    else {
+    else { // Not a card by itself, but something more complicated, user defined
 
-      PTRACE (1, "ALSA\tDevice not found");
-      return FALSE;
+      if ( ( err = snd_config_search_definition(snd_config, "pcm", _device, &config)) >= 0 ) {
+        // valid pcm name
+        real_device_name = _device;
+        card_nr = -3;
+      }
+      else {
+
+        PTRACE (1, "ALSA\tDevice/definition " + _device + " not found: " + PString(snd_strerror(err)) );
+        return FALSE;
+      }
     }
   }
     
-  if (snd_pcm_open (&os_handle, real_device_name, stream, SND_PCM_NONBLOCK) < 0) {
+  if ((err = snd_pcm_open (&os_handle, real_device_name, stream, SND_PCM_NONBLOCK)) < 0) {
 
-    PTRACE (1, "ALSA\tOpen Failed");
+    PTRACE (1, "ALSA\tOpen Failed: " + PString(snd_strerror(err)) );
     return FALSE;
   }
   else 
@@ -827,7 +870,11 @@
   if (!os_handle)
     return FALSE;
 
-  if (card_nr == -2)
+  if (card_nr == -3) {
+    // FIXME: Is it possible to get the right mixer for user defined PCMs?
+    PTRACE (3, "User defined pcm, Volume() not implemented");
+    return FALSE;
+  } else if (card_nr == -2)
     card_name = "default";
   else
     card_name = "hw:" + PString (card_nr);
@@ -922,3 +969,44 @@
 
   return TRUE;
 }
+
+
+/**
+*/
+BOOL PSoundChannelALSA::AddPcmDefinition (const PString& _devicename,
+	                                  const PSoundChannel::Directions _dir)
+{
+  int err;
+  snd_config_t* config;
+
+  // Only add it if not already in the list
+  if ( _dir == Recorder ) {
+	if ( additional_capture_devices.GetStringsIndex( _devicename ) != P_MAX_INDEX )
+		return TRUE;
+  } else {
+	if ( additional_playback_devices.GetStringsIndex( _devicename ) != P_MAX_INDEX )
+		return TRUE;
+  } 
+
+  // Initalize global snd_config for snd_config_search_definition
+  err = snd_config_update();
+  if (err < 0) {
+    return FALSE;
+  }
+
+  // Check if the name is valid
+  err = snd_config_search_definition(snd_config, "pcm", _devicename, &config);
+  if (err < 0) {
+    PTRACE (1, "ALSA\tDevice " + _devicename + " not defined");
+    return FALSE;
+  } 
+  // FIXME: walk through the tree until we find a hw node, determine if direction is possible.A
+  (_dir == Recorder) ? additional_capture_devices += _devicename : additional_playback_devices += _devicename;
+ 
+  return TRUE; 
+}
+
+
+PStringArray PSoundChannelALSA::additional_capture_devices;
+PStringArray PSoundChannelALSA::additional_playback_devices;
+
--- /tmp/sound_alsa.h_orig	2006-05-03 13:20:11.505398862 +0200
+++ /tmp/sound_alsa.h	2006-05-04 09:45:18.160684908 +0200
@@ -87,9 +87,10 @@
   BOOL SetVolume (unsigned);
   BOOL GetVolume (unsigned &);
   BOOL IsOpen() const;
+  static BOOL AddPcmDefinition(const PString& _devicename,
+                               const PSoundChannel::Directions);
 
  private:
-
   static void UpdateDictionary(PSoundChannel::Directions);
   BOOL Volume (BOOL, unsigned, unsigned &);
   PSoundChannel::Directions direction;
@@ -112,4 +113,8 @@
 
   /** Number of bytes in a ALSA frame. a frame may only be 4ms long*/
   int frameBytes; 
+
+  /** List of addional pcm definitions **/
+  static PStringArray additional_capture_devices;
+  static PStringArray additional_playback_devices;
 };
