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