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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28 #include "dsound_test.h"
29
30 #include <initguid.h>
31 #include <mmdeviceapi.h>
32
33 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
34 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
35
align(int length,int align)36 int align(int length, int align)
37 {
38 return (length / align) * align;
39 }
40
IDirectSound8_test(LPDIRECTSOUND8 dso,BOOL initialized,LPCGUID lpGuid)41 static void IDirectSound8_test(LPDIRECTSOUND8 dso, BOOL initialized,
42 LPCGUID lpGuid)
43 {
44 HRESULT rc;
45 DSCAPS dscaps;
46 int ref;
47 IUnknown * unknown;
48 IDirectSound * ds;
49 IDirectSound8 * ds8;
50 DWORD speaker_config, new_speaker_config, ref_speaker_config;
51 DWORD certified;
52
53 /* Try to Query for objects */
54 rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
55 ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %08x\n", rc);
56 if (rc==DS_OK)
57 IDirectSound8_Release(unknown);
58
59 rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
60 ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %08x\n", rc);
61 if (rc==DS_OK)
62 IDirectSound_Release(ds);
63
64 rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
65 ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) "
66 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
67 if (rc==DS_OK)
68 IDirectSound8_Release(ds8);
69
70 if (initialized == FALSE) {
71 /* try uninitialized object */
72 rc=IDirectSound8_GetCaps(dso,0);
73 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps(NULL) "
74 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
75
76 rc=IDirectSound8_GetCaps(dso,&dscaps);
77 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps() "
78 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
79
80 rc=IDirectSound8_Compact(dso);
81 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_Compact() "
82 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
83
84 rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
85 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetSpeakerConfig() "
86 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
87
88 rc=IDirectSound8_VerifyCertification(dso, &certified);
89 ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_VerifyCertification() "
90 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
91
92 rc=IDirectSound8_Initialize(dso,lpGuid);
93 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
94 "IDirectSound8_Initialize() failed: %08x\n",rc);
95 if (rc==DSERR_NODRIVER) {
96 trace(" No Driver\n");
97 goto EXIT;
98 } else if (rc==E_FAIL) {
99 trace(" No Device\n");
100 goto EXIT;
101 } else if (rc==DSERR_ALLOCATED) {
102 trace(" Already In Use\n");
103 goto EXIT;
104 }
105 }
106
107 rc=IDirectSound8_Initialize(dso,lpGuid);
108 ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound8_Initialize() "
109 "should have returned DSERR_ALREADYINITIALIZED: %08x\n", rc);
110
111 /* DSOUND: Error: Invalid caps buffer */
112 rc=IDirectSound8_GetCaps(dso,0);
113 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
114 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
115
116 ZeroMemory(&dscaps, sizeof(dscaps));
117
118 /* DSOUND: Error: Invalid caps buffer */
119 rc=IDirectSound8_GetCaps(dso,&dscaps);
120 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
121 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
122
123 dscaps.dwSize=sizeof(dscaps);
124
125 /* DSOUND: Running on a certified driver */
126 rc=IDirectSound8_GetCaps(dso,&dscaps);
127 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
128
129 rc=IDirectSound8_Compact(dso);
130 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound8_Compact() failed: %08x\n", rc);
131
132 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
133 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
134
135 rc=IDirectSound8_Compact(dso);
136 ok(rc==DS_OK,"IDirectSound8_Compact() failed: %08x\n",rc);
137
138 rc=IDirectSound8_GetSpeakerConfig(dso,0);
139 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetSpeakerConfig(NULL) "
140 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
141
142 rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
143 ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %08x\n", rc);
144 ref_speaker_config = speaker_config;
145
146 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
147 DSSPEAKER_GEOMETRY_WIDE);
148 if (speaker_config == ref_speaker_config)
149 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
150 DSSPEAKER_GEOMETRY_NARROW);
151 if(rc==DS_OK) {
152 rc=IDirectSound8_SetSpeakerConfig(dso,speaker_config);
153 ok(rc==DS_OK,"IDirectSound8_SetSpeakerConfig() failed: %08x\n", rc);
154 }
155 if (rc==DS_OK) {
156 rc=IDirectSound8_GetSpeakerConfig(dso,&new_speaker_config);
157 ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %08x\n", rc);
158 if (rc==DS_OK && speaker_config!=new_speaker_config)
159 trace("IDirectSound8_GetSpeakerConfig() failed to set speaker "
160 "config: expected 0x%08x, got 0x%08x\n",
161 speaker_config,new_speaker_config);
162 IDirectSound8_SetSpeakerConfig(dso,ref_speaker_config);
163 }
164
165 rc=IDirectSound8_VerifyCertification(dso, &certified);
166 ok(rc==DS_OK||rc==E_NOTIMPL,"IDirectSound8_VerifyCertification() failed: %08x\n", rc);
167
168 EXIT:
169 ref=IDirectSound8_Release(dso);
170 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
171 }
172
IDirectSound8_tests(void)173 static void IDirectSound8_tests(void)
174 {
175 HRESULT rc;
176 LPDIRECTSOUND8 dso=NULL;
177 LPCLASSFACTORY cf=NULL;
178
179 trace("Testing IDirectSound8\n");
180
181 rc=CoGetClassObject(&CLSID_DirectSound8, CLSCTX_INPROC_SERVER, NULL,
182 &IID_IClassFactory, (void**)&cf);
183 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound8, IID_IClassFactory) "
184 "failed: %08x\n", rc);
185
186 rc=CoGetClassObject(&CLSID_DirectSound8, CLSCTX_INPROC_SERVER, NULL,
187 &IID_IUnknown, (void**)&cf);
188 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound8, IID_IUnknown) "
189 "failed: %08x\n", rc);
190
191 /* try the COM class factory method of creation with no device specified */
192 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
193 &IID_IDirectSound8, (void**)&dso);
194 ok(rc==S_OK||rc==REGDB_E_CLASSNOTREG,"CoCreateInstance() failed: %08x\n", rc);
195 if (rc==REGDB_E_CLASSNOTREG) {
196 trace(" Class Not Registered\n");
197 return;
198 }
199 if (dso)
200 IDirectSound8_test(dso, FALSE, NULL);
201
202 /* try the COM class factory method of creation with default playback
203 * device specified */
204 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
205 &IID_IDirectSound8, (void**)&dso);
206 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %08x\n", rc);
207 if (dso)
208 IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultPlayback);
209
210 /* try the COM class factory method of creation with default voice
211 * playback device specified */
212 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
213 &IID_IDirectSound8, (void**)&dso);
214 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %08x\n", rc);
215 if (dso)
216 IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
217
218 /* try the COM class factory method of creation with a bad
219 * IID specified */
220 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
221 &CLSID_DirectSoundPrivate, (void**)&dso);
222 ok(rc==E_NOINTERFACE,
223 "CoCreateInstance(CLSID_DirectSound8,CLSID_DirectSoundPrivate) "
224 "should have failed: %08x\n",rc);
225
226 /* try the COM class factory method of creation with a bad
227 * GUID and IID specified */
228 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
229 &IID_IDirectSound8, (void**)&dso);
230 ok(rc==REGDB_E_CLASSNOTREG,
231 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound8) "
232 "should have failed: %08x\n",rc);
233
234 /* try with no device specified */
235 rc=pDirectSoundCreate8(NULL,&dso,NULL);
236 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
237 "DirectSoundCreate8() failed: %08x\n",rc);
238 if (rc==DS_OK && dso)
239 IDirectSound8_test(dso, TRUE, NULL);
240
241 /* try with default playback device specified */
242 rc=pDirectSoundCreate8(&DSDEVID_DefaultPlayback,&dso,NULL);
243 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
244 "DirectSoundCreate8() failed: %08x\n",rc);
245 if (rc==DS_OK && dso)
246 IDirectSound8_test(dso, TRUE, NULL);
247
248 /* try with default voice playback device specified */
249 rc=pDirectSoundCreate8(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
250 ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
251 "DirectSoundCreate8() failed: %08x\n",rc);
252 if (rc==DS_OK && dso)
253 IDirectSound8_test(dso, TRUE, NULL);
254
255 /* try with a bad device specified */
256 rc=pDirectSoundCreate8(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
257 ok(rc==DSERR_NODRIVER,"DirectSoundCreate8(DSDEVID_DefaultVoiceCapture) "
258 "should have failed: %08x\n",rc);
259 }
260
test_dsound8(LPGUID lpGuid)261 static HRESULT test_dsound8(LPGUID lpGuid)
262 {
263 HRESULT rc;
264 LPDIRECTSOUND8 dso=NULL;
265 int ref;
266
267 /* DSOUND: Error: Invalid interface buffer */
268 rc=pDirectSoundCreate8(lpGuid,0,NULL);
269 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate8() should have returned "
270 "DSERR_INVALIDPARAM, returned: %08x\n",rc);
271
272 /* Create the DirectSound8 object */
273 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
274 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
275 "DirectSoundCreate8() failed: %08x\n",rc);
276 if (rc!=DS_OK)
277 return rc;
278
279 /* Try the enumerated device */
280 IDirectSound8_test(dso, TRUE, lpGuid);
281
282 /* Try the COM class factory method of creation with enumerated device */
283 rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
284 &IID_IDirectSound8, (void**)&dso);
285 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
286 if (dso)
287 IDirectSound8_test(dso, FALSE, lpGuid);
288
289 /* Create a DirectSound8 object */
290 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
291 ok(rc==DS_OK,"DirectSoundCreate8() failed: %08x\n",rc);
292 if (rc==DS_OK) {
293 LPDIRECTSOUND8 dso1=NULL;
294
295 /* Create a second DirectSound8 object */
296 rc=pDirectSoundCreate8(lpGuid,&dso1,NULL);
297 ok(rc==DS_OK,"DirectSoundCreate8() failed: %08x\n",rc);
298 if (rc==DS_OK) {
299 /* Release the second DirectSound8 object */
300 ref=IDirectSound8_Release(dso1);
301 ok(ref==0,"IDirectSound8_Release() has %d references, "
302 "should have 0\n",ref);
303 ok(dso!=dso1,"DirectSound8 objects should be unique: "
304 "dso=%p,dso1=%p\n",dso,dso1);
305 }
306
307 /* Release the first DirectSound8 object */
308 ref=IDirectSound8_Release(dso);
309 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
310 ref);
311 if (ref!=0)
312 return DSERR_GENERIC;
313 } else
314 return rc;
315
316 /* Create a DirectSound8 object */
317 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
318 ok(rc==DS_OK,"DirectSoundCreate8() failed: %08x\n",rc);
319 if (rc==DS_OK) {
320 LPDIRECTSOUNDBUFFER secondary;
321 DSBUFFERDESC bufdesc;
322 WAVEFORMATEX wfx;
323
324 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
325 ZeroMemory(&bufdesc, sizeof(bufdesc));
326 bufdesc.dwSize=sizeof(bufdesc);
327 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
328 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
329 wfx.nBlockAlign);
330 bufdesc.lpwfxFormat=&wfx;
331 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
332 ok(rc==DS_OK && secondary!=NULL,
333 "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
334 "buffer: %08x\n",rc);
335 if (rc==DS_OK && secondary!=NULL) {
336 LPDIRECTSOUND3DBUFFER buffer3d;
337 LPDIRECTSOUNDBUFFER8 buffer8;
338 rc=IDirectSound8_QueryInterface(secondary,
339 &IID_IDirectSound3DBuffer,
340 (void **)&buffer3d);
341 ok(rc==DS_OK && buffer3d!=NULL,
342 "IDirectSound8_QueryInterface() failed: %08x\n", rc);
343 if (rc==DS_OK && buffer3d!=NULL) {
344 ref=IDirectSound3DBuffer_AddRef(buffer3d);
345 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
346 "should have 2\n",ref);
347 }
348 rc=IDirectSound8_QueryInterface(secondary,
349 &IID_IDirectSoundBuffer8,
350 (void **)&buffer8);
351 if (rc==DS_OK && buffer8!=NULL) {
352 ok(buffer8==(IDirectSoundBuffer8*)secondary,
353 "IDirectSoundBuffer8 iface different from IDirectSoundBuffer.\n");
354 ref=IDirectSoundBuffer8_AddRef(buffer8);
355 ok(ref==3,"IDirectSoundBuffer8_AddRef() has %d references, "
356 "should have 3\n",ref);
357 }
358 ref=IDirectSoundBuffer_AddRef(secondary);
359 ok(ref==4,"IDirectSoundBuffer_AddRef() has %d references, "
360 "should have 4\n",ref);
361 }
362 /* release with buffer */
363 ref=IDirectSound8_Release(dso);
364 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
365 ref);
366 if (ref!=0)
367 return DSERR_GENERIC;
368 } else
369 return rc;
370
371 return DS_OK;
372 }
373
test_primary8(LPGUID lpGuid)374 static HRESULT test_primary8(LPGUID lpGuid)
375 {
376 HRESULT rc;
377 LPDIRECTSOUND8 dso=NULL;
378 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
379 LPDIRECTSOUNDBUFFER8 pb8 = NULL;
380 DSBUFFERDESC bufdesc;
381 DSCAPS dscaps;
382 WAVEFORMATEX wfx;
383 int ref;
384
385 /* Create the DirectSound object */
386 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
387 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
388 "DirectSoundCreate8() failed: %08x\n",rc);
389 if (rc!=DS_OK)
390 return rc;
391
392 /* Get the device capabilities */
393 ZeroMemory(&dscaps, sizeof(dscaps));
394 dscaps.dwSize=sizeof(dscaps);
395 rc=IDirectSound8_GetCaps(dso,&dscaps);
396 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
397 if (rc!=DS_OK)
398 goto EXIT;
399
400 /* DSOUND: Error: Invalid buffer description pointer */
401 rc=IDirectSound8_CreateSoundBuffer(dso,0,0,NULL);
402 ok(rc==DSERR_INVALIDPARAM,
403 "IDirectSound8_CreateSoundBuffer should have returned "
404 "DSERR_INVALIDPARAM, returned: %08x\n",rc);
405
406 /* DSOUND: Error: Invalid buffer description pointer */
407 rc=IDirectSound8_CreateSoundBuffer(dso,0,&primary,NULL);
408 ok(rc==DSERR_INVALIDPARAM && primary==0,
409 "IDirectSound8_CreateSoundBuffer() should have returned "
410 "DSERR_INVALIDPARAM, returned: rc=%08x,dsbo=%p\n",
411 rc,primary);
412
413 ZeroMemory(&bufdesc, sizeof(bufdesc));
414 bufdesc.dwSize = sizeof(DSBUFFERDESC);
415
416 /* DSOUND: Error: Invalid dsound buffer interface pointer */
417 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,0,NULL);
418 ok(rc==DSERR_INVALIDPARAM && primary==0,
419 "IDirectSound8_CreateSoundBuffer() should have failed: rc=%08x,"
420 "dsbo=%p\n",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=%08x,"
429 "primary=%p\n",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: %08x\n", rc);
435 if (rc!=DS_OK)
436 goto EXIT;
437
438 /* Testing the primary buffer */
439 primary=NULL;
440 ZeroMemory(&bufdesc, sizeof(bufdesc));
441 bufdesc.dwSize=sizeof(bufdesc);
442 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
443 bufdesc.lpwfxFormat = &wfx;
444 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
445 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
446 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() should have "
447 "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
448 if (rc==DS_OK && primary!=NULL)
449 IDirectSoundBuffer_Release(primary);
450
451 primary=NULL;
452 ZeroMemory(&bufdesc, sizeof(bufdesc));
453 bufdesc.dwSize=sizeof(bufdesc);
454 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
455 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
456 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
457 "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: "
458 "%08x\n",rc);
459 if (rc==DSERR_CONTROLUNAVAIL)
460 trace(" No Primary\n");
461 else if (rc==DS_OK && primary!=NULL) {
462 LONG vol;
463
464 /* Try to create a second primary buffer */
465 /* DSOUND: Error: The primary buffer already exists.
466 * Any changes made to the buffer description will be ignored. */
467 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
468 ok(rc==DS_OK && second==primary,
469 "IDirectSound8_CreateSoundBuffer() should have returned original "
470 "primary buffer: %08x\n",rc);
471 ref=IDirectSoundBuffer_Release(second);
472 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
473 "should have 1\n",ref);
474
475 /* Try to duplicate a primary buffer */
476 /* DSOUND: Error: Can't duplicate primary buffers */
477 rc=IDirectSound8_DuplicateSoundBuffer(dso,primary,&third);
478 /* rc=0x88780032 */
479 ok(rc!=DS_OK,"IDirectSound8_DuplicateSoundBuffer() primary buffer "
480 "should have failed %08x\n",rc);
481
482 /* Primary buffers don't have an IDirectSoundBuffer8 */
483 rc = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer8, (LPVOID*)&pb8);
484 ok(FAILED(rc), "Primary buffer does have an IDirectSoundBuffer8: %08x\n", rc);
485
486 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
487 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc);
488
489 if (winetest_interactive) {
490 trace("Playing a 5 seconds reference tone at the current volume.\n");
491 if (rc==DS_OK)
492 trace("(the current volume is %d according to DirectSound)\n",
493 vol);
494 trace("All subsequent tones should be identical to this one.\n");
495 trace("Listen for stutter, changes in pitch, volume, etc.\n");
496 }
497 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
498 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
499
500 ref=IDirectSoundBuffer_Release(primary);
501 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
502 "should have 0\n",ref);
503 }
504
505 /* Set the CooperativeLevel back to normal */
506 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
507 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
508 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
509
510 EXIT:
511 ref=IDirectSound8_Release(dso);
512 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
513 if (ref!=0)
514 return DSERR_GENERIC;
515
516 return rc;
517 }
518
519 /*
520 * Test the primary buffer at different formats while keeping the
521 * secondary buffer at a constant format.
522 */
test_primary_secondary8(LPGUID lpGuid)523 static HRESULT test_primary_secondary8(LPGUID lpGuid)
524 {
525 HRESULT rc;
526 LPDIRECTSOUND8 dso=NULL;
527 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
528 DSBUFFERDESC bufdesc;
529 DSCAPS dscaps;
530 WAVEFORMATEX wfx, wfx2;
531 int ref;
532 unsigned int f, tag;
533
534 /* Create the DirectSound object */
535 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
536 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
537 "DirectSoundCreate8() failed: %08x\n",rc);
538 if (rc!=DS_OK)
539 return rc;
540
541 /* Get the device capabilities */
542 ZeroMemory(&dscaps, sizeof(dscaps));
543 dscaps.dwSize=sizeof(dscaps);
544 rc=IDirectSound8_GetCaps(dso,&dscaps);
545 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
546 if (rc!=DS_OK)
547 goto EXIT;
548
549 /* We must call SetCooperativeLevel before creating primary buffer */
550 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
551 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
552 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", 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 "%08x\n",rc);
563
564 if (rc==DS_OK && primary!=NULL) {
565 for (f=0;f<NB_FORMATS;f++) {
566 for (tag=0;tag<NB_TAGS;tag++) {
567 /* if float, we only want to test 32-bit */
568 if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
569 continue;
570
571 /* We must call SetCooperativeLevel to be allowed to call
572 * SetFormat */
573 /* DSOUND: Setting DirectSound cooperative level to
574 * DSSCL_PRIORITY */
575 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
576 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
577 if (rc!=DS_OK)
578 goto EXIT;
579
580 init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
581 formats[f][2]);
582 wfx2=wfx;
583 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
584 ok(rc==DS_OK
585 || rc==DSERR_INVALIDPARAM, /* 2003 */
586 "IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
587 format_string(&wfx), rc);
588
589 /* There is no guarantee that SetFormat will actually change the
590 * format to what we asked for. It depends on what the soundcard
591 * supports. So we must re-query the format.
592 */
593 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
594 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
595 if (rc==DS_OK &&
596 (wfx.wFormatTag!=wfx2.wFormatTag ||
597 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
598 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
599 wfx.nChannels!=wfx2.nChannels)) {
600 trace("Requested primary format tag=0x%04x %dx%dx%d "
601 "avg.B/s=%d align=%d\n",
602 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
603 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
604 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
605 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
606 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
607 }
608
609 /* Set the CooperativeLevel back to normal */
610 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
611 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
612 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
613
614 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
615
616 secondary=NULL;
617 ZeroMemory(&bufdesc, sizeof(bufdesc));
618 bufdesc.dwSize=sizeof(bufdesc);
619 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
620 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
621 wfx.nBlockAlign);
622 bufdesc.lpwfxFormat=&wfx2;
623 if (winetest_interactive) {
624 trace(" Testing a primary buffer at %dx%dx%d (fmt=%d) with a "
625 "secondary buffer at %dx%dx%d\n",
626 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
627 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
628 }
629 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
630 ok(rc==DS_OK && secondary!=NULL,
631 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
632 "buffer %08x\n",rc);
633
634 if (rc==DS_OK && secondary!=NULL) {
635 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
636 winetest_interactive,1.0,0,NULL,0,0);
637
638 ref=IDirectSoundBuffer_Release(secondary);
639 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
640 "should have 0\n",ref);
641 }
642 }
643 }
644
645 ref=IDirectSoundBuffer_Release(primary);
646 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
647 "should have 0\n",ref);
648 }
649
650 /* Set the CooperativeLevel back to normal */
651 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
652 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
653 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
654
655 EXIT:
656 ref=IDirectSound8_Release(dso);
657 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
658 if (ref!=0)
659 return DSERR_GENERIC;
660
661 return rc;
662 }
663
test_secondary8(LPGUID lpGuid)664 static HRESULT test_secondary8(LPGUID lpGuid)
665 {
666 HRESULT rc;
667 LPDIRECTSOUND8 dso=NULL;
668 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
669 DSBUFFERDESC bufdesc;
670 DSCAPS dscaps;
671 WAVEFORMATEX wfx, wfx1;
672 DWORD f, tag;
673 int ref;
674
675 /* Create the DirectSound object */
676 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
677 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
678 "DirectSoundCreate8() failed: %08x\n",rc);
679 if (rc!=DS_OK)
680 return rc;
681
682 /* Get the device capabilities */
683 ZeroMemory(&dscaps, sizeof(dscaps));
684 dscaps.dwSize=sizeof(dscaps);
685 rc=IDirectSound8_GetCaps(dso,&dscaps);
686 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
687 if (rc!=DS_OK)
688 goto EXIT;
689
690 /* We must call SetCooperativeLevel before creating primary buffer */
691 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
692 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
693 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
694 if (rc!=DS_OK)
695 goto EXIT;
696
697 ZeroMemory(&bufdesc, sizeof(bufdesc));
698 bufdesc.dwSize=sizeof(bufdesc);
699 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
700 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
701 ok(rc==DS_OK && primary!=NULL,
702 "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
703 "%08x\n",rc);
704
705 if (rc==DS_OK && primary!=NULL) {
706 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
707 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
708 if (rc!=DS_OK)
709 goto EXIT1;
710
711 for (f=0;f<NB_FORMATS;f++) {
712 for (tag=0;tag<NB_TAGS;tag++) {
713 WAVEFORMATEXTENSIBLE wfxe;
714
715 /* if float, we only want to test 32-bit */
716 if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
717 continue;
718
719 init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
720 formats[f][2]);
721 secondary=NULL;
722 ZeroMemory(&bufdesc, sizeof(bufdesc));
723 bufdesc.dwSize=sizeof(bufdesc);
724 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
725 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
726 wfx.nBlockAlign);
727 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
728 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() "
729 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
730 if (rc==DS_OK && secondary!=NULL)
731 IDirectSoundBuffer_Release(secondary);
732
733 secondary=NULL;
734 ZeroMemory(&bufdesc, sizeof(bufdesc));
735 bufdesc.dwSize=sizeof(bufdesc);
736 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
737 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
738 wfx.nBlockAlign);
739 bufdesc.lpwfxFormat=&wfx;
740 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
741 if (wfx.wBitsPerSample != 8 && wfx.wBitsPerSample != 16)
742 ok(((rc == DSERR_CONTROLUNAVAIL || rc == DSERR_INVALIDCALL || rc == DSERR_INVALIDPARAM /* 2003 */) && !secondary)
743 || rc == DS_OK, /* driver dependent? */
744 "IDirectSound_CreateSoundBuffer() "
745 "should have returned (DSERR_CONTROLUNAVAIL or DSERR_INVALIDCALL) "
746 "and NULL, returned: %08x %p\n", rc, secondary);
747 else
748 ok(rc==DS_OK && secondary!=NULL,
749 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
750 "buffer %08x\n",rc);
751 if (secondary)
752 IDirectSoundBuffer_Release(secondary);
753 secondary = NULL;
754
755 bufdesc.lpwfxFormat=(WAVEFORMATEX*)&wfxe;
756 wfxe.Format = wfx;
757 wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
758 wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
759 wfxe.Format.cbSize = 1;
760 wfxe.Samples.wValidBitsPerSample = wfx.wBitsPerSample;
761 wfxe.dwChannelMask = (wfx.nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO);
762
763 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
764 ok(rc==DSERR_INVALIDPARAM && !secondary,
765 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
766 rc, secondary);
767 if (secondary)
768 {
769 IDirectSoundBuffer_Release(secondary);
770 secondary=NULL;
771 }
772
773 wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx) + 1;
774
775 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
776 ok(((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL /* 2003 */) && !secondary)
777 || rc==DS_OK /* driver dependent? */,
778 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
779 rc, secondary);
780 if (secondary)
781 {
782 IDirectSoundBuffer_Release(secondary);
783 secondary=NULL;
784 }
785
786 wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
787 wfxe.SubFormat = GUID_NULL;
788 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
789 ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL) && !secondary,
790 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
791 rc, secondary);
792 if (secondary)
793 {
794 IDirectSoundBuffer_Release(secondary);
795 secondary=NULL;
796 }
797
798 wfxe.Format.cbSize = sizeof(wfxe);
799 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
800 ok((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL || rc==E_INVALIDARG) && !secondary,
801 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
802 rc, secondary);
803 if (secondary)
804 {
805 IDirectSoundBuffer_Release(secondary);
806 secondary=NULL;
807 }
808
809 wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
810 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
811 ok(rc==DS_OK && secondary,
812 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
813 rc, secondary);
814 if (secondary)
815 {
816 IDirectSoundBuffer_Release(secondary);
817 secondary=NULL;
818 }
819
820 wfxe.Format.cbSize = sizeof(wfxe) + 1;
821 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
822 ok(((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL /* 2003 */) && !secondary)
823 || rc==DS_OK /* driver dependent? */,
824 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
825 rc, secondary);
826 if (secondary)
827 {
828 IDirectSoundBuffer_Release(secondary);
829 secondary=NULL;
830 }
831
832 wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
833 ++wfxe.Samples.wValidBitsPerSample;
834 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
835 ok(rc==DSERR_INVALIDPARAM && !secondary,
836 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
837 rc, secondary);
838 if (secondary)
839 {
840 IDirectSoundBuffer_Release(secondary);
841 secondary=NULL;
842 }
843 --wfxe.Samples.wValidBitsPerSample;
844
845 wfxe.Samples.wValidBitsPerSample = 0;
846 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
847 ok(rc==DS_OK && secondary,
848 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
849 rc, secondary);
850 if (secondary)
851 {
852 IDirectSoundBuffer_Release(secondary);
853 secondary=NULL;
854 }
855 wfxe.Samples.wValidBitsPerSample = wfxe.Format.wBitsPerSample;
856
857 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
858 ok(rc==DS_OK && secondary!=NULL,
859 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
860 "buffer %08x\n",rc);
861
862 if (rc==DS_OK && secondary!=NULL) {
863 if (winetest_interactive) {
864 trace(" Testing a secondary buffer at %dx%dx%d (fmt=%d) "
865 "with a primary buffer at %dx%dx%d\n",
866 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
867 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
868 }
869 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
870 winetest_interactive,1.0,0,NULL,0,0);
871
872 ref=IDirectSoundBuffer_Release(secondary);
873 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
874 "should have 0\n",ref);
875 }
876 }
877 }
878 EXIT1:
879 ref=IDirectSoundBuffer_Release(primary);
880 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
881 "should have 0\n",ref);
882 }
883
884 /* Set the CooperativeLevel back to normal */
885 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
886 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
887 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
888
889 EXIT:
890 ref=IDirectSound8_Release(dso);
891 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
892 if (ref!=0)
893 return DSERR_GENERIC;
894
895 return rc;
896 }
897
dsenum_callback(LPGUID lpGuid,LPCSTR lpcstrDescription,LPCSTR lpcstrModule,LPVOID lpContext)898 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
899 LPCSTR lpcstrModule, LPVOID lpContext)
900 {
901 HRESULT rc;
902 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
903 rc = test_dsound8(lpGuid);
904 if (rc == DSERR_NODRIVER)
905 trace(" No Driver\n");
906 else if (rc == DSERR_ALLOCATED)
907 trace(" Already In Use\n");
908 else if (rc == E_FAIL)
909 trace(" No Device\n");
910 else {
911 test_primary8(lpGuid);
912 test_primary_secondary8(lpGuid);
913 test_secondary8(lpGuid);
914 }
915
916 return 1;
917 }
918
dsound8_tests(void)919 static void dsound8_tests(void)
920 {
921 HRESULT rc;
922 rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
923 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc);
924 }
925
test_hw_buffers(void)926 static void test_hw_buffers(void)
927 {
928 IDirectSound8 *ds;
929 IDirectSoundBuffer *primary, *primary2, **secondaries, *secondary;
930 IDirectSoundBuffer8 *buf8;
931 DSCAPS caps;
932 DSBCAPS bufcaps;
933 DSBUFFERDESC bufdesc;
934 WAVEFORMATEX fmt;
935 UINT i;
936 HRESULT hr;
937
938 hr = pDirectSoundCreate8(NULL, &ds, NULL);
939 ok(hr == S_OK || hr == DSERR_NODRIVER || hr == DSERR_ALLOCATED || hr == E_FAIL,
940 "DirectSoundCreate8 failed: %08x\n", hr);
941 if(hr != S_OK)
942 return;
943
944 caps.dwSize = sizeof(caps);
945
946 hr = IDirectSound8_GetCaps(ds, &caps);
947 ok(hr == S_OK, "GetCaps failed: %08x\n", hr);
948
949 ok(caps.dwPrimaryBuffers == 1, "Got wrong number of primary buffers: %u\n",
950 caps.dwPrimaryBuffers);
951
952 /* DSBCAPS_LOC* is ignored for primary buffers */
953 bufdesc.dwSize = sizeof(bufdesc);
954 bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
955 DSBCAPS_PRIMARYBUFFER;
956 bufdesc.dwBufferBytes = 0;
957 bufdesc.dwReserved = 0;
958 bufdesc.lpwfxFormat = NULL;
959 bufdesc.guid3DAlgorithm = GUID_NULL;
960
961 hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &primary, NULL);
962 ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
963 if(hr != S_OK){
964 IDirectSound8_Release(ds);
965 return;
966 }
967
968 bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE |
969 DSBCAPS_PRIMARYBUFFER;
970
971 hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &primary2, NULL);
972 ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
973 ok(primary == primary2, "Got different primary buffers: %p, %p\n", primary, primary2);
974 if(hr == S_OK)
975 IDirectSoundBuffer_Release(primary2);
976
977 buf8 = (IDirectSoundBuffer8 *)0xDEADBEEF;
978 hr = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer8,
979 (void**)&buf8);
980 ok(hr == E_NOINTERFACE, "QueryInterface gave wrong failure: %08x\n", hr);
981 ok(buf8 == NULL, "Pointer didn't get set to NULL\n");
982
983 fmt.wFormatTag = WAVE_FORMAT_PCM;
984 fmt.nChannels = 2;
985 fmt.nSamplesPerSec = 48000;
986 fmt.wBitsPerSample = 16;
987 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
988 fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
989 fmt.cbSize = 0;
990
991 bufdesc.lpwfxFormat = &fmt;
992 bufdesc.dwBufferBytes = fmt.nSamplesPerSec * fmt.nBlockAlign / 10;
993 bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
994 DSBCAPS_CTRLVOLUME;
995
996 secondaries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
997 sizeof(IDirectSoundBuffer *) * caps.dwMaxHwMixingAllBuffers);
998
999 /* try to fill all of the hw buffers */
1000 trace("dwMaxHwMixingAllBuffers: %u\n", caps.dwMaxHwMixingAllBuffers);
1001 trace("dwMaxHwMixingStaticBuffers: %u\n", caps.dwMaxHwMixingStaticBuffers);
1002 trace("dwMaxHwMixingStreamingBuffers: %u\n", caps.dwMaxHwMixingStreamingBuffers);
1003 for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i){
1004 hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &secondaries[i], NULL);
1005 ok(hr == S_OK || hr == E_NOTIMPL || broken(hr == DSERR_CONTROLUNAVAIL) || broken(hr == E_FAIL),
1006 "CreateSoundBuffer(%u) failed: %08x\n", i, hr);
1007 if(hr != S_OK)
1008 break;
1009
1010 bufcaps.dwSize = sizeof(bufcaps);
1011 hr = IDirectSoundBuffer_GetCaps(secondaries[i], &bufcaps);
1012 ok(hr == S_OK, "GetCaps failed: %08x\n", hr);
1013 ok((bufcaps.dwFlags & DSBCAPS_LOCHARDWARE) != 0,
1014 "Buffer wasn't allocated in hardware, dwFlags: %x\n", bufcaps.dwFlags);
1015 }
1016
1017 /* see if we can create one more */
1018 hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &secondary, NULL);
1019 ok((i == caps.dwMaxHwMixingAllBuffers && hr == DSERR_ALLOCATED) || /* out of hw buffers */
1020 (caps.dwMaxHwMixingAllBuffers == 0 && hr == DSERR_INVALIDCALL) || /* no hw buffers at all */
1021 hr == E_NOTIMPL || /* don't support hw buffers */
1022 broken(hr == DSERR_CONTROLUNAVAIL) || /* vmware winxp, others? */
1023 broken(hr == E_FAIL) || /* broken AC97 driver */
1024 broken(hr == S_OK) /* broken driver allows more hw bufs than dscaps claims */,
1025 "CreateSoundBuffer(%u) gave wrong error: %08x\n", i, hr);
1026 if(hr == S_OK)
1027 IDirectSoundBuffer_Release(secondary);
1028
1029 for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i)
1030 if(secondaries[i])
1031 IDirectSoundBuffer_Release(secondaries[i]);
1032
1033 HeapFree(GetProcessHeap(), 0, secondaries);
1034
1035 IDirectSoundBuffer_Release(primary);
1036 IDirectSound8_Release(ds);
1037 }
1038
1039 static struct {
1040 UINT dev_count;
1041 GUID guid;
1042 } default_info = { 0 };
1043
default_device_cb(GUID * guid,const char * desc,const char * module,void * user)1044 static BOOL WINAPI default_device_cb(GUID *guid, const char *desc,
1045 const char *module, void *user)
1046 {
1047 trace("guid: %p, desc: %s\n", guid, desc);
1048 if(!guid)
1049 ok(default_info.dev_count == 0, "Got NULL GUID not in first position\n");
1050 else{
1051 if(default_info.dev_count == 0){
1052 ok(IsEqualGUID(guid, &default_info.guid), "Expected default device GUID\n");
1053 }else{
1054 ok(!IsEqualGUID(guid, &default_info.guid), "Got default GUID at unexpected location: %u\n",
1055 default_info.dev_count);
1056 }
1057
1058 /* only count real devices */
1059 ++default_info.dev_count;
1060 }
1061
1062 return TRUE;
1063 }
1064
test_first_device(void)1065 static void test_first_device(void)
1066 {
1067 IMMDeviceEnumerator *devenum;
1068 IMMDevice *defdev;
1069 IPropertyStore *ps;
1070 PROPVARIANT pv;
1071 HRESULT hr;
1072
1073 hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
1074 CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&devenum);
1075 if(FAILED(hr)){
1076 win_skip("MMDevAPI is not available, skipping default device test\n");
1077 return;
1078 }
1079
1080 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, eRender,
1081 eMultimedia, &defdev);
1082 if (hr == E_NOTFOUND) {
1083 win_skip("No default device found\n");
1084 return;
1085 }
1086 ok(hr == S_OK, "GetDefaultAudioEndpoint failed: %08x\n", hr);
1087
1088 hr = IMMDevice_OpenPropertyStore(defdev, STGM_READ, &ps);
1089 ok(hr == S_OK, "OpenPropertyStore failed: %08x\n", hr);
1090
1091 PropVariantInit(&pv);
1092
1093 hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_GUID, &pv);
1094 ok(hr == S_OK, "GetValue failed: %08x\n", hr);
1095
1096 CLSIDFromString(pv.pwszVal, &default_info.guid);
1097
1098 PropVariantClear(&pv);
1099 IPropertyStore_Release(ps);
1100 IMMDevice_Release(defdev);
1101 IMMDeviceEnumerator_Release(devenum);
1102
1103 hr = pDirectSoundEnumerateA(&default_device_cb, NULL);
1104 ok(hr == S_OK, "DirectSoundEnumerateA failed: %08x\n", hr);
1105 }
1106
test_COM(void)1107 static void test_COM(void)
1108 {
1109 IDirectSound *ds;
1110 IDirectSound8 *ds8 = (IDirectSound8*)0xdeadbeef;
1111 IUnknown *unk, *unk8;
1112 ULONG refcount;
1113 HRESULT hr;
1114
1115 /* COM aggregation */
1116 hr = CoCreateInstance(&CLSID_DirectSound8, (IUnknown*)&ds, CLSCTX_INPROC_SERVER,
1117 &IID_IUnknown, (void**)&ds8);
1118 ok(hr == CLASS_E_NOAGGREGATION,
1119 "DirectSound create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
1120 ok(!ds8, "ds8 = %p\n", ds8);
1121
1122 /* Invalid RIID */
1123 hr = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
1124 &IID_IDirectSound3DBuffer, (void**)&ds8);
1125 ok(hr == E_NOINTERFACE,
1126 "DirectSound create failed: %08x, expected E_NOINTERFACE\n", hr);
1127
1128 /* Same refcount for IDirectSound and IDirectSound8 */
1129 hr = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound8,
1130 (void**)&ds8);
1131 ok(hr == S_OK, "DirectSound create failed: %08x, expected S_OK\n", hr);
1132 refcount = IDirectSound8_AddRef(ds8);
1133 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
1134 hr = IDirectSound8_QueryInterface(ds8, &IID_IDirectSound, (void**)&ds);
1135 ok(hr == S_OK, "QueryInterface for IID_IDirectSound failed: %08x\n", hr);
1136 refcount = IDirectSound8_AddRef(ds8);
1137 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
1138 refcount = IDirectSound_AddRef(ds);
1139 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
1140
1141 /* Separate refcount for IUnknown */
1142 hr = IDirectSound_QueryInterface(ds, &IID_IUnknown, (void**)&unk);
1143 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
1144 refcount = IUnknown_AddRef(unk);
1145 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
1146 hr = IDirectSound_QueryInterface(ds8, &IID_IUnknown, (void**)&unk8);
1147 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
1148 refcount = IUnknown_AddRef(unk8);
1149 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
1150 refcount = IDirectSound_AddRef(ds);
1151 ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
1152
1153 while (IDirectSound_Release(ds));
1154 while (IUnknown_Release(unk));
1155 }
1156
START_TEST(dsound8)1157 START_TEST(dsound8)
1158 {
1159 HMODULE hDsound;
1160
1161 CoInitialize(NULL);
1162
1163 hDsound = LoadLibrary("dsound.dll");
1164 if (hDsound)
1165 {
1166
1167 pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1168 "DirectSoundEnumerateA");
1169 pDirectSoundCreate8 = (void*)GetProcAddress(hDsound,
1170 "DirectSoundCreate8");
1171 if (pDirectSoundCreate8)
1172 {
1173 test_COM();
1174 IDirectSound8_tests();
1175 dsound8_tests();
1176 test_hw_buffers();
1177 test_first_device();
1178 }
1179 else
1180 skip("DirectSoundCreate8 missing - skipping all tests\n");
1181
1182 FreeLibrary(hDsound);
1183 }
1184 else
1185 skip("dsound.dll not found - skipping all tests\n");
1186
1187 CoUninitialize();
1188 }
1189