directx.c 45.2 KB
Newer Older
1
/*****************************************************************************
2
 * directx.c: Windows DirectX audio output method
3
 *****************************************************************************
4
 * Copyright (C) 2001-2009 the VideoLAN team
5
 * $Id$
6
 *
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
20 21
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 23 24 25 26 27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/

28 29 30 31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32
#include <vlc_common.h>
33
#include <vlc_plugin.h>
Clément Stenac's avatar
Clément Stenac committed
34
#include <vlc_aout.h>
35
#include <vlc_charset.h>
36

37 38
#include "windows_audio_common.h"

39 40
#include <dsound.h>

41
#define FRAME_SIZE ((int)p_aout->output.output.i_rate/20) /* Size in samples */
Gildas Bazin's avatar
 
Gildas Bazin committed
42

43 44 45 46 47 48 49
/*****************************************************************************
 * notification_thread_t: DirectX event thread
 *****************************************************************************/
typedef struct notification_thread_t
{
    VLC_COMMON_MEMBERS

50 51 52
    aout_instance_t *p_aout;
    int i_frame_size;                          /* size in bytes of one frame */
    int i_write_slot;       /* current write position in our circular buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
53 54

    mtime_t start_date;
55
    HANDLE event;
56 57 58 59 60 61 62 63 64 65 66

} notification_thread_t;

/*****************************************************************************
 * aout_sys_t: directx audio output method descriptor
 *****************************************************************************
 * This structure is part of the audio output thread descriptor.
 * It describes the direct sound specific properties of an audio device.
 *****************************************************************************/
struct aout_sys_t
{
Gildas Bazin's avatar
 
Gildas Bazin committed
67
    HINSTANCE           hdsound_dll;      /* handle of the opened dsound dll */
68

69
    char *              psz_device;              /* user defined device name */
70 71
    LPGUID              p_device_guid;

72 73 74 75 76
    LPDIRECTSOUND       p_dsobject;              /* main Direct Sound object */
    LPDIRECTSOUNDBUFFER p_dsbuffer;   /* the sound buffer we use (direct sound
                                       * takes care of mixing all the
                                       * secondary buffers into the primary) */

Gildas Bazin's avatar
 
Gildas Bazin committed
77
    notification_thread_t *p_notif;                  /* DirectSoundThread id */
78

79
    int      b_playing;                                    /* playing status */
80

81
    int      i_frame_size;                     /* Size in bytes of one frame */
Gildas Bazin's avatar
 
Gildas Bazin committed
82

83
    int      i_speaker_setup;                      /* Speaker setup override */
84

85 86
    bool     b_chan_reorder;                /* do we need channel reordering */
    int      pi_chan_table[AOUT_CHAN_MAX];
Gildas Bazin's avatar
 
Gildas Bazin committed
87
    uint32_t i_channel_mask;
88 89
    uint32_t i_bits_per_sample;
    uint32_t i_channels;
90 91 92 93 94
};

/*****************************************************************************
 * Local prototypes.
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
95 96 97
static int  OpenAudio  ( vlc_object_t * );
static void CloseAudio ( vlc_object_t * );
static void Play       ( aout_instance_t * );
98 99

/* local functions */
Gildas Bazin's avatar
 
Gildas Bazin committed
100 101
static void Probe             ( aout_instance_t * );
static int  InitDirectSound   ( aout_instance_t * );
102
static int  CreateDSBuffer    ( aout_instance_t *, int, int, int, int, int, bool );
103
static int  CreateDSBufferPCM ( aout_instance_t *, vlc_fourcc_t*, int, int, int, bool );
Gildas Bazin's avatar
 
Gildas Bazin committed
104
static void DestroyDSBuffer   ( aout_instance_t * );
105
static void* DirectSoundThread( vlc_object_t * );
Gildas Bazin's avatar
 
Gildas Bazin committed
106 107
static int  FillBuffer        ( aout_instance_t *, int, aout_buffer_t * );

108 109 110
static int ReloadDirectXDevices( vlc_object_t *, char const *,
                                vlc_value_t, vlc_value_t, void * );

111 112 113
/* Speaker setup override options list */
static const char *const speaker_list[] = { "Windows default", "Mono", "Stereo",
                                            "Quad", "5.1", "7.1" };
114 115
static const char *const ppsz_adev[] = {"default",  };
static const char *const ppsz_adev_text[] = {"default", };
116

Gildas Bazin's avatar
 
Gildas Bazin committed
117 118 119
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
120
#define DEVICE_TEXT N_("Output device")
121
#define DEVICE_LONGTEXT N_("Select your audio output device")
122

123
#define SPEAKER_TEXT N_("Speaker configuration")
124 125
#define SPEAKER_LONGTEXT N_("Select speaker configuration you want to use. " \
    "This option doesn't upmix! So NO e.g. Stereo -> 5.1 conversion." )
126

127 128 129 130 131 132
vlc_module_begin ()
    set_description( N_("DirectX audio output") )
    set_shortname( "DirectX" )
    set_capability( "audio output", 100 )
    set_category( CAT_AUDIO )
    set_subcategory( SUBCAT_AUDIO_AOUT )
133
    add_shortcut( "directx", "directsound" )
134

135
    add_string( "directx-audio-device-name", "default",
136
             DEVICE_TEXT, DEVICE_LONGTEXT, false )
137 138 139
        add_deprecated_alias( "directx-audio-device" ) /* Since 1.1.0 */
        change_string_list( ppsz_adev, ppsz_adev_text, ReloadDirectXDevices )
        change_action_add( ReloadDirectXDevices, N_("Refresh list") )
140
    add_bool( "directx-audio-float32", false, FLOAT_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
141
              FLOAT_LONGTEXT, true )
142
    add_string( "directx-audio-speaker", "Windows default",
143 144
                 SPEAKER_TEXT, SPEAKER_LONGTEXT, true )
        change_string_list( speaker_list, 0, 0 )
145

146 147
    set_callbacks( OpenAudio, CloseAudio )
vlc_module_end ()
Gildas Bazin's avatar
 
Gildas Bazin committed
148

149 150 151 152 153
/*****************************************************************************
 * OpenAudio: open the audio device
 *****************************************************************************
 * This function opens and setups Direct Sound.
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
154
static int OpenAudio( vlc_object_t *p_this )
155
{
Gildas Bazin's avatar
 
Gildas Bazin committed
156
    aout_instance_t * p_aout = (aout_instance_t *)p_this;
Gildas Bazin's avatar
 
Gildas Bazin committed
157
    vlc_value_t val;
158 159 160 161
    char * psz_speaker;
    int i = 0;

    const char * const * ppsz_compare = speaker_list;
162

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
163
    msg_Dbg( p_aout, "Opening DirectSound Audio Output" );
164 165

   /* Allocate structure */
Gildas Bazin's avatar
 
Gildas Bazin committed
166 167
    p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
    if( p_aout->output.p_sys == NULL )
168
        return VLC_ENOMEM;
169 170

    /* Initialize some variables */
Gildas Bazin's avatar
 
Gildas Bazin committed
171 172 173
    p_aout->output.p_sys->p_dsobject = NULL;
    p_aout->output.p_sys->p_dsbuffer = NULL;
    p_aout->output.p_sys->p_notif = NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
174
    p_aout->output.p_sys->b_playing = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
175 176

    p_aout->output.pf_play = Play;
177
    aout_VolumeSoftInit( p_aout );
178

179 180 181
    /* Retrieve config values */
    var_Create( p_aout, "directx-audio-float32",
                VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
182
    psz_speaker = var_CreateGetString( p_aout, "directx-audio-speaker" );
183 184 185 186 187 188 189 190 191 192 193 194

    while ( *ppsz_compare != NULL )
    {
        if ( !strncmp( *ppsz_compare, psz_speaker, strlen(*ppsz_compare) ) )
        {
            break;
        }
        ppsz_compare++; i++;
    }

    if ( *ppsz_compare == NULL )
    {
195
        msg_Err( p_aout, "(%s) isn't valid speaker setup option", psz_speaker );
196 197 198
        msg_Err( p_aout, "Defaulting to Windows default speaker config");
        i = 0;
    }
199
    free( psz_speaker );
200 201
    p_aout->output.p_sys->i_speaker_setup = i;

202 203
    p_aout->output.p_sys->p_device_guid = 0;

204
    /* Initialise DirectSound */
Gildas Bazin's avatar
 
Gildas Bazin committed
205
    if( InitDirectSound( p_aout ) )
206
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
207 208
        msg_Err( p_aout, "cannot initialize DirectSound" );
        goto error;
209 210
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
211 212 213 214 215 216 217 218
    if( var_Type( p_aout, "audio-device" ) == 0 )
    {
        Probe( p_aout );
    }

    if( var_Get( p_aout, "audio-device", &val ) < 0 )
    {
        /* Probe() has failed. */
Gildas Bazin's avatar
 
Gildas Bazin committed
219
        goto error;
Gildas Bazin's avatar
 
Gildas Bazin committed
220 221 222
    }

    /* Open the device */
Gildas Bazin's avatar
 
Gildas Bazin committed
223
    if( val.i_int == AOUT_VAR_SPDIF )
224
    {
225
        p_aout->output.output.i_format = VLC_CODEC_SPDIFL;
Gildas Bazin's avatar
 
Gildas Bazin committed
226 227 228 229 230 231 232 233

        /* Calculate the frame size in bytes */
        p_aout->output.i_nb_samples = A52_FRAME_NB;
        p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
        p_aout->output.output.i_frame_length = A52_FRAME_NB;
        p_aout->output.p_sys->i_frame_size =
            p_aout->output.output.i_bytes_per_frame;

234
        if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
Gildas Bazin's avatar
 
Gildas Bazin committed
235 236 237
                            p_aout->output.output.i_physical_channels,
                            aout_FormatNbChannels( &p_aout->output.output ),
                            p_aout->output.output.i_rate,
238
                            p_aout->output.p_sys->i_frame_size, false )
Gildas Bazin's avatar
 
Gildas Bazin committed
239 240
            != VLC_SUCCESS )
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
241
            msg_Err( p_aout, "cannot open directx audio device" );
Gildas Bazin's avatar
 
Gildas Bazin committed
242 243 244 245 246 247 248 249
            free( p_aout->output.p_sys );
            return VLC_EGENERIC;
        }

        aout_VolumeNoneInit( p_aout );
    }
    else
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
250
        if( val.i_int == AOUT_VAR_5_1 )
Gildas Bazin's avatar
 
Gildas Bazin committed
251 252 253 254 255 256
        {
            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;
        }
257 258 259 260 261 262 263 264
        else if( val.i_int == AOUT_VAR_7_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_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
                           | AOUT_CHAN_LFE;
        }
265 266 267 268 269 270
        else if( val.i_int == AOUT_VAR_3F2R )
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
                   | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
271
        else if( val.i_int == AOUT_VAR_2F2R )
Gildas Bazin's avatar
 
Gildas Bazin committed
272 273 274 275 276
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
                   | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
277
        else if( val.i_int == AOUT_VAR_MONO )
Gildas Bazin's avatar
 
Gildas Bazin committed
278 279 280 281 282 283 284 285
        {
            p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
        }
        else
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        }
286

Gildas Bazin's avatar
 
Gildas Bazin committed
287 288 289
        if( CreateDSBufferPCM( p_aout, &p_aout->output.output.i_format,
                               p_aout->output.output.i_physical_channels,
                               aout_FormatNbChannels( &p_aout->output.output ),
290
                               p_aout->output.output.i_rate, false )
Gildas Bazin's avatar
 
Gildas Bazin committed
291
            != VLC_SUCCESS )
Gildas Bazin's avatar
 
Gildas Bazin committed
292
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
293
            msg_Err( p_aout, "cannot open directx audio device" );
Gildas Bazin's avatar
 
Gildas Bazin committed
294 295
            free( p_aout->output.p_sys );
            return VLC_EGENERIC;
Gildas Bazin's avatar
 
Gildas Bazin committed
296
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
297 298 299 300 301

        /* Calculate the frame size in bytes */
        p_aout->output.i_nb_samples = FRAME_SIZE;
        aout_FormatPrepare( &p_aout->output.output );
        aout_VolumeSoftInit( p_aout );
Gildas Bazin's avatar
 
Gildas Bazin committed
302
    }
303

304 305 306 307 308 309 310 311 312
    /* 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;

    p_aout->output.p_sys->p_notif->event = CreateEvent( 0, FALSE, FALSE, 0 );
    p_aout->output.p_sys->p_notif->i_frame_size =
        p_aout->output.p_sys->i_frame_size;

Christophe Massiot's avatar
Christophe Massiot committed
313 314 315
    /* then launch the notification thread */
    msg_Dbg( p_aout, "creating DirectSoundThread" );
    if( vlc_thread_create( p_aout->output.p_sys->p_notif,
Gildas Bazin's avatar
 
Gildas Bazin committed
316
                           DirectSoundThread,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
317
                           VLC_THREAD_PRIORITY_HIGHEST ) )
Christophe Massiot's avatar
Christophe Massiot committed
318 319
    {
        msg_Err( p_aout, "cannot create DirectSoundThread" );
320
        CloseHandle( p_aout->output.p_sys->p_notif->event );
321
        vlc_object_release( p_aout->output.p_sys->p_notif );
322
        p_aout->output.p_sys->p_notif = NULL;
Christophe Massiot's avatar
Christophe Massiot committed
323 324 325 326 327
        goto error;
    }

    vlc_object_attach( p_aout->output.p_sys->p_notif, p_aout );

Gildas Bazin's avatar
 
Gildas Bazin committed
328
    return VLC_SUCCESS;
Christophe Massiot's avatar
Christophe Massiot committed
329 330

 error:
Gildas Bazin's avatar
 
Gildas Bazin committed
331
    CloseAudio( VLC_OBJECT(p_aout) );
332
    return VLC_EGENERIC;
Gildas Bazin's avatar
 
Gildas Bazin committed
333 334
}

Gildas Bazin's avatar
 
Gildas Bazin committed
335 336 337 338 339
/*****************************************************************************
 * Probe: probe the audio device for available formats and channels
 *****************************************************************************/
static void Probe( aout_instance_t * p_aout )
{
Gildas Bazin's avatar
 
Gildas Bazin committed
340
    vlc_value_t val, text;
341
    vlc_fourcc_t i_format;
Gildas Bazin's avatar
 
Gildas Bazin committed
342 343
    unsigned int i_physical_channels;
    DWORD ui_speaker_config;
344
    bool is_default_output_set = false;
Gildas Bazin's avatar
 
Gildas Bazin committed
345

Gildas Bazin's avatar
 
Gildas Bazin committed
346
    var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
347
    text.psz_string = _("Audio Device");
Gildas Bazin's avatar
 
Gildas Bazin committed
348
    var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
Gildas Bazin's avatar
 
Gildas Bazin committed
349 350 351 352 353 354 355 356

    /* Test for 5.1 support */
    i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                          AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
                          AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
    if( p_aout->output.output.i_physical_channels == i_physical_channels )
    {
        if( CreateDSBufferPCM( p_aout, &i_format, i_physical_channels, 6,
357
                               p_aout->output.output.i_rate, true )
Gildas Bazin's avatar
 
Gildas Bazin committed
358 359
            == VLC_SUCCESS )
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
360
            val.i_int = AOUT_VAR_5_1;
361
            text.psz_string = (char*) "5.1";
Gildas Bazin's avatar
 
Gildas Bazin committed
362 363
            var_Change( p_aout, "audio-device",
                        VLC_VAR_ADDCHOICE, &val, &text );
364 365
            var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL );
            is_default_output_set = true;
Gildas Bazin's avatar
 
Gildas Bazin committed
366 367 368 369
            msg_Dbg( p_aout, "device supports 5.1 channels" );
        }
    }

370 371 372 373 374
    /* Test for 7.1 support */
    i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                             AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
                             AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
                             AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
Rémi Duraffort's avatar
Rémi Duraffort committed
375 376 377
    if( p_aout->output.output.i_physical_channels == i_physical_channels )
    {
        if( CreateDSBufferPCM( p_aout, &i_format, i_physical_channels, 8,
378
                                  p_aout->output.output.i_rate, true )
Rémi Duraffort's avatar
Rémi Duraffort committed
379 380 381 382 383 384 385 386 387 388 389
            == VLC_SUCCESS )
        {
            val.i_int = AOUT_VAR_7_1;
            text.psz_string = (char*) "7.1";
            var_Change( p_aout, "audio-device",
                        VLC_VAR_ADDCHOICE, &val, &text );
            var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL );
            is_default_output_set = true;
            msg_Dbg( p_aout, "device supports 7.1 channels" );
        }
    }
390

391 392 393 394 395 396 397
    /* Test for 3 Front 2 Rear support */
    i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                          AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
                          AOUT_CHAN_REARRIGHT;
    if( p_aout->output.output.i_physical_channels == i_physical_channels )
    {
        if( CreateDSBufferPCM( p_aout, &i_format, i_physical_channels, 5,
398
                               p_aout->output.output.i_rate, true )
399 400 401
            == VLC_SUCCESS )
        {
            val.i_int = AOUT_VAR_3F2R;
402
            text.psz_string = _("3 Front 2 Rear");
403 404
            var_Change( p_aout, "audio-device",
                        VLC_VAR_ADDCHOICE, &val, &text );
405 406 407 408 409
            if(!is_default_output_set)
            {
                var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL );
                is_default_output_set = true;
            }
410 411 412 413
            msg_Dbg( p_aout, "device supports 5 channels" );
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
414 415 416 417 418 419 420
    /* Test for 2 Front 2 Rear support */
    i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                          AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
    if( ( p_aout->output.output.i_physical_channels & i_physical_channels )
        == i_physical_channels )
    {
        if( CreateDSBufferPCM( p_aout, &i_format, i_physical_channels, 4,
421
                               p_aout->output.output.i_rate, true )
Gildas Bazin's avatar
 
Gildas Bazin committed
422 423
            == VLC_SUCCESS )
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
424
            val.i_int = AOUT_VAR_2F2R;
425
            text.psz_string = _("2 Front 2 Rear");
Gildas Bazin's avatar
 
Gildas Bazin committed
426 427
            var_Change( p_aout, "audio-device",
                        VLC_VAR_ADDCHOICE, &val, &text );
428 429 430 431 432
            if(!is_default_output_set)
            {
                var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL );
                is_default_output_set = true;
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
433 434 435 436 437 438 439
            msg_Dbg( p_aout, "device supports 4 channels" );
        }
    }

    /* Test for stereo support */
    i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
    if( CreateDSBufferPCM( p_aout, &i_format, i_physical_channels, 2,
440
                           p_aout->output.output.i_rate, true )
Gildas Bazin's avatar
 
Gildas Bazin committed
441 442
        == VLC_SUCCESS )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
443
        val.i_int = AOUT_VAR_STEREO;
444
        text.psz_string = _("Stereo");
Gildas Bazin's avatar
 
Gildas Bazin committed
445
        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
446 447 448 449 450 451
        if(!is_default_output_set)
        {
            var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL );
            is_default_output_set = true;
            msg_Dbg( p_aout, "device supports 2 channels (DEFAULT!)" );
        }
452
        else msg_Dbg( p_aout, "device supports 2 channels" );
Gildas Bazin's avatar
 
Gildas Bazin committed
453 454 455 456 457
    }

    /* Test for mono support */
    i_physical_channels = AOUT_CHAN_CENTER;
    if( CreateDSBufferPCM( p_aout, &i_format, i_physical_channels, 1,
458
                           p_aout->output.output.i_rate, true )
Gildas Bazin's avatar
 
Gildas Bazin committed
459 460
        == VLC_SUCCESS )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
461
        val.i_int = AOUT_VAR_MONO;
462
        text.psz_string = _("Mono");
Gildas Bazin's avatar
 
Gildas Bazin committed
463
        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
Gildas Bazin's avatar
 
Gildas Bazin committed
464 465 466 467 468 469 470 471 472
        msg_Dbg( p_aout, "device supports 1 channel" );
    }

    /* Check the speaker configuration to determine which channel config should
     * be the default */
    if FAILED( IDirectSound_GetSpeakerConfig( p_aout->output.p_sys->p_dsobject,
                                              &ui_speaker_config ) )
    {
        ui_speaker_config = DSSPEAKER_STEREO;
473
        msg_Dbg( p_aout, "GetSpeakerConfig failed" );
Gildas Bazin's avatar
 
Gildas Bazin committed
474 475 476
    }
    switch( DSSPEAKER_CONFIG(ui_speaker_config) )
    {
477
    case DSSPEAKER_7POINT1:
478
        msg_Dbg( p_aout, "Windows says your SpeakerConfig is 7.1" );
479 480
        val.i_int = AOUT_VAR_7_1;
        break;
Gildas Bazin's avatar
 
Gildas Bazin committed
481
    case DSSPEAKER_5POINT1:
482
        msg_Dbg( p_aout, "Windows says your SpeakerConfig is 5.1" );
Gildas Bazin's avatar
 
Gildas Bazin committed
483
        val.i_int = AOUT_VAR_5_1;
Gildas Bazin's avatar
 
Gildas Bazin committed
484 485
        break;
    case DSSPEAKER_QUAD:
486
        msg_Dbg( p_aout, "Windows says your SpeakerConfig is Quad" );
Gildas Bazin's avatar
 
Gildas Bazin committed
487
        val.i_int = AOUT_VAR_2F2R;
Gildas Bazin's avatar
 
Gildas Bazin committed
488
        break;
Gildas Bazin's avatar
 
Gildas Bazin committed
489 490
#if 0 /* Lots of people just get their settings wrong and complain that
       * this is a problem with VLC so just don't ever set mono by default. */
Gildas Bazin's avatar
 
Gildas Bazin committed
491
    case DSSPEAKER_MONO:
Gildas Bazin's avatar
 
Gildas Bazin committed
492
        val.i_int = AOUT_VAR_MONO;
Gildas Bazin's avatar
 
Gildas Bazin committed
493
        break;
Gildas Bazin's avatar
 
Gildas Bazin committed
494
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
495
    case DSSPEAKER_SURROUND:
496
        msg_Dbg( p_aout, "Windows says your SpeakerConfig is surround" );
Gildas Bazin's avatar
 
Gildas Bazin committed
497
    case DSSPEAKER_STEREO:
498
        msg_Dbg( p_aout, "Windows says your SpeakerConfig is stereo" );
Gildas Bazin's avatar
 
Gildas Bazin committed
499
    default:
500
        /* If nothing else is found, choose stereo output */
Gildas Bazin's avatar
 
Gildas Bazin committed
501
        val.i_int = AOUT_VAR_STEREO;
Gildas Bazin's avatar
 
Gildas Bazin committed
502 503
        break;
    }
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534

    /* Check if we want to override speaker config */
    switch( p_aout->output.p_sys->i_speaker_setup )
    {
    case 0: /* Default value aka Windows default speaker setup */
        break;
    case 1: /* Mono */
        msg_Dbg( p_aout, "SpeakerConfig is forced to Mono" );
        val.i_int = AOUT_VAR_MONO;
        break;
    case 2: /* Stereo */
        msg_Dbg( p_aout, "SpeakerConfig is forced to Stereo" );
        val.i_int = AOUT_VAR_STEREO;
        break;
    case 3: /* Quad */
        msg_Dbg( p_aout, "SpeakerConfig is forced to Quad" );
        val.i_int = AOUT_VAR_2F2R;
        break;
    case 4: /* 5.1 */
        msg_Dbg( p_aout, "SpeakerConfig is forced to 5.1" );
        val.i_int = AOUT_VAR_5_1;
        break;
    case 5: /* 7.1 */
        msg_Dbg( p_aout, "SpeakerConfig is forced to 7.1" );
        val.i_int = AOUT_VAR_7_1;
        break;
    default:
        msg_Dbg( p_aout, "SpeakerConfig is forced to non-existing value" );
        break;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
535 536
    var_Set( p_aout, "audio-device", val );

Gildas Bazin's avatar
 
Gildas Bazin committed
537 538 539
    /* Test for SPDIF support */
    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
    {
540
        if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
Gildas Bazin's avatar
 
Gildas Bazin committed
541 542 543
                            p_aout->output.output.i_physical_channels,
                            aout_FormatNbChannels( &p_aout->output.output ),
                            p_aout->output.output.i_rate,
544
                            AOUT_SPDIF_SIZE, true )
Gildas Bazin's avatar
 
Gildas Bazin committed
545 546 547
            == VLC_SUCCESS )
        {
            msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
Gildas Bazin's avatar
 
Gildas Bazin committed
548
            val.i_int = AOUT_VAR_SPDIF;
549
            text.psz_string = _("A/52 over S/PDIF");
Gildas Bazin's avatar
 
Gildas Bazin committed
550 551
            var_Change( p_aout, "audio-device",
                        VLC_VAR_ADDCHOICE, &val, &text );
552
            if( var_InheritBool( p_aout, "spdif" ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
553 554 555 556
                var_Set( p_aout, "audio-device", val );
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
557 558 559 560 561 562 563 564
    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;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
565
    var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
566
    var_TriggerCallback( p_aout, "intf-change" );
Gildas Bazin's avatar
 
Gildas Bazin committed
567 568
}

Gildas Bazin's avatar
 
Gildas Bazin committed
569
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
570 571 572
 * Play: we'll start playing the directsound buffer here because at least here
 *       we know the first buffer has been put in the aout fifo and we also
 *       know its date.
Gildas Bazin's avatar
 
Gildas Bazin committed
573
 *****************************************************************************/
574
static void Play( aout_instance_t *p_aout )
Gildas Bazin's avatar
 
Gildas Bazin committed
575
{
Gildas Bazin's avatar
 
Gildas Bazin committed
576 577 578 579 580 581 582 583 584 585 586
    if( !p_aout->output.p_sys->b_playing )
    {
        aout_buffer_t *p_buffer;

        p_aout->output.p_sys->b_playing = 1;

        /* get the playing date of the first aout buffer */
        p_aout->output.p_sys->p_notif->start_date =
            aout_FifoFirstDate( p_aout, &p_aout->output.fifo );

        /* fill in the first samples */
587
        for( int i = 0; i < FRAMES_NUM; i++ )
588 589 590 591 592
        {
            p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
            if( !p_buffer ) break;
            FillBuffer( p_aout, i, p_buffer );
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
593 594

        /* wake up the audio output thread */
595
        SetEvent( p_aout->output.p_sys->p_notif->event );
Gildas Bazin's avatar
 
Gildas Bazin committed
596
    }
597 598 599 600 601
}

/*****************************************************************************
 * CloseAudio: close the audio device
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
602
static void CloseAudio( vlc_object_t *p_this )
603
{
Gildas Bazin's avatar
 
Gildas Bazin committed
604
    aout_instance_t * p_aout = (aout_instance_t *)p_this;
605
    aout_sys_t *p_sys = p_aout->output.p_sys;
606

607
    msg_Dbg( p_aout, "closing audio device" );
608 609

    /* kill the position notification thread, if any */
610
    if( p_sys->p_notif )
611
    {
612 613 614
        vlc_object_kill( p_sys->p_notif );
        /* wake up the audio thread if needed */
        if( !p_sys->b_playing ) SetEvent( p_sys->p_notif->event );
Gildas Bazin's avatar
 
Gildas Bazin committed
615

616
        vlc_thread_join( p_sys->p_notif );
617
        vlc_object_release( p_sys->p_notif );
618 619 620
    }

    /* release the secondary buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
621
    DestroyDSBuffer( p_aout );
622 623

    /* finally release the DirectSound object */
624
    if( p_sys->p_dsobject ) IDirectSound_Release( p_sys->p_dsobject );
625

626
    /* free DSOUND.DLL */
627
    if( p_sys->hdsound_dll ) FreeLibrary( p_sys->hdsound_dll );
Gildas Bazin's avatar
 
Gildas Bazin committed
628

629
    free( p_aout->output.p_sys->p_device_guid );
630
    free( p_sys );
631 632
}

633 634 635
/*****************************************************************************
 * CallBackDirectSoundEnum: callback to enumerate available devices
 *****************************************************************************/
636 637
static int CALLBACK CallBackDirectSoundEnum( LPGUID p_guid, LPCWSTR psz_desc,
                                             LPCWSTR psz_mod, LPVOID _p_aout )
638
{
639 640
    VLC_UNUSED( psz_mod );

641 642
    aout_instance_t *p_aout = (aout_instance_t *)_p_aout;

643 644
    char *psz_device = FromWide( psz_desc );
    msg_Dbg( p_aout, "found device: %s", psz_device );
645

646 647
    if( p_aout->output.p_sys->psz_device &&
        !strcmp(p_aout->output.p_sys->psz_device, psz_device) && p_guid )
648
    {
649
        /* Use the device corresponding to psz_device */
650 651
        p_aout->output.p_sys->p_device_guid = malloc( sizeof( GUID ) );
        *p_aout->output.p_sys->p_device_guid = *p_guid;
652
        msg_Dbg( p_aout, "using device: %s", psz_device );
653
    }
654 655 656 657 658
    else
    {
        /* If no default device has been selected, chose the first one */
        if( !p_aout->output.p_sys->psz_device && p_guid )
        {
659
            p_aout->output.p_sys->psz_device = strdup( psz_device );
660 661
            p_aout->output.p_sys->p_device_guid = malloc( sizeof( GUID ) );
            *p_aout->output.p_sys->p_device_guid = *p_guid;
662
            msg_Dbg( p_aout, "using device: %s", psz_device );
663 664
        }
    }
665 666

    free( psz_device );
667
    return true;
668 669
}

670
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
671
 * InitDirectSound: handle all the gory details of DirectSound initialisation
672
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
673
static int InitDirectSound( aout_instance_t *p_aout )
674 675
{
    HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
676
    HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKW, LPVOID);
677

Gildas Bazin's avatar
 
Gildas Bazin committed
678 679
    p_aout->output.p_sys->hdsound_dll = LoadLibrary("DSOUND.DLL");
    if( p_aout->output.p_sys->hdsound_dll == NULL )
680
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
681 682
        msg_Warn( p_aout, "cannot open DSOUND.DLL" );
        goto error;
683 684
    }

685 686 687
    OurDirectSoundCreate = (void *)
        GetProcAddress( p_aout->output.p_sys->hdsound_dll,
                        "DirectSoundCreate" );
688 689
    if( OurDirectSoundCreate == NULL )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
690 691
        msg_Warn( p_aout, "GetProcAddress FAILED" );
        goto error;
692 693
    }

694 695 696
    /* Get DirectSoundEnumerate */
    OurDirectSoundEnumerate = (void *)
       GetProcAddress( p_aout->output.p_sys->hdsound_dll,
697
                       "DirectSoundEnumerateW" );
698 699
    if( OurDirectSoundEnumerate )
    {
700
        p_aout->output.p_sys->psz_device = var_InheritString(p_aout, "directx-audio-device-name");
701
        /* Attempt enumeration */
702
        if( FAILED( OurDirectSoundEnumerate( CallBackDirectSoundEnum,
703 704 705 706 707 708
                                             p_aout ) ) )
        {
            msg_Dbg( p_aout, "enumeration of DirectSound devices failed" );
        }
    }

709
    /* Create the direct sound object */
710
    if FAILED( OurDirectSoundCreate( p_aout->output.p_sys->p_device_guid,
711
                                     &p_aout->output.p_sys->p_dsobject,
Gildas Bazin's avatar
 
Gildas Bazin committed
712
                                     NULL ) )
713 714
    {
        msg_Warn( p_aout, "cannot create a direct sound device" );
Gildas Bazin's avatar
 
Gildas Bazin committed
715
        goto error;
716 717 718 719 720 721 722 723 724 725 726 727
    }

    /* 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
     * application will be hearable when it will have the focus.
     * !!! (this is not really working as intended yet because to set the
     * cooperative level you need the window handle of your application, and
     * I don't know of any easy way to get it. Especially since we might play
     * sound without any video, and so what window handle should we use ???
     * The hack for now is to use the Desktop window handle - it seems to be
     * working */
Gildas Bazin's avatar
 
Gildas Bazin committed
728 729 730
    if( IDirectSound_SetCooperativeLevel( p_aout->output.p_sys->p_dsobject,
                                          GetDesktopWindow(),
                                          DSSCL_EXCLUSIVE) )
731 732 733 734
    {
        msg_Warn( p_aout, "cannot set direct sound cooperative level" );
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
735
    return VLC_SUCCESS;
Gildas Bazin's avatar
 
Gildas Bazin committed
736 737 738 739 740 741 742 743

 error:
    p_aout->output.p_sys->p_dsobject = NULL;
    if( p_aout->output.p_sys->hdsound_dll )
    {
        FreeLibrary( p_aout->output.p_sys->hdsound_dll );
        p_aout->output.p_sys->hdsound_dll = NULL;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
744
    return VLC_EGENERIC;
Gildas Bazin's avatar
 
Gildas Bazin committed
745

746 747 748
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
749
 * CreateDSBuffer: Creates a direct sound buffer of the required format.
750 751 752 753 754 755 756 757
 *****************************************************************************
 * This function creates the buffer we'll use to play audio.
 * In DirectSound there are two kinds of buffers:
 * - the primary buffer: which is the actual buffer that the soundcard plays
 * - the secondary buffer(s): these buffers are the one actually used by
 *    applications and DirectSound takes care of mixing them into the primary.
 *
 * Once you create a secondary buffer, you cannot change its format anymore so
Gildas Bazin's avatar
 
Gildas Bazin committed
758
 * you have to release the current one and create another.
759
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
760 761
static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
                           int i_channels, int i_nb_channels, int i_rate,
762
                           int i_bytes_per_frame, bool b_probe )
763
{
Gildas Bazin's avatar
 
Gildas Bazin committed
764
    WAVEFORMATEXTENSIBLE waveformat;
765
    DSBUFFERDESC         dsbdesc;
Gildas Bazin's avatar
 
Gildas Bazin committed
766
    unsigned int         i;
767

Gildas Bazin's avatar
 
Gildas Bazin committed
768 769
    /* First set the sound buffer format */
    waveformat.dwChannelMask = 0;
770
    for( i = 0; i < sizeof(pi_channels_src)/sizeof(uint32_t); i++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
771
    {
772 773
        if( i_channels & pi_channels_src[i] )
            waveformat.dwChannelMask |= pi_channels_in[i];
774
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
775

Gildas Bazin's avatar
 
Gildas Bazin committed
776
    switch( i_format )
Gildas Bazin's avatar
 
Gildas Bazin committed
777
    {
778
    case VLC_CODEC_SPDIFL:
Gildas Bazin's avatar
 
Gildas Bazin committed
779
        i_nb_channels = 2;
Gildas Bazin's avatar
 
Gildas Bazin committed
780 781
        /* To prevent channel re-ordering */
        waveformat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
Gildas Bazin's avatar
 
Gildas Bazin committed
782 783 784 785
        waveformat.Format.wBitsPerSample = 16;
        waveformat.Samples.wValidBitsPerSample =
            waveformat.Format.wBitsPerSample;
        waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
Gildas Bazin's avatar
 
Gildas Bazin committed
786
        waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
Gildas Bazin's avatar
 
Gildas Bazin committed
787
        break;
Gildas Bazin's avatar
 
Gildas Bazin committed
788

789
    case VLC_CODEC_FL32:
Gildas Bazin's avatar
 
Gildas Bazin committed
790 791 792 793
        waveformat.Format.wBitsPerSample = sizeof(float) * 8;
        waveformat.Samples.wValidBitsPerSample =
            waveformat.Format.wBitsPerSample;
        waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
Gildas Bazin's avatar
 
Gildas Bazin committed
794
        waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
Gildas Bazin's avatar
 
Gildas Bazin committed
795 796
        break;

797
    case VLC_CODEC_S16L:
Gildas Bazin's avatar
 
Gildas Bazin committed
798 799 800 801
        waveformat.Format.wBitsPerSample = 16;
        waveformat.Samples.wValidBitsPerSample =
            waveformat.Format.wBitsPerSample;
        waveformat.Format.wFormatTag = WAVE_FORMAT_PCM;
Gildas Bazin's avatar
 
Gildas Bazin committed
802
        waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
Gildas Bazin's avatar
 
Gildas Bazin committed
803 804
        break;
    }
805

Gildas Bazin's avatar
 
Gildas Bazin committed
806 807 808 809 810 811 812
    waveformat.Format.nChannels = i_nb_channels;
    waveformat.Format.nSamplesPerSec = i_rate;
    waveformat.Format.nBlockAlign =
        waveformat.Format.wBitsPerSample / 8 * i_nb_channels;
    waveformat.Format.nAvgBytesPerSec =
        waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;

813 814 815
    p_aout->output.p_sys->i_bits_per_sample = waveformat.Format.wBitsPerSample;
    p_aout->output.p_sys->i_channels = i_nb_channels;

816 817 818 819 820 821
    /* Then fill in the direct sound descriptor */
    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
                    | DSBCAPS_GLOBALFOCUS;      /* Allows background playing */

Gildas Bazin's avatar
 
Gildas Bazin committed
822 823 824 825 826 827 828 829 830 831
    /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
    if( i_nb_channels <= 2 )
    {
        waveformat.Format.cbSize = 0;
    }
    else
    {
        waveformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
        waveformat.Format.cbSize =
            sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
Gildas Bazin's avatar
 
Gildas Bazin committed
832

833 834 835
        /* Needed for 5.1 on emu101k */
        dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
836 837 838 839 840 841 842 843

    dsbdesc.dwBufferBytes = FRAMES_NUM * i_bytes_per_frame;   /* buffer size */
    dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&waveformat;

    if FAILED( IDirectSound_CreateSoundBuffer(
                   p_aout->output.p_sys->p_dsobject, &dsbdesc,
                   &p_aout->output.p_sys->p_dsbuffer, NULL) )
    {
844 845 846 847 848
        if( dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE )
        {
            /* Try without DSBCAPS_LOCHARDWARE */
            dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
            if FAILED( IDirectSound_CreateSoundBuffer(
Gildas Bazin's avatar
 
Gildas Bazin committed
849 850
                   p_aout->output.p_sys->p_dsobject, &dsbdesc,
                   &p_aout->output.p_sys->p_dsbuffer, NULL) )
851 852 853 854 855 856 857
            {
                return VLC_EGENERIC;
            }
            if( !b_probe )
                msg_Dbg( p_aout, "couldn't use hardware sound buffer" );
        }
        else
Gildas Bazin's avatar
 
Gildas Bazin committed
858 859 860
        {
            return VLC_EGENERIC;
        }
861 862
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
863 864 865 866 867 868 869
    /* Stop here if we were just probing */
    if( b_probe )
    {
        IDirectSoundBuffer_Release( p_aout->output.p_sys->p_dsbuffer );
        p_aout->output.p_sys->p_dsbuffer = NULL;
        return VLC_SUCCESS;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
870

871
    p_aout->output.p_sys->i_frame_size = i_bytes_per_frame;
Gildas Bazin's avatar
 
Gildas Bazin committed
872
    p_aout->output.p_sys->i_channel_mask = waveformat.dwChannelMask;
873 874 875 876 877 878 879 880 881
    p_aout->output.p_sys->b_chan_reorder =
        aout_CheckChannelReorder( pi_channels_in, pi_channels_out,
                                  waveformat.dwChannelMask, i_nb_channels,
                                  p_aout->output.p_sys->pi_chan_table );

    if( p_aout->output.p_sys->b_chan_reorder )
    {
        msg_Dbg( p_aout, "channel reordering needed" );
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
882

Gildas Bazin's avatar
 
Gildas Bazin committed
883
    return VLC_SUCCESS;
884 885 886
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
887 888 889 890 891
 * CreateDSBufferPCM: creates a PCM direct sound buffer.
 *****************************************************************************
 * We first try to create a WAVE_FORMAT_IEEE_FLOAT buffer if supported by
 * the hardware, otherwise we create a WAVE_FORMAT_PCM buffer.
 ****************************************************************************/
892
static int CreateDSBufferPCM( aout_instance_t *p_aout, vlc_fourcc_t *i_format,
Gildas Bazin's avatar
 
Gildas Bazin committed
893
                              int i_channels, int i_nb_channels, int i_rate,
894
                              bool b_probe )
Gildas Bazin's avatar
 
Gildas Bazin committed
895
{
Gildas Bazin's avatar
 
Gildas Bazin committed
896
    /* Float32 audio samples are not supported for 5.1 output on the emu101k */
897 898
    if( !var_GetBool( p_aout, "directx-audio-float32" ) ||
        i_nb_channels > 2 ||
899
        CreateDSBuffer( p_aout, VLC_CODEC_FL32,
Gildas Bazin's avatar
 
Gildas Bazin committed
900 901 902 903
                        i_channels, i_nb_channels, i_rate,
                        FRAME_SIZE * 4 * i_nb_channels, b_probe )
        != VLC_SUCCESS )
    {
904
        if ( CreateDSBuffer( p_aout, VLC_CODEC_S16L,
Gildas Bazin's avatar
 
Gildas Bazin committed
905 906 907 908 909 910 911 912
                             i_channels, i_nb_channels, i_rate,
                             FRAME_SIZE * 2 * i_nb_channels, b_probe )
             != VLC_SUCCESS )
        {
            return VLC_EGENERIC;
        }
        else
        {
913
            *i_format = VLC_CODEC_S16L;
Gildas Bazin's avatar
 
Gildas Bazin committed
914 915 916 917 918
            return VLC_SUCCESS;
        }
    }
    else
    {
919
        *i_format = VLC_CODEC_FL32;
Gildas Bazin's avatar
 
Gildas Bazin committed
920 921 922 923 924 925
        return VLC_SUCCESS;
    }
}

/*****************************************************************************
 * DestroyDSBuffer
926
 *****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
927
 * This function destroys the secondary buffer.
928
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
929
static void DestroyDSBuffer( aout_instance_t *p_aout )
930
{
Gildas Bazin's avatar
 
Gildas Bazin committed
931
    if( p_aout->output.p_sys->p_dsbuffer )