Index: directx.c
===================================================================
--- directx.c	(revision 11090)
+++ directx.c	(working copy)
@@ -143,7 +143,20 @@
 
 } notification_thread_t;
 
+
 /*****************************************************************************
+ * directSoundDevice: List of available audio devices
+ *****************************************************************************/
+struct directSoundDevice;
+typedef struct directSoundDevice 
+{
+  LPGUID p_guid;
+  char *psz_description;
+  char *psz_module;
+  struct directSoundDevice *p_next;
+} directSoundDevice;
+
+/*****************************************************************************
  * aout_sys_t: directx audio output method descriptor
  *****************************************************************************
  * This structure is part of the audio output thread descriptor.
@@ -161,7 +174,7 @@
     notification_thread_t *p_notif;                  /* DirectSoundThread id */
 
     int b_playing;                                         /* playing status */
-
+    int i_device_id;                           /*  User defined device index */
     int i_frame_size;                         /* Size in bytes of one frame */
 
     vlc_bool_t b_chan_reorder;              /* do we need channel reordering */
@@ -206,6 +219,10 @@
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
+#define FLOAT_TEXT N_("Output device")
+#define FLOAT_LONGTEXT N_( \
+    "DirectX device number: 0 default device, 1..N device by number" \
+    "(Note that the default device appears as 0 AND another number)." )
 vlc_module_begin();
     set_description( _("DirectX audio output") );
     set_shortname( "DirectX" );
@@ -213,6 +230,10 @@
     set_category( CAT_AUDIO );
     set_subcategory( SUBCAT_AUDIO_AOUT );
     add_shortcut( "directx" );
+    /* Add variable to VLC directx-device, default value 0, don't callback, 
+     name the GUI field, GUI tooltip, display as advanced in preferences */
+    add_integer( "directx-device", 0, NULL, FLOAT_TEXT, 
+                 FLOAT_LONGTEXT, VLC_TRUE );
     set_callbacks( OpenAudio, CloseAudio );
 vlc_module_end();
 
@@ -247,6 +268,13 @@
     p_aout->output.pf_play = Play;
     aout_VolumeSoftInit( p_aout );
 
+		
+    /* Retrieve output device id from config */		
+    var_Create( p_aout, "directx-device", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT);
+    var_Get( p_aout, "directx-device", &val );
+    p_aout->output.p_sys->i_device_id = val.i_int;
+		
+
     /* Initialise DirectSound */
     if( InitDirectSound( p_aout ) )
     {
@@ -594,12 +622,73 @@
 }
 
 /*****************************************************************************
+ * CallBackDirectSoundEnum: callback to enumerate available devices
+ *****************************************************************************/
+static int CALLBACK CallBackDirectSoundEnum (LPGUID p_guid, LPCSTR psz_desc,
+    LPCSTR psz_mod, LPVOID p_list)
+{
+    directSoundDevice *p_ad;
+    directSoundDevice *p_otherad = (directSoundDevice *)p_list;
+    p_ad = malloc( sizeof( directSoundDevice ) );
+
+    /* GUID == NULL is primary (default) device */
+    if (p_guid == NULL)
+    {
+        p_ad->p_guid = NULL;
+    }
+    else
+    {
+        p_ad->p_guid = malloc( sizeof( GUID ) );
+        memcpy( p_ad->p_guid, p_guid, sizeof( GUID ) );
+    }
+
+    /* Desc & mod not used, kept for next author to use if needed */
+    p_ad->psz_description = malloc( sizeof(char) * (strlen(psz_desc) + 1) );
+    strcpy(p_ad->psz_description, psz_desc);
+    p_ad->psz_module = malloc( sizeof(char) * (strlen(psz_mod) + 1) );
+    strcpy(p_ad->psz_module, psz_mod);
+
+    /* add to end of list */
+    p_ad->p_next = NULL;
+    while( p_otherad->p_next != NULL )
+        p_otherad = p_otherad->p_next;
+    p_otherad->p_next = p_ad;    
+    return 1;
+}
+/*****************************************************************************
+ * DirectSoundEnumCleanup: free memory used when enumerating devices
+ *****************************************************************************/
+static void DirectSoundEnumCleanup(directSoundDevice *p_headDev) {  
+    directSoundDevice *p_currDev; /* current device */
+    directSoundDevice *p_delDev;  /* pointer for deleting devices */
+    /* clean up: delete the enumerated devices */
+    p_currDev = p_headDev->p_next;		
+    while ( p_currDev->p_next != NULL )
+    {
+        p_delDev = p_currDev;
+        p_currDev = p_currDev->p_next;
+        free( p_delDev->p_guid );
+        free( p_delDev );
+    }
+    free( p_currDev->p_guid );
+    free( p_currDev );
+    free( p_headDev );
+}
+/*****************************************************************************
  * InitDirectSound: handle all the gory details of DirectSound initialisation
  *****************************************************************************/
 static int InitDirectSound( aout_instance_t *p_aout )
 {
     HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
+    HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACK, LPVOID);
+    int i_selectedId;             /* user defined index of device */		
+    directSoundDevice *p_headDev; /* head of device list */
+    directSoundDevice *p_currDev; /* current device */		
 
+    i_selectedId = p_aout->output.p_sys->i_device_id; /* get user selected */
+    p_headDev = malloc( sizeof( directSoundDevice ) ); 
+    p_headDev->p_next = NULL;	  
+		
     p_aout->output.p_sys->hdsound_dll = LoadLibrary("DSOUND.DLL");
     if( p_aout->output.p_sys->hdsound_dll == NULL )
     {
@@ -615,15 +704,56 @@
         msg_Warn( p_aout, "GetProcAddress FAILED" );
         goto error;
     }
-
-    /* Create the direct sound object */
-    if FAILED( OurDirectSoundCreate( NULL, &p_aout->output.p_sys->p_dsobject,
+    
+    /* Get DirectSoundEnumerate 
+       (note getting ASCII call, not Unicode DirectSoundEnumerateW) */
+    OurDirectSoundEnumerate = (void *)GetProcAddress(
+                                         p_aout->output.p_sys->hdsound_dll,
+                                         "DirectSoundEnumerateA" );
+    
+    if( OurDirectSoundCreate == NULL )
+    {
+        msg_Warn( p_aout, "GetProcAddress DirectSoundEnumerateA FAILED" );
+        goto error;
+    }   
+                                       
+    /* attempt enumeration */
+    if (FAILED ( OurDirectSoundEnumerate( CallBackDirectSoundEnum, 
+                                          p_headDev ) ) )
+    {
+        msg_Warn( p_aout, "Enumeration of DirectSound devices FAILED" );
+        goto error;
+    }
+    else
+    {						
+        /* ignore negative device id 
+           (unnecessary, will default to first device) 
+           ignore id past end of list
+           (default to last device) */
+			     			
+        /* loop through to the selected device */
+        p_currDev = p_headDev->p_next;
+        while ( p_currDev->p_next != NULL && 0 < i_selectedId ) 
+        {
+            i_selectedId--;
+            p_currDev = p_currDev->p_next;
+        }
+    }
+		
+    /* Create the direct sound object */    
+    if FAILED( OurDirectSoundCreate( p_currDev->p_guid, 
+                                     &p_aout->output.p_sys->p_dsobject,
                                      NULL ) )
     {
+        /* clean up enumerated devices */    
+        DirectSoundEnumCleanup(p_headDev);
         msg_Warn( p_aout, "cannot create a direct sound device" );
         goto error;
     }
 
+    /* clean up enumerated devices */    
+    DirectSoundEnumCleanup( p_headDev );
+    
     /* Set DirectSound Cooperative level, ie what control we want over Windows
      * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
      * settings of the primary buffer, but also that only the sound of our
