- merge audio headers
[reactos.git] / dll / directx / dsound / tests / dsound.c
1 /*
2 * Tests basic sound playback in DirectSound.
3 * In particular we test each standard Windows sound format to make sure
4 * we handle the sound card/driver quirks correctly.
5 *
6 * Part of this test involves playing test tones. But this only makes
7 * sense if someone is going to carefully listen to it, and would only
8 * bother everyone else.
9 * So this is only done if the test is being run in interactive mode.
10 *
11 * Copyright (c) 2002-2004 Francois Gouget
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
30 #include <windows.h>
31
32 #include "wine/test.h"
33 #include "dsound.h"
34 #include "dxerr8.h"
35 #include "dsconf.h"
36
37 #include "dsound_test.h"
38
39 static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
40 LPCGUID lpGuid)
41 {
42 HRESULT rc;
43 DSCAPS dscaps;
44 int ref;
45 IUnknown * unknown;
46 IDirectSound * ds;
47 IDirectSound8 * ds8;
48 DWORD speaker_config, new_speaker_config;
49
50 /* Try to Query for objects */
51 rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
52 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
53 DXGetErrorString8(rc));
54 if (rc==DS_OK)
55 IDirectSound_Release(unknown);
56
57 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
58 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
59 DXGetErrorString8(rc));
60 if (rc==DS_OK)
61 IDirectSound_Release(ds);
62
63 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
64 ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
65 "should have failed: %s\n",DXGetErrorString8(rc));
66 if (rc==DS_OK)
67 IDirectSound8_Release(ds8);
68
69 if (initialized == FALSE) {
70 /* try unitialized object */
71 rc=IDirectSound_GetCaps(dso,0);
72 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
73 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
74 DXGetErrorString8(rc));
75
76 rc=IDirectSound_GetCaps(dso,&dscaps);
77 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
78 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
79 DXGetErrorString8(rc));
80
81 rc=IDirectSound_Compact(dso);
82 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
83 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
84 DXGetErrorString8(rc));
85
86 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
87 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
88 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
89 DXGetErrorString8(rc));
90
91 rc=IDirectSound_Initialize(dso,lpGuid);
92 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
93 "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc));
94 if (rc==DSERR_NODRIVER) {
95 trace(" No Driver\n");
96 goto EXIT;
97 } else if (rc==E_FAIL) {
98 trace(" No Device\n");
99 goto EXIT;
100 } else if (rc==DSERR_ALLOCATED) {
101 trace(" Already In Use\n");
102 goto EXIT;
103 }
104 }
105
106 rc=IDirectSound_Initialize(dso,lpGuid);
107 ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() "
108 "should have returned DSERR_ALREADYINITIALIZED: %s\n",
109 DXGetErrorString8(rc));
110
111 /* DSOUND: Error: Invalid caps buffer */
112 rc=IDirectSound_GetCaps(dso,0);
113 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
114 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
115 DXGetErrorString8(rc));
116
117 ZeroMemory(&dscaps, sizeof(dscaps));
118
119 /* DSOUND: Error: Invalid caps buffer */
120 rc=IDirectSound_GetCaps(dso,&dscaps);
121 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
122 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
123 DXGetErrorString8(rc));
124
125 dscaps.dwSize=sizeof(dscaps);
126
127 /* DSOUND: Running on a certified driver */
128 rc=IDirectSound_GetCaps(dso,&dscaps);
129 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
130
131 rc=IDirectSound_Compact(dso);
132 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
133 DXGetErrorString8(rc));
134
135 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
136 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
137 DXGetErrorString8(rc));
138
139 rc=IDirectSound_Compact(dso);
140 ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
141
142 rc=IDirectSound_GetSpeakerConfig(dso,0);
143 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
144 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
145 DXGetErrorString8(rc));
146
147 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
148 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
149 DXGetErrorString8(rc));
150
151 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
152 DSSPEAKER_GEOMETRY_WIDE);
153 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
154 ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
155 DXGetErrorString8(rc));
156 if (rc==DS_OK) {
157 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
158 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
159 DXGetErrorString8(rc));
160 if (rc==DS_OK && speaker_config!=new_speaker_config)
161 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
162 "config: expected 0x%08lx, got 0x%08lx\n",
163 speaker_config,new_speaker_config);
164 }
165
166 EXIT:
167 ref=IDirectSound_Release(dso);
168 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
169 }
170
171 static void IDirectSound_tests(void)
172 {
173 HRESULT rc;
174 LPDIRECTSOUND dso=NULL;
175
176 trace("Testing IDirectSound\n");
177
178 /* try the COM class factory method of creation with no 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, NULL);
185
186 /* try the COM class factory method of creation with default playback
187 * 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_DefaultPlayback);
194
195 /* try the COM class factory method of creation with default voice
196 * playback device specified */
197 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
198 &IID_IDirectSound, (void**)&dso);
199 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
200 DXGetErrorString8(rc));
201 if (dso)
202 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
203
204 /* try the COM class factory method of creation with a bad
205 * IID specified */
206 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
207 &CLSID_DirectSoundPrivate, (void**)&dso);
208 ok(rc==E_NOINTERFACE,
209 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
210 "should have failed: %s\n",DXGetErrorString8(rc));
211
212 /* try the COM class factory method of creation with a bad
213 * GUID and IID specified */
214 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
215 &IID_IDirectSound, (void**)&dso);
216 ok(rc==REGDB_E_CLASSNOTREG,
217 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
218 "should have failed: %s\n",DXGetErrorString8(rc));
219
220 /* try with no device specified */
221 rc=DirectSoundCreate(NULL,&dso,NULL);
222 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
223 "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
224 if (rc==S_OK && dso)
225 IDirectSound_test(dso, TRUE, NULL);
226
227 /* try with default playback device specified */
228 rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
229 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
230 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
231 DXGetErrorString8(rc));
232 if (rc==DS_OK && dso)
233 IDirectSound_test(dso, TRUE, NULL);
234
235 /* try with default voice playback device specified */
236 rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
237 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
238 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
239 DXGetErrorString8(rc));
240 if (rc==DS_OK && dso)
241 IDirectSound_test(dso, TRUE, NULL);
242
243 /* try with a bad device specified */
244 rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
245 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
246 "should have failed: %s\n",DXGetErrorString8(rc));
247 if (rc==DS_OK && dso)
248 IDirectSound_Release(dso);
249 }
250
251 static HRESULT test_dsound(LPGUID lpGuid)
252 {
253 HRESULT rc;
254 LPDIRECTSOUND dso=NULL;
255 int ref;
256
257 /* DSOUND: Error: Invalid interface buffer */
258 rc=DirectSoundCreate(lpGuid,0,NULL);
259 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
260 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
261
262 /* Create the DirectSound object */
263 rc=DirectSoundCreate(lpGuid,&dso,NULL);
264 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
265 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
266 if (rc!=DS_OK)
267 return rc;
268
269 /* Try the enumerated device */
270 IDirectSound_test(dso, TRUE, lpGuid);
271
272 /* Try the COM class factory method of creation with enumerated device */
273 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
274 &IID_IDirectSound, (void**)&dso);
275 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
276 DXGetErrorString8(rc));
277 if (dso)
278 IDirectSound_test(dso, FALSE, lpGuid);
279
280 /* Create a DirectSound object */
281 rc=DirectSoundCreate(lpGuid,&dso,NULL);
282 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
283 if (rc==DS_OK) {
284 LPDIRECTSOUND dso1=NULL;
285
286 /* Create a second DirectSound object */
287 rc=DirectSoundCreate(lpGuid,&dso1,NULL);
288 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
289 if (rc==DS_OK) {
290 /* Release the second DirectSound object */
291 ref=IDirectSound_Release(dso1);
292 ok(ref==0,"IDirectSound_Release() has %d references, should have "
293 "0\n",ref);
294 ok(dso!=dso1,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso,dso1);
295 }
296
297 /* Release the first DirectSound object */
298 ref=IDirectSound_Release(dso);
299 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
300 ref);
301 if (ref!=0)
302 return DSERR_GENERIC;
303 } else
304 return rc;
305
306 /* Create a DirectSound object */
307 rc=DirectSoundCreate(lpGuid,&dso,NULL);
308 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
309 if (rc==DS_OK) {
310 LPDIRECTSOUNDBUFFER secondary;
311 DSBUFFERDESC bufdesc;
312 WAVEFORMATEX wfx;
313
314 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
315 ZeroMemory(&bufdesc, sizeof(bufdesc));
316 bufdesc.dwSize=sizeof(bufdesc);
317 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
318 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
319 wfx.nBlockAlign);
320 bufdesc.lpwfxFormat=&wfx;
321 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
322 ok(rc==DS_OK && secondary!=NULL,
323 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
324 "buffer %s\n",DXGetErrorString8(rc));
325 if (rc==DS_OK && secondary!=NULL) {
326 LPDIRECTSOUND3DBUFFER buffer3d;
327 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
328 (void **)&buffer3d);
329 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
330 "failed: %s\n",DXGetErrorString8(rc));
331 if (rc==DS_OK && buffer3d!=NULL) {
332 ref=IDirectSound3DBuffer_AddRef(buffer3d);
333 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
334 "should have 2\n",ref);
335 }
336 ref=IDirectSoundBuffer_AddRef(secondary);
337 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
338 "should have 2\n",ref);
339 }
340 /* release with buffer */
341 ref=IDirectSound_Release(dso);
342 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
343 ref);
344 if (ref!=0)
345 return DSERR_GENERIC;
346 } else
347 return rc;
348
349 return DS_OK;
350 }
351
352 static HRESULT test_primary(LPGUID lpGuid)
353 {
354 HRESULT rc;
355 LPDIRECTSOUND dso=NULL;
356 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
357 DSBUFFERDESC bufdesc;
358 DSCAPS dscaps;
359 WAVEFORMATEX wfx;
360 int ref;
361
362 /* Create the DirectSound object */
363 rc=DirectSoundCreate(lpGuid,&dso,NULL);
364 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
365 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
366 if (rc!=DS_OK)
367 return rc;
368
369 /* Get the device capabilities */
370 ZeroMemory(&dscaps, sizeof(dscaps));
371 dscaps.dwSize=sizeof(dscaps);
372 rc=IDirectSound_GetCaps(dso,&dscaps);
373 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
374 if (rc!=DS_OK)
375 goto EXIT;
376
377 /* DSOUND: Error: Invalid buffer description pointer */
378 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
379 ok(rc==DSERR_INVALIDPARAM,
380 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
381 DXGetErrorString8(rc));
382
383 /* DSOUND: Error: Invalid buffer description pointer */
384 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
385 ok(rc==DSERR_INVALIDPARAM && primary==0,
386 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
387 "dsbo=%p\n",DXGetErrorString8(rc),primary);
388
389 /* DSOUND: Error: Invalid buffer description pointer */
390 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
391 ok(rc==DSERR_INVALIDPARAM && primary==0,
392 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
393 "dsbo=0x%p\n",DXGetErrorString8(rc),primary);
394
395 ZeroMemory(&bufdesc, sizeof(bufdesc));
396
397 /* DSOUND: Error: Invalid size */
398 /* DSOUND: Error: Invalid buffer description */
399 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
400 ok(rc==DSERR_INVALIDPARAM && primary==0,
401 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
402 "primary=%p\n",DXGetErrorString8(rc),primary);
403
404 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
405 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
406 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
407 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
408 DXGetErrorString8(rc));
409 if (rc!=DS_OK)
410 goto EXIT;
411
412 /* Testing the primary buffer */
413 primary=NULL;
414 ZeroMemory(&bufdesc, sizeof(bufdesc));
415 bufdesc.dwSize=sizeof(bufdesc);
416 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
417 bufdesc.lpwfxFormat = &wfx;
418 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
419 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
420 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
421 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
422 if (rc==DS_OK && primary!=NULL)
423 IDirectSoundBuffer_Release(primary);
424
425 primary=NULL;
426 ZeroMemory(&bufdesc, sizeof(bufdesc));
427 bufdesc.dwSize=sizeof(bufdesc);
428 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
429 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
430 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
431 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
432 "%s\n",DXGetErrorString8(rc));
433 if (rc==DSERR_CONTROLUNAVAIL)
434 trace(" No Primary\n");
435 else if (rc==DS_OK && primary!=NULL) {
436 LONG vol;
437
438 /* Try to create a second primary buffer */
439 /* DSOUND: Error: The primary buffer already exists.
440 * Any changes made to the buffer description will be ignored. */
441 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
442 ok(rc==DS_OK && second==primary,
443 "IDirectSound_CreateSoundBuffer() should have returned original "
444 "primary buffer: %s\n",DXGetErrorString8(rc));
445 ref=IDirectSoundBuffer_Release(second);
446 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
447 "should have 1\n",ref);
448
449 /* Try to duplicate a primary buffer */
450 /* DSOUND: Error: Can't duplicate primary buffers */
451 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
452 /* rc=0x88780032 */
453 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
454 "should have failed %s\n",DXGetErrorString8(rc));
455
456 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
457 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
458 DXGetErrorString8(rc));
459
460 if (winetest_interactive) {
461 trace("Playing a 5 seconds reference tone at the current "
462 "volume.\n");
463 if (rc==DS_OK)
464 trace("(the current volume is %ld according to DirectSound)\n",
465 vol);
466 trace("All subsequent tones should be identical to this one.\n");
467 trace("Listen for stutter, changes in pitch, volume, etc.\n");
468 }
469 test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
470 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
471
472 ref=IDirectSoundBuffer_Release(primary);
473 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
474 "should have 0\n",ref);
475 }
476
477 /* Set the CooperativeLevel back to normal */
478 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
479 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
480 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
481 DXGetErrorString8(rc));
482
483 EXIT:
484 ref=IDirectSound_Release(dso);
485 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
486 if (ref!=0)
487 return DSERR_GENERIC;
488
489 return rc;
490 }
491
492 /*
493 * Test the primary buffer at different formats while keeping the
494 * secondary buffer at a constant format.
495 */
496 static HRESULT test_primary_secondary(LPGUID lpGuid)
497 {
498 HRESULT rc;
499 LPDIRECTSOUND dso=NULL;
500 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
501 DSBUFFERDESC bufdesc;
502 DSCAPS dscaps;
503 WAVEFORMATEX wfx, wfx2;
504 int f,ref;
505
506 /* Create the DirectSound object */
507 rc=DirectSoundCreate(lpGuid,&dso,NULL);
508 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
509 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
510 if (rc!=DS_OK)
511 return rc;
512
513 /* Get the device capabilities */
514 ZeroMemory(&dscaps, sizeof(dscaps));
515 dscaps.dwSize=sizeof(dscaps);
516 rc=IDirectSound_GetCaps(dso,&dscaps);
517 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
518 if (rc!=DS_OK)
519 goto EXIT;
520
521 /* We must call SetCooperativeLevel before creating primary buffer */
522 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
523 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
524 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
525 DXGetErrorString8(rc));
526 if (rc!=DS_OK)
527 goto EXIT;
528
529 ZeroMemory(&bufdesc, sizeof(bufdesc));
530 bufdesc.dwSize=sizeof(bufdesc);
531 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
532 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
533 ok(rc==DS_OK && primary!=NULL,
534 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
535 "%s\n",DXGetErrorString8(rc));
536
537 if (rc==DS_OK && primary!=NULL) {
538 for (f=0;f<NB_FORMATS;f++) {
539 /* We must call SetCooperativeLevel to be allowed to call
540 * SetFormat */
541 /* DSOUND: Setting DirectSound cooperative level to
542 * DSSCL_PRIORITY */
543 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
544 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
545 DXGetErrorString8(rc));
546 if (rc!=DS_OK)
547 goto EXIT;
548
549 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
550 formats[f][2]);
551 wfx2=wfx;
552 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
553 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
554 DXGetErrorString8(rc));
555
556 /* There is no garantee that SetFormat will actually change the
557 * format to what we asked for. It depends on what the soundcard
558 * supports. So we must re-query the format.
559 */
560 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
561 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
562 DXGetErrorString8(rc));
563 if (rc==DS_OK &&
564 (wfx.wFormatTag!=wfx2.wFormatTag ||
565 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
566 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
567 wfx.nChannels!=wfx2.nChannels)) {
568 trace("Requested primary format tag=0x%04x %ldx%dx%d "
569 "avg.B/s=%ld align=%d\n",
570 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
571 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
572 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
573 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
574 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
575 }
576
577 /* Set the CooperativeLevel back to normal */
578 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
579 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
580 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
581 DXGetErrorString8(rc));
582
583 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
584
585 secondary=NULL;
586 ZeroMemory(&bufdesc, sizeof(bufdesc));
587 bufdesc.dwSize=sizeof(bufdesc);
588 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
589 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
590 wfx.nBlockAlign);
591 bufdesc.lpwfxFormat=&wfx2;
592 if (winetest_interactive) {
593 trace(" Testing a primary buffer at %ldx%dx%d with a "
594 "secondary buffer at %ldx%dx%d\n",
595 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
596 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
597 }
598 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
599 ok(rc==DS_OK && secondary!=NULL,
600 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
601 "buffer %s\n",DXGetErrorString8(rc));
602
603 if (rc==DS_OK && secondary!=NULL) {
604 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
605 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
606
607 ref=IDirectSoundBuffer_Release(secondary);
608 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
609 "should have 0\n",ref);
610 }
611 }
612
613 ref=IDirectSoundBuffer_Release(primary);
614 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
615 "should have 0\n",ref);
616 }
617
618 /* Set the CooperativeLevel back to normal */
619 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
620 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
621 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
622 DXGetErrorString8(rc));
623
624 EXIT:
625 ref=IDirectSound_Release(dso);
626 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
627 if (ref!=0)
628 return DSERR_GENERIC;
629
630 return rc;
631 }
632
633 static HRESULT test_secondary(LPGUID lpGuid)
634 {
635 HRESULT rc;
636 LPDIRECTSOUND dso=NULL;
637 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
638 DSBUFFERDESC bufdesc;
639 DSCAPS dscaps;
640 WAVEFORMATEX wfx, wfx1;
641 DWORD f;
642 int ref;
643
644 /* Create the DirectSound object */
645 rc=DirectSoundCreate(lpGuid,&dso,NULL);
646 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
647 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
648 if (rc!=DS_OK)
649 return rc;
650
651 /* Get the device capabilities */
652 ZeroMemory(&dscaps, sizeof(dscaps));
653 dscaps.dwSize=sizeof(dscaps);
654 rc=IDirectSound_GetCaps(dso,&dscaps);
655 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
656 if (rc!=DS_OK)
657 goto EXIT;
658
659 /* We must call SetCooperativeLevel before creating primary buffer */
660 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
661 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
662 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
663 DXGetErrorString8(rc));
664 if (rc!=DS_OK)
665 goto EXIT;
666
667 ZeroMemory(&bufdesc, sizeof(bufdesc));
668 bufdesc.dwSize=sizeof(bufdesc);
669 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
670 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
671 ok(rc==DS_OK && primary!=NULL,
672 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
673 "%s\n",DXGetErrorString8(rc));
674
675 if (rc==DS_OK && primary!=NULL) {
676 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
677 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
678 DXGetErrorString8(rc));
679 if (rc!=DS_OK)
680 goto EXIT1;
681
682 for (f=0;f<NB_FORMATS;f++) {
683 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
684 formats[f][2]);
685 secondary=NULL;
686 ZeroMemory(&bufdesc, sizeof(bufdesc));
687 bufdesc.dwSize=sizeof(bufdesc);
688 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
689 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
690 wfx.nBlockAlign);
691 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
692 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
693 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
694 DXGetErrorString8(rc));
695 if (rc==DS_OK && secondary!=NULL)
696 IDirectSoundBuffer_Release(secondary);
697
698 secondary=NULL;
699 ZeroMemory(&bufdesc, sizeof(bufdesc));
700 bufdesc.dwSize=sizeof(bufdesc);
701 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
702 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
703 wfx.nBlockAlign);
704 bufdesc.lpwfxFormat=&wfx;
705 if (winetest_interactive) {
706 trace(" Testing a secondary buffer at %ldx%dx%d "
707 "with a primary buffer at %ldx%dx%d\n",
708 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
709 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
710 }
711 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
712 ok(rc==DS_OK && secondary!=NULL,
713 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
714 "buffer %s\n",DXGetErrorString8(rc));
715
716 if (rc==DS_OK && secondary!=NULL) {
717 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
718 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
719
720 ref=IDirectSoundBuffer_Release(secondary);
721 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
722 "should have 0\n",ref);
723 }
724 }
725 EXIT1:
726 ref=IDirectSoundBuffer_Release(primary);
727 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
728 "should have 0\n",ref);
729 }
730
731 /* Set the CooperativeLevel back to normal */
732 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
733 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
734 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
735 DXGetErrorString8(rc));
736
737 EXIT:
738 ref=IDirectSound_Release(dso);
739 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
740 if (ref!=0)
741 return DSERR_GENERIC;
742
743 return rc;
744 }
745
746 static HRESULT test_block_align(LPGUID lpGuid)
747 {
748 HRESULT rc;
749 LPDIRECTSOUND dso=NULL;
750 LPDIRECTSOUNDBUFFER secondary=NULL;
751 DSBUFFERDESC bufdesc;
752 DSBCAPS dsbcaps;
753 WAVEFORMATEX wfx;
754 int ref;
755
756 /* Create the DirectSound object */
757 rc=DirectSoundCreate(lpGuid,&dso,NULL);
758 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
759 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
760 if (rc!=DS_OK)
761 return rc;
762
763 init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
764 ZeroMemory(&bufdesc, sizeof(bufdesc));
765 bufdesc.dwSize=sizeof(bufdesc);
766 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
767 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
768 bufdesc.lpwfxFormat=&wfx;
769 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
770 ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
771 "should have returned DS_OK, returned: %s\n",
772 DXGetErrorString8(rc));
773
774 if (rc==DS_OK && secondary!=NULL) {
775 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
776 dsbcaps.dwSize = sizeof(dsbcaps);
777 rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
778 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
779 "returned: %s\n", DXGetErrorString8(rc));
780 if (rc==DS_OK)
781 ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
782 "Buffer size not a multiple of nBlockAlign: requested %ld, "
783 "got %ld, should be %ld\n", bufdesc.dwBufferBytes,
784 dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
785 ref=IDirectSoundBuffer_Release(secondary);
786 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
787 "should have 0\n",ref);
788 }
789
790 ref=IDirectSound_Release(dso);
791 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
792 if (ref!=0)
793 return DSERR_GENERIC;
794
795 return rc;
796 }
797
798 static struct fmt {
799 int bits;
800 int channels;
801 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
802
803 static HRESULT test_frequency(LPGUID lpGuid)
804 {
805 HRESULT rc;
806 LPDIRECTSOUND dso=NULL;
807 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
808 DSBUFFERDESC bufdesc;
809 DSCAPS dscaps;
810 WAVEFORMATEX wfx, wfx1;
811 DWORD f, r;
812 int ref;
813 int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
814 48000, 96000 };
815
816 /* Create the DirectSound object */
817 rc=DirectSoundCreate(lpGuid,&dso,NULL);
818 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
819 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
820 if (rc!=DS_OK)
821 return rc;
822
823 /* Get the device capabilities */
824 ZeroMemory(&dscaps, sizeof(dscaps));
825 dscaps.dwSize=sizeof(dscaps);
826 rc=IDirectSound_GetCaps(dso,&dscaps);
827 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
828 if (rc!=DS_OK)
829 goto EXIT;
830
831 /* We must call SetCooperativeLevel before creating primary buffer */
832 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
833 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
834 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
835 DXGetErrorString8(rc));
836 if (rc!=DS_OK)
837 goto EXIT;
838
839 ZeroMemory(&bufdesc, sizeof(bufdesc));
840 bufdesc.dwSize=sizeof(bufdesc);
841 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
842 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
843 ok(rc==DS_OK && primary!=NULL,
844 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
845 "%s\n",DXGetErrorString8(rc));
846
847 if (rc==DS_OK && primary!=NULL) {
848 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
849 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
850 DXGetErrorString8(rc));
851 if (rc!=DS_OK)
852 goto EXIT1;
853
854 for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
855 for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
856 init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
857 fmts[f].channels);
858 secondary=NULL;
859 ZeroMemory(&bufdesc, sizeof(bufdesc));
860 bufdesc.dwSize=sizeof(bufdesc);
861 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
862 bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
863 BUFFER_LEN/1000,wfx.nBlockAlign);
864 bufdesc.lpwfxFormat=&wfx;
865 if (winetest_interactive) {
866 trace(" Testing a secondary buffer at %ldx%dx%d "
867 "with a primary buffer at %ldx%dx%d\n",
868 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
869 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
870 }
871 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
872 ok(rc==DS_OK && secondary!=NULL,
873 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
874 "buffer %s\n",DXGetErrorString8(rc));
875
876 if (rc==DS_OK && secondary!=NULL) {
877 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
878 winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
879
880 ref=IDirectSoundBuffer_Release(secondary);
881 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
882 "should have 0\n",ref);
883 }
884 }
885 }
886 EXIT1:
887 ref=IDirectSoundBuffer_Release(primary);
888 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
889 "should have 0\n",ref);
890 }
891
892 /* Set the CooperativeLevel back to normal */
893 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
894 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
895 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
896 DXGetErrorString8(rc));
897
898 EXIT:
899 ref=IDirectSound_Release(dso);
900 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
901 if (ref!=0)
902 return DSERR_GENERIC;
903
904 return rc;
905 }
906
907 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
908 LPCSTR lpcstrModule, LPVOID lpContext)
909 {
910 HRESULT rc;
911 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
912 rc = test_dsound(lpGuid);
913 if (rc == DSERR_NODRIVER)
914 trace(" No Driver\n");
915 else if (rc == DSERR_ALLOCATED)
916 trace(" Already In Use\n");
917 else if (rc == E_FAIL)
918 trace(" No Device\n");
919 else {
920 test_block_align(lpGuid);
921 test_primary(lpGuid);
922 test_primary_secondary(lpGuid);
923 test_secondary(lpGuid);
924 test_frequency(lpGuid);
925 }
926
927 return 1;
928 }
929
930 static void dsound_tests(void)
931 {
932 HRESULT rc;
933 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
934 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
935 }
936
937 START_TEST(dsound)
938 {
939 CoInitialize(NULL);
940
941 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
942
943 IDirectSound_tests();
944 dsound_tests();
945
946 CoUninitialize();
947 }