Don't consider a device that is already in use a test failure.
[wine/wine-kai.git] / dlls / dsound / tests / dsound.c
bloba0eb895de3ad32e2b9e9381cabec000135842ec6
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
30 #include <windows.h>
32 #include <math.h>
33 #include <stdlib.h>
35 #include "wine/test.h"
36 #include "windef.h"
37 #include "wingdi.h"
38 #include "dsound.h"
39 #include "dxerr8.h"
40 #include "dsconf.h"
42 #include "dsound_test.h"
44 static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
45 LPCGUID lpGuid)
47 HRESULT rc;
48 DSCAPS dscaps;
49 int ref;
50 IUnknown * unknown;
51 IDirectSound * ds;
52 IDirectSound8 * ds8;
53 DWORD speaker_config, new_speaker_config;
55 /* Try to Query for objects */
56 rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
57 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
58 DXGetErrorString8(rc));
59 if (rc==DS_OK)
60 IDirectSound_Release(unknown);
62 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
63 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
64 DXGetErrorString8(rc));
65 if (rc==DS_OK)
66 IDirectSound_Release(ds);
68 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
69 ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
70 "should have failed: %s\n",DXGetErrorString8(rc));
71 if (rc==DS_OK)
72 IDirectSound8_Release(ds8);
74 if (initialized == FALSE) {
75 /* try unitialized object */
76 rc=IDirectSound_GetCaps(dso,0);
77 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
78 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
79 DXGetErrorString8(rc));
81 rc=IDirectSound_GetCaps(dso,&dscaps);
82 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
83 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
84 DXGetErrorString8(rc));
86 rc=IDirectSound_Compact(dso);
87 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
88 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
89 DXGetErrorString8(rc));
91 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
92 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
93 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
94 DXGetErrorString8(rc));
96 rc=IDirectSound_Initialize(dso,lpGuid);
97 ok(rc==DS_OK||rc==DSERR_NODRIVER,"IDirectSound_Initialize() failed: %s\n",
98 DXGetErrorString8(rc));
99 if (rc==DSERR_NODRIVER)
100 return;
103 /* DSOUND: Error: Invalid caps buffer */
104 rc=IDirectSound_GetCaps(dso,0);
105 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
106 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
107 DXGetErrorString8(rc));
109 ZeroMemory(&dscaps, sizeof(dscaps));
111 /* DSOUND: Error: Invalid caps buffer */
112 rc=IDirectSound_GetCaps(dso,&dscaps);
113 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
114 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
115 DXGetErrorString8(rc));
117 dscaps.dwSize=sizeof(dscaps);
119 /* DSOUND: Running on a certified driver */
120 rc=IDirectSound_GetCaps(dso,&dscaps);
121 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
123 rc=IDirectSound_Compact(dso);
124 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
125 DXGetErrorString8(rc));
127 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
128 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
129 DXGetErrorString8(rc));
131 rc=IDirectSound_Compact(dso);
132 ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
134 rc=IDirectSound_GetSpeakerConfig(dso,0);
135 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
136 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
137 DXGetErrorString8(rc));
139 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
140 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
141 DXGetErrorString8(rc));
143 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
144 DSSPEAKER_GEOMETRY_WIDE);
145 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
146 ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
147 DXGetErrorString8(rc));
148 if (rc==DS_OK) {
149 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
150 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
151 DXGetErrorString8(rc));
152 if (rc==DS_OK && speaker_config!=new_speaker_config)
153 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
154 "config: expected 0x%08lx, got 0x%08lx\n",
155 speaker_config,new_speaker_config);
158 ref=IDirectSound_Release(dso);
159 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
162 static void IDirectSound_tests()
164 HRESULT rc;
165 LPDIRECTSOUND dso=NULL;
167 trace("Testing IDirectSound\n");
169 /* try the COM class factory method of creation with no device specified */
170 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
171 &IID_IDirectSound, (void**)&dso);
172 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
173 DXGetErrorString8(rc));
174 if (dso)
175 IDirectSound_test(dso, FALSE, NULL);
177 /* try the COM class factory method of creation with default playback
178 * device specified */
179 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
180 &IID_IDirectSound, (void**)&dso);
181 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
182 DXGetErrorString8(rc));
183 if (dso)
184 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
186 /* try the COM class factory method of creation with default voice
187 * playback device specified */
188 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
189 &IID_IDirectSound, (void**)&dso);
190 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
191 DXGetErrorString8(rc));
192 if (dso)
193 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
195 /* try the COM class factory method of creation with a bad
196 * IID specified */
197 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
198 &CLSID_DirectSoundPrivate, (void**)&dso);
199 ok(rc==E_NOINTERFACE,
200 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
201 "should have failed: %s\n",DXGetErrorString8(rc));
203 /* try the COM class factory method of creation with a bad
204 * GUID and IID specified */
205 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
206 &IID_IDirectSound, (void**)&dso);
207 ok(rc==REGDB_E_CLASSNOTREG,
208 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
209 "should have failed: %s\n",DXGetErrorString8(rc));
211 /* try with no device specified */
212 rc=DirectSoundCreate(NULL,&dso,NULL);
213 ok(rc==S_OK||rc==DSERR_NODRIVER,"DirectSoundCreate(NULL) failed: %s\n",
214 DXGetErrorString8(rc));
215 if (rc==S_OK && dso)
216 IDirectSound_test(dso, TRUE, NULL);
218 /* try with default playback device specified */
219 rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
220 ok(rc==S_OK||rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultPlayback)"
221 " failed: %s\n", DXGetErrorString8(rc));
222 if (rc==DS_OK && dso)
223 IDirectSound_test(dso, TRUE, NULL);
225 /* try with default voice playback device specified */
226 rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
227 ok(rc==S_OK||rc==DSERR_NODRIVER,
228 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
229 DXGetErrorString8(rc));
230 if (rc==DS_OK && dso)
231 IDirectSound_test(dso, TRUE, NULL);
233 /* try with a bad device specified */
234 rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
235 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
236 "should have failed: %s\n",DXGetErrorString8(rc));
239 static HRESULT test_dsound(LPGUID lpGuid)
241 HRESULT rc;
242 LPDIRECTSOUND dso=NULL;
243 int ref;
245 /* DSOUND: Error: Invalid interface buffer */
246 rc=DirectSoundCreate(lpGuid,0,NULL);
247 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
248 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
250 /* Create the DirectSound object */
251 rc=DirectSoundCreate(lpGuid,&dso,NULL);
252 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
253 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
254 if (rc!=DS_OK)
255 return rc;
257 /* Try the enumerated device */
258 IDirectSound_test(dso, TRUE, lpGuid);
260 /* Try the COM class factory method of creation with enumerated device */
261 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
262 &IID_IDirectSound, (void**)&dso);
263 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
264 DXGetErrorString8(rc));
265 if (dso)
266 IDirectSound_test(dso, FALSE, lpGuid);
268 /* Create a DirectSound object */
269 rc=DirectSoundCreate(lpGuid,&dso,NULL);
270 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
271 if (rc==DS_OK) {
272 LPDIRECTSOUND dso1=NULL;
274 /* Create a second DirectSound object */
275 rc=DirectSoundCreate(lpGuid,&dso1,NULL);
276 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
277 if (rc==DS_OK) {
278 /* Release the second DirectSound object */
279 ref=IDirectSound_Release(dso1);
280 ok(ref==0,"IDirectSound_Release() has %d references, should have "
281 "0\n",ref);
282 ok(dso!=dso1,"DirectSound objects should be unique: "
283 "dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
286 /* Release the first DirectSound object */
287 ref=IDirectSound_Release(dso);
288 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
289 ref);
290 if (ref!=0)
291 return DSERR_GENERIC;
292 } else
293 return rc;
295 /* Create a DirectSound object */
296 rc=DirectSoundCreate(lpGuid,&dso,NULL);
297 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
298 if (rc==DS_OK) {
299 LPDIRECTSOUNDBUFFER secondary;
300 DSBUFFERDESC bufdesc;
301 WAVEFORMATEX wfx;
303 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
304 ZeroMemory(&bufdesc, sizeof(bufdesc));
305 bufdesc.dwSize=sizeof(bufdesc);
306 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
307 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
308 bufdesc.lpwfxFormat=&wfx;
309 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
310 ok(rc==DS_OK && secondary!=NULL,
311 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
312 "buffer %s\n",DXGetErrorString8(rc));
313 if (rc==DS_OK && secondary!=NULL) {
314 LPDIRECTSOUND3DBUFFER buffer3d;
315 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
316 (void **)&buffer3d);
317 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
318 "failed: %s\n",DXGetErrorString8(rc));
319 if (rc==DS_OK && buffer3d!=NULL) {
320 ref=IDirectSound3DBuffer_AddRef(buffer3d);
321 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
322 "should have 2\n",ref);
324 ref=IDirectSoundBuffer_AddRef(secondary);
325 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
326 "should have 2\n",ref);
328 /* release with buffer */
329 ref=IDirectSound_Release(dso);
330 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
331 ref);
332 if (ref!=0)
333 return DSERR_GENERIC;
334 } else
335 return rc;
337 return DS_OK;
340 static HRESULT test_primary(LPGUID lpGuid)
342 HRESULT rc;
343 LPDIRECTSOUND dso=NULL;
344 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
345 DSBUFFERDESC bufdesc;
346 DSCAPS dscaps;
347 WAVEFORMATEX wfx;
348 int ref;
350 /* Create the DirectSound object */
351 rc=DirectSoundCreate(lpGuid,&dso,NULL);
352 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
353 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
354 if (rc!=DS_OK)
355 return rc;
357 /* Get the device capabilities */
358 ZeroMemory(&dscaps, sizeof(dscaps));
359 dscaps.dwSize=sizeof(dscaps);
360 rc=IDirectSound_GetCaps(dso,&dscaps);
361 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
362 if (rc!=DS_OK)
363 goto EXIT;
365 /* DSOUND: Error: Invalid buffer description pointer */
366 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
367 ok(rc==DSERR_INVALIDPARAM,
368 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
369 DXGetErrorString8(rc));
371 /* DSOUND: Error: Invalid buffer description pointer */
372 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
373 ok(rc==DSERR_INVALIDPARAM && primary==0,
374 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
375 "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
377 /* DSOUND: Error: Invalid buffer description pointer */
378 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
379 ok(rc==DSERR_INVALIDPARAM && primary==0,
380 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
381 "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
383 ZeroMemory(&bufdesc, sizeof(bufdesc));
385 /* DSOUND: Error: Invalid size */
386 /* DSOUND: Error: Invalid buffer description */
387 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
388 ok(rc==DSERR_INVALIDPARAM && primary==0,
389 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
390 "primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
392 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
393 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
394 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
395 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
396 DXGetErrorString8(rc));
397 if (rc!=DS_OK)
398 goto EXIT;
400 /* Testing the primary buffer */
401 primary=NULL;
402 ZeroMemory(&bufdesc, sizeof(bufdesc));
403 bufdesc.dwSize=sizeof(bufdesc);
404 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
405 bufdesc.lpwfxFormat = &wfx;
406 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
407 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
408 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
409 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
410 if (rc==DS_OK && primary!=NULL)
411 IDirectSoundBuffer_Release(primary);
413 primary=NULL;
414 ZeroMemory(&bufdesc, sizeof(bufdesc));
415 bufdesc.dwSize=sizeof(bufdesc);
416 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
417 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
418 ok(rc==DS_OK && primary!=NULL,
419 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
420 "%s\n",DXGetErrorString8(rc));
421 if (rc==DS_OK && primary!=NULL) {
422 LONG vol;
424 /* Try to create a second primary buffer */
425 /* DSOUND: Error: The primary buffer already exists.
426 * Any changes made to the buffer description will be ignored. */
427 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
428 ok(rc==DS_OK && second==primary,
429 "IDirectSound_CreateSoundBuffer() should have returned original "
430 "primary buffer: %s\n",DXGetErrorString8(rc));
431 ref=IDirectSoundBuffer_Release(second);
432 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
433 "should have 1\n",ref);
435 /* Try to duplicate a primary buffer */
436 /* DSOUND: Error: Can't duplicate primary buffers */
437 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
438 /* rc=0x88780032 */
439 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
440 "should have failed %s\n",DXGetErrorString8(rc));
442 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
443 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
444 DXGetErrorString8(rc));
446 if (winetest_interactive) {
447 trace("Playing a 5 seconds reference tone at the current "
448 "volume.\n");
449 if (rc==DS_OK)
450 trace("(the current volume is %ld according to DirectSound)\n",
451 vol);
452 trace("All subsequent tones should be identical to this one.\n");
453 trace("Listen for stutter, changes in pitch, volume, etc.\n");
455 test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
456 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
458 ref=IDirectSoundBuffer_Release(primary);
459 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
460 "should have 0\n",ref);
463 /* Set the CooperativeLevel back to normal */
464 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
465 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
466 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
467 DXGetErrorString8(rc));
469 EXIT:
470 ref=IDirectSound_Release(dso);
471 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
472 if (ref!=0)
473 return DSERR_GENERIC;
475 return rc;
479 * Test the primary buffer at different formats while keeping the
480 * secondary buffer at a constant format.
482 static HRESULT test_primary_secondary(LPGUID lpGuid)
484 HRESULT rc;
485 LPDIRECTSOUND dso=NULL;
486 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
487 DSBUFFERDESC bufdesc;
488 DSCAPS dscaps;
489 WAVEFORMATEX wfx, wfx2;
490 int f,ref;
492 /* Create the DirectSound object */
493 rc=DirectSoundCreate(lpGuid,&dso,NULL);
494 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
495 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
496 if (rc!=DS_OK)
497 return rc;
499 /* Get the device capabilities */
500 ZeroMemory(&dscaps, sizeof(dscaps));
501 dscaps.dwSize=sizeof(dscaps);
502 rc=IDirectSound_GetCaps(dso,&dscaps);
503 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
504 if (rc!=DS_OK)
505 goto EXIT;
507 /* We must call SetCooperativeLevel before creating primary buffer */
508 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
509 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
510 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
511 DXGetErrorString8(rc));
512 if (rc!=DS_OK)
513 goto EXIT;
515 ZeroMemory(&bufdesc, sizeof(bufdesc));
516 bufdesc.dwSize=sizeof(bufdesc);
517 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
518 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
519 ok(rc==DS_OK && primary!=NULL,
520 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
521 "%s\n",DXGetErrorString8(rc));
523 if (rc==DS_OK && primary!=NULL) {
524 for (f=0;f<NB_FORMATS;f++) {
525 /* We must call SetCooperativeLevel to be allowed to call
526 * SetFormat */
527 /* DSOUND: Setting DirectSound cooperative level to
528 * DSSCL_PRIORITY */
529 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
530 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
531 DXGetErrorString8(rc));
532 if (rc!=DS_OK)
533 goto EXIT;
535 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
536 formats[f][2]);
537 wfx2=wfx;
538 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
539 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
540 DXGetErrorString8(rc));
542 /* There is no garantee that SetFormat will actually change the
543 * format to what we asked for. It depends on what the soundcard
544 * supports. So we must re-query the format.
546 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
547 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
548 DXGetErrorString8(rc));
549 if (rc==DS_OK &&
550 (wfx.wFormatTag!=wfx2.wFormatTag ||
551 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
552 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
553 wfx.nChannels!=wfx2.nChannels)) {
554 trace("Requested primary format tag=0x%04x %ldx%dx%d "
555 "avg.B/s=%ld align=%d\n",
556 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
557 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
558 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
559 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
560 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
563 /* Set the CooperativeLevel back to normal */
564 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
565 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
566 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
567 DXGetErrorString8(rc));
569 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
571 secondary=NULL;
572 ZeroMemory(&bufdesc, sizeof(bufdesc));
573 bufdesc.dwSize=sizeof(bufdesc);
574 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
575 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
576 bufdesc.lpwfxFormat=&wfx2;
577 if (winetest_interactive) {
578 trace(" Testing a primary buffer at %ldx%dx%d with a "
579 "secondary buffer at %ldx%dx%d\n",
580 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
581 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
583 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
584 ok(rc==DS_OK && secondary!=NULL,
585 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
586 "buffer %s\n",DXGetErrorString8(rc));
588 if (rc==DS_OK && secondary!=NULL) {
589 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
590 winetest_interactive,1.0,0,NULL,0,0);
592 ref=IDirectSoundBuffer_Release(secondary);
593 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
594 "should have 0\n",ref);
598 ref=IDirectSoundBuffer_Release(primary);
599 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
600 "should have 0\n",ref);
603 /* Set the CooperativeLevel back to normal */
604 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
605 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
606 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
607 DXGetErrorString8(rc));
609 EXIT:
610 ref=IDirectSound_Release(dso);
611 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
612 if (ref!=0)
613 return DSERR_GENERIC;
615 return rc;
618 static HRESULT test_secondary(LPGUID lpGuid)
620 HRESULT rc;
621 LPDIRECTSOUND dso=NULL;
622 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
623 DSBUFFERDESC bufdesc;
624 DSCAPS dscaps;
625 WAVEFORMATEX wfx;
626 DWORD f;
627 int ref;
629 /* Create the DirectSound object */
630 rc=DirectSoundCreate(lpGuid,&dso,NULL);
631 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
632 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
633 if (rc!=DS_OK)
634 return rc;
636 /* Get the device capabilities */
637 ZeroMemory(&dscaps, sizeof(dscaps));
638 dscaps.dwSize=sizeof(dscaps);
639 rc=IDirectSound_GetCaps(dso,&dscaps);
640 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
641 if (rc!=DS_OK)
642 goto EXIT;
644 /* We must call SetCooperativeLevel before creating primary buffer */
645 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
646 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
647 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
648 DXGetErrorString8(rc));
649 if (rc!=DS_OK)
650 goto EXIT;
652 ZeroMemory(&bufdesc, sizeof(bufdesc));
653 bufdesc.dwSize=sizeof(bufdesc);
654 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
655 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
656 ok(rc==DS_OK && primary!=NULL,
657 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
658 "%s\n",DXGetErrorString8(rc));
660 if (rc==DS_OK && primary!=NULL) {
661 for (f=0;f<NB_FORMATS;f++) {
662 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
663 formats[f][2]);
664 secondary=NULL;
665 ZeroMemory(&bufdesc, sizeof(bufdesc));
666 bufdesc.dwSize=sizeof(bufdesc);
667 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
668 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
669 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
670 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
671 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
672 DXGetErrorString8(rc));
673 if (rc==DS_OK && secondary!=NULL)
674 IDirectSoundBuffer_Release(secondary);
676 secondary=NULL;
677 ZeroMemory(&bufdesc, sizeof(bufdesc));
678 bufdesc.dwSize=sizeof(bufdesc);
679 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
680 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
681 bufdesc.lpwfxFormat=&wfx;
682 if (winetest_interactive) {
683 trace(" Testing a secondary buffer at %ldx%dx%d\n",
684 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
686 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
687 ok(rc==DS_OK && secondary!=NULL,
688 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
689 "buffer %s\n",DXGetErrorString8(rc));
691 if (rc==DS_OK && secondary!=NULL) {
692 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
693 winetest_interactive,1.0,0,NULL,0,0);
695 ref=IDirectSoundBuffer_Release(secondary);
696 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
697 "should have 0\n",ref);
701 ref=IDirectSoundBuffer_Release(primary);
702 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
703 "should have 0\n",ref);
706 /* Set the CooperativeLevel back to normal */
707 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
708 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
709 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
710 DXGetErrorString8(rc));
712 EXIT:
713 ref=IDirectSound_Release(dso);
714 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
715 if (ref!=0)
716 return DSERR_GENERIC;
718 return rc;
721 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
722 LPCSTR lpcstrModule, LPVOID lpContext)
724 HRESULT rc;
725 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
726 rc = test_dsound(lpGuid);
727 if (rc == DSERR_NODRIVER)
728 trace(" No Driver\n");
729 else if (rc == DSERR_ALLOCATED)
730 trace(" Already In Use\n");
731 else {
732 test_primary(lpGuid);
733 test_primary_secondary(lpGuid);
734 test_secondary(lpGuid);
737 return 1;
740 static void dsound_tests()
742 HRESULT rc;
743 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
744 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
747 START_TEST(dsound)
749 CoInitialize(NULL);
751 IDirectSound_tests();
752 dsound_tests();