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