[DSOUND_WINETEST] Add a PCH.
[reactos.git] / modules / rostests / winetests / dsound / 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 * Copyright (c) 2007 Maarten Lankhorst
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29 #include "dsound_test.h"
30
31 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
32
33 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
34 static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID,LPDIRECTSOUND*,
35 LPUNKNOWN)=NULL;
36
37 static BOOL gotdx8;
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, ref_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: %08x\n", rc);
53 if (rc==DS_OK)
54 IDirectSound_Release(unknown);
55
56 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
57 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %08x\n", rc);
58 if (rc==DS_OK)
59 IDirectSound_Release(ds);
60
61 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
62 ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
63 "should have failed: %08x\n",rc);
64 if (rc==DS_OK)
65 IDirectSound8_Release(ds8);
66
67 if (initialized == FALSE) {
68 /* try uninitialized object */
69 rc=IDirectSound_GetCaps(dso,0);
70 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
71 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
72
73 rc=IDirectSound_GetCaps(dso,&dscaps);
74 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
75 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
76
77 rc=IDirectSound_Compact(dso);
78 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
79 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
80
81 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
82 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
83 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
84
85 rc=IDirectSound_Initialize(dso,lpGuid);
86 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
87 "IDirectSound_Initialize() failed: %08x\n",rc);
88 if (rc==DSERR_NODRIVER) {
89 trace(" No Driver\n");
90 goto EXIT;
91 } else if (rc==E_FAIL) {
92 trace(" No Device\n");
93 goto EXIT;
94 } else if (rc==DSERR_ALLOCATED) {
95 trace(" Already In Use\n");
96 goto EXIT;
97 }
98 }
99
100 rc=IDirectSound_Initialize(dso,lpGuid);
101 ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() "
102 "should have returned DSERR_ALREADYINITIALIZED: %08x\n", rc);
103
104 /* DSOUND: Error: Invalid caps buffer */
105 rc=IDirectSound_GetCaps(dso,0);
106 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
107 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
108
109 ZeroMemory(&dscaps, sizeof(dscaps));
110
111 /* DSOUND: Error: Invalid caps buffer */
112 rc=IDirectSound_GetCaps(dso,&dscaps);
113 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
114 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
115
116 dscaps.dwSize=sizeof(dscaps);
117
118 /* DSOUND: Running on a certified driver */
119 rc=IDirectSound_GetCaps(dso,&dscaps);
120 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
121
122 rc=IDirectSound_Compact(dso);
123 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %08x\n", rc);
124
125 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
126 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
127
128 rc=IDirectSound_Compact(dso);
129 ok(rc==DS_OK,"IDirectSound_Compact() failed: %08x\n",rc);
130
131 rc=IDirectSound_GetSpeakerConfig(dso,0);
132 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
133 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
134
135 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
136 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %08x\n", rc);
137 ref_speaker_config = speaker_config;
138
139 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
140 DSSPEAKER_GEOMETRY_WIDE);
141 if (speaker_config == ref_speaker_config)
142 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
143 DSSPEAKER_GEOMETRY_NARROW);
144 if(rc==DS_OK) {
145 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
146 ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %08x\n", rc);
147 }
148 if (rc==DS_OK) {
149 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
150 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %08x\n", rc);
151 if (rc==DS_OK && speaker_config!=new_speaker_config)
152 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
153 "config: expected 0x%08x, got 0x%08x\n",
154 speaker_config,new_speaker_config);
155 IDirectSound_SetSpeakerConfig(dso,ref_speaker_config);
156 }
157
158 EXIT:
159 ref=IDirectSound_Release(dso);
160 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
161 }
162
163 static void IDirectSound_tests(void)
164 {
165 HRESULT rc;
166 IDirectSound *dso=(IDirectSound*)0xdeadbeef;
167 LPCLASSFACTORY cf=NULL;
168
169 trace("Testing IDirectSound\n");
170
171 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
172 &IID_IClassFactory, (void**)&cf);
173 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
174 "failed: %08x\n", rc);
175
176 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
177 &IID_IUnknown, (void**)&cf);
178 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IUnknown) "
179 "failed: %08x\n", rc);
180
181 /* COM aggregation */
182 rc=CoCreateInstance(&CLSID_DirectSound, (IUnknown*)&dso, CLSCTX_INPROC_SERVER,
183 &IID_IDirectSound, (void**)&dso);
184 ok(rc==CLASS_E_NOAGGREGATION || broken(rc==DSERR_INVALIDPARAM),
185 "DirectMusicPerformance create failed: %08x, expected CLASS_E_NOAGGREGATION\n", rc);
186
187 /* try the COM class factory method of creation with no 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: %08x\n", rc);
191 if (dso)
192 IDirectSound_test(dso, FALSE, NULL);
193
194 /* try the COM class factory method of creation with default playback
195 * device specified */
196 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
197 &IID_IDirectSound, (void**)&dso);
198 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
199 if (dso)
200 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
201
202 /* try the COM class factory method of creation with default voice
203 * playback device specified */
204 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
205 &IID_IDirectSound, (void**)&dso);
206 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
207 if (dso)
208 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
209
210 /* try the COM class factory method of creation with a bad
211 * IID specified */
212 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
213 &CLSID_DirectSoundPrivate, (void**)&dso);
214 ok(rc==E_NOINTERFACE,
215 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
216 "should have failed: %08x\n",rc);
217
218 /* try the COM class factory method of creation with a bad
219 * GUID and IID specified */
220 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
221 &IID_IDirectSound, (void**)&dso);
222 ok(rc==REGDB_E_CLASSNOTREG,
223 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
224 "should have failed: %08x\n",rc);
225
226 /* try with no device specified */
227 rc=pDirectSoundCreate(NULL,&dso,NULL);
228 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
229 "DirectSoundCreate(NULL) failed: %08x\n",rc);
230 if (rc==S_OK && dso)
231 IDirectSound_test(dso, TRUE, NULL);
232
233 /* try with default playback device specified */
234 rc=pDirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
235 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
236 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %08x\n", rc);
237 if (rc==DS_OK && dso)
238 IDirectSound_test(dso, TRUE, NULL);
239
240 /* try with default voice playback device specified */
241 rc=pDirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
242 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
243 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %08x\n", rc);
244 if (rc==DS_OK && dso)
245 IDirectSound_test(dso, TRUE, NULL);
246
247 /* try with a bad device specified */
248 rc=pDirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
249 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
250 "should have failed: %08x\n",rc);
251 if (rc==DS_OK && dso)
252 IDirectSound_Release(dso);
253 }
254
255 static HRESULT test_dsound(LPGUID lpGuid)
256 {
257 HRESULT rc;
258 LPDIRECTSOUND dso=NULL;
259 int ref;
260
261 /* DSOUND: Error: Invalid interface buffer */
262 rc=pDirectSoundCreate(lpGuid,0,NULL);
263 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
264 "DSERR_INVALIDPARAM, returned: %08x\n",rc);
265
266 /* Create the DirectSound object */
267 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
268 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
269 "DirectSoundCreate() failed: %08x\n",rc);
270 if (rc!=DS_OK)
271 return rc;
272
273 /* Try the enumerated device */
274 IDirectSound_test(dso, TRUE, lpGuid);
275
276 /* Try the COM class factory method of creation with enumerated device */
277 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
278 &IID_IDirectSound, (void**)&dso);
279 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
280 if (dso)
281 IDirectSound_test(dso, FALSE, lpGuid);
282
283 /* Create a DirectSound object */
284 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
285 ok(rc==DS_OK,"DirectSoundCreate() failed: %08x\n",rc);
286 if (rc==DS_OK) {
287 LPDIRECTSOUND dso1=NULL;
288
289 /* Create a second DirectSound object */
290 rc=pDirectSoundCreate(lpGuid,&dso1,NULL);
291 ok(rc==DS_OK,"DirectSoundCreate() failed: %08x\n",rc);
292 if (rc==DS_OK) {
293 /* Release the second DirectSound object */
294 ref=IDirectSound_Release(dso1);
295 ok(ref==0,"IDirectSound_Release() has %d references, should have "
296 "0\n",ref);
297 ok(dso!=dso1,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso,dso1);
298 }
299
300 /* Release the first DirectSound object */
301 ref=IDirectSound_Release(dso);
302 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
303 ref);
304 if (ref!=0)
305 return DSERR_GENERIC;
306 } else
307 return rc;
308
309 /* Create a DirectSound object */
310 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
311 ok(rc==DS_OK,"DirectSoundCreate() failed: %08x\n",rc);
312 if (rc==DS_OK) {
313 LPDIRECTSOUNDBUFFER secondary;
314 DSBUFFERDESC bufdesc;
315 WAVEFORMATEX wfx;
316
317 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
318 ZeroMemory(&bufdesc, sizeof(bufdesc));
319 bufdesc.dwSize=sizeof(bufdesc);
320 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
321 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
322 wfx.nBlockAlign);
323 bufdesc.lpwfxFormat=&wfx;
324 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
325 ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
326 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
327 "buffer %08x\n",rc);
328 if (rc==DS_OK && secondary!=NULL) {
329 LPDIRECTSOUND3DBUFFER buffer3d;
330 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
331 (void **)&buffer3d);
332 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
333 "failed: %08x\n",rc);
334 if (rc==DS_OK && buffer3d!=NULL) {
335 ref=IDirectSound3DBuffer_AddRef(buffer3d);
336 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
337 "should have 2\n",ref);
338 }
339 ref=IDirectSoundBuffer_AddRef(secondary);
340 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
341 "should have 2\n",ref);
342 }
343 /* release with buffer */
344 ref=IDirectSound_Release(dso);
345 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
346 ref);
347 if (ref!=0)
348 return DSERR_GENERIC;
349 } else
350 return rc;
351
352 return DS_OK;
353 }
354
355 static HRESULT test_primary(LPGUID lpGuid)
356 {
357 HRESULT rc;
358 LPDIRECTSOUND dso=NULL;
359 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
360 DSBUFFERDESC bufdesc;
361 DSCAPS dscaps;
362 WAVEFORMATEX wfx;
363 int ref;
364
365 /* Create the DirectSound object */
366 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
367 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
368 "DirectSoundCreate() failed: %08x\n",rc);
369 if (rc!=DS_OK)
370 return rc;
371
372 /* Get the device capabilities */
373 ZeroMemory(&dscaps, sizeof(dscaps));
374 dscaps.dwSize=sizeof(dscaps);
375 rc=IDirectSound_GetCaps(dso,&dscaps);
376 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
377 if (rc!=DS_OK)
378 goto EXIT;
379
380 /* DSOUND: Error: Invalid buffer description pointer */
381 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
382 ok(rc==DSERR_INVALIDPARAM,
383 "IDirectSound_CreateSoundBuffer() should have failed: %08x\n", rc);
384
385 /* DSOUND: Error: NULL pointer is invalid */
386 /* DSOUND: Error: Invalid buffer description pointer */
387 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
388 ok(rc==DSERR_INVALIDPARAM && primary==0,
389 "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
390 "dsbo=%p\n",rc,primary);
391
392 /* DSOUND: Error: Invalid size */
393 /* DSOUND: Error: Invalid buffer description */
394 primary=NULL;
395 ZeroMemory(&bufdesc, sizeof(bufdesc));
396 bufdesc.dwSize=sizeof(bufdesc)-1;
397 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
398 ok(rc==DSERR_INVALIDPARAM && primary==0,
399 "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
400 "primary=%p\n",rc,primary);
401
402 /* DSOUND: Error: DSBCAPS_PRIMARYBUFFER flag with non-NULL lpwfxFormat */
403 /* DSOUND: Error: Invalid buffer description pointer */
404 primary=NULL;
405 ZeroMemory(&bufdesc, sizeof(bufdesc));
406 bufdesc.dwSize=sizeof(bufdesc);
407 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
408 bufdesc.lpwfxFormat=&wfx;
409 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
410 ok(rc==DSERR_INVALIDPARAM && primary==0,
411 "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
412 "primary=%p\n",rc,primary);
413
414 /* DSOUND: Error: No DSBCAPS_PRIMARYBUFFER flag with NULL lpwfxFormat */
415 /* DSOUND: Error: Invalid buffer description pointer */
416 primary=NULL;
417 ZeroMemory(&bufdesc, sizeof(bufdesc));
418 bufdesc.dwSize=sizeof(bufdesc);
419 bufdesc.dwFlags=0;
420 bufdesc.lpwfxFormat=NULL;
421 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
422 ok(rc==DSERR_INVALIDPARAM && primary==0,
423 "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
424 "primary=%p\n",rc,primary);
425
426 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
427 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
428 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
429 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
430 if (rc!=DS_OK)
431 goto EXIT;
432
433 /* Testing the primary buffer */
434 primary=NULL;
435 ZeroMemory(&bufdesc, sizeof(bufdesc));
436 bufdesc.dwSize=sizeof(bufdesc);
437 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
438 bufdesc.lpwfxFormat = &wfx;
439 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
440 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
441 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
442 "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
443 if (rc==DS_OK && primary!=NULL)
444 IDirectSoundBuffer_Release(primary);
445
446 primary=NULL;
447 ZeroMemory(&bufdesc, sizeof(bufdesc));
448 bufdesc.dwSize=sizeof(bufdesc);
449 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
450 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
451 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
452 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: %08x\n",rc);
453 if (rc==DSERR_CONTROLUNAVAIL)
454 trace(" No Primary\n");
455 else if (rc==DS_OK && primary!=NULL) {
456 LONG vol;
457
458 /* Try to create a second primary buffer */
459 /* DSOUND: Error: The primary buffer already exists.
460 * Any changes made to the buffer description will be ignored. */
461 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
462 ok(rc==DS_OK && second==primary,
463 "IDirectSound_CreateSoundBuffer() should have returned original "
464 "primary buffer: %08x\n",rc);
465 ref=IDirectSoundBuffer_Release(second);
466 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
467 "should have 1\n",ref);
468
469 /* Try to duplicate a primary buffer */
470 /* DSOUND: Error: Can't duplicate primary buffers */
471 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
472 /* rc=0x88780032 */
473 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
474 "should have failed %08x\n",rc);
475
476 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
477 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc);
478
479 if (winetest_interactive) {
480 trace("Playing a 5 seconds reference tone at the current "
481 "volume.\n");
482 if (rc==DS_OK)
483 trace("(the current volume is %d according to DirectSound)\n",
484 vol);
485 trace("All subsequent tones should be identical to this one.\n");
486 trace("Listen for stutter, changes in pitch, volume, etc.\n");
487 }
488 test_buffer(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
489 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
490
491 ref=IDirectSoundBuffer_Release(primary);
492 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references\n",ref);
493
494 ref=IDirectSoundBuffer_AddRef(primary);
495 ok(ref==1,"IDirectSoundBuffer_AddRef() primary has %d references\n",ref);
496
497 ref=IDirectSoundBuffer_Release(primary);
498 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references\n",ref);
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=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
508 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
509
510 EXIT:
511 ref=IDirectSound_Release(dso);
512 ok(ref==0,"IDirectSound_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 */
523 static HRESULT test_primary_secondary(LPGUID lpGuid)
524 {
525 HRESULT rc;
526 LPDIRECTSOUND dso=NULL;
527 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
528 DSBUFFERDESC bufdesc;
529 DSCAPS dscaps;
530 WAVEFORMATEX wfx, wfx2;
531 int f,ref,tag;
532
533 /* Create the DirectSound object */
534 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
535 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
536 "DirectSoundCreate() failed: %08x\n",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=IDirectSound_GetCaps(dso,&dscaps);
544 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",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=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
551 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
552 if (rc!=DS_OK)
553 goto EXIT;
554
555 ZeroMemory(&bufdesc, sizeof(bufdesc));
556 bufdesc.dwSize=sizeof(bufdesc);
557 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
558 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
559 ok(rc==DS_OK && primary!=NULL,
560 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer %08x\n",rc);
561
562 if (rc==DS_OK && primary!=NULL) {
563 for (f=0;f<NB_FORMATS;f++) {
564 for (tag=0;tag<NB_TAGS;tag++) {
565 /* if float, we only want to test 32-bit */
566 if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
567 continue;
568
569 /* We must call SetCooperativeLevel to be allowed to call
570 * SetFormat */
571 /* DSOUND: Setting DirectSound cooperative level to
572 * DSSCL_PRIORITY */
573 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
574 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
575 if (rc!=DS_OK)
576 goto EXIT;
577
578 init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
579 formats[f][2]);
580 wfx2=wfx;
581 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
582
583 if (wfx.wBitsPerSample <= 16)
584 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
585 format_string(&wfx), rc);
586 else
587 ok(rc==DS_OK || rc == E_INVALIDARG, "SetFormat (%s) failed: %08x\n",
588 format_string(&wfx), rc);
589
590 /* There is no guarantee that SetFormat will actually change the
591 * format to what we asked for. It depends on what the soundcard
592 * supports. So we must re-query the format.
593 */
594 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
595 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
596 if (rc==DS_OK &&
597 (wfx.wFormatTag!=wfx2.wFormatTag ||
598 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
599 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
600 wfx.nChannels!=wfx2.nChannels)) {
601 trace("Requested primary format tag=0x%04x %dx%dx%d "
602 "avg.B/s=%d align=%d\n",
603 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
604 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
605 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
606 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
607 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
608 }
609
610 /* Set the CooperativeLevel back to normal */
611 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
612 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
613 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
614
615 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
616
617 secondary=NULL;
618 ZeroMemory(&bufdesc, sizeof(bufdesc));
619 bufdesc.dwSize=sizeof(bufdesc);
620 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
621 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
622 wfx.nBlockAlign);
623 bufdesc.lpwfxFormat=&wfx2;
624 if (winetest_interactive) {
625 trace(" Testing a primary buffer at %dx%dx%d (fmt=%d) with a "
626 "secondary buffer at %dx%dx%d\n",
627 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
628 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
629 }
630 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
631 ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
632 "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
633
634 if (rc==DS_OK && secondary!=NULL) {
635 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
636 winetest_interactive,1.0,0,NULL,0,0,FALSE,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=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
653 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
654
655 EXIT:
656 ref=IDirectSound_Release(dso);
657 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
658 if (ref!=0)
659 return DSERR_GENERIC;
660
661 return rc;
662 }
663
664 static HRESULT test_secondary(LPGUID lpGuid)
665 {
666 HRESULT rc;
667 LPDIRECTSOUND 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=pDirectSoundCreate(lpGuid,&dso,NULL);
677 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
678 "DirectSoundCreate() 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=IDirectSound_GetCaps(dso,&dscaps);
686 ok(rc==DS_OK,"IDirectSound_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=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
693 ok(rc==DS_OK,"IDirectSound_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=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
701 ok(rc==DS_OK && primary!=NULL,
702 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer %08x\n",rc);
703
704 if (rc==DS_OK && primary!=NULL) {
705 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
706 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
707 if (rc!=DS_OK)
708 goto EXIT1;
709
710 for (f=0;f<NB_FORMATS;f++) {
711 for (tag=0;tag<NB_TAGS;tag++) {
712 WAVEFORMATEXTENSIBLE wfxe;
713
714 /* if float, we only want to test 32-bit */
715 if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
716 continue;
717
718 init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
719 formats[f][2]);
720 secondary=NULL;
721 ZeroMemory(&bufdesc, sizeof(bufdesc));
722 bufdesc.dwSize=sizeof(bufdesc);
723 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
724 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
725 wfx.nBlockAlign);
726 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
727 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
728 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
729 if (rc==DS_OK && secondary!=NULL)
730 IDirectSoundBuffer_Release(secondary);
731
732 secondary=NULL;
733 ZeroMemory(&bufdesc, sizeof(bufdesc));
734 bufdesc.dwSize=sizeof(bufdesc);
735 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
736 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
737 wfx.nBlockAlign);
738 bufdesc.lpwfxFormat=&wfx;
739 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
740 if (gotdx8 || wfx.wBitsPerSample <= 16 || wfx.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
741 {
742 if (wfx.wBitsPerSample > 16)
743 ok(broken((rc == DSERR_CONTROLUNAVAIL || rc == DSERR_INVALIDCALL || rc == DSERR_INVALIDPARAM /* 2003 */) && !secondary)
744 || rc == DS_OK, /* driver dependent? */
745 "IDirectSound_CreateSoundBuffer() "
746 "should have returned (DSERR_CONTROLUNAVAIL or DSERR_INVALIDCALL) "
747 "and NULL, returned: %08x %p\n", rc, secondary);
748 else
749 ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
750 "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
751 }
752 else
753 ok(rc==E_INVALIDARG, "Creating %d bpp buffer on dx < 8 returned: %p %08x\n",
754 wfx.wBitsPerSample, secondary, rc);
755
756 if (!gotdx8)
757 {
758 win_skip("Not doing the WAVE_FORMAT_EXTENSIBLE tests\n");
759 /* Apparently they succeed with bogus values,
760 * which means that older dsound doesn't look at them
761 */
762 goto no_wfe;
763 }
764
765 if (secondary)
766 IDirectSoundBuffer_Release(secondary);
767 secondary = NULL;
768
769 bufdesc.lpwfxFormat=(WAVEFORMATEX*)&wfxe;
770 wfxe.Format = wfx;
771 wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
772 wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
773 wfxe.Format.cbSize = 1;
774 wfxe.Samples.wValidBitsPerSample = wfx.wBitsPerSample;
775 wfxe.dwChannelMask = (wfx.nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO);
776
777 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
778 ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL /* 2003 */) && !secondary,
779 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
780 rc, secondary);
781 if (secondary)
782 {
783 IDirectSoundBuffer_Release(secondary);
784 secondary=NULL;
785 }
786
787 wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx) + 1;
788
789 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
790 ok(((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL || rc==DSERR_INVALIDPARAM)
791 && !secondary)
792 || rc==DS_OK, /* 2003 / 2008 */
793 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
794 rc, secondary);
795 if (secondary)
796 {
797 IDirectSoundBuffer_Release(secondary);
798 secondary=NULL;
799 }
800
801 wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
802 wfxe.SubFormat = GUID_NULL;
803 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
804 ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL) && !secondary,
805 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
806 rc, secondary);
807 if (secondary)
808 {
809 IDirectSoundBuffer_Release(secondary);
810 secondary=NULL;
811 }
812 wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
813
814 ++wfxe.Samples.wValidBitsPerSample;
815 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
816 ok(rc==DSERR_INVALIDPARAM && !secondary,
817 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
818 rc, secondary);
819 if (secondary)
820 {
821 IDirectSoundBuffer_Release(secondary);
822 secondary=NULL;
823 }
824 --wfxe.Samples.wValidBitsPerSample;
825
826 wfxe.Samples.wValidBitsPerSample = 0;
827 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
828 ok(rc==DS_OK && secondary,
829 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
830 rc, secondary);
831 if (secondary)
832 {
833 IDirectSoundBuffer_Release(secondary);
834 secondary=NULL;
835 }
836 wfxe.Samples.wValidBitsPerSample = wfxe.Format.wBitsPerSample;
837
838 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
839 ok(rc==DS_OK && secondary!=NULL,
840 "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
841
842 no_wfe:
843 if (rc==DS_OK && secondary!=NULL) {
844 if (winetest_interactive) {
845 trace(" Testing a secondary buffer at %dx%dx%d (fmt=%d) "
846 "with a primary buffer at %dx%dx%d\n",
847 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
848 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
849 }
850 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
851 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
852
853 ref=IDirectSoundBuffer_Release(secondary);
854 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
855 "should have 0\n",ref);
856 }
857 }
858 }
859 EXIT1:
860 ref=IDirectSoundBuffer_Release(primary);
861 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
862 "should have 0\n",ref);
863 }
864
865 /* Set the CooperativeLevel back to normal */
866 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
867 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
868 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
869
870 EXIT:
871 ref=IDirectSound_Release(dso);
872 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
873 if (ref!=0)
874 return DSERR_GENERIC;
875
876 return rc;
877 }
878
879 static HRESULT test_block_align(LPGUID lpGuid)
880 {
881 HRESULT rc;
882 LPDIRECTSOUND dso=NULL;
883 LPDIRECTSOUNDBUFFER secondary=NULL;
884 DSBUFFERDESC bufdesc;
885 DSBCAPS dsbcaps;
886 WAVEFORMATEX wfx;
887 DWORD pos, pos2;
888 int ref;
889
890 /* Create the DirectSound object */
891 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
892 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
893 "DirectSoundCreate() failed: %08x\n",rc);
894 if (rc!=DS_OK)
895 return rc;
896
897 init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
898 ZeroMemory(&bufdesc, sizeof(bufdesc));
899 bufdesc.dwSize=sizeof(bufdesc);
900 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
901 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
902 bufdesc.lpwfxFormat=&wfx;
903 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
904 ok(rc == DS_OK || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
905 "IDirectSound_CreateSoundBuffer() should have returned DS_OK, returned: %08x\n", rc);
906
907 if (rc==DS_OK && secondary!=NULL) {
908 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
909 dsbcaps.dwSize = sizeof(dsbcaps);
910 rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
911 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
912 "returned: %08x\n", rc);
913 if (rc==DS_OK && wfx.nBlockAlign > 1)
914 {
915 ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
916 "Buffer size not a multiple of nBlockAlign: requested %d, "
917 "got %d, should be %d\n", bufdesc.dwBufferBytes,
918 dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
919
920 rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 0);
921 ok(rc == DS_OK, "Could not set position to 0: %08x\n", rc);
922 rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos, NULL);
923 ok(rc == DS_OK, "Could not get position: %08x\n", rc);
924 rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 1);
925 ok(rc == DS_OK, "Could not set position to 1: %08x\n", rc);
926 rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos2, NULL);
927 ok(rc == DS_OK, "Could not get new position: %08x\n", rc);
928 ok(pos == pos2, "Positions not the same! Old position: %d, new position: %d\n", pos, pos2);
929 }
930 ref=IDirectSoundBuffer_Release(secondary);
931 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
932 "should have 0\n",ref);
933 }
934
935 ref=IDirectSound_Release(dso);
936 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
937 if (ref!=0)
938 return DSERR_GENERIC;
939
940 return rc;
941 }
942
943 static struct fmt {
944 int bits;
945 int channels;
946 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
947
948 static HRESULT test_frequency(LPGUID lpGuid)
949 {
950 HRESULT rc;
951 LPDIRECTSOUND dso=NULL;
952 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
953 DSBUFFERDESC bufdesc;
954 DSCAPS dscaps;
955 WAVEFORMATEX wfx, wfx1;
956 DWORD f, r;
957 int ref;
958 int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
959 48000, 96000 };
960
961 /* Create the DirectSound object */
962 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
963 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
964 "DirectSoundCreate() failed: %08x\n",rc);
965 if (rc!=DS_OK)
966 return rc;
967
968 /* Get the device capabilities */
969 ZeroMemory(&dscaps, sizeof(dscaps));
970 dscaps.dwSize=sizeof(dscaps);
971 rc=IDirectSound_GetCaps(dso,&dscaps);
972 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
973 if (rc!=DS_OK)
974 goto EXIT;
975
976 /* We must call SetCooperativeLevel before creating primary buffer */
977 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
978 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
979 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
980 if (rc!=DS_OK)
981 goto EXIT;
982
983 ZeroMemory(&bufdesc, sizeof(bufdesc));
984 bufdesc.dwSize=sizeof(bufdesc);
985 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
986 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
987 ok(rc==DS_OK && primary!=NULL,
988 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer %08x\n",rc);
989
990 if (rc==DS_OK && primary!=NULL) {
991 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
992 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
993 if (rc!=DS_OK)
994 goto EXIT1;
995
996 for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
997 for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
998 init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
999 fmts[f].channels);
1000 secondary=NULL;
1001 ZeroMemory(&bufdesc, sizeof(bufdesc));
1002 bufdesc.dwSize=sizeof(bufdesc);
1003 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
1004 bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
1005 BUFFER_LEN/1000,wfx.nBlockAlign);
1006 bufdesc.lpwfxFormat=&wfx;
1007 if (winetest_interactive) {
1008 trace(" Testing a secondary buffer at %dx%dx%d "
1009 "with a primary buffer at %dx%dx%d\n",
1010 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
1011 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
1012 }
1013 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
1014 ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
1015 "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
1016
1017 if (rc==DS_OK && secondary!=NULL) {
1018 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
1019 winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
1020
1021 ref=IDirectSoundBuffer_Release(secondary);
1022 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1023 "should have 0\n",ref);
1024 }
1025 }
1026 }
1027 EXIT1:
1028 ref=IDirectSoundBuffer_Release(primary);
1029 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1030 "should have 0\n",ref);
1031 }
1032
1033 /* Set the CooperativeLevel back to normal */
1034 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
1035 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
1036 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1037
1038 EXIT:
1039 ref=IDirectSound_Release(dso);
1040 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1041 if (ref!=0)
1042 return DSERR_GENERIC;
1043
1044 return rc;
1045 }
1046
1047 static HRESULT test_notify(LPDIRECTSOUNDBUFFER dsb,
1048 DWORD count, LPHANDLE event,
1049 DWORD expected)
1050 {
1051 HRESULT rc;
1052 DWORD ret;
1053
1054 rc=IDirectSoundBuffer_SetCurrentPosition(dsb,0);
1055 ok(rc==DS_OK,
1056 "IDirectSoundBuffer_SetCurrentPosition failed %08x\n",rc);
1057 if(rc!=DS_OK)
1058 return rc;
1059
1060 rc=IDirectSoundBuffer_Play(dsb,0,0,0);
1061 ok(rc==DS_OK,"IDirectSoundBuffer_Play failed %08x\n",rc);
1062 if(rc!=DS_OK)
1063 return rc;
1064
1065 rc=IDirectSoundBuffer_Stop(dsb);
1066 ok(rc==DS_OK,"IDirectSoundBuffer_Stop failed %08x\n",rc);
1067 if(rc!=DS_OK)
1068 return rc;
1069
1070 ret=WaitForMultipleObjects(count,event,FALSE,0);
1071 ok(ret==expected,"expected %d. got %d\n",expected,ret);
1072 return rc;
1073 }
1074
1075 static HRESULT test_duplicate(LPGUID lpGuid)
1076 {
1077 HRESULT rc;
1078 LPDIRECTSOUND dso=NULL;
1079 LPDIRECTSOUNDBUFFER primary=NULL;
1080 DSBUFFERDESC bufdesc;
1081 int ref;
1082
1083 /* Create the DirectSound object */
1084 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
1085 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
1086 "DirectSoundCreate() failed: %08x\n",rc);
1087 if (rc!=DS_OK)
1088 return rc;
1089
1090 /* We must call SetCooperativeLevel before creating primary buffer */
1091 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1092 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1093 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1094 if (rc!=DS_OK)
1095 goto EXIT;
1096
1097 ZeroMemory(&bufdesc, sizeof(bufdesc));
1098 bufdesc.dwSize=sizeof(bufdesc);
1099 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
1100 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1101 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
1102 "to create a primary buffer %08x\n",rc);
1103
1104 if (rc==DS_OK && primary!=NULL) {
1105 LPDIRECTSOUNDBUFFER original=NULL;
1106 WAVEFORMATEX wfx;
1107
1108 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,1);
1109 ZeroMemory(&bufdesc, sizeof(bufdesc));
1110 bufdesc.dwSize=sizeof(bufdesc);
1111 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLPOSITIONNOTIFY;
1112 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec/100; /* very short buffer */
1113 bufdesc.lpwfxFormat=&wfx;
1114 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&original,NULL);
1115 ok(rc==DS_OK && original!=NULL,
1116 "IDirectSound_CreateSoundBuffer() failed to create a original "
1117 "buffer %08x\n",rc);
1118 if (rc==DS_OK && original!=NULL) {
1119 LPDIRECTSOUNDBUFFER duplicated=NULL;
1120 LPDIRECTSOUNDNOTIFY notify=NULL;
1121 HANDLE event[2];
1122 LPVOID buf=NULL;
1123 DWORD bufsize;
1124 int i;
1125
1126 /* Prepare notify events */
1127 for (i=0;i<sizeof(event)/sizeof(event[0]);i++) {
1128 event[i] = CreateEvent(NULL,FALSE,FALSE,NULL);
1129 }
1130
1131 /* Make silent buffer */
1132 rc=IDirectSoundBuffer_Lock(original,0,0,&buf,&bufsize,
1133 NULL,NULL,DSBLOCK_ENTIREBUFFER);
1134 ok(rc==DS_OK && buf!=NULL,
1135 "IDirectSoundBuffer_Lock failed to lock the buffer %08x\n",rc);
1136 if (rc==DS_OK && buf!=NULL) {
1137 ZeroMemory(buf,bufsize);
1138 rc=IDirectSoundBuffer_Unlock(original,buf,bufsize,
1139 NULL,0);
1140 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock failed to unlock "
1141 "%08x\n",rc);
1142 }
1143
1144 rc=IDirectSoundBuffer_QueryInterface(original,
1145 &IID_IDirectSoundNotify,
1146 (void**)&notify);
1147 ok(rc==DS_OK && notify!=NULL,
1148 "IDirectSoundBuffer_QueryInterface() failed to create a "
1149 "notification %08x\n",rc);
1150 if (rc==DS_OK && notify!=NULL) {
1151 DSBPOSITIONNOTIFY dsbpn;
1152 LPDIRECTSOUNDNOTIFY dup_notify=NULL;
1153
1154 dsbpn.dwOffset=DSBPN_OFFSETSTOP;
1155 dsbpn.hEventNotify=event[0];
1156 rc=IDirectSoundNotify_SetNotificationPositions(notify,
1157 1,&dsbpn);
1158 ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions "
1159 "failed %08x\n",rc);
1160
1161 rc=IDirectSound_DuplicateSoundBuffer(dso,original,&duplicated);
1162 ok(rc==DS_OK && duplicated!=NULL,
1163 "IDirectSound_DuplicateSoundBuffer failed %08x\n",rc);
1164
1165 trace("testing duplicated buffer without notifications.\n");
1166 test_notify(duplicated,sizeof(event)/sizeof(event[0]),
1167 event,WAIT_TIMEOUT);
1168
1169 rc=IDirectSoundBuffer_QueryInterface(duplicated,
1170 &IID_IDirectSoundNotify,
1171 (void**)&dup_notify);
1172 ok(rc==DS_OK&&dup_notify!=NULL,
1173 "IDirectSoundBuffer_QueryInterface() failed to create a "
1174 "notification %08x\n",rc);
1175 if(rc==DS_OK&&dup_notify!=NULL) {
1176 dsbpn.dwOffset=DSBPN_OFFSETSTOP;
1177 dsbpn.hEventNotify=event[1];
1178 rc=IDirectSoundNotify_SetNotificationPositions(dup_notify,
1179 1,&dsbpn);
1180 ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions "
1181 "failed %08x\n",rc);
1182
1183 trace("testing duplicated buffer with a notification.\n");
1184 test_notify(duplicated,sizeof(event)/sizeof(event[0]),
1185 event,WAIT_OBJECT_0+1);
1186
1187 ref=IDirectSoundNotify_Release(dup_notify);
1188 ok(ref==0,"IDirectSoundNotify_Release() has %d references, "
1189 "should have 0\n",ref);
1190 }
1191 ref=IDirectSoundNotify_Release(notify);
1192 ok(ref==0,"IDirectSoundNotify_Release() has %d references, "
1193 "should have 0\n",ref);
1194
1195 trace("testing original buffer with a notification.\n");
1196 test_notify(original,sizeof(event)/sizeof(event[0]),
1197 event,WAIT_OBJECT_0);
1198
1199 ref=IDirectSoundBuffer_Release(duplicated);
1200 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1201 "should have 0\n",ref);
1202 }
1203 ref=IDirectSoundBuffer_Release(original);
1204 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1205 "should have 0\n",ref);
1206 }
1207 ref=IDirectSoundBuffer_Release(primary);
1208 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1209 "should have 0\n",ref);
1210 }
1211
1212 /* Set the CooperativeLevel back to normal */
1213 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
1214 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
1215 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1216
1217 EXIT:
1218 ref=IDirectSound_Release(dso);
1219 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1220 if (ref!=0)
1221 return DSERR_GENERIC;
1222
1223 return rc;
1224 }
1225
1226 static HRESULT test_invalid_fmts(LPGUID lpGuid)
1227 {
1228 HRESULT rc;
1229 LPDIRECTSOUND dso=NULL;
1230 LPDIRECTSOUNDBUFFER primary=NULL;
1231 DSBUFFERDESC bufdesc;
1232
1233 /* Create the DirectSound object */
1234 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
1235 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
1236 "DirectSoundCreate() failed: %08x\n",rc);
1237 if (rc!=DS_OK)
1238 return rc;
1239
1240 /* We must call SetCooperativeLevel before creating primary buffer */
1241 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1242 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1243 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1244 if (rc!=DS_OK){
1245 IDirectSound_Release(dso);
1246 return rc;
1247 }
1248
1249 ZeroMemory(&bufdesc, sizeof(bufdesc));
1250 bufdesc.dwSize=sizeof(bufdesc);
1251 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
1252 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1253 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
1254 "to create a primary buffer %08x\n",rc);
1255
1256 if (rc==DS_OK && primary!=NULL) {
1257 WAVEFORMATEX wfx;
1258 WAVEFORMATEXTENSIBLE fmtex;
1259
1260 wfx.wFormatTag = WAVE_FORMAT_PCM;
1261 wfx.nChannels = 0;
1262 wfx.nSamplesPerSec = 44100;
1263 wfx.wBitsPerSample = 16;
1264 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1265 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1266 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1267 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1268
1269 wfx.nChannels = 2;
1270 wfx.nSamplesPerSec = 44100;
1271 wfx.wBitsPerSample = 0;
1272 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1273 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1274 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1275 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1276
1277 wfx.nChannels = 2;
1278 wfx.nSamplesPerSec = 44100;
1279 wfx.wBitsPerSample = 2;
1280 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1281 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1282 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1283 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1284
1285 wfx.nChannels = 2;
1286 wfx.nSamplesPerSec = 44100;
1287 wfx.wBitsPerSample = 12;
1288 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1289 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1290 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1291 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1292
1293 wfx.nChannels = 2;
1294 wfx.nSamplesPerSec = 0;
1295 wfx.wBitsPerSample = 16;
1296 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1297 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1298 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1299 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1300
1301 wfx.nChannels = 2;
1302 wfx.nSamplesPerSec = 44100;
1303 wfx.wBitsPerSample = 16;
1304 wfx.nBlockAlign = 0;
1305 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1306 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1307 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1308
1309 wfx.nChannels = 2;
1310 wfx.nSamplesPerSec = 44100;
1311 wfx.wBitsPerSample = 16;
1312 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1313 wfx.nAvgBytesPerSec = 0;
1314 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1315 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1316
1317 wfx.nChannels = 2;
1318 wfx.nSamplesPerSec = 44100;
1319 wfx.wBitsPerSample = 16;
1320 wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample / 8) - 1;
1321 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1322 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1323 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1324
1325 wfx.nChannels = 2;
1326 wfx.nSamplesPerSec = 44100;
1327 wfx.wBitsPerSample = 16;
1328 wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample / 8) + 1;
1329 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1330 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1331 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1332
1333 wfx.nChannels = 2;
1334 wfx.nSamplesPerSec = 44100;
1335 wfx.wBitsPerSample = 16;
1336 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1337 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign + 1;
1338 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1339 ok(rc == S_OK, "SetFormat: %08x\n", rc);
1340
1341 rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1342 ok(rc == S_OK, "GetFormat: %08x\n", rc);
1343 ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
1344 ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1345 ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1346 ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1347 ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1348 ok(wfx.nAvgBytesPerSec == 44100 * 4 + 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1349
1350 wfx.nChannels = 2;
1351 wfx.nSamplesPerSec = 44100;
1352 wfx.wBitsPerSample = 16;
1353 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1354 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign - 1;
1355 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1356 ok(rc == S_OK, "SetFormat: %08x\n", rc);
1357
1358 rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1359 ok(rc == S_OK, "GetFormat: %08x\n", rc);
1360 ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
1361 ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1362 ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1363 ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1364 ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1365 ok(wfx.nAvgBytesPerSec == 44100 * 4 - 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1366
1367 wfx.nChannels = 2;
1368 wfx.nSamplesPerSec = 44100;
1369 wfx.wBitsPerSample = 16;
1370 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1371 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign + 1;
1372 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1373 ok(rc == S_OK, "SetFormat: %08x\n", rc);
1374
1375 rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1376 ok(rc == S_OK, "GetFormat: %08x\n", rc);
1377 ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
1378 ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1379 ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1380 ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1381 ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1382 ok(wfx.nAvgBytesPerSec == 44100 * 4 + 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1383
1384 wfx.wFormatTag = WAVE_FORMAT_ALAW;
1385 wfx.nChannels = 2;
1386 wfx.nSamplesPerSec = 44100;
1387 wfx.wBitsPerSample = 16;
1388 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1389 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1390 rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1391 ok(rc == S_OK, "SetFormat: %08x\n", rc);
1392
1393 rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1394 ok(rc == S_OK, "GetFormat: %08x\n", rc);
1395 ok(wfx.wFormatTag == WAVE_FORMAT_ALAW, "format: 0x%x\n", wfx.wFormatTag);
1396 ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1397 ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1398 ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1399 ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1400 ok(wfx.nAvgBytesPerSec == 44100 * 4, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1401
1402 if(!gotdx8){
1403 win_skip("Not doing the WAVE_FORMAT_EXTENSIBLE tests\n");
1404 goto done;
1405 }
1406
1407 fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1408 fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1409 fmtex.Format.nChannels = 2;
1410 fmtex.Format.nSamplesPerSec = 44100;
1411 fmtex.Format.wBitsPerSample = 16;
1412 fmtex.Format.nBlockAlign = fmtex.Format.nChannels * fmtex.Format.wBitsPerSample / 8;
1413 fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;
1414 fmtex.Samples.wValidBitsPerSample = 0;
1415 fmtex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1416 fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1417 rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
1418 ok(rc == S_OK, "SetFormat: %08x\n", rc);
1419
1420 rc = IDirectSoundBuffer_GetFormat(primary, (WAVEFORMATEX*)&fmtex, sizeof(fmtex), NULL);
1421 ok(rc == S_OK, "GetFormat: %08x\n", rc);
1422 ok(fmtex.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE, "format: 0x%x\n", fmtex.Format.wFormatTag);
1423 ok(fmtex.Format.nChannels == 2, "channels: %u\n", fmtex.Format.nChannels);
1424 ok(fmtex.Format.nSamplesPerSec == 44100, "rate: %u\n", fmtex.Format.nSamplesPerSec);
1425 ok(fmtex.Format.wBitsPerSample == 16, "bps: %u\n", fmtex.Format.wBitsPerSample);
1426 ok(fmtex.Format.nBlockAlign == 4, "blockalign: %u\n", fmtex.Format.nBlockAlign);
1427 ok(fmtex.Format.nAvgBytesPerSec == 44100 * 4, "avgbytes: %u\n", fmtex.Format.nAvgBytesPerSec);
1428 ok(fmtex.Samples.wValidBitsPerSample == 0 || /* <= XP */
1429 fmtex.Samples.wValidBitsPerSample == 16, /* >= Vista */
1430 "validbits: %u\n", fmtex.Samples.wValidBitsPerSample);
1431 ok(IsEqualGUID(&fmtex.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM), "subtype incorrect\n");
1432
1433 fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1434 fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1435 fmtex.Format.nChannels = 2;
1436 fmtex.Format.nSamplesPerSec = 44100;
1437 fmtex.Format.wBitsPerSample = 24;
1438 fmtex.Format.nBlockAlign = fmtex.Format.nChannels * fmtex.Format.wBitsPerSample / 8;
1439 fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;
1440 fmtex.Samples.wValidBitsPerSample = 20;
1441 fmtex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1442 fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1443 rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
1444 ok(rc == S_OK, "SetFormat: %08x\n", rc);
1445
1446 rc = IDirectSoundBuffer_GetFormat(primary, (WAVEFORMATEX*)&fmtex, sizeof(fmtex), NULL);
1447 ok(rc == S_OK, "GetFormat: %08x\n", rc);
1448 ok(fmtex.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE, "format: 0x%x\n", fmtex.Format.wFormatTag);
1449 ok(fmtex.Format.nChannels == 2, "channels: %u\n", fmtex.Format.nChannels);
1450 ok(fmtex.Format.nSamplesPerSec == 44100, "rate: %u\n", fmtex.Format.nSamplesPerSec);
1451 ok(fmtex.Format.wBitsPerSample == 24, "bps: %u\n", fmtex.Format.wBitsPerSample);
1452 ok(fmtex.Format.nBlockAlign == 6, "blockalign: %u\n", fmtex.Format.nBlockAlign);
1453 ok(fmtex.Format.nAvgBytesPerSec == 44100 * 6, "avgbytes: %u\n", fmtex.Format.nAvgBytesPerSec);
1454 ok(fmtex.Samples.wValidBitsPerSample == 20, "validbits: %u\n", fmtex.Samples.wValidBitsPerSample);
1455 ok(IsEqualGUID(&fmtex.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM), "subtype incorrect\n");
1456
1457 fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1458 fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1459 fmtex.Format.nChannels = 2;
1460 fmtex.Format.nSamplesPerSec = 44100;
1461 fmtex.Format.wBitsPerSample = 24;
1462 fmtex.Format.nBlockAlign = fmtex.Format.nChannels * fmtex.Format.wBitsPerSample / 8;
1463 fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;
1464 fmtex.Samples.wValidBitsPerSample = 32;
1465 fmtex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1466 fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1467 rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
1468 ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1469
1470 IDirectSoundBuffer_Release(primary);
1471 }
1472
1473 done:
1474 IDirectSound_Release(dso);
1475
1476 return S_OK;
1477 }
1478
1479 static unsigned int number;
1480
1481 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1482 LPCSTR lpcstrModule, LPVOID lpContext)
1483 {
1484 HRESULT rc;
1485 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1486
1487 /* Don't test the primary device */
1488 if (!number++)
1489 {
1490 ok (!lpcstrModule[0], "lpcstrModule(%s) != NULL\n", lpcstrModule);
1491 return 1;
1492 }
1493
1494 rc = test_dsound(lpGuid);
1495 if (rc == DSERR_NODRIVER)
1496 trace(" No Driver\n");
1497 else if (rc == DSERR_ALLOCATED)
1498 trace(" Already In Use\n");
1499 else if (rc == E_FAIL)
1500 trace(" No Device\n");
1501 else {
1502 test_block_align(lpGuid);
1503 test_primary(lpGuid);
1504 test_primary_secondary(lpGuid);
1505 test_secondary(lpGuid);
1506 test_frequency(lpGuid);
1507 test_duplicate(lpGuid);
1508 test_invalid_fmts(lpGuid);
1509 }
1510
1511 return 1;
1512 }
1513
1514 static void dsound_tests(void)
1515 {
1516 HRESULT rc;
1517 rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
1518 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc);
1519 }
1520
1521 static void test_hw_buffers(void)
1522 {
1523 IDirectSound *ds;
1524 IDirectSoundBuffer *primary, *primary2, **secondaries, *secondary;
1525 IDirectSoundBuffer8 *buf8;
1526 DSCAPS caps;
1527 DSBCAPS bufcaps;
1528 DSBUFFERDESC bufdesc;
1529 WAVEFORMATEX fmt;
1530 UINT i;
1531 HRESULT hr;
1532
1533 hr = pDirectSoundCreate(NULL, &ds, NULL);
1534 ok(hr == S_OK || hr == DSERR_NODRIVER || hr == DSERR_ALLOCATED || hr == E_FAIL,
1535 "DirectSoundCreate failed: %08x\n", hr);
1536 if(hr != S_OK)
1537 return;
1538
1539 caps.dwSize = sizeof(caps);
1540
1541 hr = IDirectSound_GetCaps(ds, &caps);
1542 ok(hr == S_OK, "GetCaps failed: %08x\n", hr);
1543
1544 ok(caps.dwPrimaryBuffers == 1, "Got wrong number of primary buffers: %u\n",
1545 caps.dwPrimaryBuffers);
1546
1547 /* DSBCAPS_LOC* is ignored for primary buffers */
1548 bufdesc.dwSize = sizeof(bufdesc);
1549 bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
1550 DSBCAPS_PRIMARYBUFFER;
1551 bufdesc.dwBufferBytes = 0;
1552 bufdesc.dwReserved = 0;
1553 bufdesc.lpwfxFormat = NULL;
1554 bufdesc.guid3DAlgorithm = GUID_NULL;
1555
1556 hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &primary, NULL);
1557 ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
1558 if(hr != S_OK){
1559 IDirectSound_Release(ds);
1560 return;
1561 }
1562
1563 bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE |
1564 DSBCAPS_PRIMARYBUFFER;
1565
1566 hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &primary2, NULL);
1567 ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
1568 ok(primary == primary2, "Got different primary buffers: %p, %p\n", primary, primary2);
1569 if(hr == S_OK)
1570 IDirectSoundBuffer_Release(primary2);
1571
1572 buf8 = (IDirectSoundBuffer8 *)0xDEADBEEF;
1573 hr = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer8,
1574 (void**)&buf8);
1575 ok(hr == E_NOINTERFACE, "QueryInterface gave wrong failure: %08x\n", hr);
1576 ok(buf8 == NULL, "Pointer didn't get set to NULL\n");
1577
1578 fmt.wFormatTag = WAVE_FORMAT_PCM;
1579 fmt.nChannels = 2;
1580 fmt.nSamplesPerSec = 48000;
1581 fmt.wBitsPerSample = 16;
1582 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
1583 fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
1584 fmt.cbSize = 0;
1585
1586 bufdesc.lpwfxFormat = &fmt;
1587 bufdesc.dwBufferBytes = fmt.nSamplesPerSec * fmt.nBlockAlign / 10;
1588 bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
1589 DSBCAPS_CTRLVOLUME;
1590
1591 secondaries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1592 sizeof(IDirectSoundBuffer *) * caps.dwMaxHwMixingAllBuffers);
1593
1594 /* try to fill all of the hw buffers */
1595 trace("dwMaxHwMixingAllBuffers: %u\n", caps.dwMaxHwMixingAllBuffers);
1596 trace("dwMaxHwMixingStaticBuffers: %u\n", caps.dwMaxHwMixingStaticBuffers);
1597 trace("dwMaxHwMixingStreamingBuffers: %u\n", caps.dwMaxHwMixingStreamingBuffers);
1598 for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i){
1599 hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &secondaries[i], NULL);
1600 ok(hr == S_OK || hr == E_NOTIMPL || broken(hr == DSERR_CONTROLUNAVAIL) || broken(hr == E_FAIL),
1601 "CreateSoundBuffer(%u) failed: %08x\n", i, hr);
1602 if(hr != S_OK)
1603 break;
1604
1605 bufcaps.dwSize = sizeof(bufcaps);
1606 hr = IDirectSoundBuffer_GetCaps(secondaries[i], &bufcaps);
1607 ok(hr == S_OK, "GetCaps failed: %08x\n", hr);
1608 ok((bufcaps.dwFlags & DSBCAPS_LOCHARDWARE) != 0,
1609 "Buffer wasn't allocated in hardware, dwFlags: %x\n", bufcaps.dwFlags);
1610 }
1611
1612 /* see if we can create one more */
1613 hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &secondary, NULL);
1614 ok((i == caps.dwMaxHwMixingAllBuffers && hr == DSERR_ALLOCATED) || /* out of hw buffers */
1615 (caps.dwMaxHwMixingAllBuffers == 0 && hr == DSERR_INVALIDCALL) || /* no hw buffers at all */
1616 hr == E_NOTIMPL || /* don't support hw buffers */
1617 broken(hr == DSERR_CONTROLUNAVAIL) || /* vmware winxp, others? */
1618 broken(hr == E_FAIL) || /* broken AC97 driver */
1619 broken(hr == S_OK) /* broken driver allows more hw bufs than dscaps claims */,
1620 "CreateSoundBuffer(%u) gave wrong error: %08x\n", i, hr);
1621 if(hr == S_OK)
1622 IDirectSoundBuffer_Release(secondary);
1623
1624 for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i)
1625 if(secondaries[i])
1626 IDirectSoundBuffer_Release(secondaries[i]);
1627 HeapFree(GetProcessHeap(), 0, secondaries);
1628
1629 IDirectSoundBuffer_Release(primary);
1630 IDirectSound_Release(ds);
1631 }
1632
1633 START_TEST(dsound)
1634 {
1635 HMODULE hDsound;
1636
1637 CoInitialize(NULL);
1638
1639 hDsound = LoadLibrary("dsound.dll");
1640 if (hDsound)
1641 {
1642 BOOL ret;
1643
1644 ret = FreeLibrary(hDsound);
1645 ok( ret, "FreeLibrary(1) returned %d\n", GetLastError());
1646 }
1647
1648 hDsound = LoadLibrary("dsound.dll");
1649 if (hDsound)
1650 {
1651
1652 pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1653 "DirectSoundEnumerateA");
1654 pDirectSoundCreate = (void*)GetProcAddress(hDsound,
1655 "DirectSoundCreate");
1656
1657 gotdx8 = !!GetProcAddress(hDsound, "DirectSoundCreate8");
1658
1659 IDirectSound_tests();
1660 dsound_tests();
1661 test_hw_buffers();
1662
1663 FreeLibrary(hDsound);
1664 }
1665 else
1666 win_skip("dsound.dll not found - skipping all tests\n");
1667
1668 CoUninitialize();
1669 }