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