Only print format info when in interactive mode for capture test.
[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 "dxerr8.h"
40 #include "dsconf.h"
41
42 #include "dsound_test.h"
43
44 static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
45                               LPCGUID lpGuid)
46 {
47     HRESULT rc;
48     DSCAPS dscaps;
49     int ref;
50     IUnknown * unknown;
51     IDirectSound * ds;
52     IDirectSound8 * ds8;
53     DWORD speaker_config, new_speaker_config;
54
55     /* Try to Query for objects */
56     rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
57     ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
58        DXGetErrorString8(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",
64        DXGetErrorString8(rc));
65     if (rc==DS_OK)
66         IDirectSound_Release(ds);
67
68     rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
69     ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
70        "should have failed: %s\n",DXGetErrorString8(rc));
71     if (rc==DS_OK)
72         IDirectSound8_Release(ds8);
73
74     if (initialized == FALSE) {
75         /* try unitialized object */
76         rc=IDirectSound_GetCaps(dso,0);
77         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
78            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
79            DXGetErrorString8(rc));
80
81         rc=IDirectSound_GetCaps(dso,&dscaps);
82         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
83            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
84            DXGetErrorString8(rc));
85
86         rc=IDirectSound_Compact(dso);
87         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
88            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
89            DXGetErrorString8(rc));
90
91         rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
92         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
93            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
94            DXGetErrorString8(rc));
95
96         rc=IDirectSound_Initialize(dso,lpGuid);
97         ok(rc==DS_OK,"IDirectSound_Initialize() failed: %s\n",
98            DXGetErrorString8(rc));
99     }
100
101     /* DSOUND: Error: Invalid caps buffer */
102     rc=IDirectSound_GetCaps(dso,0);
103     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
104        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
105        DXGetErrorString8(rc));
106
107     ZeroMemory(&dscaps, sizeof(dscaps));
108
109     /* DSOUND: Error: Invalid caps buffer */
110     rc=IDirectSound_GetCaps(dso,&dscaps);
111     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
112        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
113        DXGetErrorString8(rc));
114
115     dscaps.dwSize=sizeof(dscaps);
116
117     /* DSOUND: Running on a certified driver */
118     rc=IDirectSound_GetCaps(dso,&dscaps);
119     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
120
121     rc=IDirectSound_Compact(dso);
122     ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
123        DXGetErrorString8(rc));
124
125     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
126     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
127        DXGetErrorString8(rc));
128
129     rc=IDirectSound_Compact(dso);
130     ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
131
132     rc=IDirectSound_GetSpeakerConfig(dso,0);
133     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
134        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
135        DXGetErrorString8(rc));
136
137     rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
138     ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
139        DXGetErrorString8(rc));
140
141     speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
142                                         DSSPEAKER_GEOMETRY_WIDE);
143     rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
144     ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
145        DXGetErrorString8(rc));
146     if (rc==DS_OK) {
147         rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
148         ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
149            DXGetErrorString8(rc));
150         if (rc==DS_OK && speaker_config!=new_speaker_config)
151                trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
152                "config: expected 0x%08lx, got 0x%08lx\n",
153                speaker_config,new_speaker_config);
154     }
155
156     ref=IDirectSound_Release(dso);
157     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
158 }
159
160 static void IDirectSound_tests()
161 {
162     HRESULT rc;
163     LPDIRECTSOUND dso=NULL;
164
165     trace("Testing IDirectSound\n");
166
167     /* try the COM class factory method of creation with no device specified */
168     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
169                         &IID_IDirectSound, (void**)&dso);
170     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
171        DXGetErrorString8(rc));
172     if (dso)
173         IDirectSound_test(dso, FALSE, NULL);
174
175     /* try the COM class factory method of creation with default playback
176      * device specified */
177     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
178                         &IID_IDirectSound, (void**)&dso);
179     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
180        DXGetErrorString8(rc));
181     if (dso)
182         IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
183
184     /* try the COM class factory method of creation with default voice
185      * playback device specified */
186     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
187                         &IID_IDirectSound, (void**)&dso);
188     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
189        DXGetErrorString8(rc));
190     if (dso)
191         IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
192
193     /* try the COM class factory method of creation with a bad
194      * IID specified */
195     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
196                         &CLSID_DirectSoundPrivate, (void**)&dso);
197     ok(rc==E_NOINTERFACE,
198        "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
199        "should have failed: %s\n",DXGetErrorString8(rc));
200
201     /* try the COM class factory method of creation with a bad
202      * GUID and IID specified */
203     rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
204                         &IID_IDirectSound, (void**)&dso);
205     ok(rc==REGDB_E_CLASSNOTREG,
206        "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
207        "should have failed: %s\n",DXGetErrorString8(rc));
208
209     /* try with no device specified */
210     rc=DirectSoundCreate(NULL,&dso,NULL);
211     ok(rc==S_OK,"DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
212     if (dso)
213         IDirectSound_test(dso, TRUE, NULL);
214
215     /* try with default playback device specified */
216     rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
217     ok(rc==S_OK,"DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
218        DXGetErrorString8(rc));
219     if (dso)
220         IDirectSound_test(dso, TRUE, NULL);
221
222     /* try with default voice playback device specified */
223     rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
224     ok(rc==S_OK,"DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
225        DXGetErrorString8(rc));
226     if (dso)
227         IDirectSound_test(dso, TRUE, NULL);
228
229     /* try with a bad device specified */
230     rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
231     ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
232        "should have failed: %s\n",DXGetErrorString8(rc));
233 }
234
235 static HRESULT test_dsound(LPGUID lpGuid)
236 {
237     HRESULT rc;
238     LPDIRECTSOUND dso=NULL;
239     int ref;
240
241     /* DSOUND: Error: Invalid interface buffer */
242     rc=DirectSoundCreate(lpGuid,0,NULL);
243     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
244        "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
245
246     /* Create the DirectSound object */
247     rc=DirectSoundCreate(lpGuid,&dso,NULL);
248     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
249     if (rc!=DS_OK)
250         return rc;
251
252     /* Try the enumerated device */
253     IDirectSound_test(dso, TRUE, lpGuid);
254
255     /* Try the COM class factory method of creation with enumerated device */
256     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
257                         &IID_IDirectSound, (void**)&dso);
258     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
259        DXGetErrorString8(rc));
260     if (dso)
261         IDirectSound_test(dso, FALSE, lpGuid);
262
263     /* Create a DirectSound object */
264     rc=DirectSoundCreate(lpGuid,&dso,NULL);
265     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
266     if (rc==DS_OK) {
267         LPDIRECTSOUND dso1=NULL;
268
269         /* Create a second DirectSound object */
270         rc=DirectSoundCreate(lpGuid,&dso1,NULL);
271         ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
272         if (rc==DS_OK) {
273             /* Release the second DirectSound object */
274             ref=IDirectSound_Release(dso1);
275             ok(ref==0,"IDirectSound_Release() has %d references, should have "
276                "0\n",ref);
277             ok(dso!=dso1,"DirectSound objects should be unique: "
278                "dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
279         }
280
281         /* Release the first DirectSound object */
282         ref=IDirectSound_Release(dso);
283         ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
284            ref);
285         if (ref!=0)
286             return DSERR_GENERIC;
287     } else
288         return rc;
289
290     /* Create a DirectSound object */
291     rc=DirectSoundCreate(lpGuid,&dso,NULL);
292     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
293     if (rc==DS_OK) {
294         LPDIRECTSOUNDBUFFER secondary;
295         DSBUFFERDESC bufdesc;
296         WAVEFORMATEX wfx;
297
298         init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
299         ZeroMemory(&bufdesc, sizeof(bufdesc));
300         bufdesc.dwSize=sizeof(bufdesc);
301         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
302         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
303         bufdesc.lpwfxFormat=&wfx;
304         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
305         ok(rc==DS_OK && secondary!=NULL,
306            "IDirectSound_CreateSoundBuffer() failed to create a secondary "
307            "buffer %s\n",DXGetErrorString8(rc));
308         if (rc==DS_OK && secondary!=NULL) {
309             LPDIRECTSOUND3DBUFFER buffer3d;
310             rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
311                                            (void **)&buffer3d);
312             ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
313                "failed:  %s\n",DXGetErrorString8(rc));
314             if (rc==DS_OK && buffer3d!=NULL) {
315                 ref=IDirectSound3DBuffer_AddRef(buffer3d);
316                 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
317                    "should have 2\n",ref);
318             }
319             ref=IDirectSoundBuffer_AddRef(secondary);
320             ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
321                "should have 2\n",ref);
322         }
323         /* release with buffer */
324         ref=IDirectSound_Release(dso);
325         ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
326            ref);
327         if (ref!=0)
328             return DSERR_GENERIC;
329     } else
330         return rc;
331
332     return DS_OK;
333 }
334
335 static HRESULT test_primary(LPGUID lpGuid)
336 {
337     HRESULT rc;
338     LPDIRECTSOUND dso=NULL;
339     LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
340     DSBUFFERDESC bufdesc;
341     DSCAPS dscaps;
342     int ref;
343
344     /* Create the DirectSound object */
345     rc=DirectSoundCreate(lpGuid,&dso,NULL);
346     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
347     if (rc!=DS_OK)
348         return rc;
349
350     /* Get the device capabilities */
351     ZeroMemory(&dscaps, sizeof(dscaps));
352     dscaps.dwSize=sizeof(dscaps);
353     rc=IDirectSound_GetCaps(dso,&dscaps);
354     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
355     if (rc!=DS_OK)
356         goto EXIT;
357
358     /* DSOUND: Error: Invalid buffer description pointer */
359     rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
360     ok(rc==DSERR_INVALIDPARAM,
361        "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
362        DXGetErrorString8(rc));
363
364     /* DSOUND: Error: Invalid buffer description pointer */
365     rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
366     ok(rc==DSERR_INVALIDPARAM && primary==0,
367        "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
368        "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
369
370     /* DSOUND: Error: Invalid buffer description pointer */
371     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
372     ok(rc==DSERR_INVALIDPARAM && primary==0,
373        "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
374        "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
375
376     ZeroMemory(&bufdesc, sizeof(bufdesc));
377
378     /* DSOUND: Error: Invalid size */
379     /* DSOUND: Error: Invalid buffer description */
380     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
381     ok(rc==DSERR_INVALIDPARAM && primary==0,
382        "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
383        "primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
384
385     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
386     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
387     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
388     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
389        DXGetErrorString8(rc));
390     if (rc!=DS_OK)
391         goto EXIT;
392
393     /* Testing the primary buffer */
394     primary=NULL;
395     ZeroMemory(&bufdesc, sizeof(bufdesc));
396     bufdesc.dwSize=sizeof(bufdesc);
397     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
398     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
399     ok(rc==DS_OK && primary!=NULL,
400        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
401        "%s\n",DXGetErrorString8(rc));
402     if (rc==DS_OK && primary!=NULL) {
403         LONG vol;
404
405         /* Try to create a second primary buffer */
406         /* DSOUND: Error: The primary buffer already exists.
407          * Any changes made to the buffer description will be ignored. */
408         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
409         ok(rc==DS_OK && second==primary,
410            "IDirectSound_CreateSoundBuffer() should have returned original "
411            "primary buffer: %s\n",DXGetErrorString8(rc));
412         ref=IDirectSoundBuffer_Release(second);
413         ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
414            "should have 1\n",ref);
415
416         /* Try to duplicate a primary buffer */
417         /* DSOUND: Error: Can't duplicate primary buffers */
418         rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
419         /* rc=0x88780032 */
420         ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
421            "should have failed %s\n",DXGetErrorString8(rc));
422
423         rc=IDirectSoundBuffer_GetVolume(primary,&vol);
424         ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
425            DXGetErrorString8(rc));
426
427         if (winetest_interactive) {
428             trace("Playing a 5 seconds reference tone at the current "
429                   "volume.\n");
430             if (rc==DS_OK)
431                 trace("(the current volume is %ld according to DirectSound)\n",
432                       vol);
433             trace("All subsequent tones should be identical to this one.\n");
434             trace("Listen for stutter, changes in pitch, volume, etc.\n");
435         }
436         test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
437                     !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
438
439         ref=IDirectSoundBuffer_Release(primary);
440         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
441            "should have 0\n",ref);
442     }
443
444     /* Set the CooperativeLevel back to normal */
445     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
446     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
447     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
448        DXGetErrorString8(rc));
449
450 EXIT:
451     ref=IDirectSound_Release(dso);
452     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
453     if (ref!=0)
454         return DSERR_GENERIC;
455
456     return rc;
457 }
458
459 /*
460  * Test the primary buffer at different formats while keeping the
461  * secondary buffer at a constant format.
462  */
463 static HRESULT test_primary_secondary(LPGUID lpGuid)
464 {
465     HRESULT rc;
466     LPDIRECTSOUND dso=NULL;
467     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
468     DSBUFFERDESC bufdesc;
469     DSCAPS dscaps;
470     WAVEFORMATEX wfx, wfx2;
471     int f,ref;
472
473     /* Create the DirectSound object */
474     rc=DirectSoundCreate(lpGuid,&dso,NULL);
475     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
476     if (rc!=DS_OK)
477         return rc;
478
479     /* Get the device capabilities */
480     ZeroMemory(&dscaps, sizeof(dscaps));
481     dscaps.dwSize=sizeof(dscaps);
482     rc=IDirectSound_GetCaps(dso,&dscaps);
483     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
484     if (rc!=DS_OK)
485         goto EXIT;
486
487     /* We must call SetCooperativeLevel before creating primary buffer */
488     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
489     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
490     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
491        DXGetErrorString8(rc));
492     if (rc!=DS_OK)
493         goto EXIT;
494
495     ZeroMemory(&bufdesc, sizeof(bufdesc));
496     bufdesc.dwSize=sizeof(bufdesc);
497     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
498     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
499     ok(rc==DS_OK && primary!=NULL,
500        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
501        "%s\n",DXGetErrorString8(rc));
502
503     if (rc==DS_OK && primary!=NULL) {
504         for (f=0;f<NB_FORMATS;f++) {
505             /* We must call SetCooperativeLevel to be allowed to call
506              * SetFormat */
507             /* DSOUND: Setting DirectSound cooperative level to
508              * DSSCL_PRIORITY */
509             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
510             ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
511                DXGetErrorString8(rc));
512             if (rc!=DS_OK)
513                 goto EXIT;
514
515             init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
516                         formats[f][2]);
517             wfx2=wfx;
518             rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
519             ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
520                DXGetErrorString8(rc));
521
522             /* There is no garantee that SetFormat will actually change the
523              * format to what we asked for. It depends on what the soundcard
524              * supports. So we must re-query the format.
525              */
526             rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
527             ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
528                DXGetErrorString8(rc));
529             if (rc==DS_OK &&
530                 (wfx.wFormatTag!=wfx2.wFormatTag ||
531                  wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
532                  wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
533                  wfx.nChannels!=wfx2.nChannels)) {
534                 trace("Requested primary format tag=0x%04x %ldx%dx%d "
535                       "avg.B/s=%ld align=%d\n",
536                       wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
537                       wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
538                 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
539                       wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
540                       wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
541             }
542
543             /* Set the CooperativeLevel back to normal */
544             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
545             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
546             ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
547                DXGetErrorString8(rc));
548
549             init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
550
551             secondary=NULL;
552             ZeroMemory(&bufdesc, sizeof(bufdesc));
553             bufdesc.dwSize=sizeof(bufdesc);
554             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
555             bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
556             bufdesc.lpwfxFormat=&wfx2;
557             if (winetest_interactive) {
558                 trace("  Testing a primary buffer at %ldx%dx%d with a "
559                       "secondary buffer at %ldx%dx%d\n",
560                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
561                       wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
562             }
563             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
564             ok(rc==DS_OK && secondary!=NULL,
565                "IDirectSound_CreateSoundBuffer() failed to create a secondary "
566                "buffer %s\n",DXGetErrorString8(rc));
567
568             if (rc==DS_OK && secondary!=NULL) {
569                 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
570                             winetest_interactive,1.0,0,NULL,0,0);
571
572                 ref=IDirectSoundBuffer_Release(secondary);
573                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
574                    "should have 0\n",ref);
575             }
576         }
577
578         ref=IDirectSoundBuffer_Release(primary);
579         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
580            "should have 0\n",ref);
581     }
582
583     /* Set the CooperativeLevel back to normal */
584     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
585     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
586     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
587        DXGetErrorString8(rc));
588
589 EXIT:
590     ref=IDirectSound_Release(dso);
591     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
592     if (ref!=0)
593         return DSERR_GENERIC;
594
595     return rc;
596 }
597
598 static HRESULT test_secondary(LPGUID lpGuid)
599 {
600     HRESULT rc;
601     LPDIRECTSOUND dso=NULL;
602     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
603     DSBUFFERDESC bufdesc;
604     DSCAPS dscaps;
605     WAVEFORMATEX wfx;
606     DWORD f;
607     int ref;
608
609     /* Create the DirectSound object */
610     rc=DirectSoundCreate(lpGuid,&dso,NULL);
611     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
612     if (rc!=DS_OK)
613         return rc;
614
615     /* Get the device capabilities */
616     ZeroMemory(&dscaps, sizeof(dscaps));
617     dscaps.dwSize=sizeof(dscaps);
618     rc=IDirectSound_GetCaps(dso,&dscaps);
619     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
620     if (rc!=DS_OK)
621         goto EXIT;
622
623     /* We must call SetCooperativeLevel before creating primary buffer */
624     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
625     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
626     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
627        DXGetErrorString8(rc));
628     if (rc!=DS_OK)
629         goto EXIT;
630
631     ZeroMemory(&bufdesc, sizeof(bufdesc));
632     bufdesc.dwSize=sizeof(bufdesc);
633     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
634     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
635     ok(rc==DS_OK && primary!=NULL,
636        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
637        "%s\n",DXGetErrorString8(rc));
638
639     if (rc==DS_OK && primary!=NULL) {
640         for (f=0;f<NB_FORMATS;f++) {
641             init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
642                         formats[f][2]);
643             secondary=NULL;
644             ZeroMemory(&bufdesc, sizeof(bufdesc));
645             bufdesc.dwSize=sizeof(bufdesc);
646             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
647             bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
648             bufdesc.lpwfxFormat=&wfx;
649             if (winetest_interactive) {
650                 trace("  Testing a secondary buffer at %ldx%dx%d\n",
651                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
652             }
653             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
654             ok(rc==DS_OK && secondary!=NULL,
655                "IDirectSound_CreateSoundBuffer() failed to create a secondary "
656                "buffer %s\n",DXGetErrorString8(rc));
657
658             if (rc==DS_OK && secondary!=NULL) {
659                 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
660                             winetest_interactive,1.0,0,NULL,0,0);
661
662                 ref=IDirectSoundBuffer_Release(secondary);
663                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
664                    "should have 0\n",ref);
665             }
666         }
667
668         ref=IDirectSoundBuffer_Release(primary);
669         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
670            "should have 0\n",ref);
671     }
672
673     /* Set the CooperativeLevel back to normal */
674     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
675     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
676     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
677        DXGetErrorString8(rc));
678
679 EXIT:
680     ref=IDirectSound_Release(dso);
681     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
682     if (ref!=0)
683         return DSERR_GENERIC;
684
685     return rc;
686 }
687
688 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
689                                    LPCSTR lpcstrModule, LPVOID lpContext)
690 {
691     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
692     test_dsound(lpGuid);
693     test_primary(lpGuid);
694     test_primary_secondary(lpGuid);
695     test_secondary(lpGuid);
696
697     return 1;
698 }
699
700 static void dsound_tests()
701 {
702     HRESULT rc;
703     rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
704     ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
705 }
706
707 START_TEST(dsound)
708 {
709     CoInitialize(NULL);
710
711     IDirectSound_tests();
712     dsound_tests();
713 }