* 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>
*
#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
} 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
* 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 );
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 );
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 */
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;
}
}
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;
}
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,
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;
}
*****************************************************************************/
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 |
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" );
}
}
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" );
}
}
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" );
}
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" );
}
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 );
== 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;
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'):
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'):
waveformat.Samples.wValidBitsPerSample =
waveformat.Format.wBitsPerSample;
waveformat.Format.wFormatTag = WAVE_FORMAT_PCM;
- waveformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+ waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
break;
}
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;
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 */
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;
}
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 )
(float *)p_write_position,
p_aout->output.p_sys->pi_chan_table,
aout_FormatNbChannels( &p_aout->output.output ) );
+
+ aout_BufferFree( p_buffer );
}
else
{