]> git.sesse.net Git - vlc/blobdiff - modules/audio_output/directx.c
* configure.ac: bumped version number to 0.6.1.
[vlc] / modules / audio_output / directx.c
index d94d2c799232c5fd4f9c8b7a79b30ad7340adc3e..ed7c407e65d8b4b308d95b528b6ce93059d99100 100644 (file)
@@ -2,7 +2,7 @@
  * directx.c: Windows DirectX audio output method
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: directx.c,v 1.15 2003/03/03 14:21:08 gbazin Exp $
+ * $Id: directx.c,v 1.22 2003/07/11 23:14:03 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -39,7 +39,7 @@
 #include <dsound.h>
 
 #define FRAME_SIZE 2048              /* The size is in samples, not in bytes */
-#define FRAMES_NUM 4
+#define FRAMES_NUM 8
 
 /* frame buffer status */
 #define FRAME_QUEUED 0
@@ -123,15 +123,9 @@ typedef struct {
 } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
 #endif
 
-#ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
-DEFINE_GUID( KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
-#endif
-#ifndef KSDATAFORMAT_SUBTYPE_PCM
-DEFINE_GUID( KSDATAFORMAT_SUBTYPE_PCM, WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
-#endif
-#ifndef KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF
-DEFINE_GUID( KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF, WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
-#endif
+DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_PCM, WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF, WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
 
 /*****************************************************************************
  * notification_thread_t: DirectX event thread
@@ -212,7 +206,7 @@ static void InterleaveS16     ( int16_t *, int16_t *, int *, int );
  * Module descriptor
  *****************************************************************************/
 vlc_module_begin();
-    set_description( _("DirectX audio module") );
+    set_description( _("DirectX audio output") );
     set_capability( "audio output", 100 );
     add_shortcut( "directx" );
     set_callbacks( OpenAudio, CloseAudio );
@@ -257,11 +251,6 @@ static int OpenAudio( vlc_object_t *p_this )
         goto error;
     }
 
-    /* Now we need to setup our DirectSound play notification structure */
-    p_aout->output.p_sys->p_notif =
-        vlc_object_create( p_aout, sizeof(notification_thread_t) );
-    p_aout->output.p_sys->p_notif->p_aout = p_aout;
-
     if( var_Type( p_aout, "audio-device" ) == 0 )
     {
         Probe( p_aout );
@@ -270,19 +259,22 @@ static int OpenAudio( vlc_object_t *p_this )
     if( var_Get( p_aout, "audio-device", &val ) < 0 )
     {
         /* Probe() has failed. */
-        free( p_aout->output.p_sys );
-        return VLC_EGENERIC;
+        goto error;
     }
 
+    /* Now we need to setup our DirectSound play notification structure */
+    p_aout->output.p_sys->p_notif =
+        vlc_object_create( p_aout, sizeof(notification_thread_t) );
+    p_aout->output.p_sys->p_notif->p_aout = p_aout;
+
     /* Then create the notification events */
     for( i = 0; i < FRAMES_NUM; i++ )
         p_aout->output.p_sys->p_notif->p_events[i].hEventNotify =
             CreateEvent( NULL, FALSE, FALSE, NULL );
 
     /* Open the device */
-    if( !strcmp( val.psz_string, N_("A/52 over S/PDIF") ) )
+    if( val.i_int == AOUT_VAR_SPDIF )
     {
-        free( val.psz_string );
         p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
 
         /* Calculate the frame size in bytes */
@@ -299,7 +291,7 @@ static int OpenAudio( vlc_object_t *p_this )
                             p_aout->output.p_sys->i_frame_size, VLC_FALSE )
             != VLC_SUCCESS )
         {
-            msg_Err( p_aout, "cannot open waveout audio device" );
+            msg_Err( p_aout, "cannot open directx audio device" );
             free( p_aout->output.p_sys );
             return VLC_EGENERIC;
         }
@@ -308,20 +300,20 @@ static int OpenAudio( vlc_object_t *p_this )
     }
     else
     {
-        if( !strcmp( val.psz_string, N_("5.1") ) )
+        if( val.i_int == AOUT_VAR_5_1 )
         {
             p_aout->output.output.i_physical_channels
                 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
                    | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                    | AOUT_CHAN_LFE;
         }
-        else if( !strcmp( val.psz_string, N_("2 Front 2 Rear") ) )
+        else if( val.i_int == AOUT_VAR_2F2R )
         {
             p_aout->output.output.i_physical_channels
                 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
                    | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
         }
-        else if( !strcmp( val.psz_string, "Mono" ) )
+        else if( val.i_int == AOUT_VAR_MONO )
         {
             p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
         }
@@ -330,7 +322,6 @@ static int OpenAudio( vlc_object_t *p_this )
             p_aout->output.output.i_physical_channels
                 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
         }
-        free( val.psz_string );
 
         if( CreateDSBufferPCM( p_aout, &p_aout->output.output.i_format,
                                p_aout->output.output.i_physical_channels,
@@ -338,7 +329,7 @@ static int OpenAudio( vlc_object_t *p_this )
                                p_aout->output.output.i_rate, VLC_FALSE )
             != VLC_SUCCESS )
         {
-            msg_Err( p_aout, "cannot open waveout audio device" );
+            msg_Err( p_aout, "cannot open directx audio device" );
             free( p_aout->output.p_sys );
             return VLC_EGENERIC;
         }
@@ -377,12 +368,14 @@ static int OpenAudio( vlc_object_t *p_this )
  *****************************************************************************/
 static void Probe( aout_instance_t * p_aout )
 {
-    vlc_value_t val;
+    vlc_value_t val, text;
     int i_format;
     unsigned int i_physical_channels;
     DWORD ui_speaker_config;
 
-    var_Create( p_aout, "audio-device", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
+    var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
+    text.psz_string = _("Audio device");
+    var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
 
     /* Test for 5.1 support */
     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
@@ -394,8 +387,10 @@ static void Probe( aout_instance_t * p_aout )
                                p_aout->output.output.i_rate, VLC_TRUE )
             == VLC_SUCCESS )
         {
-            val.psz_string = N_("5.1");
-            var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
+            val.i_int = AOUT_VAR_5_1;
+            text.psz_string = N_("5.1");
+            var_Change( p_aout, "audio-device",
+                        VLC_VAR_ADDCHOICE, &val, &text );
             msg_Dbg( p_aout, "device supports 5.1 channels" );
         }
     }
@@ -410,8 +405,10 @@ static void Probe( aout_instance_t * p_aout )
                                p_aout->output.output.i_rate, VLC_TRUE )
             == VLC_SUCCESS )
         {
-            val.psz_string = N_("2 Front 2 Rear");
-            var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
+            val.i_int = AOUT_VAR_2F2R;
+            text.psz_string = N_("2 Front 2 Rear");
+            var_Change( p_aout, "audio-device",
+                        VLC_VAR_ADDCHOICE, &val, &text );
             msg_Dbg( p_aout, "device supports 4 channels" );
         }
     }
@@ -422,8 +419,9 @@ static void Probe( aout_instance_t * p_aout )
                            p_aout->output.output.i_rate, VLC_TRUE )
         == VLC_SUCCESS )
     {
-        val.psz_string = N_("Stereo");
-        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
+        val.i_int = AOUT_VAR_STEREO;
+        text.psz_string = N_("Stereo");
+        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
         msg_Dbg( p_aout, "device supports 2 channels" );
     }
 
@@ -433,8 +431,9 @@ static void Probe( aout_instance_t * p_aout )
                            p_aout->output.output.i_rate, VLC_TRUE )
         == VLC_SUCCESS )
     {
-        val.psz_string = N_("Mono");
-        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );        
+        val.i_int = AOUT_VAR_MONO;
+        text.psz_string = N_("Mono");
+        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
         msg_Dbg( p_aout, "device supports 1 channel" );
     }
 
@@ -448,18 +447,18 @@ static void Probe( aout_instance_t * p_aout )
     switch( DSSPEAKER_CONFIG(ui_speaker_config) )
     {
     case DSSPEAKER_5POINT1:
-        val.psz_string = N_("5.1");
+        val.i_int = AOUT_VAR_5_1;
         break;
     case DSSPEAKER_QUAD:
-        val.psz_string = N_("2 Front 2 Rear");
+        val.i_int = AOUT_VAR_2F2R;
         break;
     case DSSPEAKER_MONO:
-        val.psz_string = N_("Mono");
+        val.i_int = AOUT_VAR_MONO;
         break;
     case DSSPEAKER_SURROUND:
     case DSSPEAKER_STEREO:
     default:
-        val.psz_string = N_("Stereo");
+        val.i_int = AOUT_VAR_STEREO;
         break;
     }
     var_Set( p_aout, "audio-device", val );
@@ -475,13 +474,23 @@ static void Probe( aout_instance_t * p_aout )
             == VLC_SUCCESS )
         {
             msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
-            val.psz_string = N_("A/52 over S/PDIF");
-            var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
+            val.i_int = AOUT_VAR_SPDIF;
+            text.psz_string = N_("A/52 over S/PDIF");
+            var_Change( p_aout, "audio-device",
+                        VLC_VAR_ADDCHOICE, &val, &text );
             if( config_GetInt( p_aout, "spdif" ) )
                 var_Set( p_aout, "audio-device", val );
         }
     }
 
+    var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
+    if( val.i_int <= 0 )
+    {
+        /* Probe() has failed. */
+        var_Destroy( p_aout, "audio-device" );
+        return;
+    }
+
     var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
 
     val.b_bool = VLC_TRUE;
@@ -657,7 +666,7 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
         waveformat.Samples.wValidBitsPerSample =
             waveformat.Format.wBitsPerSample;
         waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
-        waveformat.SubFormat = KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
+        waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
         break;
 
     case VLC_FOURCC('f','l','3','2'):
@@ -665,7 +674,7 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
         waveformat.Samples.wValidBitsPerSample =
             waveformat.Format.wBitsPerSample;
         waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
-        waveformat.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+        waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
         break;
 
     case VLC_FOURCC('s','1','6','l'):
@@ -673,7 +682,7 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
         waveformat.Samples.wValidBitsPerSample =
             waveformat.Format.wBitsPerSample;
         waveformat.Format.wFormatTag = WAVE_FORMAT_PCM;
-        waveformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+        waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
         break;
     }
 
@@ -702,7 +711,8 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
     dsbdesc.dwSize = sizeof(DSBUFFERDESC);
     dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
                     | DSBCAPS_CTRLPOSITIONNOTIFY     /* We need notification */
-                    | DSBCAPS_GLOBALFOCUS;      /* Allows background playing */
+                    | DSBCAPS_GLOBALFOCUS       /* Allows background playing */
+                    | DSBCAPS_LOCHARDWARE;      /* Needed for 5.1 on emu101k */
     dsbdesc.dwBufferBytes = FRAMES_NUM * i_bytes_per_frame;   /* buffer size */
     dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&waveformat;
 
@@ -710,7 +720,15 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
                    p_aout->output.p_sys->p_dsobject, &dsbdesc,
                    &p_aout->output.p_sys->p_dsbuffer, NULL) )
     {
-        goto error;
+        /* Try without DSBCAPS_LOCHARDWARE */
+        dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
+        if FAILED( IDirectSound_CreateSoundBuffer(
+                   p_aout->output.p_sys->p_dsobject, &dsbdesc,
+                   &p_aout->output.p_sys->p_dsbuffer, NULL) )
+        {
+            return VLC_EGENERIC;
+        }
+        if( !b_probe ) msg_Dbg( p_aout, "couldn't use hardware sound buffer" );
     }
 
     /* Stop here if we were just probing */
@@ -759,16 +777,7 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
     return VLC_SUCCESS;
 
  error:
-    if( p_aout->output.p_sys->p_dsbuffer )
-    {
-        IDirectSoundBuffer_Release( p_aout->output.p_sys->p_dsbuffer );
-        p_aout->output.p_sys->p_dsbuffer = NULL;
-    }
-    if( p_aout->output.p_sys->p_dsnotify )
-    {
-        IDirectSoundBuffer_Release( p_aout->output.p_sys->p_dsbuffer );
-        p_aout->output.p_sys->p_dsnotify = NULL;
-    }
+    DestroyDSBuffer( p_aout );
     return VLC_EGENERIC;
 }
 
@@ -782,7 +791,10 @@ static int CreateDSBufferPCM( aout_instance_t *p_aout, int *i_format,
                               int i_channels, int i_nb_channels, int i_rate,
                               vlc_bool_t b_probe )
 {
-    if( CreateDSBuffer( p_aout, VLC_FOURCC('f','l','3','2'),
+    /* Float32 audio samples are not supported for 5.1 output on the emu101k */
+
+    if( i_nb_channels > 2 ||
+        CreateDSBuffer( p_aout, VLC_FOURCC('f','l','3','2'),
                         i_channels, i_nb_channels, i_rate,
                         FRAME_SIZE * 4 * i_nb_channels, b_probe )
         != VLC_SUCCESS )
@@ -888,6 +900,8 @@ static int FillBuffer( aout_instance_t *p_aout, int i_frame,
                              (float *)p_write_position,
                              p_aout->output.p_sys->pi_chan_table,
                              aout_FormatNbChannels( &p_aout->output.output ) );
+
+        aout_BufferFree( p_buffer );
     }
     else
     {