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