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