Get and print the DirectSound primary buffer volume.
[wine] / dlls / dsound / tests / dsound.c
1 /*
2  * Tests basic sound playback in DirectSound.
3  * In particular we test each standard Windows sound format to make sure
4  * we handle the sound card/driver quirks correctly.
5  *
6  * Part of this test involves playing test tones. But this only makes
7  * sense if someone is going to carefully listen to it, and would only
8  * bother everyone else.
9  * So this is only done if the test is being run in interactive mode.
10  *
11  * Copyright (c) 2002-2004 Francois Gouget
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
30 #include <windows.h>
31
32 #include <math.h>
33 #include <stdlib.h>
34
35 #include "wine/test.h"
36 #include "windef.h"
37 #include "wingdi.h"
38 #include "dsound.h"
39 #include "dxerr9.h"
40
41 #include "dsound_test.h"
42
43 static void dsound_dsound_tests()
44 {
45     HRESULT rc;
46     LPDIRECTSOUND dso=NULL;
47     DSCAPS dscaps;
48     int ref;
49     IUnknown * unknown;
50     IDirectSound * ds;
51     IDirectSound8 * ds8;
52
53     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void**)&dso);
54     ok(rc==S_OK,"CoCreateInstance failed: %s\n",DXGetErrorString9(rc));
55     if (dso) {
56         /* Try to Query for objects */
57         rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
58         ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
59         if (rc==DS_OK)
60             IDirectSound_Release(unknown);
61
62         rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
63         ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
64         if (rc==DS_OK)
65             IDirectSound_Release(ds);
66
67         rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
68         ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) should have failed: %s\n",DXGetErrorString9(rc));
69         if (rc==DS_OK)
70             IDirectSound8_Release(ds8);
71
72         rc=IDirectSound_Initialize(dso,NULL);
73         ok(rc==DS_OK,"IDirectSound_Initialize(NULL) failed: %s\n",DXGetErrorString9(rc));
74
75         /* DSOUND: Error: Invalid caps buffer */
76         rc=IDirectSound_GetCaps(dso,0);
77         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
78
79         ZeroMemory(&dscaps, sizeof(dscaps));
80
81         /* DSOUND: Error: Invalid caps buffer */
82         rc=IDirectSound_GetCaps(dso,&dscaps);
83         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
84
85         dscaps.dwSize=sizeof(dscaps);
86
87         /* DSOUND: Running on a certified driver */
88         rc=IDirectSound_GetCaps(dso,&dscaps);
89         ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
90         if (rc==DS_OK) {
91             trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
92                   dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
93                   dscaps.dwMaxSecondarySampleRate);
94         }
95
96         ref=IDirectSound_Release(dso);
97         ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
98     }
99
100     rc=DirectSoundCreate(NULL,&dso,NULL);
101     ok(rc==S_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
102     if (dso) {
103         /* Try to Query for objects */
104         rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
105         ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
106         if (rc==DS_OK)
107             IDirectSound_Release(unknown);
108
109         rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
110         ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
111         if (rc==DS_OK)
112             IDirectSound_Release(ds);
113
114         rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
115         ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) should have failed: %s\n",DXGetErrorString9(rc));
116         if (rc==DS_OK)
117             IDirectSound8_Release(ds8);
118
119         /* DSOUND: Error: Invalid caps buffer */
120         rc=IDirectSound_GetCaps(dso,0);
121         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
122
123         ZeroMemory(&dscaps, sizeof(dscaps));
124
125         /* DSOUND: Error: Invalid caps buffer */
126         rc=IDirectSound_GetCaps(dso,&dscaps);
127         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
128
129         dscaps.dwSize=sizeof(dscaps);
130
131         /* DSOUND: Running on a certified driver */
132         rc=IDirectSound_GetCaps(dso,&dscaps);
133         ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
134         if (rc==DS_OK) {
135             trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
136                   dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
137                   dscaps.dwMaxSecondarySampleRate);
138         }
139
140         ref=IDirectSound_Release(dso);
141         ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
142     }
143 }
144
145 static void dsound_dsound8_tests()
146 {
147     HRESULT rc;
148     LPDIRECTSOUND8 dso=NULL;
149     DSCAPS dscaps;
150     int ref;
151     IUnknown * unknown;
152     IDirectSound * ds;
153     IDirectSound8 * ds8;
154
155     rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound8, (void**)&dso);
156     ok(rc==S_OK,"CoCreateInstance failed: %s\n",DXGetErrorString9(rc));
157     if (dso) {
158         /* Try to Query for objects */
159         rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
160         ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
161         if (rc==DS_OK)
162             IDirectSound8_Release(unknown);
163
164         rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
165         ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
166         if (rc==DS_OK)
167             IDirectSound_Release(ds);
168
169         rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
170         ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) should have failed: %s\n",DXGetErrorString9(rc));
171         if (rc==DS_OK)
172             IDirectSound8_Release(ds8);
173
174         rc=IDirectSound8_Initialize(dso,NULL);
175         ok(rc==DS_OK,"IDirectSound_Initialize(NULL) failed: %s\n",DXGetErrorString9(rc));
176
177         /* DSOUND: Error: Invalid caps buffer */
178         rc=IDirectSound8_GetCaps(dso,0);
179         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
180
181         ZeroMemory(&dscaps, sizeof(dscaps));
182
183         /* DSOUND: Error: Invalid caps buffer */
184         rc=IDirectSound8_GetCaps(dso,&dscaps);
185         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
186
187         dscaps.dwSize=sizeof(dscaps);
188
189         /* DSOUND: Running on a certified driver */
190         rc=IDirectSound8_GetCaps(dso,&dscaps);
191         ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
192         if (rc==DS_OK) {
193             trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
194                   dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
195                   dscaps.dwMaxSecondarySampleRate);
196         }
197
198         ref=IDirectSound8_Release(dso);
199         ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
200     }
201
202     rc=DirectSoundCreate8(NULL,&dso,NULL);
203     ok(rc==S_OK,"DirectSoundCreate8 failed: %s\n",DXGetErrorString9(rc));
204     if (dso) {
205         /* Try to Query for objects */
206         rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
207         ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
208         if (rc==DS_OK)
209             IDirectSound8_Release(unknown);
210
211         rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
212         ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
213         if (rc==DS_OK)
214             IDirectSound_Release(ds);
215
216         rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
217         ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) should have failed: %s\n",DXGetErrorString9(rc));
218         if (rc==DS_OK)
219             IDirectSound8_Release(ds8);
220
221         /* DSOUND: Error: Invalid caps buffer */
222         rc=IDirectSound8_GetCaps(dso,0);
223         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
224
225         ZeroMemory(&dscaps, sizeof(dscaps));
226
227         /* DSOUND: Error: Invalid caps buffer */
228         rc=IDirectSound8_GetCaps(dso,&dscaps);
229         ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
230
231         dscaps.dwSize=sizeof(dscaps);
232
233         /* DSOUND: Running on a certified driver */
234         rc=IDirectSound8_GetCaps(dso,&dscaps);
235         ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
236         if (rc==DS_OK) {
237             trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
238                   dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
239                   dscaps.dwMaxSecondarySampleRate);
240         }
241
242         ref=IDirectSound8_Release(dso);
243         ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
244     }
245 }
246
247 static HRESULT test_dsound(LPGUID lpGuid)
248 {
249     HRESULT rc;
250     LPDIRECTSOUND dso=NULL;
251     DSCAPS dscaps;
252     int ref;
253     IUnknown * unknown;
254     IDirectSound * ds;
255     IDirectSound8 * ds8;
256
257     /* DSOUND: Error: Invalid interface buffer */
258     rc=DirectSoundCreate(lpGuid,0,NULL);
259     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate should have failed: %s\n",DXGetErrorString9(rc));
260
261     /* Create the DirectSound object */
262     rc=DirectSoundCreate(lpGuid,&dso,NULL);
263     ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
264     if (rc!=DS_OK)
265         return rc;
266
267     /* Try to Query for objects */
268     rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
269     ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
270     if (rc==DS_OK)
271         IDirectSound_Release(unknown);
272
273     rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
274     ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
275     if (rc==DS_OK)
276         IDirectSound_Release(ds);
277
278     rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
279     ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) should have failed: %s\n",DXGetErrorString9(rc));
280     if (rc==DS_OK)
281         IDirectSound8_Release(ds8);
282
283     /* DSOUND: Error: Invalid caps buffer */
284     rc=IDirectSound_GetCaps(dso,0);
285     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
286
287     ZeroMemory(&dscaps, sizeof(dscaps));
288
289     /* DSOUND: Error: Invalid caps buffer */
290     rc=IDirectSound_GetCaps(dso,&dscaps);
291     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
292
293     dscaps.dwSize=sizeof(dscaps);
294
295     /* DSOUND: Running on a certified driver */
296     rc=IDirectSound_GetCaps(dso,&dscaps);
297     ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
298     if (rc==DS_OK) {
299         trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
300               dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
301               dscaps.dwMaxSecondarySampleRate);
302     }
303
304     /* Release the DirectSound object */
305     ref=IDirectSound_Release(dso);
306     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
307     if (ref!=0)
308         return DSERR_GENERIC;
309
310     /* Create a DirectSound object */
311     rc=DirectSoundCreate(lpGuid,&dso,NULL);
312     ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
313     if (rc==DS_OK) {
314         LPDIRECTSOUND dso1=NULL;
315
316         /* Create a second DirectSound object */
317         rc=DirectSoundCreate(lpGuid,&dso1,NULL);
318         ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
319         if (rc==DS_OK) {
320             /* Release the second DirectSound object */
321             ref=IDirectSound_Release(dso1);
322             ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
323             ok(dso!=dso1,"DirectSound objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
324         }
325
326         /* Release the first DirectSound object */
327         ref=IDirectSound_Release(dso);
328         ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
329         if (ref!=0)
330             return DSERR_GENERIC;
331     } else
332         return rc;
333
334     /* Create a DirectSound object */
335     rc=DirectSoundCreate(lpGuid,&dso,NULL);
336     ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
337     if (rc==DS_OK) {
338         LPDIRECTSOUNDBUFFER secondary;
339         DSBUFFERDESC bufdesc;
340         WAVEFORMATEX wfx;
341
342         init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
343         ZeroMemory(&bufdesc, sizeof(bufdesc));
344         bufdesc.dwSize=sizeof(bufdesc);
345         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
346         bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
347         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
348         bufdesc.lpwfxFormat=&wfx;
349         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
350         ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n", rc);
351         if (rc==DS_OK && secondary!=NULL) {
352             LPDIRECTSOUND3DBUFFER buffer3d;
353             rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer, (void **)&buffer3d);
354             ok(rc==DS_OK && buffer3d!=NULL,"QueryInterface failed:  %s\n",DXGetErrorString9(rc));
355             /* add some more refs */
356             IDirectSound3DBuffer_AddRef(buffer3d);
357             IDirectSoundBuffer_AddRef(secondary);
358         }
359         /* release with buffer */
360         ref=IDirectSound_Release(dso);
361         ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
362         if (ref!=0)
363             return DSERR_GENERIC;
364     } else
365         return rc;
366
367     return DS_OK;
368 }
369
370 static HRESULT test_dsound8(LPGUID lpGuid)
371 {
372     HRESULT rc;
373     LPDIRECTSOUND8 dso=NULL;
374     DSCAPS dscaps;
375     int ref;
376     IUnknown * unknown;
377     IDirectSound * ds;
378     IDirectSound8 * ds8;
379
380     /* DSOUND: Error: Invalid interface buffer */
381     rc=DirectSoundCreate8(lpGuid,0,NULL);
382     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate8 should have failed: %s\n",DXGetErrorString9(rc));
383
384     /* Create the DirectSound8 object */
385     rc=DirectSoundCreate8(lpGuid,&dso,NULL);
386     ok(rc==DS_OK,"DirectSoundCreate8 failed: %s\n",DXGetErrorString9(rc));
387     if (rc!=DS_OK)
388         return rc;
389
390     /* Try to Query for objects */
391     rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
392     ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
393     if (rc==DS_OK)
394         IDirectSound8_Release(unknown);
395
396     rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
397     ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
398     if (rc==DS_OK)
399         IDirectSound_Release(ds);
400
401     rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
402     ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) failed: %s\n",DXGetErrorString9(rc));
403     if (rc==DS_OK)
404         IDirectSound8_Release(ds8);
405
406     /* DSOUND: Error: Invalid caps buffer */
407     rc=IDirectSound8_GetCaps(dso,0);
408     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
409
410     ZeroMemory(&dscaps, sizeof(dscaps));
411
412     /* DSOUND: Error: Invalid caps buffer */
413     rc=IDirectSound8_GetCaps(dso,&dscaps);
414     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
415
416     dscaps.dwSize=sizeof(dscaps);
417
418     /* DSOUND: Running on a certified driver */
419     rc=IDirectSound8_GetCaps(dso,&dscaps);
420     ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
421     if (rc==DS_OK) {
422         trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
423               dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
424               dscaps.dwMaxSecondarySampleRate);
425     }
426
427     /* Release the DirectSound8 object */
428     ref=IDirectSound8_Release(dso);
429     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
430     if (ref!=0)
431         return DSERR_GENERIC;
432
433     /* Create a DirectSound8 object */
434     rc=DirectSoundCreate8(lpGuid,&dso,NULL);
435     ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
436     if (rc==DS_OK) {
437         LPDIRECTSOUND8 dso1=NULL;
438
439         /* Create a second DirectSound8 object */
440         rc=DirectSoundCreate8(lpGuid,&dso1,NULL);
441         ok(rc==DS_OK,"DirectSoundCreate8 failed: %s\n",DXGetErrorString9(rc));
442         if (rc==DS_OK) {
443             /* Release the second DirectSound8 object */
444             ref=IDirectSound8_Release(dso1);
445             ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
446             ok(dso!=dso1,"DirectSound8 objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
447         }
448
449         /* Release the first DirectSound8 object */
450         ref=IDirectSound8_Release(dso);
451         ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
452         if (ref!=0)
453             return DSERR_GENERIC;
454     } else
455         return rc;
456
457     /* Create a DirectSound8 object */
458     rc=DirectSoundCreate8(lpGuid,&dso,NULL);
459     ok(rc==DS_OK,"DirectSoundCreate8 failed: %s\n",DXGetErrorString9(rc));
460     if (rc==DS_OK) {
461         LPDIRECTSOUNDBUFFER secondary;
462         DSBUFFERDESC bufdesc;
463         WAVEFORMATEX wfx;
464
465         init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
466         ZeroMemory(&bufdesc, sizeof(bufdesc));
467         bufdesc.dwSize=sizeof(bufdesc);
468         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
469         bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
470         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
471         bufdesc.lpwfxFormat=&wfx;
472         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
473         ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n", rc);
474         if (rc==DS_OK && secondary!=NULL) {
475             LPDIRECTSOUND3DBUFFER buffer3d;
476             rc=IDirectSound8_QueryInterface(secondary, &IID_IDirectSound3DBuffer, (void **)&buffer3d);
477             ok(rc==DS_OK && buffer3d!=NULL,"QueryInterface failed:  %s\n",DXGetErrorString9(rc));
478             /* add some more refs */
479             IDirectSound3DBuffer_AddRef(buffer3d);
480             IDirectSoundBuffer8_AddRef(secondary);
481         }
482         /* release with buffer */
483         ref=IDirectSound8_Release(dso);
484         ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
485         if (ref!=0)
486             return DSERR_GENERIC;
487     } else
488         return rc;
489
490     return DS_OK;
491 }
492
493 static HRESULT test_primary(LPGUID lpGuid)
494 {
495     HRESULT rc;
496     LPDIRECTSOUND dso=NULL;
497     LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
498     DSBUFFERDESC bufdesc;
499     DSCAPS dscaps;
500     int ref;
501
502     /* Create the DirectSound object */
503     rc=DirectSoundCreate(lpGuid,&dso,NULL);
504     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
505     if (rc!=DS_OK)
506         return rc;
507
508     /* Get the device capabilities */
509     ZeroMemory(&dscaps, sizeof(dscaps));
510     dscaps.dwSize=sizeof(dscaps);
511     rc=IDirectSound_GetCaps(dso,&dscaps);
512     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
513     if (rc!=DS_OK)
514         goto EXIT;
515
516     /* DSOUND: Error: Invalid buffer description pointer */
517     rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
518     ok(rc==DSERR_INVALIDPARAM,"CreateSoundBuffer should have failed: 0x%lx\n",rc);
519
520     /* DSOUND: Error: Invalid buffer description pointer */
521     rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
522     ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
523
524     /* DSOUND: Error: Invalid buffer description pointer */
525     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
526     ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
527
528     ZeroMemory(&bufdesc, sizeof(bufdesc));
529
530     /* DSOUND: Error: Invalid size */
531     /* DSOUND: Error: Invalid buffer description */
532     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
533     ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,primary=0x%lx\n",rc,(DWORD)primary);
534
535     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
536     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
537     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
538     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
539     if (rc!=DS_OK)
540         goto EXIT;
541
542     /* Testing the primary buffer */
543     primary=NULL;
544     ZeroMemory(&bufdesc, sizeof(bufdesc));
545     bufdesc.dwSize=sizeof(bufdesc);
546     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
547     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
548     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
549     if (rc==DS_OK && primary!=NULL) {
550         LONG vol;
551
552         /* Try to create a second primary buffer */
553         /* DSOUND: Error: The primary buffer already exists.  Any changes made to the buffer description will be ignored. */
554         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
555         ok(rc==DS_OK && second==primary,"CreateSoundBuffer should have returned original primary buffer: 0x%lx\n",rc);
556         ref=IDirectSoundBuffer_Release(second);
557         ok(ref==1,"IDirectSoundBuffer_Release primary has %d references, should have 1\n",ref);
558
559         /* Try to duplicate a primary buffer */
560         /* DSOUND: Error: Can't duplicate primary buffers */
561         rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
562         /* rc=0x88780032 */
563         ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc);
564
565         rc=IDirectSoundBuffer_GetVolume(primary,&vol);
566         ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
567
568         if (winetest_interactive)
569         {
570             trace("Playing a 5 seconds reference tone at the current volume.\n");
571             if (rc==DS_OK)
572                 trace("(the current volume is %ld according to DirectSound)\n",vol);
573             trace("All subsequent tones should be identical to this one.\n");
574             trace("Listen for stutter, changes in pitch, volume, etc.\n");
575         }
576         test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
577
578         ref=IDirectSoundBuffer_Release(primary);
579         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
580     }
581
582     /* Set the CooperativeLevel back to normal */
583     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
584     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
585     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
586
587 EXIT:
588     ref=IDirectSound_Release(dso);
589     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
590     if (ref!=0)
591         return DSERR_GENERIC;
592
593     return rc;
594 }
595
596 static HRESULT test_secondary(LPGUID lpGuid)
597 {
598     HRESULT rc;
599     LPDIRECTSOUND dso=NULL;
600     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
601     DSBUFFERDESC bufdesc;
602     DSCAPS dscaps;
603     WAVEFORMATEX wfx;
604     int f,ref;
605
606     /* Create the DirectSound object */
607     rc=DirectSoundCreate(lpGuid,&dso,NULL);
608     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
609     if (rc!=DS_OK)
610         return rc;
611
612     /* Get the device capabilities */
613     ZeroMemory(&dscaps, sizeof(dscaps));
614     dscaps.dwSize=sizeof(dscaps);
615     rc=IDirectSound_GetCaps(dso,&dscaps);
616     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
617     if (rc!=DS_OK)
618         goto EXIT;
619
620     /* We must call SetCooperativeLevel before creating primary buffer */
621     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
622     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
623     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
624     if (rc!=DS_OK)
625         goto EXIT;
626
627     ZeroMemory(&bufdesc, sizeof(bufdesc));
628     bufdesc.dwSize=sizeof(bufdesc);
629     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
630     bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
631     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
632     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer 0x%lx\n", rc);
633
634     if (rc==DS_OK && primary!=NULL) {
635         for (f=0;f<NB_FORMATS;f++) {
636             init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],formats[f][2]);
637             secondary=NULL;
638             ZeroMemory(&bufdesc, sizeof(bufdesc));
639             bufdesc.dwSize=sizeof(bufdesc);
640             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
641             bufdesc.dwFlags|=(DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
642             bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
643             bufdesc.lpwfxFormat=&wfx;
644             trace("  Testing a secondary buffer at %ldx%dx%d\n",
645                   wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
646             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
647             ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n",rc);
648
649             if (rc==DS_OK && secondary!=NULL) {
650                 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,1.0,0,NULL,0,0);
651
652                 ref=IDirectSoundBuffer_Release(secondary);
653                 ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
654             }
655         }
656
657         ref=IDirectSoundBuffer_Release(primary);
658         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
659     }
660
661     /* Set the CooperativeLevel back to normal */
662     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
663     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
664     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
665
666 EXIT:
667     ref=IDirectSound_Release(dso);
668     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
669     if (ref!=0)
670         return DSERR_GENERIC;
671
672     return rc;
673 }
674
675 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
676                                    LPCSTR lpcstrModule, LPVOID lpContext)
677 {
678     trace("*** Testing %s - %s\n",lpcstrDescription,lpcstrModule);
679     test_dsound(lpGuid);
680     test_dsound8(lpGuid);
681     test_primary(lpGuid);
682     test_secondary(lpGuid);
683
684     return 1;
685 }
686
687 static void dsound_tests()
688 {
689     HRESULT rc;
690     rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
691     ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc);
692 }
693
694 START_TEST(dsound)
695 {
696     CoInitialize(NULL);
697
698     dsound_dsound_tests();
699     dsound_dsound8_tests();
700     dsound_tests();
701 }