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