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.
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.
11 * Copyright (c) 2002-2004 Francois Gouget
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/test.h"
36 #include "dsound_test.h"
38 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
40 int align(int length, int align)
42 return (length / align) * align;
45 static void IDirectSound8_test(LPDIRECTSOUND8 dso, BOOL initialized,
54 DWORD speaker_config, new_speaker_config;
57 /* Try to Query for objects */
58 rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
59 ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %s\n",
60 DXGetErrorString8(rc));
62 IDirectSound8_Release(unknown);
64 rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
65 ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %s\n",
66 DXGetErrorString8(rc));
68 IDirectSound_Release(ds);
70 rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
71 ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) "
72 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
73 DXGetErrorString8(rc));
75 IDirectSound8_Release(ds8);
77 if (initialized == FALSE) {
78 /* try uninitialized object */
79 rc=IDirectSound8_GetCaps(dso,0);
80 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps(NULL) "
81 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
82 DXGetErrorString8(rc));
84 rc=IDirectSound8_GetCaps(dso,&dscaps);
85 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps() "
86 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
87 DXGetErrorString8(rc));
89 rc=IDirectSound8_Compact(dso);
90 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_Compact() "
91 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
92 DXGetErrorString8(rc));
94 rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
95 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetSpeakerConfig() "
96 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
97 DXGetErrorString8(rc));
99 rc=IDirectSound8_VerifyCertification(dso, &certified);
100 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_VerifyCertification() "
101 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
102 DXGetErrorString8(rc));
104 rc=IDirectSound8_Initialize(dso,lpGuid);
105 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
106 "IDirectSound8_Initialize() failed: %s\n",DXGetErrorString8(rc));
107 if (rc==DSERR_NODRIVER) {
108 trace(" No Driver\n");
110 } else if (rc==E_FAIL) {
111 trace(" No Device\n");
113 } else if (rc==DSERR_ALLOCATED) {
114 trace(" Already In Use\n");
119 rc=IDirectSound8_Initialize(dso,lpGuid);
120 ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound8_Initialize() "
121 "should have returned DSERR_ALREADYINITIALIZED: %s\n",
122 DXGetErrorString8(rc));
124 /* DSOUND: Error: Invalid caps buffer */
125 rc=IDirectSound8_GetCaps(dso,0);
126 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
127 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
128 DXGetErrorString8(rc));
130 ZeroMemory(&dscaps, sizeof(dscaps));
132 /* DSOUND: Error: Invalid caps buffer */
133 rc=IDirectSound8_GetCaps(dso,&dscaps);
134 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
135 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
136 DXGetErrorString8(rc));
138 dscaps.dwSize=sizeof(dscaps);
140 /* DSOUND: Running on a certified driver */
141 rc=IDirectSound8_GetCaps(dso,&dscaps);
142 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
144 rc=IDirectSound8_Compact(dso);
145 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound8_Compact() failed: %s\n",
146 DXGetErrorString8(rc));
148 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
149 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
150 DXGetErrorString8(rc));
152 rc=IDirectSound8_Compact(dso);
153 ok(rc==DS_OK,"IDirectSound8_Compact() failed: %s\n",DXGetErrorString8(rc));
155 rc=IDirectSound8_GetSpeakerConfig(dso,0);
156 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetSpeakerConfig(NULL) "
157 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
158 DXGetErrorString8(rc));
160 rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
161 ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %s\n",
162 DXGetErrorString8(rc));
164 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
165 DSSPEAKER_GEOMETRY_WIDE);
166 rc=IDirectSound8_SetSpeakerConfig(dso,speaker_config);
167 ok(rc==DS_OK,"IDirectSound8_SetSpeakerConfig() failed: %s\n",
168 DXGetErrorString8(rc));
170 rc=IDirectSound8_GetSpeakerConfig(dso,&new_speaker_config);
171 ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %s\n",
172 DXGetErrorString8(rc));
173 if (rc==DS_OK && speaker_config!=new_speaker_config)
174 trace("IDirectSound8_GetSpeakerConfig() failed to set speaker "
175 "config: expected 0x%08x, got 0x%08x\n",
176 speaker_config,new_speaker_config);
179 rc=IDirectSound8_VerifyCertification(dso, &certified);
180 ok(rc==DS_OK||rc==E_NOTIMPL,"IDirectSound8_VerifyCertification() failed: %s\n",
181 DXGetErrorString8(rc));
184 ref=IDirectSound8_Release(dso);
185 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
188 static void IDirectSound8_tests(void)
191 LPDIRECTSOUND8 dso=NULL;
192 LPCLASSFACTORY cf=NULL;
194 trace("Testing IDirectSound8\n");
196 rc=CoGetClassObject(&CLSID_DirectSound8, CLSCTX_INPROC_SERVER, NULL,
197 &IID_IClassFactory, (void**)&cf);
198 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound8, IID_IClassFactory) "
199 "failed: %s\n", DXGetErrorString8(rc));
201 rc=CoGetClassObject(&CLSID_DirectSound8, CLSCTX_INPROC_SERVER, NULL,
202 &IID_IUnknown, (void**)&cf);
203 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound8, IID_IUnknown) "
204 "failed: %s\n", DXGetErrorString8(rc));
206 /* try the COM class factory method of creation with no device specified */
207 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
208 &IID_IDirectSound8, (void**)&dso);
209 ok(rc==S_OK||rc==REGDB_E_CLASSNOTREG,"CoCreateInstance() failed: %s\n",
210 DXGetErrorString8(rc));
211 if (rc==REGDB_E_CLASSNOTREG) {
212 trace(" Class Not Registered\n");
216 IDirectSound8_test(dso, FALSE, NULL);
218 /* try the COM class factory method of creation with default playback
219 * device specified */
220 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
221 &IID_IDirectSound8, (void**)&dso);
222 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %s\n",
223 DXGetErrorString8(rc));
225 IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultPlayback);
227 /* try the COM class factory method of creation with default voice
228 * playback device specified */
229 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
230 &IID_IDirectSound8, (void**)&dso);
231 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %s\n",
232 DXGetErrorString8(rc));
234 IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
236 /* try the COM class factory method of creation with a bad
238 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
239 &CLSID_DirectSoundPrivate, (void**)&dso);
240 ok(rc==E_NOINTERFACE,
241 "CoCreateInstance(CLSID_DirectSound8,CLSID_DirectSoundPrivate) "
242 "should have failed: %s\n",DXGetErrorString8(rc));
244 /* try the COM class factory method of creation with a bad
245 * GUID and IID specified */
246 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
247 &IID_IDirectSound8, (void**)&dso);
248 ok(rc==REGDB_E_CLASSNOTREG,
249 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound8) "
250 "should have failed: %s\n",DXGetErrorString8(rc));
252 /* try with no device specified */
253 rc=pDirectSoundCreate8(NULL,&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);
259 /* try with default playback device specified */
260 rc=pDirectSoundCreate8(&DSDEVID_DefaultPlayback,&dso,NULL);
261 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
262 "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
263 if (rc==DS_OK && dso)
264 IDirectSound8_test(dso, TRUE, NULL);
266 /* try with default voice playback device specified */
267 rc=pDirectSoundCreate8(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
268 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
269 "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
270 if (rc==DS_OK && dso)
271 IDirectSound8_test(dso, TRUE, NULL);
273 /* try with a bad device specified */
274 rc=pDirectSoundCreate8(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
275 ok(rc==DSERR_NODRIVER,"DirectSoundCreate8(DSDEVID_DefaultVoiceCapture) "
276 "should have failed: %s\n",DXGetErrorString8(rc));
279 static HRESULT test_dsound8(LPGUID lpGuid)
282 LPDIRECTSOUND8 dso=NULL;
285 /* DSOUND: Error: Invalid interface buffer */
286 rc=pDirectSoundCreate8(lpGuid,0,NULL);
287 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate8() should have returned "
288 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
290 /* Create the DirectSound8 object */
291 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
292 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
293 "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
297 /* Try the enumerated device */
298 IDirectSound8_test(dso, TRUE, lpGuid);
300 /* Try the COM class factory method of creation with enumerated device */
301 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
302 &IID_IDirectSound8, (void**)&dso);
303 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
304 DXGetErrorString8(rc));
306 IDirectSound8_test(dso, FALSE, lpGuid);
308 /* Create a DirectSound8 object */
309 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
310 ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
312 LPDIRECTSOUND8 dso1=NULL;
314 /* Create a second DirectSound8 object */
315 rc=pDirectSoundCreate8(lpGuid,&dso1,NULL);
316 ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
318 /* Release the second DirectSound8 object */
319 ref=IDirectSound8_Release(dso1);
320 ok(ref==0,"IDirectSound8_Release() has %d references, "
321 "should have 0\n",ref);
322 ok(dso!=dso1,"DirectSound8 objects should be unique: "
323 "dso=%p,dso1=%p\n",dso,dso1);
326 /* Release the first DirectSound8 object */
327 ref=IDirectSound8_Release(dso);
328 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
331 return DSERR_GENERIC;
335 /* Create a DirectSound8 object */
336 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
337 ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
339 LPDIRECTSOUNDBUFFER secondary;
340 DSBUFFERDESC bufdesc;
343 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
344 ZeroMemory(&bufdesc, sizeof(bufdesc));
345 bufdesc.dwSize=sizeof(bufdesc);
346 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
347 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
349 bufdesc.lpwfxFormat=&wfx;
350 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
351 ok(rc==DS_OK && secondary!=NULL,
352 "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
353 "buffer: %s\n",DXGetErrorString8(rc));
354 if (rc==DS_OK && secondary!=NULL) {
355 LPDIRECTSOUND3DBUFFER buffer3d;
356 LPDIRECTSOUNDBUFFER8 buffer8;
357 rc=IDirectSound8_QueryInterface(secondary,
358 &IID_IDirectSound3DBuffer,
360 ok(rc==DS_OK && buffer3d!=NULL,
361 "IDirectSound8_QueryInterface() failed: %s\n",
362 DXGetErrorString8(rc));
363 if (rc==DS_OK && buffer3d!=NULL) {
364 ref=IDirectSound3DBuffer_AddRef(buffer3d);
365 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
366 "should have 2\n",ref);
368 rc=IDirectSound8_QueryInterface(secondary,
369 &IID_IDirectSoundBuffer8,
371 if (rc==DS_OK && buffer8!=NULL) {
372 ref=IDirectSoundBuffer8_AddRef(buffer8);
373 ok(ref==3,"IDirectSoundBuffer8_AddRef() has %d references, "
374 "should have 3\n",ref);
376 ref=IDirectSoundBuffer_AddRef(secondary);
377 ok(ref==4,"IDirectSoundBuffer_AddRef() has %d references, "
378 "should have 4\n",ref);
380 /* release with buffer */
381 ref=IDirectSound8_Release(dso);
382 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
385 return DSERR_GENERIC;
392 static HRESULT test_primary8(LPGUID lpGuid)
395 LPDIRECTSOUND8 dso=NULL;
396 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
397 DSBUFFERDESC bufdesc;
402 /* Create the DirectSound object */
403 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
404 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
405 "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
409 /* Get the device capabilities */
410 ZeroMemory(&dscaps, sizeof(dscaps));
411 dscaps.dwSize=sizeof(dscaps);
412 rc=IDirectSound8_GetCaps(dso,&dscaps);
413 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
417 /* DSOUND: Error: Invalid buffer description pointer */
418 rc=IDirectSound8_CreateSoundBuffer(dso,0,0,NULL);
419 ok(rc==DSERR_INVALIDPARAM,
420 "IDirectSound8_CreateSoundBuffer should have returned "
421 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
423 /* DSOUND: Error: Invalid buffer description pointer */
424 rc=IDirectSound8_CreateSoundBuffer(dso,0,&primary,NULL);
425 ok(rc==DSERR_INVALIDPARAM && primary==0,
426 "IDirectSound8_CreateSoundBuffer() should have returned "
427 "DSERR_INVALIDPARAM, returned: rc=%s,dsbo=%p\n",
428 DXGetErrorString8(rc),primary);
430 /* DSOUND: Error: Invalid buffer description pointer */
431 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,0,NULL);
432 ok(rc==DSERR_INVALIDPARAM && primary==0,
433 "IDirectSound8_CreateSoundBuffer() should have failed: rc=%s,"
434 "dsbo=%p\n",DXGetErrorString8(rc),primary);
436 ZeroMemory(&bufdesc, sizeof(bufdesc));
438 /* DSOUND: Error: Invalid size */
439 /* DSOUND: Error: Invalid buffer description */
440 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
441 ok(rc==DSERR_INVALIDPARAM && primary==0,
442 "IDirectSound8_CreateSoundBuffer() should have failed: rc=%s,"
443 "primary=%p\n",DXGetErrorString8(rc),primary);
445 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
446 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
447 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
448 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
449 DXGetErrorString8(rc));
453 /* Testing the primary buffer */
455 ZeroMemory(&bufdesc, sizeof(bufdesc));
456 bufdesc.dwSize=sizeof(bufdesc);
457 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
458 bufdesc.lpwfxFormat = &wfx;
459 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
460 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
461 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() should have "
462 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
463 if (rc==DS_OK && primary!=NULL)
464 IDirectSoundBuffer_Release(primary);
467 ZeroMemory(&bufdesc, sizeof(bufdesc));
468 bufdesc.dwSize=sizeof(bufdesc);
469 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
470 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
471 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
472 "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: "
473 "%s\n",DXGetErrorString8(rc));
474 if (rc==DSERR_CONTROLUNAVAIL)
475 trace(" No Primary\n");
476 else if (rc==DS_OK && primary!=NULL) {
479 /* Try to create a second primary buffer */
480 /* DSOUND: Error: The primary buffer already exists.
481 * Any changes made to the buffer description will be ignored. */
482 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
483 ok(rc==DS_OK && second==primary,
484 "IDirectSound8_CreateSoundBuffer() should have returned original "
485 "primary buffer: %s\n",DXGetErrorString8(rc));
486 ref=IDirectSoundBuffer_Release(second);
487 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
488 "should have 1\n",ref);
490 /* Try to duplicate a primary buffer */
491 /* DSOUND: Error: Can't duplicate primary buffers */
492 rc=IDirectSound8_DuplicateSoundBuffer(dso,primary,&third);
494 ok(rc!=DS_OK,"IDirectSound8_DuplicateSoundBuffer() primary buffer "
495 "should have failed %s\n",DXGetErrorString8(rc));
497 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
498 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
499 DXGetErrorString8(rc));
501 if (winetest_interactive) {
502 trace("Playing a 5 seconds reference tone at the current volume.\n");
504 trace("(the current volume is %d according to DirectSound)\n",
506 trace("All subsequent tones should be identical to this one.\n");
507 trace("Listen for stutter, changes in pitch, volume, etc.\n");
509 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
510 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
512 ref=IDirectSoundBuffer_Release(primary);
513 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
514 "should have 0\n",ref);
517 /* Set the CooperativeLevel back to normal */
518 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
519 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
520 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
521 DXGetErrorString8(rc));
524 ref=IDirectSound8_Release(dso);
525 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
527 return DSERR_GENERIC;
533 * Test the primary buffer at different formats while keeping the
534 * secondary buffer at a constant format.
536 static HRESULT test_primary_secondary8(LPGUID lpGuid)
539 LPDIRECTSOUND8 dso=NULL;
540 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
541 DSBUFFERDESC bufdesc;
543 WAVEFORMATEX wfx, wfx2;
547 /* Create the DirectSound object */
548 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
549 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
550 "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
554 /* Get the device capabilities */
555 ZeroMemory(&dscaps, sizeof(dscaps));
556 dscaps.dwSize=sizeof(dscaps);
557 rc=IDirectSound8_GetCaps(dso,&dscaps);
558 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
562 /* We must call SetCooperativeLevel before creating primary buffer */
563 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
564 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
565 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
566 DXGetErrorString8(rc));
570 ZeroMemory(&bufdesc, sizeof(bufdesc));
571 bufdesc.dwSize=sizeof(bufdesc);
572 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
573 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
574 ok(rc==DS_OK && primary!=NULL,
575 "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
576 "%s\n",DXGetErrorString8(rc));
578 if (rc==DS_OK && primary!=NULL) {
579 for (f=0;f<NB_FORMATS;f++) {
580 /* We must call SetCooperativeLevel to be allowed to call
582 /* DSOUND: Setting DirectSound cooperative level to
584 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
585 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
586 DXGetErrorString8(rc));
590 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
593 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
594 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %s\n",
595 format_string(&wfx), DXGetErrorString8(rc));
597 /* There is no guarantee that SetFormat will actually change the
598 * format to what we asked for. It depends on what the soundcard
599 * supports. So we must re-query the format.
601 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
602 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
603 DXGetErrorString8(rc));
605 (wfx.wFormatTag!=wfx2.wFormatTag ||
606 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
607 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
608 wfx.nChannels!=wfx2.nChannels)) {
609 trace("Requested primary format tag=0x%04x %dx%dx%d "
610 "avg.B/s=%d align=%d\n",
611 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
612 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
613 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
614 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
615 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
618 /* Set the CooperativeLevel back to normal */
619 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
620 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
621 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
622 DXGetErrorString8(rc));
624 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
627 ZeroMemory(&bufdesc, sizeof(bufdesc));
628 bufdesc.dwSize=sizeof(bufdesc);
629 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
630 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
632 bufdesc.lpwfxFormat=&wfx2;
633 if (winetest_interactive) {
634 trace(" Testing a primary buffer at %dx%dx%d with a "
635 "secondary buffer at %dx%dx%d\n",
636 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
637 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
639 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
640 ok(rc==DS_OK && secondary!=NULL,
641 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
642 "buffer %s\n",DXGetErrorString8(rc));
644 if (rc==DS_OK && secondary!=NULL) {
645 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
646 winetest_interactive,1.0,0,NULL,0,0);
648 ref=IDirectSoundBuffer_Release(secondary);
649 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
650 "should have 0\n",ref);
654 ref=IDirectSoundBuffer_Release(primary);
655 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
656 "should have 0\n",ref);
659 /* Set the CooperativeLevel back to normal */
660 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
661 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
662 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
663 DXGetErrorString8(rc));
666 ref=IDirectSound8_Release(dso);
667 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
669 return DSERR_GENERIC;
674 static HRESULT test_secondary8(LPGUID lpGuid)
677 LPDIRECTSOUND8 dso=NULL;
678 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
679 DSBUFFERDESC bufdesc;
681 WAVEFORMATEX wfx, wfx1;
685 /* Create the DirectSound object */
686 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
687 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
688 "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
692 /* Get the device capabilities */
693 ZeroMemory(&dscaps, sizeof(dscaps));
694 dscaps.dwSize=sizeof(dscaps);
695 rc=IDirectSound8_GetCaps(dso,&dscaps);
696 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
700 /* We must call SetCooperativeLevel before creating primary buffer */
701 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
702 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
703 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
704 DXGetErrorString8(rc));
708 ZeroMemory(&bufdesc, sizeof(bufdesc));
709 bufdesc.dwSize=sizeof(bufdesc);
710 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
711 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
712 ok(rc==DS_OK && primary!=NULL,
713 "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
714 "%s\n",DXGetErrorString8(rc));
716 if (rc==DS_OK && primary!=NULL) {
717 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
718 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
719 DXGetErrorString8(rc));
723 for (f=0;f<NB_FORMATS;f++) {
724 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
727 ZeroMemory(&bufdesc, sizeof(bufdesc));
728 bufdesc.dwSize=sizeof(bufdesc);
729 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
730 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
732 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
733 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() "
734 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
735 DXGetErrorString8(rc));
736 if (rc==DS_OK && secondary!=NULL)
737 IDirectSoundBuffer_Release(secondary);
740 ZeroMemory(&bufdesc, sizeof(bufdesc));
741 bufdesc.dwSize=sizeof(bufdesc);
742 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
743 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
745 bufdesc.lpwfxFormat=&wfx;
746 if (winetest_interactive) {
747 trace(" Testing a secondary buffer at %dx%dx%d "
748 "with a primary buffer at %dx%dx%d\n",
749 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
750 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
752 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
753 ok(rc==DS_OK && secondary!=NULL,
754 "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
755 "buffer: %s\n",DXGetErrorString8(rc));
757 if (rc==DS_OK && secondary!=NULL) {
758 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
759 winetest_interactive,1.0,0,NULL,0,0);
761 ref=IDirectSoundBuffer_Release(secondary);
762 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
763 "should have 0\n",ref);
767 ref=IDirectSoundBuffer_Release(primary);
768 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
769 "should have 0\n",ref);
772 /* Set the CooperativeLevel back to normal */
773 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
774 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
775 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
776 DXGetErrorString8(rc));
779 ref=IDirectSound8_Release(dso);
780 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
782 return DSERR_GENERIC;
787 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
788 LPCSTR lpcstrModule, LPVOID lpContext)
791 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
792 rc = test_dsound8(lpGuid);
793 if (rc == DSERR_NODRIVER)
794 trace(" No Driver\n");
795 else if (rc == DSERR_ALLOCATED)
796 trace(" Already In Use\n");
797 else if (rc == E_FAIL)
798 trace(" No Device\n");
800 test_primary8(lpGuid);
801 test_primary_secondary8(lpGuid);
802 test_secondary8(lpGuid);
808 static void dsound8_tests(void)
811 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
812 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
815 const char * get_file_version(const char * file_name)
817 static char version[32];
818 static char backslash[] = "\\";
822 size = GetFileVersionInfoSizeA("dsound.dll", &handle);
824 char * data = HeapAlloc(GetProcessHeap(), 0, size);
826 if (GetFileVersionInfoA("dsound.dll", handle, size, data)) {
827 VS_FIXEDFILEINFO *pFixedVersionInfo;
829 if (VerQueryValueA(data, backslash, (LPVOID *)&pFixedVersionInfo, &len)) {
830 sprintf(version, "%d.%d.%d.%d",
831 pFixedVersionInfo->dwFileVersionMS >> 16,
832 pFixedVersionInfo->dwFileVersionMS & 0xffff,
833 pFixedVersionInfo->dwFileVersionLS >> 16,
834 pFixedVersionInfo->dwFileVersionLS & 0xffff);
836 sprintf(version, "not available");
838 sprintf(version, "failed");
840 HeapFree(GetProcessHeap(), 0, data);
842 sprintf(version, "failed");
844 sprintf(version, "not available");
855 hDsound = GetModuleHandleA("dsound.dll");
856 ok(hDsound != NULL, "dsound.dll not loaded!\n");
857 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
859 pDirectSoundCreate8 = (void*)GetProcAddress(hDsound, "DirectSoundCreate8");
860 if (!pDirectSoundCreate8) {
861 trace("dsound8 test skipped\n");
865 IDirectSound8_tests();