]> git.sesse.net Git - vlc/blob - plugins/directx/aout_directx.c
61f4728a3bb7f08126d7d79212720a3df9dddd5d
[vlc] / plugins / directx / aout_directx.c
1 /*****************************************************************************
2  * aout_directx.c: Windows DirectX audio output method
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  * $Id: aout_directx.c,v 1.7 2001/07/30 00:53:04 sam Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #define MODULE_NAME directx
25 #include "modules_inner.h"
26
27 /* The most important thing to do for now is to fix the audio bug we've got
28  * on startup: the audio will start later than the video (sometimes) and
29  * is trying to catching up with it.
30  * At first sight it seems to be a scheduling problem
31  */
32
33
34 /*****************************************************************************
35  * Preamble
36  *****************************************************************************/
37 #include "defs.h"
38
39 #include <errno.h>                                                 /* ENOMEM */
40 #include <fcntl.h>                                       /* open(), O_WRONLY */
41 #include <string.h>                                            /* strerror() */
42
43 #ifdef HAVE_UNISTD_H
44 #   include <unistd.h>                                   /* write(), close() */
45 #endif
46
47 #include <stdio.h>                                           /* "intf_msg.h" */
48 #include <stdlib.h>                            /* calloc(), malloc(), free() */
49
50 #include "config.h"
51 #include "common.h"                                     /* boolean_t, byte_t */
52 #include "threads.h"
53 #include "mtime.h"
54 #include "tests.h"
55
56 #if defined( _MSC_VER )
57 #   include <dsound.h>
58 #else
59 #   include "directx.h"
60 #endif
61
62 #include "audio_output.h"                                   /* aout_thread_t */
63
64 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
65 #include "main.h"
66
67 #include "modules.h"
68 #include "modules_export.h"
69
70 /*****************************************************************************
71  * aout_sys_t: directx audio output method descriptor
72  *****************************************************************************
73  * This structure is part of the audio output thread descriptor.
74  * It describes the direct sound specific properties of an audio device.
75  *****************************************************************************/
76
77 typedef struct aout_sys_s
78 {
79     LPDIRECTSOUND       p_dsobject;              /* main Direct Sound object */
80
81     LPDIRECTSOUNDBUFFER p_dsbuffer_primary;     /* the actual sound card buffer
82                                                    (not used directly) */
83
84     LPDIRECTSOUNDBUFFER p_dsbuffer;   /* the sound buffer we use (direct sound
85                                        * takes care of mixing all the
86                                        * secondary buffers into the primary) */
87
88     HINSTANCE           hdsound_dll;      /* handle of the opened dsound dll */
89
90     long l_buffer_size;                       /* secondary sound buffer size */
91     long l_write_position;             /* next write position for the buffer */
92
93     boolean_t b_active;
94
95 } aout_sys_t;
96
97 /*****************************************************************************
98  * Local prototypes.
99  *****************************************************************************/
100 static int     aout_Probe       ( probedata_t *p_data );
101 static int     aout_Open        ( aout_thread_t *p_aout );
102 static int     aout_SetFormat   ( aout_thread_t *p_aout );
103 static long    aout_GetBufInfo  ( aout_thread_t *p_aout, long l_buffer_info );
104 static void    aout_Play        ( aout_thread_t *p_aout,
105                                   byte_t *buffer, int i_size );
106 static void    aout_Close       ( aout_thread_t *p_aout );
107
108 /* local functions */
109 static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout );
110 static int DirectxInitDSound( aout_thread_t *p_aout );
111
112 /*****************************************************************************
113  * Functions exported as capabilities. They are declared as static so that
114  * we don't pollute the namespace too much.
115  *****************************************************************************/
116 void _M( aout_getfunctions )( function_list_t * p_function_list )
117 {
118     p_function_list->pf_probe = aout_Probe;
119     p_function_list->functions.aout.pf_open = aout_Open;
120     p_function_list->functions.aout.pf_setformat = aout_SetFormat;
121     p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
122     p_function_list->functions.aout.pf_play = aout_Play;
123     p_function_list->functions.aout.pf_close = aout_Close;
124 }
125
126 /*****************************************************************************
127  * aout_Probe: probe the audio device and return a score
128  *****************************************************************************
129  * This function tries to probe for a Direct Sound  device and returns a
130  * score to the plugin manager so that it can select the best plugin.
131  *****************************************************************************/
132 static int aout_Probe( probedata_t *p_data )
133 {
134     /* For now just assume the computer has a sound device */
135     if( TestMethod( AOUT_METHOD_VAR, "directx" ) )
136     {
137         return( 999 );
138     }
139     return( 400 );
140 }
141
142 /*****************************************************************************
143  * aout_Open: open the audio device
144  *****************************************************************************
145  * This function opens and setups Direct Sound.
146  *****************************************************************************/
147 static int aout_Open( aout_thread_t *p_aout )
148 {
149     HRESULT dsresult;
150     DSBUFFERDESC dsbuffer_desc;
151     WAVEFORMATEX waveformat;
152
153     intf_WarnMsg( 3, "aout: DirectX aout_Open ");
154
155    /* Allocate structure */
156     p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
157
158     if( p_aout->p_sys == NULL )
159     {
160         intf_ErrMsg( "aout error: %s", strerror(ENOMEM) );
161         return( 1 );
162     }
163
164     /* Initialize some variables */
165     p_aout->p_sys->p_dsobject = NULL;
166     p_aout->p_sys->p_dsbuffer_primary = NULL;
167     p_aout->p_sys->p_dsbuffer = NULL;
168
169     p_aout->psz_device = 0;
170     p_aout->i_format   = AOUT_FORMAT_DEFAULT;
171     p_aout->i_channels = 1 + main_GetIntVariable( AOUT_STEREO_VAR,
172                                                   AOUT_STEREO_DEFAULT );
173     p_aout->l_rate     = main_GetIntVariable( AOUT_RATE_VAR,
174                                               AOUT_RATE_DEFAULT );
175
176     /* Initialise DirectSound */
177     if( DirectxInitDSound( p_aout ) )
178     {
179         intf_WarnMsg( 3, "aout: can't initialise DirectSound ");
180         return( 1 );
181     }
182
183     /* Obtain (not create) Direct Sound primary buffer */
184     memset( &dsbuffer_desc, 0, sizeof(DSBUFFERDESC) );
185     dsbuffer_desc.dwSize = sizeof(DSBUFFERDESC);
186     dsbuffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
187     intf_WarnMsg( 3, "aout: Create direct sound primary buffer ");
188     dsresult = IDirectSound_CreateSoundBuffer(p_aout->p_sys->p_dsobject,
189                                             &dsbuffer_desc,
190                                             &p_aout->p_sys->p_dsbuffer_primary,
191                                             NULL);
192     if( dsresult != DS_OK )
193     {
194         intf_WarnMsg( 3, "aout: can't create direct sound primary buffer ");
195         IDirectSound_Release( p_aout->p_sys->p_dsobject );
196         p_aout->p_sys->p_dsobject = NULL;
197         p_aout->p_sys->p_dsbuffer_primary = NULL;
198         return( 1 );
199     }
200
201     /* Set Direct Sound primary buffer format because the default value set by
202      * Windows is usually not the high quality value */
203     memset(&waveformat, 0, sizeof(WAVEFORMATEX)); 
204     waveformat.wFormatTag = WAVE_FORMAT_PCM; 
205     waveformat.nChannels = 2; 
206     waveformat.nSamplesPerSec = 44100; 
207     waveformat.wBitsPerSample = 16; 
208     waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
209                                  waveformat.nChannels;
210     waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
211                                      waveformat.nBlockAlign;
212
213     dsresult = IDirectSoundBuffer_SetFormat(p_aout->p_sys->p_dsbuffer_primary,
214                                             &waveformat);
215     if( dsresult != DS_OK )
216     {
217         intf_WarnMsg( 3, "aout: can't set primary buffer format");
218     }
219
220 #if 0
221     /* ensure the primary buffer is playing. We won't actually hear anything
222      * until the secondary buffer is playing */
223     dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer_primary,
224                                         0,
225                                         0,
226                                         DSBPLAY_LOOPING);
227     if( dsresult != DS_OK )
228     {
229         intf_WarnMsg( 3, "aout: can't play direct sound primary buffer ");
230         IDirectSound_Release( p_aout->p_sys->p_dsbuffer_primary );
231         IDirectSound_Release( p_aout->p_sys->p_dsobject );
232         p_aout->p_sys->p_dsobject = NULL;
233         p_aout->p_sys->p_dsbuffer_primary = NULL;
234         return( 1 );
235     }
236 #endif
237
238     return( 0 );
239 }
240
241 /*****************************************************************************
242  * aout_SetFormat: reset the audio device and sets its format
243  *****************************************************************************
244  * This functions set a new audio format.
245  * For this we need to close the current secondary buffer and create another
246  * one with the desired format.
247  *****************************************************************************/
248 static int aout_SetFormat( aout_thread_t *p_aout )
249 {
250     HRESULT dsresult;
251
252     intf_WarnMsg( 3, "aout: DirectX aout_SetFormat ");
253
254     /* first release the current secondary buffer */
255     if( p_aout->p_sys->p_dsbuffer != NULL )
256     {
257         IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
258         p_aout->p_sys->p_dsbuffer = NULL;
259     }
260
261     /* then create a new secondary buffer */
262     dsresult = DirectxCreateSecondaryBuffer( p_aout );    
263     if( dsresult != DS_OK )
264     {
265         intf_WarnMsg( 3, "aout: DirectX aout_SetFormat cannot create buffer");
266         return( 1 );
267     }
268
269     p_aout->i_latency = 0;
270   
271     return( 0 );
272 }
273
274 /*****************************************************************************
275  * aout_GetBufInfo: buffer status query
276  *****************************************************************************
277  * returns the number of bytes in the audio buffer compared to the size of
278  * l_buffer_limit...
279  *****************************************************************************/
280 static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
281 {
282     long l_play_position, l_notused, l_result;
283     HRESULT dsresult;
284
285     dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
286                                                  &l_play_position, &l_notused);
287     if( dsresult == DSERR_BUFFERLOST )
288     {
289         IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
290         dsresult = IDirectSoundBuffer_GetCurrentPosition(
291                                                  p_aout->p_sys->p_dsbuffer,
292                                                  &l_play_position, &l_notused
293                                                         );
294     }
295     if( dsresult != DS_OK )
296     {
297         intf_WarnMsg(3,"aout: DirectX aout_GetBufInfo cannot get current pos");
298         return( l_buffer_limit );
299     }
300
301 #if 0
302     /* temporary hack. When you start playing a new file, the play position
303      * doesn't start changing immediatly, even though sound is already
304      * playing from the sound card */
305     if( l_play_position == 0 )
306     { 
307        intf_WarnMsg( 5, "aout: DirectX aout_GetBufInfo: %li", l_buffer_limit);
308        return( l_buffer_limit );
309     }
310 #endif
311
312     l_result = (p_aout->p_sys->l_write_position >= l_play_position) ?
313       (p_aout->p_sys->l_write_position - l_play_position) /2
314                : (p_aout->p_sys->l_buffer_size - l_play_position
315                   + p_aout->p_sys->l_write_position) /2 ;
316
317 #if 0
318     intf_WarnMsg( 5, "aout: DirectX aout_GetBufInfo: %li", l_result);
319 #endif
320     return l_result;
321 }
322
323 /*****************************************************************************
324  * aout_Play: play a sound buffer
325  *****************************************************************************
326  * This function writes a buffer of i_length bytes
327  *****************************************************************************/
328 static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
329 {
330     VOID            *p_write_position, *p_start_buffer;
331     long            l_bytes1, l_bytes2;
332     long            l_play_position, l_notused, l_buffer_free_length;
333     HRESULT         dsresult;
334
335     /* We want to copy data to the circular sound buffer, so we first need to
336      * find out were in the buffer we can write our data */
337     dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
338                                                      &l_play_position,
339                                                      &l_notused);
340     if( dsresult == DSERR_BUFFERLOST )
341     {
342         IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
343         dsresult = IDirectSoundBuffer_GetCurrentPosition(
344                                                  p_aout->p_sys->p_dsbuffer,
345                                                  &l_play_position, &l_notused
346                                                         );
347     }
348     if( dsresult != DS_OK )
349     {
350         intf_WarnMsg( 3, "aout: DirectX aout_Play can'get buffer position");
351     }
352
353 #if 1
354     /* check that we are not overflowing the circular buffer (everything should
355      * be alright but just in case) */
356     l_buffer_free_length =  l_play_position - p_aout->p_sys->l_write_position;
357     if( l_buffer_free_length <= 0 )
358         l_buffer_free_length += p_aout->p_sys->l_buffer_size;
359
360     if( i_size > l_buffer_free_length )
361     {
362         intf_WarnMsg( 3, "aout: DirectX aout_Play buffer overflow: size %i, free %i !!!", i_size, l_buffer_free_length);
363         intf_WarnMsg( 3, "aout: DirectX aout_Play buffer overflow: writepos %i, readpos %i !!!", p_aout->p_sys->l_write_position, l_play_position);
364         /*i_size = l_buffer_free_length;*/
365
366         /* Update the write pointer */
367         p_aout->p_sys->l_write_position = l_notused;
368
369     }
370     else
371     {
372 #if 0
373         intf_WarnMsg( 4, "aout: DirectX aout_Play buffer: size %i, free %i !!!"
374                       , i_size, l_buffer_free_length);
375         intf_WarnMsg( 4, "aout: DirectX aout_Play buffer: writepos %i, readpos %i !!!", p_aout->p_sys->l_write_position, l_play_position);
376 #endif
377     }
378 #endif
379
380     /* Before copying anything, we have to lock the buffer */
381     dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
382                    p_aout->p_sys->l_write_position,  /* Offset of lock start */
383                    i_size,                        /* Number of bytes to lock */
384                    &p_write_position,               /* Address of lock start */
385                    &l_bytes1,    /* Count of bytes locked before wrap around */
386                    &p_start_buffer,        /* Buffer adress (if wrap around) */
387                    &l_bytes2,            /* Count of bytes after wrap around */
388                    0);                                              /* Flags */
389     if( dsresult == DSERR_BUFFERLOST )
390     {
391         IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
392         dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
393                                             p_aout->p_sys->l_write_position,
394                                             i_size,
395                                             &p_write_position,
396                                             &l_bytes1,
397                                             &p_start_buffer,
398                                             &l_bytes2,
399                                             0);
400
401     }
402     if( dsresult != DS_OK )
403     {
404         intf_WarnMsg( 3, "aout: DirectX aout_Play can't lock buffer");
405         return;
406     }
407
408     /* Now do the actual memcopy (two memcpy because the buffer is circular) */
409     memcpy( p_write_position, buffer, l_bytes1 );
410     if( p_start_buffer != NULL )
411     {
412         memcpy( p_start_buffer, buffer + l_bytes1, l_bytes2 );
413     }
414
415     /* Now the data has been copied, unlock the buffer */
416     IDirectSoundBuffer_Unlock( p_aout->p_sys->p_dsbuffer, 
417             p_write_position, l_bytes1, p_start_buffer, l_bytes2 );
418
419     /* Update the write position index of the buffer*/
420     p_aout->p_sys->l_write_position += i_size;
421     p_aout->p_sys->l_write_position %= p_aout->p_sys->l_buffer_size;
422
423     /* The play function has no effect if the buffer is already playing */
424     dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
425                                         0,                         /* Unused */
426                                         0,                         /* Unused */
427                                         DSBPLAY_LOOPING );          /* Flags */
428     if( dsresult == DSERR_BUFFERLOST )
429     {
430         IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
431         dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
432                                             0,                     /* Unused */
433                                             0,                     /* Unused */
434                                             DSBPLAY_LOOPING );      /* Flags */
435     }
436     if( dsresult != DS_OK )
437     {
438         intf_WarnMsg( 3, "aout: DirectX aout_Play can't play buffer");
439         return;
440     }
441
442 }
443
444 /*****************************************************************************
445  * aout_Close: close the audio device
446  *****************************************************************************/
447 static void aout_Close( aout_thread_t *p_aout )
448 {
449
450     intf_WarnMsg( 3, "aout: DirectX aout_Close ");
451
452     /* make sure the buffer isn't playing */
453     if( p_aout->p_sys->p_dsbuffer != NULL )
454     {
455         IDirectSoundBuffer_Stop( p_aout->p_sys->p_dsbuffer );
456     }
457
458     /* first release the secondary buffer */
459     if( p_aout->p_sys->p_dsbuffer != NULL )
460     {
461         IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
462         p_aout->p_sys->p_dsbuffer = NULL;
463     }  
464
465     /* then release the primary buffer */
466     if( p_aout->p_sys->p_dsbuffer_primary != NULL )
467     {
468         IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer_primary );
469         p_aout->p_sys->p_dsbuffer_primary = NULL;
470     }  
471
472     /* finally release the DirectSound object */
473     if( p_aout->p_sys->p_dsobject != NULL )
474     {
475         IDirectSound_Release( p_aout->p_sys->p_dsobject );
476         p_aout->p_sys->p_dsobject = NULL;
477     }  
478     
479     /* free DSOUND.DLL */
480     if( p_aout->p_sys->hdsound_dll != NULL )
481     {
482        FreeLibrary( p_aout->p_sys->hdsound_dll );
483        p_aout->p_sys->hdsound_dll = NULL;
484     }
485
486     /* Close the Output. */
487     if ( p_aout->p_sys != NULL )
488     { 
489         free( p_aout->p_sys );
490         p_aout->p_sys = NULL;
491     }
492 }
493
494 /*****************************************************************************
495  * DirectxInitDSound
496  *****************************************************************************
497  *****************************************************************************/
498 static int DirectxInitDSound( aout_thread_t *p_aout )
499 {
500     HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
501
502     p_aout->p_sys->hdsound_dll = LoadLibrary("DSOUND.DLL");
503     if( p_aout->p_sys->hdsound_dll == NULL )
504     {
505       intf_WarnMsg( 3, "aout: can't open DSOUND.DLL ");
506       return( 1 );
507     }
508
509     OurDirectSoundCreate = (void *)GetProcAddress( p_aout->p_sys->hdsound_dll,
510                                                    "DirectSoundCreate" );
511
512     if( OurDirectSoundCreate == NULL )
513     {
514       intf_WarnMsg( 3, "aout: GetProcAddress FAILED ");
515       FreeLibrary( p_aout->p_sys->hdsound_dll );
516       p_aout->p_sys->hdsound_dll = NULL;
517       return( 1 );
518     }
519
520     /* Create the direct sound object */
521     if( OurDirectSoundCreate(NULL, &p_aout->p_sys->p_dsobject, NULL) != DS_OK )
522     {
523         intf_WarnMsg( 3, "aout: can't create a direct sound device ");
524         p_aout->p_sys->p_dsobject = NULL;
525         FreeLibrary( p_aout->p_sys->hdsound_dll );
526         p_aout->p_sys->hdsound_dll = NULL;
527         return( 1 );
528     }
529
530     /* Set DirectSound Cooperative level, ie what control we want over Windows
531      * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
532      * settings of the primary buffer, but also that only the sound of our
533      * application will be hearable when it will have the focus.
534      * !!! (this is not really working as intended yet because to set the
535      * cooperative level you need the window handle of your application, and
536      * I don't know of any easy way to get it. Especially since we might play
537      * sound without any video, and so what window handle should we use ???
538      * The hack for now is to use the Desktop window handle - it seems to be
539      * working */
540     if( IDirectSound_SetCooperativeLevel(p_aout->p_sys->p_dsobject,
541                                          GetDesktopWindow(),
542                                          DSSCL_EXCLUSIVE) )
543     {
544         intf_WarnMsg( 3, "aout: can't set direct sound cooperative level ");
545     }
546
547     return( 0 );
548 }
549
550 /*****************************************************************************
551  * DirectxCreateSecondaryBuffer
552  *****************************************************************************
553  * This function creates the buffer we'll use to play audio.
554  * In DirectSound there are two kinds of buffers:
555  * - the primary buffer: which is the actual buffer that the soundcard plays
556  * - the secondary buffer(s): these buffers are the one actually used by
557  *    applications and DirectSound takes care of mixing them into the primary.
558  *
559  * Once you create a secondary buffer, you cannot change its format anymore so
560  * you have to release the current and create another one.
561  *****************************************************************************/
562 static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
563 {
564     WAVEFORMATEX waveformat;
565     DSBUFFERDESC dsbdesc;
566     DSBCAPS      dsbcaps;
567
568     /* First set the buffer format */
569     memset(&waveformat, 0, sizeof(WAVEFORMATEX)); 
570     waveformat.wFormatTag = WAVE_FORMAT_PCM; 
571     waveformat.nChannels = p_aout->i_channels; 
572     waveformat.nSamplesPerSec = p_aout->l_rate; 
573     waveformat.wBitsPerSample = 16; 
574     waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
575                                  waveformat.nChannels;
576     waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
577                                      waveformat.nBlockAlign;
578
579     /* Then fill in the descriptor */
580     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); 
581     dsbdesc.dwSize = sizeof(DSBUFFERDESC); 
582     dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
583                     | DSBCAPS_GLOBALFOCUS;      /* Allows background playing */
584     dsbdesc.dwBufferBytes = waveformat.nAvgBytesPerSec * 2;  /* 2 sec buffer */
585     dsbdesc.lpwfxFormat = &waveformat; 
586  
587     if( IDirectSound_CreateSoundBuffer( p_aout->p_sys->p_dsobject,
588                                         &dsbdesc,
589                                         &p_aout->p_sys->p_dsbuffer,
590                                         NULL) != DS_OK )
591     {
592         intf_WarnMsg( 3, "aout: can't create direct sound secondary buffer ");
593         p_aout->p_sys->p_dsbuffer = NULL;
594         return( 1 );
595     }
596
597     /* backup the size of the secondary sound buffer */
598     memset(&dsbcaps, 0, sizeof(DSBCAPS)); 
599     dsbcaps.dwSize = sizeof(DSBCAPS);
600     IDirectSoundBuffer_GetCaps( p_aout->p_sys->p_dsbuffer, &dsbcaps  );
601     p_aout->p_sys->l_buffer_size = dsbcaps.dwBufferBytes;
602     p_aout->p_sys->l_write_position = 0;
603     intf_WarnMsg( 3, "aout: DirectX DirectxCreateSecondaryBuffer: %li",
604                   p_aout->p_sys->l_buffer_size);
605
606     return( 0 );
607 }