1 /*
2 * Tests the panning and 3D functions of DirectSound
3 *
4 * Part of this test involves playing test tones. But this only makes
5 * sense if someone is going to carefully listen to it, and would only
6 * bother everyone else.
7 * So this is only done if the test is being run in interactive mode.
8 *
9 * Copyright (c) 2002-2004 Francois Gouget
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26 #include "dsound_test.h"
27
28 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
29 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
30
31 typedef struct {
32 char* wave;
33 DWORD wave_len;
34
35 LPDIRECTSOUNDBUFFER dsbo;
36 LPWAVEFORMATEX wfx;
37 DWORD buffer_size;
38 DWORD written;
39 DWORD played;
40 DWORD offset;
41 } play_state_t;
42
buffer_refill8(play_state_t * state,DWORD size)43 static int buffer_refill8(play_state_t* state, DWORD size)
44 {
45 LPVOID ptr1,ptr2;
46 DWORD len1,len2;
47 HRESULT rc;
48
49 if (size>state->wave_len-state->written)
50 size=state->wave_len-state->written;
51
52 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
53 &ptr1,&len1,&ptr2,&len2,0);
54 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
55 if (rc!=DS_OK)
56 return -1;
57
58 memcpy(ptr1,state->wave+state->written,len1);
59 state->written+=len1;
60 if (ptr2!=NULL) {
61 memcpy(ptr2,state->wave+state->written,len2);
62 state->written+=len2;
63 }
64 state->offset=state->written % state->buffer_size;
65 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
66 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
67 if (rc!=DS_OK)
68 return -1;
69 return size;
70 }
71
buffer_silence8(play_state_t * state,DWORD size)72 static int buffer_silence8(play_state_t* state, DWORD size)
73 {
74 LPVOID ptr1,ptr2;
75 DWORD len1,len2;
76 HRESULT rc;
77 BYTE s;
78
79 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
80 &ptr1,&len1,&ptr2,&len2,0);
81 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
82 if (rc!=DS_OK)
83 return -1;
84
85 s=(state->wfx->wBitsPerSample==8?0x80:0);
86 memset(ptr1,s,len1);
87 if (ptr2!=NULL) {
88 memset(ptr2,s,len2);
89 }
90 state->offset=(state->offset+size) % state->buffer_size;
91 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
92 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
93 if (rc!=DS_OK)
94 return -1;
95 return size;
96 }
97
buffer_service8(play_state_t * state)98 static int buffer_service8(play_state_t* state)
99 {
100 DWORD last_play_pos,play_pos,buf_free;
101 HRESULT rc;
102
103 rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
104 ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %08x\n", rc);
105 if (rc!=DS_OK) {
106 goto STOP;
107 }
108
109 /* Update the amount played */
110 last_play_pos=state->played % state->buffer_size;
111 if (play_pos<last_play_pos)
112 state->played+=state->buffer_size-last_play_pos+play_pos;
113 else
114 state->played+=play_pos-last_play_pos;
115
116 if (winetest_debug > 1)
117 trace("buf size=%d last_play_pos=%d play_pos=%d played=%d / %d\n",
118 state->buffer_size,last_play_pos,play_pos,state->played,
119 state->wave_len);
120
121 if (state->played>state->wave_len)
122 {
123 /* Everything has been played */
124 goto STOP;
125 }
126
127 /* Refill the buffer */
128 if (state->offset<=play_pos)
129 buf_free=play_pos-state->offset;
130 else
131 buf_free=state->buffer_size-state->offset+play_pos;
132
133 if (winetest_debug > 1)
134 trace("offset=%d free=%d written=%d / %d\n",
135 state->offset,buf_free,state->written,state->wave_len);
136 if (buf_free==0)
137 return 1;
138
139 if (state->written<state->wave_len)
140 {
141 int w=buffer_refill8(state,buf_free);
142 if (w==-1)
143 goto STOP;
144 buf_free-=w;
145 if (state->written==state->wave_len && winetest_debug > 1)
146 trace("last sound byte at %d\n",
147 (state->written % state->buffer_size));
148 }
149
150 if (buf_free>0) {
151 /* Fill with silence */
152 if (winetest_debug > 1)
153 trace("writing %d bytes of silence\n",buf_free);
154 if (buffer_silence8(state,buf_free)==-1)
155 goto STOP;
156 }
157 return 1;
158
159 STOP:
160 if (winetest_debug > 1)
161 trace("stopping playback\n");
162 rc=IDirectSoundBuffer_Stop(state->dsbo);
163 ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %08x\n", rc);
164 return 0;
165 }
166
test_buffer8(LPDIRECTSOUND8 dso,LPDIRECTSOUNDBUFFER * dsbo,BOOL is_primary,BOOL set_volume,LONG volume,BOOL set_pan,LONG pan,BOOL play,double duration,BOOL buffer3d,LPDIRECTSOUND3DLISTENER listener,BOOL move_listener,BOOL move_sound)167 void test_buffer8(LPDIRECTSOUND8 dso, LPDIRECTSOUNDBUFFER * dsbo,
168 BOOL is_primary, BOOL set_volume, LONG volume,
169 BOOL set_pan, LONG pan, BOOL play, double duration,
170 BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
171 BOOL move_listener, BOOL move_sound)
172 {
173 HRESULT rc;
174 DSBCAPS dsbcaps;
175 WAVEFORMATEX wfx,wfx2;
176 DWORD size,status,freq;
177 BOOL ieee = FALSE;
178 int ref;
179
180 /* DSOUND: Error: Invalid caps pointer */
181 rc=IDirectSoundBuffer_GetCaps(*dsbo,0);
182 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
183 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
184
185 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
186
187 /* DSOUND: Error: Invalid caps pointer */
188 rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
189 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
190 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
191
192 dsbcaps.dwSize=sizeof(dsbcaps);
193 rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
194 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
195 if (rc==DS_OK && winetest_debug > 1) {
196 trace(" Caps: flags=0x%08x size=%d\n",dsbcaps.dwFlags,
197 dsbcaps.dwBufferBytes);
198 }
199
200 /* Query the format size. */
201 size=0;
202 rc=IDirectSoundBuffer_GetFormat(*dsbo,NULL,0,&size);
203 ok(rc==DS_OK && size!=0,"IDirectSoundBuffer_GetFormat() should have "
204 "returned the needed size: rc=%08x size=%d\n",rc,size);
205
206 ok(size == sizeof(WAVEFORMATEX) || size == sizeof(WAVEFORMATEXTENSIBLE),
207 "Expected a correct structure size, got %d\n", size);
208
209 if (size == sizeof(WAVEFORMATEX)) {
210 rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,size,NULL);
211 ieee = (wfx.wFormatTag == WAVE_FORMAT_IEEE_FLOAT);
212 } else if (size == sizeof(WAVEFORMATEXTENSIBLE)) {
213 WAVEFORMATEXTENSIBLE wfxe;
214 rc=IDirectSoundBuffer_GetFormat(*dsbo,(WAVEFORMATEX*)&wfxe,size,NULL);
215 wfx = wfxe.Format;
216 ieee = IsEqualGUID(&wfxe.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
217 } else
218 return;
219
220 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
221 if (rc==DS_OK && winetest_debug > 1) {
222 trace(" Format: %s tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
223 is_primary ? "Primary" : "Secondary",
224 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
225 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
226 }
227
228 /* DSOUND: Error: Invalid frequency buffer */
229 rc=IDirectSoundBuffer_GetFrequency(*dsbo,0);
230 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetFrequency() should have "
231 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
232
233 /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
234 rc=IDirectSoundBuffer_GetFrequency(*dsbo,&freq);
235 ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
236 (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
237 "IDirectSoundBuffer_GetFrequency() failed: %08x\n",rc);
238 if (rc==DS_OK) {
239 ok(freq==wfx.nSamplesPerSec,"The frequency returned by GetFrequency "
240 "%d does not match the format %d\n",freq,wfx.nSamplesPerSec);
241 }
242
243 /* DSOUND: Error: Invalid status pointer */
244 rc=IDirectSoundBuffer_GetStatus(*dsbo,0);
245 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetStatus() should have "
246 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
247
248 rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
249 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
250 ok(status==0,"status=0x%x instead of 0\n",status);
251
252 if (is_primary) {
253 DSBCAPS new_dsbcaps;
254 /* We must call SetCooperativeLevel to be allowed to call SetFormat */
255 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
256 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
257 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) "
258 "failed: %08x\n",rc);
259 if (rc!=DS_OK)
260 return;
261
262 /* DSOUND: Error: Invalid format pointer */
263 rc=IDirectSoundBuffer_SetFormat(*dsbo,0);
264 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_SetFormat() should have "
265 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
266
267 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
268 rc=IDirectSoundBuffer_SetFormat(*dsbo,&wfx2);
269 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
270 format_string(&wfx2), rc);
271
272 /* There is no guarantee that SetFormat will actually change the
273 * format to what we asked for. It depends on what the soundcard
274 * supports. So we must re-query the format.
275 */
276 rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,sizeof(wfx),NULL);
277 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
278 if (rc==DS_OK &&
279 (wfx.wFormatTag!=wfx2.wFormatTag ||
280 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
281 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
282 wfx.nChannels!=wfx2.nChannels)) {
283 trace("Requested format tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
284 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
285 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
286 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
287 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
288 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
289 }
290
291 ZeroMemory(&new_dsbcaps, sizeof(new_dsbcaps));
292 new_dsbcaps.dwSize = sizeof(new_dsbcaps);
293 rc=IDirectSoundBuffer_GetCaps(*dsbo,&new_dsbcaps);
294 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
295 if (rc==DS_OK && winetest_debug > 1) {
296 trace(" new Caps: flags=0x%08x size=%d\n",new_dsbcaps.dwFlags,
297 new_dsbcaps.dwBufferBytes);
298 }
299
300 /* Check for primary buffer size change */
301 ok(new_dsbcaps.dwBufferBytes == dsbcaps.dwBufferBytes,
302 " buffer size changed after SetFormat() - "
303 "previous size was %u, current size is %u\n",
304 dsbcaps.dwBufferBytes, new_dsbcaps.dwBufferBytes);
305 dsbcaps.dwBufferBytes = new_dsbcaps.dwBufferBytes;
306
307 /* Check for primary buffer flags change */
308 ok(new_dsbcaps.dwFlags == dsbcaps.dwFlags,
309 " flags changed after SetFormat() - "
310 "previous flags were %08x, current flags are %08x\n",
311 dsbcaps.dwFlags, new_dsbcaps.dwFlags);
312
313 /* Set the CooperativeLevel back to normal */
314 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
315 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
316 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
317 "failed: %08x\n",rc);
318 }
319
320 if (play) {
321 play_state_t state;
322 DS3DLISTENER listener_param;
323 LPDIRECTSOUND3DBUFFER buffer=NULL;
324 DS3DBUFFER buffer_param;
325 DWORD start_time,now;
326 LPVOID buffer1;
327 DWORD length1;
328
329 if (winetest_interactive) {
330 trace(" Playing %g second 440Hz tone at %dx%dx%d\n", duration,
331 wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
332 }
333
334 if (is_primary) {
335 /* We must call SetCooperativeLevel to be allowed to call Lock */
336 /* DSOUND: Setting DirectSound cooperative level to
337 * DSSCL_WRITEPRIMARY */
338 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),
339 DSSCL_WRITEPRIMARY);
340 ok(rc==DS_OK,
341 "IDirectSound8_SetCooperativeLevel(DSSCL_WRITEPRIMARY) failed: %08x\n",rc);
342 if (rc!=DS_OK)
343 return;
344 }
345 if (buffer3d) {
346 LPDIRECTSOUNDBUFFER temp_buffer;
347
348 rc=IDirectSoundBuffer_QueryInterface(*dsbo,&IID_IDirectSound3DBuffer,
349 (LPVOID *)&buffer);
350 ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
351 if (rc!=DS_OK)
352 return;
353
354 /* check the COM interface */
355 rc=IDirectSoundBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
356 (LPVOID *)&temp_buffer);
357 ok(rc==DS_OK && temp_buffer!=NULL,
358 "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
359 ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
360 temp_buffer,*dsbo);
361 ref=IDirectSoundBuffer_Release(temp_buffer);
362 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
363 "should have 1\n",ref);
364
365 temp_buffer=NULL;
366 rc=IDirectSound3DBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
367 (LPVOID *)&temp_buffer);
368 ok(rc==DS_OK && temp_buffer!=NULL,
369 "IDirectSound3DBuffer_QueryInterface() failed: %08x\n", rc);
370 ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
371 temp_buffer,*dsbo);
372 ref=IDirectSoundBuffer_Release(temp_buffer);
373 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
374 "should have 1\n",ref);
375
376 ref=IDirectSoundBuffer_Release(*dsbo);
377 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
378 "should have 0\n",ref);
379
380 rc=IDirectSound3DBuffer_QueryInterface(buffer,
381 &IID_IDirectSoundBuffer,
382 (LPVOID *)dsbo);
383 ok(rc==DS_OK && *dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface() "
384 "failed: %08x\n",rc);
385
386 /* DSOUND: Error: Invalid buffer */
387 rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
388 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
389 "failed: %08x\n",rc);
390
391 ZeroMemory(&buffer_param, sizeof(buffer_param));
392
393 /* DSOUND: Error: Invalid buffer */
394 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
395 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
396 "failed: %08x\n",rc);
397
398 buffer_param.dwSize=sizeof(buffer_param);
399 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
400 ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters() failed: %08x\n", rc);
401 }
402 if (set_volume) {
403 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
404 LONG val;
405 rc=IDirectSoundBuffer_GetVolume(*dsbo,&val);
406 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc);
407
408 rc=IDirectSoundBuffer_SetVolume(*dsbo,volume);
409 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume() failed: %08x\n", rc);
410 } else {
411 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
412 rc=IDirectSoundBuffer_GetVolume(*dsbo,&volume);
413 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetVolume() "
414 "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
415 }
416 }
417
418 if (set_pan) {
419 if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
420 LONG val;
421 rc=IDirectSoundBuffer_GetPan(*dsbo,&val);
422 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan() failed: %08x\n", rc);
423
424 rc=IDirectSoundBuffer_SetPan(*dsbo,pan);
425 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan() failed: %08x\n", rc);
426 } else {
427 /* DSOUND: Error: Buffer does not have CTRLPAN */
428 rc=IDirectSoundBuffer_GetPan(*dsbo,&pan);
429 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetPan() "
430 "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
431 }
432 }
433
434 /* try an offset past the end of the buffer */
435 rc = IDirectSoundBuffer_Lock(*dsbo, dsbcaps.dwBufferBytes, 0, &buffer1,
436 &length1, NULL, NULL,
437 DSBLOCK_ENTIREBUFFER);
438 ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
439 "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
440
441 /* try a size larger than the buffer */
442 rc = IDirectSoundBuffer_Lock(*dsbo, 0, dsbcaps.dwBufferBytes + 1,
443 &buffer1, &length1, NULL, NULL,
444 DSBLOCK_FROMWRITECURSOR);
445 ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
446 "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
447
448 state.wave=wave_generate_la(&wfx,duration,&state.wave_len,ieee);
449
450 state.dsbo=*dsbo;
451 state.wfx=&wfx;
452 state.buffer_size=dsbcaps.dwBufferBytes;
453 state.played=state.written=state.offset=0;
454 buffer_refill8(&state,state.buffer_size);
455
456 rc=IDirectSoundBuffer_Play(*dsbo,0,0,DSBPLAY_LOOPING);
457 ok(rc==DS_OK,"IDirectSoundBuffer_Play() failed: %08x\n", rc);
458
459 rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
460 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
461 ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
462 "GetStatus: bad status: %x\n",status);
463
464 if (listener) {
465 ZeroMemory(&listener_param,sizeof(listener_param));
466 listener_param.dwSize=sizeof(listener_param);
467 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
468 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
469 "failed: %08x\n",rc);
470 if (move_listener) {
471 listener_param.vPosition.x = -5.0f;
472 listener_param.vVelocity.x = (float)(10.0/duration);
473 }
474 rc=IDirectSound3DListener_SetAllParameters(listener,
475 &listener_param,
476 DS3D_IMMEDIATE);
477 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n", rc);
478 }
479 if (buffer3d) {
480 if (move_sound) {
481 buffer_param.vPosition.x = 100.0f;
482 buffer_param.vVelocity.x = (float)(-200.0/duration);
483 }
484 buffer_param.flMinDistance = 10;
485 rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,
486 DS3D_IMMEDIATE);
487 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
488 }
489
490 start_time=GetTickCount();
491 while (buffer_service8(&state)) {
492 WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
493 now=GetTickCount();
494 if (listener && move_listener) {
495 listener_param.vPosition.x = (float)(-5.0+10.0*(now-start_time)/1000/duration);
496 if (winetest_debug>2)
497 trace("listener position=%g\n",listener_param.vPosition.x);
498 rc=IDirectSound3DListener_SetPosition(listener,
499 listener_param.vPosition.x,listener_param.vPosition.y,
500 listener_param.vPosition.z,DS3D_IMMEDIATE);
501 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n",rc);
502 }
503 if (buffer3d && move_sound) {
504 buffer_param.vPosition.x = (float)(100-200.0*(now-start_time)/1000/duration);
505 if (winetest_debug>2)
506 trace("sound position=%g\n",buffer_param.vPosition.x);
507 rc=IDirectSound3DBuffer_SetPosition(buffer,
508 buffer_param.vPosition.x,buffer_param.vPosition.y,
509 buffer_param.vPosition.z,DS3D_IMMEDIATE);
510 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
511 }
512 }
513 /* Check the sound duration was within 10% of the expected value */
514 now=GetTickCount();
515 ok(fabs(1000*duration-now+start_time)<=100*duration,
516 "The sound played for %d ms instead of %g ms\n",
517 now-start_time,1000*duration);
518
519 HeapFree(GetProcessHeap(), 0, state.wave);
520 if (is_primary) {
521 /* Set the CooperativeLevel back to normal */
522 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
523 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
524 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
525 "failed: %08x\n",rc);
526 }
527 if (buffer3d) {
528 ref=IDirectSound3DBuffer_Release(buffer);
529 ok(ref==0,"IDirectSound3DBuffer_Release() has %d references, "
530 "should have 0\n",ref);
531 }
532 }
533 }
534
test_secondary8(LPGUID lpGuid,int play,int has_3d,int has_3dbuffer,int has_listener,int has_duplicate,int move_listener,int move_sound)535 static HRESULT test_secondary8(LPGUID lpGuid, int play,
536 int has_3d, int has_3dbuffer,
537 int has_listener, int has_duplicate,
538 int move_listener, int move_sound)
539 {
540 HRESULT rc;
541 LPDIRECTSOUND8 dso=NULL;
542 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
543 LPDIRECTSOUND3DLISTENER listener=NULL;
544 DSBUFFERDESC bufdesc;
545 WAVEFORMATEX wfx, wfx1;
546 int ref;
547
548 /* Create the DirectSound object */
549 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
550 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
551 if (rc!=DS_OK)
552 return rc;
553
554 /* We must call SetCooperativeLevel before creating primary buffer */
555 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
556 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
557 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
558 if (rc!=DS_OK)
559 goto EXIT;
560
561 ZeroMemory(&bufdesc, sizeof(bufdesc));
562 bufdesc.dwSize=sizeof(bufdesc);
563 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
564 if (has_3d)
565 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
566 else
567 bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
568 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
569 ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
570 "IDirectSound8_CreateSoundBuffer() failed to create a %sprimary buffer: %08x\n",has_3d?"3D ":"", rc);
571 if (rc == DSERR_CONTROLUNAVAIL)
572 trace(" No Primary\n");
573 else if (rc==DS_OK && primary!=NULL) {
574 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
575 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
576 if (rc!=DS_OK)
577 goto EXIT1;
578
579 if (has_listener) {
580 rc=IDirectSoundBuffer_QueryInterface(primary,
581 &IID_IDirectSound3DListener,
582 (void **)&listener);
583 ok(rc==DS_OK && listener!=NULL,
584 "IDirectSoundBuffer_QueryInterface() failed to get a 3D "
585 "listener %08x\n",rc);
586 ref=IDirectSoundBuffer_Release(primary);
587 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
588 "should have 0\n",ref);
589 if (rc==DS_OK && listener!=NULL) {
590 DS3DLISTENER listener_param;
591 ZeroMemory(&listener_param,sizeof(listener_param));
592 /* DSOUND: Error: Invalid buffer */
593 rc=IDirectSound3DListener_GetAllParameters(listener,0);
594 ok(rc==DSERR_INVALIDPARAM,
595 "IDirectSound3dListener_GetAllParameters() should have "
596 "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
597
598 /* DSOUND: Error: Invalid buffer */
599 rc=IDirectSound3DListener_GetAllParameters(listener,
600 &listener_param);
601 ok(rc==DSERR_INVALIDPARAM,
602 "IDirectSound3dListener_GetAllParameters() should have "
603 "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
604
605 listener_param.dwSize=sizeof(listener_param);
606 rc=IDirectSound3DListener_GetAllParameters(listener,
607 &listener_param);
608 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
609 "failed: %08x\n",rc);
610 } else {
611 ok(listener==NULL, "IDirectSoundBuffer_QueryInterface() "
612 "failed but returned a listener anyway\n");
613 ok(rc!=DS_OK, "IDirectSoundBuffer_QueryInterface() succeeded "
614 "but returned a NULL listener\n");
615 if (listener) {
616 ref=IDirectSound3DListener_Release(listener);
617 ok(ref==0,"IDirectSound3dListener_Release() listener has "
618 "%d references, should have 0\n",ref);
619 }
620 goto EXIT2;
621 }
622 }
623
624 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
625 secondary=NULL;
626 ZeroMemory(&bufdesc, sizeof(bufdesc));
627 bufdesc.dwSize=sizeof(bufdesc);
628 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
629 if (has_3d)
630 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
631 else
632 bufdesc.dwFlags|=
633 (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
634 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
635 wfx.nBlockAlign);
636 bufdesc.lpwfxFormat=&wfx;
637 if (has_3d) {
638 /* a stereo 3D buffer should fail */
639 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
640 ok(rc==DSERR_INVALIDPARAM,
641 "IDirectSound8_CreateSoundBuffer(secondary) should have "
642 "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
643 if (secondary)
644 {
645 ref=IDirectSoundBuffer_Release(secondary);
646 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, should have 0\n",ref);
647 }
648 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,1);
649 }
650
651 if (winetest_interactive) {
652 trace(" Testing a %s%ssecondary buffer %s%s%s%sat %dx%dx%d "
653 "with a primary buffer at %dx%dx%d\n",
654 has_3dbuffer?"3D ":"",
655 has_duplicate?"duplicated ":"",
656 listener!=NULL||move_sound?"with ":"",
657 move_listener?"moving ":"",
658 listener!=NULL?"listener ":"",
659 listener&&move_sound?"and moving sound ":move_sound?
660 "moving sound ":"",
661 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
662 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
663 }
664 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
665 ok(rc==DS_OK && secondary!=NULL,"IDirectSound8_CreateSoundBuffer() "
666 "failed to create a %s%ssecondary buffer %s%s%s%sat %dx%dx%d (%s): %08x\n",
667 has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"",
668 listener!=NULL||move_sound?"with ":"", move_listener?"moving ":"",
669 listener!=NULL?"listener ":"",
670 listener&&move_sound?"and moving sound ":move_sound?
671 "moving sound ":"",
672 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
673 getDSBCAPS(bufdesc.dwFlags),rc);
674 if (rc==DS_OK && secondary!=NULL) {
675 if (!has_3d) {
676 LONG refvol,vol,refpan,pan;
677
678 /* Check the initial secondary buffer's volume and pan */
679 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
680 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(secondary) failed: %08x\n",rc);
681 ok(vol==0,"wrong volume for a new secondary buffer: %d\n",vol);
682 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
683 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: %08x\n",rc);
684 ok(pan==0,"wrong pan for a new secondary buffer: %d\n",pan);
685
686 /* Check that changing the secondary buffer's volume and pan
687 * does not impact the primary buffer's volume and pan
688 */
689 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
690 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: %08x\n",rc);
691 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
692 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
693
694 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
695 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
696 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
697 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
698 ok(vol==-1000,"secondary: wrong volume %d instead of -1000\n",
699 vol);
700 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
701 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
702 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
703 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: %08x\n",rc);
704 ok(pan==-1000,"secondary: wrong pan %d instead of -1000\n",
705 pan);
706
707 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
708 ok(rc==DS_OK,"IDirectSoundBuffer_`GetVolume(primary) failed: i%08x\n",rc);
709 ok(vol==refvol,"The primary volume changed from %d to %d\n",
710 refvol,vol);
711 rc=IDirectSoundBuffer_GetPan(primary,&pan);
712 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
713 ok(pan==refpan,"The primary pan changed from %d to %d\n",
714 refpan,pan);
715
716 rc=IDirectSoundBuffer_SetVolume(secondary,0);
717 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
718 rc=IDirectSoundBuffer_SetPan(secondary,0);
719 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
720 }
721 if (has_duplicate) {
722 LPDIRECTSOUNDBUFFER duplicated=NULL;
723
724 /* DSOUND: Error: Invalid source buffer */
725 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,0);
726 ok(rc==DSERR_INVALIDPARAM,
727 "IDirectSound8_DuplicateSoundBuffer() should have returned "
728 "DSERR_INVALIDPARAM, returned: %08x\n",rc);
729
730 /* DSOUND: Error: Invalid dest buffer */
731 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,0);
732 ok(rc==DSERR_INVALIDPARAM,
733 "IDirectSound8_DuplicateSoundBuffer() should have returned "
734 "DSERR_INVALIDPARAM, returned: %08x\n",rc);
735
736 /* DSOUND: Error: Invalid source buffer */
737 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,&duplicated);
738 ok(rc==DSERR_INVALIDPARAM,
739 "IDirectSound8_DuplicateSoundBuffer() should have returned "
740 "DSERR_INVALIDPARAM, returned: %08x\n",rc);
741
742 duplicated=NULL;
743 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,
744 &duplicated);
745 ok(rc==DS_OK && duplicated!=NULL,
746 "IDirectSound8_DuplicateSoundBuffer() failed to duplicate "
747 "a secondary buffer: %08x\n",rc);
748
749 if (rc==DS_OK && duplicated!=NULL) {
750 ref=IDirectSoundBuffer_Release(secondary);
751 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
752 "references, should have 0\n",ref);
753 secondary=duplicated;
754 }
755 }
756
757 if (rc==DS_OK && secondary!=NULL) {
758 double duration;
759 duration=(move_listener || move_sound?4.0:1.0);
760 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
761 winetest_interactive,duration,has_3dbuffer,
762 listener,move_listener,move_sound);
763 ref=IDirectSoundBuffer_Release(secondary);
764 ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, "
765 "should have 0\n",has_duplicate?"duplicated":"secondary",
766 ref);
767 }
768 }
769 EXIT1:
770 if (has_listener) {
771 if (listener) {
772 ref=IDirectSound3DListener_Release(listener);
773 ok(ref==0,"IDirectSound3dListener_Release() listener has %d "
774 "references, should have 0\n",ref);
775 }
776 } else {
777 ref=IDirectSoundBuffer_Release(primary);
778 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
779 "should have 0\n",ref);
780 }
781 } else {
782 ok(primary==NULL,"IDirectSound8_CreateSoundBuffer(primary) failed "
783 "but primary created anyway\n");
784 ok(rc!=DS_OK,"IDirectSound8_CreateSoundBuffer(primary) succeeded "
785 "but primary not created\n");
786 if (primary) {
787 ref=IDirectSoundBuffer_Release(primary);
788 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
789 "should have 0\n",ref);
790 }
791 }
792 EXIT2:
793 /* Set the CooperativeLevel back to normal */
794 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
795 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
796 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
797
798 EXIT:
799 ref=IDirectSound8_Release(dso);
800 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
801 if (ref!=0)
802 return DSERR_GENERIC;
803
804 return rc;
805 }
806
test_for_driver8(LPGUID lpGuid)807 static HRESULT test_for_driver8(LPGUID lpGuid)
808 {
809 HRESULT rc;
810 LPDIRECTSOUND8 dso=NULL;
811 int ref;
812
813 /* Create the DirectSound object */
814 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
815 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
816 "DirectSoundCreate8() failed: %08x\n",rc);
817 if (rc!=DS_OK)
818 return rc;
819
820 ref=IDirectSound8_Release(dso);
821 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
822 if (ref!=0)
823 return DSERR_GENERIC;
824
825 return rc;
826 }
827
test_primary8(LPGUID lpGuid)828 static HRESULT test_primary8(LPGUID lpGuid)
829 {
830 HRESULT rc;
831 LPDIRECTSOUND8 dso=NULL;
832 LPDIRECTSOUNDBUFFER primary=NULL;
833 DSBUFFERDESC bufdesc;
834 DSCAPS dscaps;
835 int ref, i;
836
837 /* Create the DirectSound object */
838 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
839 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
840 if (rc!=DS_OK)
841 return rc;
842
843 /* Get the device capabilities */
844 ZeroMemory(&dscaps, sizeof(dscaps));
845 dscaps.dwSize=sizeof(dscaps);
846 rc=IDirectSound8_GetCaps(dso,&dscaps);
847 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
848 if (rc!=DS_OK)
849 goto EXIT;
850
851 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
852 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
853 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
854 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
855 if (rc!=DS_OK)
856 goto EXIT;
857
858 /* Testing the primary buffer */
859 primary=NULL;
860 ZeroMemory(&bufdesc, sizeof(bufdesc));
861 bufdesc.dwSize=sizeof(bufdesc);
862 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
863 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
864 ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
865 "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: %08x\n",rc);
866 if (rc == DSERR_CONTROLUNAVAIL)
867 trace(" No Primary\n");
868 else if (rc==DS_OK && primary!=NULL) {
869 test_buffer8(dso,&primary,1,TRUE,0,TRUE,0,winetest_interactive &&
870 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
871 if (winetest_interactive) {
872 LONG volume,pan;
873
874 volume = DSBVOLUME_MAX;
875 for (i = 0; i < 6; i++) {
876 test_buffer8(dso,&primary,1,TRUE,volume,TRUE,0,
877 winetest_interactive &&
878 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
879 1.0,0,NULL,0,0);
880 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
881 }
882
883 pan = DSBPAN_LEFT;
884 for (i = 0; i < 7; i++) {
885 test_buffer8(dso,&primary,1,TRUE,0,TRUE,pan,
886 winetest_interactive &&
887 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
888 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
889 }
890 }
891 ref=IDirectSoundBuffer_Release(primary);
892 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
893 "should have 0\n",ref);
894 }
895
896 /* Set the CooperativeLevel back to normal */
897 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
898 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
899 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
900
901 EXIT:
902 ref=IDirectSound8_Release(dso);
903 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
904 if (ref!=0)
905 return DSERR_GENERIC;
906
907 return rc;
908 }
909
test_primary_3d8(LPGUID lpGuid)910 static HRESULT test_primary_3d8(LPGUID lpGuid)
911 {
912 HRESULT rc;
913 LPDIRECTSOUND8 dso=NULL;
914 LPDIRECTSOUNDBUFFER primary=NULL;
915 DSBUFFERDESC bufdesc;
916 DSCAPS dscaps;
917 int ref;
918
919 /* Create the DirectSound object */
920 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
921 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
922 if (rc!=DS_OK)
923 return rc;
924
925 /* Get the device capabilities */
926 ZeroMemory(&dscaps, sizeof(dscaps));
927 dscaps.dwSize=sizeof(dscaps);
928 rc=IDirectSound8_GetCaps(dso,&dscaps);
929 ok(rc==DS_OK,"IDirectSound8_GetCaps failed: %08x\n",rc);
930 if (rc!=DS_OK)
931 goto EXIT;
932
933 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
934 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
935 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
936 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
937 if (rc!=DS_OK)
938 goto EXIT;
939
940 primary=NULL;
941 ZeroMemory(&bufdesc, sizeof(bufdesc));
942 bufdesc.dwSize=sizeof(bufdesc);
943 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
944 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
945 ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
946 "to create a primary buffer: %08x\n",rc);
947 if (rc==DS_OK && primary!=NULL) {
948 ref=IDirectSoundBuffer_Release(primary);
949 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
950 "should have 0\n",ref);
951 primary=NULL;
952 ZeroMemory(&bufdesc, sizeof(bufdesc));
953 bufdesc.dwSize=sizeof(bufdesc);
954 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
955 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
956 ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() "
957 "failed to create a 3D primary buffer: %08x\n",rc);
958 if (rc==DS_OK && primary!=NULL) {
959 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
960 winetest_interactive &&
961 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
962 ref=IDirectSoundBuffer_Release(primary);
963 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
964 "should have 0\n",ref);
965 }
966 }
967 /* Set the CooperativeLevel back to normal */
968 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
969 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
970 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
971
972 EXIT:
973 ref=IDirectSound8_Release(dso);
974 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
975 if (ref!=0)
976 return DSERR_GENERIC;
977
978 return rc;
979 }
980
test_primary_3d_with_listener8(LPGUID lpGuid)981 static HRESULT test_primary_3d_with_listener8(LPGUID lpGuid)
982 {
983 HRESULT rc;
984 LPDIRECTSOUND8 dso=NULL;
985 LPDIRECTSOUNDBUFFER primary=NULL;
986 DSBUFFERDESC bufdesc;
987 DSCAPS dscaps;
988 int ref;
989
990 /* Create the DirectSound object */
991 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
992 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
993 if (rc!=DS_OK)
994 return rc;
995
996 /* Get the device capabilities */
997 ZeroMemory(&dscaps, sizeof(dscaps));
998 dscaps.dwSize=sizeof(dscaps);
999 rc=IDirectSound8_GetCaps(dso,&dscaps);
1000 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
1001 if (rc!=DS_OK)
1002 goto EXIT;
1003
1004 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
1005 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1006 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1007 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
1008 if (rc!=DS_OK)
1009 goto EXIT;
1010 primary=NULL;
1011 ZeroMemory(&bufdesc, sizeof(bufdesc));
1012 bufdesc.dwSize=sizeof(bufdesc);
1013 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
1014 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1015 ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
1016 "to create a 3D primary buffer %08x\n",rc);
1017 if (rc==DS_OK && primary!=NULL) {
1018 LPDIRECTSOUND3DLISTENER listener=NULL;
1019 rc=IDirectSoundBuffer_QueryInterface(primary,
1020 &IID_IDirectSound3DListener,
1021 (void **)&listener);
1022 ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface() "
1023 "failed to get a 3D listener: %08x\n",rc);
1024 if (rc==DS_OK && listener!=NULL) {
1025 LPDIRECTSOUNDBUFFER temp_buffer=NULL;
1026
1027 /* Checking the COM interface */
1028 rc=IDirectSoundBuffer_QueryInterface(primary,
1029 &IID_IDirectSoundBuffer,
1030 (LPVOID *)&temp_buffer);
1031 ok(rc==DS_OK && temp_buffer!=NULL,
1032 "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
1033 ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1034 if (rc==DS_OK && temp_buffer!=NULL) {
1035 ref=IDirectSoundBuffer_Release(temp_buffer);
1036 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1037 "should have 1\n",ref);
1038
1039 temp_buffer=NULL;
1040 rc=IDirectSound3DListener_QueryInterface(listener,
1041 &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
1042 ok(rc==DS_OK && temp_buffer!=NULL,
1043 "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
1044 ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1045 ref=IDirectSoundBuffer_Release(temp_buffer);
1046 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1047 "should have 1\n",ref);
1048
1049 /* Testing the buffer */
1050 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
1051 winetest_interactive &&
1052 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
1053 1.0,0,listener,0,0);
1054 }
1055
1056 /* Testing the reference counting */
1057 ref=IDirectSound3DListener_Release(listener);
1058 ok(ref==0,"IDirectSound3DListener_Release() listener has %d "
1059 "references, should have 0\n",ref);
1060 }
1061
1062 /* Testing the reference counting */
1063 ref=IDirectSoundBuffer_Release(primary);
1064 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1065 "should have 0\n",ref);
1066 }
1067
1068 EXIT:
1069 ref=IDirectSound8_Release(dso);
1070 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
1071 if (ref!=0)
1072 return DSERR_GENERIC;
1073
1074 return rc;
1075 }
1076
1077 static unsigned driver_count = 0;
1078
dsenum_callback(LPGUID lpGuid,LPCSTR lpcstrDescription,LPCSTR lpcstrModule,LPVOID lpContext)1079 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1080 LPCSTR lpcstrModule, LPVOID lpContext)
1081 {
1082 HRESULT rc;
1083 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1084 driver_count++;
1085
1086 rc = test_for_driver8(lpGuid);
1087 if (rc == DSERR_NODRIVER) {
1088 trace(" No Driver\n");
1089 return 1;
1090 } else if (rc == DSERR_ALLOCATED) {
1091 trace(" Already In Use\n");
1092 return 1;
1093 } else if (rc == E_FAIL) {
1094 trace(" No Device\n");
1095 return 1;
1096 }
1097
1098 trace(" Testing the primary buffer\n");
1099 test_primary8(lpGuid);
1100
1101 trace(" Testing 3D primary buffer\n");
1102 test_primary_3d8(lpGuid);
1103
1104 trace(" Testing 3D primary buffer with listener\n");
1105 test_primary_3d_with_listener8(lpGuid);
1106
1107 /* Testing secondary buffers */
1108 test_secondary8(lpGuid,winetest_interactive,0,0,0,0,0,0);
1109 test_secondary8(lpGuid,winetest_interactive,0,0,0,1,0,0);
1110
1111 /* Testing 3D secondary buffers */
1112 test_secondary8(lpGuid,winetest_interactive,1,0,0,0,0,0);
1113 test_secondary8(lpGuid,winetest_interactive,1,1,0,0,0,0);
1114 test_secondary8(lpGuid,winetest_interactive,1,1,0,1,0,0);
1115 test_secondary8(lpGuid,winetest_interactive,1,0,1,0,0,0);
1116 test_secondary8(lpGuid,winetest_interactive,1,0,1,1,0,0);
1117 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,0);
1118 test_secondary8(lpGuid,winetest_interactive,1,1,1,1,0,0);
1119 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,0);
1120 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,1);
1121 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,1);
1122
1123 return 1;
1124 }
1125
ds3d8_tests(void)1126 static void ds3d8_tests(void)
1127 {
1128 HRESULT rc;
1129 rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
1130 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc);
1131 trace("tested %u DirectSound drivers\n", driver_count);
1132 }
1133
START_TEST(ds3d8)1134 START_TEST(ds3d8)
1135 {
1136 HMODULE hDsound;
1137
1138 CoInitialize(NULL);
1139
1140 hDsound = LoadLibrary("dsound.dll");
1141 if (hDsound)
1142 {
1143
1144 pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1145 "DirectSoundEnumerateA");
1146 pDirectSoundCreate8 = (void*)GetProcAddress(hDsound,
1147 "DirectSoundCreate8");
1148 if (pDirectSoundCreate8)
1149 ds3d8_tests();
1150 else
1151 skip("DirectSoundCreate8 missing - skipping all tests\n");
1152
1153 FreeLibrary(hDsound);
1154 }
1155 else
1156 skip("dsound.dll not found - skipping all tests\n");
1157
1158 CoUninitialize();
1159 }
1160