Don't consider a device in use a failure.
[wine/wine-kai.git] / dlls / dsound / tests / dsound.c
blob1989a4cdb273312bc858551ee1fc12b82c9182b0
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||rc==DSERR_ALLOCATED,
98 "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc));
99 if (rc==DSERR_NODRIVER) {
100 trace(" No Driver\n");
101 return;
102 } else if (rc==DSERR_ALLOCATED) {
103 trace(" Already Allocated\n");
104 return;
108 /* DSOUND: Error: Invalid caps buffer */
109 rc=IDirectSound_GetCaps(dso,0);
110 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
111 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
112 DXGetErrorString8(rc));
114 ZeroMemory(&dscaps, sizeof(dscaps));
116 /* DSOUND: Error: Invalid caps buffer */
117 rc=IDirectSound_GetCaps(dso,&dscaps);
118 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
119 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
120 DXGetErrorString8(rc));
122 dscaps.dwSize=sizeof(dscaps);
124 /* DSOUND: Running on a certified driver */
125 rc=IDirectSound_GetCaps(dso,&dscaps);
126 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
128 rc=IDirectSound_Compact(dso);
129 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
130 DXGetErrorString8(rc));
132 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
133 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
134 DXGetErrorString8(rc));
136 rc=IDirectSound_Compact(dso);
137 ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
139 rc=IDirectSound_GetSpeakerConfig(dso,0);
140 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
141 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
142 DXGetErrorString8(rc));
144 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
145 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
146 DXGetErrorString8(rc));
148 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
149 DSSPEAKER_GEOMETRY_WIDE);
150 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
151 ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
152 DXGetErrorString8(rc));
153 if (rc==DS_OK) {
154 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
155 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
156 DXGetErrorString8(rc));
157 if (rc==DS_OK && speaker_config!=new_speaker_config)
158 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
159 "config: expected 0x%08lx, got 0x%08lx\n",
160 speaker_config,new_speaker_config);
163 ref=IDirectSound_Release(dso);
164 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
167 static void IDirectSound_tests()
169 HRESULT rc;
170 LPDIRECTSOUND dso=NULL;
172 trace("Testing IDirectSound\n");
174 /* try the COM class factory method of creation with no device specified */
175 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
176 &IID_IDirectSound, (void**)&dso);
177 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
178 DXGetErrorString8(rc));
179 if (dso)
180 IDirectSound_test(dso, FALSE, NULL);
182 /* try the COM class factory method of creation with default playback
183 * device specified */
184 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
185 &IID_IDirectSound, (void**)&dso);
186 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
187 DXGetErrorString8(rc));
188 if (dso)
189 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
191 /* try the COM class factory method of creation with default voice
192 * playback device specified */
193 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
194 &IID_IDirectSound, (void**)&dso);
195 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
196 DXGetErrorString8(rc));
197 if (dso)
198 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
200 /* try the COM class factory method of creation with a bad
201 * IID specified */
202 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
203 &CLSID_DirectSoundPrivate, (void**)&dso);
204 ok(rc==E_NOINTERFACE,
205 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
206 "should have failed: %s\n",DXGetErrorString8(rc));
208 /* try the COM class factory method of creation with a bad
209 * GUID and IID specified */
210 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
211 &IID_IDirectSound, (void**)&dso);
212 ok(rc==REGDB_E_CLASSNOTREG,
213 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
214 "should have failed: %s\n",DXGetErrorString8(rc));
216 /* try with no device specified */
217 rc=DirectSoundCreate(NULL,&dso,NULL);
218 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
219 "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
220 if (rc==S_OK && dso)
221 IDirectSound_test(dso, TRUE, NULL);
223 /* try with default playback device specified */
224 rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
225 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
226 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
227 DXGetErrorString8(rc));
228 if (rc==DS_OK && dso)
229 IDirectSound_test(dso, TRUE, NULL);
231 /* try with default voice playback device specified */
232 rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
233 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
234 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
235 DXGetErrorString8(rc));
236 if (rc==DS_OK && dso)
237 IDirectSound_test(dso, TRUE, NULL);
239 /* try with a bad device specified */
240 rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
241 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
242 "should have failed: %s\n",DXGetErrorString8(rc));
245 static HRESULT test_dsound(LPGUID lpGuid)
247 HRESULT rc;
248 LPDIRECTSOUND dso=NULL;
249 int ref;
251 /* DSOUND: Error: Invalid interface buffer */
252 rc=DirectSoundCreate(lpGuid,0,NULL);
253 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
254 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
256 /* Create the DirectSound object */
257 rc=DirectSoundCreate(lpGuid,&dso,NULL);
258 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
259 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
260 if (rc!=DS_OK)
261 return rc;
263 /* Try the enumerated device */
264 IDirectSound_test(dso, TRUE, lpGuid);
266 /* Try the COM class factory method of creation with enumerated device */
267 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
268 &IID_IDirectSound, (void**)&dso);
269 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
270 DXGetErrorString8(rc));
271 if (dso)
272 IDirectSound_test(dso, FALSE, lpGuid);
274 /* Create a DirectSound object */
275 rc=DirectSoundCreate(lpGuid,&dso,NULL);
276 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
277 if (rc==DS_OK) {
278 LPDIRECTSOUND dso1=NULL;
280 /* Create a second DirectSound object */
281 rc=DirectSoundCreate(lpGuid,&dso1,NULL);
282 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
283 if (rc==DS_OK) {
284 /* Release the second DirectSound object */
285 ref=IDirectSound_Release(dso1);
286 ok(ref==0,"IDirectSound_Release() has %d references, should have "
287 "0\n",ref);
288 ok(dso!=dso1,"DirectSound objects should be unique: "
289 "dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
292 /* Release the first DirectSound object */
293 ref=IDirectSound_Release(dso);
294 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
295 ref);
296 if (ref!=0)
297 return DSERR_GENERIC;
298 } else
299 return rc;
301 /* Create a DirectSound object */
302 rc=DirectSoundCreate(lpGuid,&dso,NULL);
303 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
304 if (rc==DS_OK) {
305 LPDIRECTSOUNDBUFFER secondary;
306 DSBUFFERDESC bufdesc;
307 WAVEFORMATEX wfx;
309 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
310 ZeroMemory(&bufdesc, sizeof(bufdesc));
311 bufdesc.dwSize=sizeof(bufdesc);
312 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
313 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
314 bufdesc.lpwfxFormat=&wfx;
315 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
316 ok(rc==DS_OK && secondary!=NULL,
317 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
318 "buffer %s\n",DXGetErrorString8(rc));
319 if (rc==DS_OK && secondary!=NULL) {
320 LPDIRECTSOUND3DBUFFER buffer3d;
321 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
322 (void **)&buffer3d);
323 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
324 "failed: %s\n",DXGetErrorString8(rc));
325 if (rc==DS_OK && buffer3d!=NULL) {
326 ref=IDirectSound3DBuffer_AddRef(buffer3d);
327 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
328 "should have 2\n",ref);
330 ref=IDirectSoundBuffer_AddRef(secondary);
331 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
332 "should have 2\n",ref);
334 /* release with buffer */
335 ref=IDirectSound_Release(dso);
336 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
337 ref);
338 if (ref!=0)
339 return DSERR_GENERIC;
340 } else
341 return rc;
343 return DS_OK;
346 static HRESULT test_primary(LPGUID lpGuid)
348 HRESULT rc;
349 LPDIRECTSOUND dso=NULL;
350 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
351 DSBUFFERDESC bufdesc;
352 DSCAPS dscaps;
353 WAVEFORMATEX wfx;
354 int ref;
356 /* Create the DirectSound object */
357 rc=DirectSoundCreate(lpGuid,&dso,NULL);
358 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
359 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
360 if (rc!=DS_OK)
361 return rc;
363 /* Get the device capabilities */
364 ZeroMemory(&dscaps, sizeof(dscaps));
365 dscaps.dwSize=sizeof(dscaps);
366 rc=IDirectSound_GetCaps(dso,&dscaps);
367 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
368 if (rc!=DS_OK)
369 goto EXIT;
371 /* DSOUND: Error: Invalid buffer description pointer */
372 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
373 ok(rc==DSERR_INVALIDPARAM,
374 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
375 DXGetErrorString8(rc));
377 /* DSOUND: Error: Invalid buffer description pointer */
378 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,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 /* DSOUND: Error: Invalid buffer description pointer */
384 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
385 ok(rc==DSERR_INVALIDPARAM && primary==0,
386 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
387 "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
389 ZeroMemory(&bufdesc, sizeof(bufdesc));
391 /* DSOUND: Error: Invalid size */
392 /* DSOUND: Error: Invalid buffer description */
393 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
394 ok(rc==DSERR_INVALIDPARAM && primary==0,
395 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
396 "primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
398 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
399 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
400 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
401 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
402 DXGetErrorString8(rc));
403 if (rc!=DS_OK)
404 goto EXIT;
406 /* Testing the primary buffer */
407 primary=NULL;
408 ZeroMemory(&bufdesc, sizeof(bufdesc));
409 bufdesc.dwSize=sizeof(bufdesc);
410 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
411 bufdesc.lpwfxFormat = &wfx;
412 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
413 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
414 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
415 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
416 if (rc==DS_OK && primary!=NULL)
417 IDirectSoundBuffer_Release(primary);
419 primary=NULL;
420 ZeroMemory(&bufdesc, sizeof(bufdesc));
421 bufdesc.dwSize=sizeof(bufdesc);
422 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
423 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
424 ok(rc==DS_OK && primary!=NULL,
425 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
426 "%s\n",DXGetErrorString8(rc));
427 if (rc==DS_OK && primary!=NULL) {
428 LONG vol;
430 /* Try to create a second primary buffer */
431 /* DSOUND: Error: The primary buffer already exists.
432 * Any changes made to the buffer description will be ignored. */
433 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
434 ok(rc==DS_OK && second==primary,
435 "IDirectSound_CreateSoundBuffer() should have returned original "
436 "primary buffer: %s\n",DXGetErrorString8(rc));
437 ref=IDirectSoundBuffer_Release(second);
438 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
439 "should have 1\n",ref);
441 /* Try to duplicate a primary buffer */
442 /* DSOUND: Error: Can't duplicate primary buffers */
443 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
444 /* rc=0x88780032 */
445 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
446 "should have failed %s\n",DXGetErrorString8(rc));
448 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
449 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
450 DXGetErrorString8(rc));
452 if (winetest_interactive) {
453 trace("Playing a 5 seconds reference tone at the current "
454 "volume.\n");
455 if (rc==DS_OK)
456 trace("(the current volume is %ld according to DirectSound)\n",
457 vol);
458 trace("All subsequent tones should be identical to this one.\n");
459 trace("Listen for stutter, changes in pitch, volume, etc.\n");
461 test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
462 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
464 ref=IDirectSoundBuffer_Release(primary);
465 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
466 "should have 0\n",ref);
469 /* Set the CooperativeLevel back to normal */
470 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
471 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
472 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
473 DXGetErrorString8(rc));
475 EXIT:
476 ref=IDirectSound_Release(dso);
477 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
478 if (ref!=0)
479 return DSERR_GENERIC;
481 return rc;
485 * Test the primary buffer at different formats while keeping the
486 * secondary buffer at a constant format.
488 static HRESULT test_primary_secondary(LPGUID lpGuid)
490 HRESULT rc;
491 LPDIRECTSOUND dso=NULL;
492 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
493 DSBUFFERDESC bufdesc;
494 DSCAPS dscaps;
495 WAVEFORMATEX wfx, wfx2;
496 int f,ref;
498 /* Create the DirectSound object */
499 rc=DirectSoundCreate(lpGuid,&dso,NULL);
500 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
501 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
502 if (rc!=DS_OK)
503 return rc;
505 /* Get the device capabilities */
506 ZeroMemory(&dscaps, sizeof(dscaps));
507 dscaps.dwSize=sizeof(dscaps);
508 rc=IDirectSound_GetCaps(dso,&dscaps);
509 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
510 if (rc!=DS_OK)
511 goto EXIT;
513 /* We must call SetCooperativeLevel before creating primary buffer */
514 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
515 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
516 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
517 DXGetErrorString8(rc));
518 if (rc!=DS_OK)
519 goto EXIT;
521 ZeroMemory(&bufdesc, sizeof(bufdesc));
522 bufdesc.dwSize=sizeof(bufdesc);
523 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
524 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
525 ok(rc==DS_OK && primary!=NULL,
526 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
527 "%s\n",DXGetErrorString8(rc));
529 if (rc==DS_OK && primary!=NULL) {
530 for (f=0;f<NB_FORMATS;f++) {
531 /* We must call SetCooperativeLevel to be allowed to call
532 * SetFormat */
533 /* DSOUND: Setting DirectSound cooperative level to
534 * DSSCL_PRIORITY */
535 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
536 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
537 DXGetErrorString8(rc));
538 if (rc!=DS_OK)
539 goto EXIT;
541 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
542 formats[f][2]);
543 wfx2=wfx;
544 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
545 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
546 DXGetErrorString8(rc));
548 /* There is no garantee that SetFormat will actually change the
549 * format to what we asked for. It depends on what the soundcard
550 * supports. So we must re-query the format.
552 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
553 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
554 DXGetErrorString8(rc));
555 if (rc==DS_OK &&
556 (wfx.wFormatTag!=wfx2.wFormatTag ||
557 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
558 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
559 wfx.nChannels!=wfx2.nChannels)) {
560 trace("Requested primary format tag=0x%04x %ldx%dx%d "
561 "avg.B/s=%ld align=%d\n",
562 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
563 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
564 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
565 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
566 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
569 /* Set the CooperativeLevel back to normal */
570 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
571 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
572 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
573 DXGetErrorString8(rc));
575 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
577 secondary=NULL;
578 ZeroMemory(&bufdesc, sizeof(bufdesc));
579 bufdesc.dwSize=sizeof(bufdesc);
580 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
581 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
582 bufdesc.lpwfxFormat=&wfx2;
583 if (winetest_interactive) {
584 trace(" Testing a primary buffer at %ldx%dx%d with a "
585 "secondary buffer at %ldx%dx%d\n",
586 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
587 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
589 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
590 ok(rc==DS_OK && secondary!=NULL,
591 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
592 "buffer %s\n",DXGetErrorString8(rc));
594 if (rc==DS_OK && secondary!=NULL) {
595 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
596 winetest_interactive,1.0,0,NULL,0,0);
598 ref=IDirectSoundBuffer_Release(secondary);
599 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
600 "should have 0\n",ref);
604 ref=IDirectSoundBuffer_Release(primary);
605 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
606 "should have 0\n",ref);
609 /* Set the CooperativeLevel back to normal */
610 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
611 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
612 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
613 DXGetErrorString8(rc));
615 EXIT:
616 ref=IDirectSound_Release(dso);
617 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
618 if (ref!=0)
619 return DSERR_GENERIC;
621 return rc;
624 static HRESULT test_secondary(LPGUID lpGuid)
626 HRESULT rc;
627 LPDIRECTSOUND dso=NULL;
628 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
629 DSBUFFERDESC bufdesc;
630 DSCAPS dscaps;
631 WAVEFORMATEX wfx;
632 DWORD f;
633 int ref;
635 /* Create the DirectSound object */
636 rc=DirectSoundCreate(lpGuid,&dso,NULL);
637 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
638 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
639 if (rc!=DS_OK)
640 return rc;
642 /* Get the device capabilities */
643 ZeroMemory(&dscaps, sizeof(dscaps));
644 dscaps.dwSize=sizeof(dscaps);
645 rc=IDirectSound_GetCaps(dso,&dscaps);
646 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
647 if (rc!=DS_OK)
648 goto EXIT;
650 /* We must call SetCooperativeLevel before creating primary buffer */
651 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
652 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
653 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
654 DXGetErrorString8(rc));
655 if (rc!=DS_OK)
656 goto EXIT;
658 ZeroMemory(&bufdesc, sizeof(bufdesc));
659 bufdesc.dwSize=sizeof(bufdesc);
660 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
661 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
662 ok(rc==DS_OK && primary!=NULL,
663 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
664 "%s\n",DXGetErrorString8(rc));
666 if (rc==DS_OK && primary!=NULL) {
667 for (f=0;f<NB_FORMATS;f++) {
668 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
669 formats[f][2]);
670 secondary=NULL;
671 ZeroMemory(&bufdesc, sizeof(bufdesc));
672 bufdesc.dwSize=sizeof(bufdesc);
673 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
674 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
675 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
676 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
677 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
678 DXGetErrorString8(rc));
679 if (rc==DS_OK && secondary!=NULL)
680 IDirectSoundBuffer_Release(secondary);
682 secondary=NULL;
683 ZeroMemory(&bufdesc, sizeof(bufdesc));
684 bufdesc.dwSize=sizeof(bufdesc);
685 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
686 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
687 bufdesc.lpwfxFormat=&wfx;
688 if (winetest_interactive) {
689 trace(" Testing a secondary buffer at %ldx%dx%d\n",
690 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
692 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
693 ok(rc==DS_OK && secondary!=NULL,
694 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
695 "buffer %s\n",DXGetErrorString8(rc));
697 if (rc==DS_OK && secondary!=NULL) {
698 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
699 winetest_interactive,1.0,0,NULL,0,0);
701 ref=IDirectSoundBuffer_Release(secondary);
702 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
703 "should have 0\n",ref);
707 ref=IDirectSoundBuffer_Release(primary);
708 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
709 "should have 0\n",ref);
712 /* Set the CooperativeLevel back to normal */
713 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
714 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
715 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
716 DXGetErrorString8(rc));
718 EXIT:
719 ref=IDirectSound_Release(dso);
720 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
721 if (ref!=0)
722 return DSERR_GENERIC;
724 return rc;
727 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
728 LPCSTR lpcstrModule, LPVOID lpContext)
730 HRESULT rc;
731 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
732 rc = test_dsound(lpGuid);
733 if (rc == DSERR_NODRIVER)
734 trace(" No Driver\n");
735 else if (rc == DSERR_ALLOCATED)
736 trace(" Already In Use\n");
737 else {
738 test_primary(lpGuid);
739 test_primary_secondary(lpGuid);
740 test_secondary(lpGuid);
743 return 1;
746 static void dsound_tests()
748 HRESULT rc;
749 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
750 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
753 START_TEST(dsound)
755 CoInitialize(NULL);
757 IDirectSound_tests();
758 dsound_tests();