Release 0.9.61.
[wine/gsoc-2012-control.git] / dlls / dsound / tests / ds3d8.c
blobb072068b73c82fd7c60aa88598ba23ede428ed07
1 /*
2 * Tests the panning and 3D functions of DirectSound
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.
9 * Copyright (c) 2002-2004 Francois Gouget
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.
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.
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
26 #include <windows.h>
28 #include <math.h>
30 #include "wine/test.h"
31 #include "dsound.h"
32 #include "dxerr8.h"
33 #include "mmreg.h"
34 #include "dsound_test.h"
36 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
37 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
39 typedef struct {
40 char* wave;
41 DWORD wave_len;
43 LPDIRECTSOUNDBUFFER dsbo;
44 LPWAVEFORMATEX wfx;
45 DWORD buffer_size;
46 DWORD written;
47 DWORD played;
48 DWORD offset;
49 } play_state_t;
51 static int buffer_refill8(play_state_t* state, DWORD size)
53 LPVOID ptr1,ptr2;
54 DWORD len1,len2;
55 HRESULT rc;
57 if (size>state->wave_len-state->written)
58 size=state->wave_len-state->written;
60 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
61 &ptr1,&len1,&ptr2,&len2,0);
62 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %s\n",
63 DXGetErrorString8(rc));
64 if (rc!=DS_OK)
65 return -1;
67 memcpy(ptr1,state->wave+state->written,len1);
68 state->written+=len1;
69 if (ptr2!=NULL) {
70 memcpy(ptr2,state->wave+state->written,len2);
71 state->written+=len2;
73 state->offset=state->written % state->buffer_size;
74 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
75 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %s\n",
76 DXGetErrorString8(rc));
77 if (rc!=DS_OK)
78 return -1;
79 return size;
82 static int buffer_silence8(play_state_t* state, DWORD size)
84 LPVOID ptr1,ptr2;
85 DWORD len1,len2;
86 HRESULT rc;
87 BYTE s;
89 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
90 &ptr1,&len1,&ptr2,&len2,0);
91 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %s\n",
92 DXGetErrorString8(rc));
93 if (rc!=DS_OK)
94 return -1;
96 s=(state->wfx->wBitsPerSample==8?0x80:0);
97 memset(ptr1,s,len1);
98 if (ptr2!=NULL) {
99 memset(ptr2,s,len2);
101 state->offset=(state->offset+size) % state->buffer_size;
102 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
103 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %s\n",
104 DXGetErrorString8(rc));
105 if (rc!=DS_OK)
106 return -1;
107 return size;
110 static int buffer_service8(play_state_t* state)
112 DWORD last_play_pos,play_pos,buf_free;
113 HRESULT rc;
115 rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
116 ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %s\n",
117 DXGetErrorString8(rc));
118 if (rc!=DS_OK) {
119 goto STOP;
122 /* Update the amount played */
123 last_play_pos=state->played % state->buffer_size;
124 if (play_pos<last_play_pos)
125 state->played+=state->buffer_size-last_play_pos+play_pos;
126 else
127 state->played+=play_pos-last_play_pos;
129 if (winetest_debug > 1)
130 trace("buf size=%d last_play_pos=%d play_pos=%d played=%d / %d\n",
131 state->buffer_size,last_play_pos,play_pos,state->played,
132 state->wave_len);
134 if (state->played>state->wave_len)
136 /* Everything has been played */
137 goto STOP;
140 /* Refill the buffer */
141 if (state->offset<=play_pos)
142 buf_free=play_pos-state->offset;
143 else
144 buf_free=state->buffer_size-state->offset+play_pos;
146 if (winetest_debug > 1)
147 trace("offset=%d free=%d written=%d / %d\n",
148 state->offset,buf_free,state->written,state->wave_len);
149 if (buf_free==0)
150 return 1;
152 if (state->written<state->wave_len)
154 int w=buffer_refill8(state,buf_free);
155 if (w==-1)
156 goto STOP;
157 buf_free-=w;
158 if (state->written==state->wave_len && winetest_debug > 1)
159 trace("last sound byte at %d\n",
160 (state->written % state->buffer_size));
163 if (buf_free>0) {
164 /* Fill with silence */
165 if (winetest_debug > 1)
166 trace("writing %d bytes of silence\n",buf_free);
167 if (buffer_silence8(state,buf_free)==-1)
168 goto STOP;
170 return 1;
172 STOP:
173 if (winetest_debug > 1)
174 trace("stopping playback\n");
175 rc=IDirectSoundBuffer_Stop(state->dsbo);
176 ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %s\n",
177 DXGetErrorString8(rc));
178 return 0;
181 void test_buffer8(LPDIRECTSOUND8 dso, LPDIRECTSOUNDBUFFER * dsbo,
182 BOOL is_primary, BOOL set_volume, LONG volume,
183 BOOL set_pan, LONG pan, BOOL play, double duration,
184 BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
185 BOOL move_listener, BOOL move_sound)
187 HRESULT rc;
188 DSBCAPS dsbcaps;
189 WAVEFORMATEX wfx,wfx2;
190 DWORD size,status,freq;
191 int ref;
193 /* DSOUND: Error: Invalid caps pointer */
194 rc=IDirectSoundBuffer_GetCaps(*dsbo,0);
195 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
196 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
198 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
200 /* DSOUND: Error: Invalid caps pointer */
201 rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
202 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
203 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
205 dsbcaps.dwSize=sizeof(dsbcaps);
206 rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
207 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %s\n",
208 DXGetErrorString8(rc));
209 if (rc==DS_OK && winetest_debug > 1) {
210 trace(" Caps: flags=0x%08x size=%d\n",dsbcaps.dwFlags,
211 dsbcaps.dwBufferBytes);
214 /* Query the format size. */
215 size=0;
216 rc=IDirectSoundBuffer_GetFormat(*dsbo,NULL,0,&size);
217 ok(rc==DS_OK && size!=0,"IDirectSoundBuffer_GetFormat() should have "
218 "returned the needed size: rc=%s size=%d\n",DXGetErrorString8(rc),size);
220 ok(size == sizeof(WAVEFORMATEX) || size == sizeof(WAVEFORMATEXTENSIBLE),
221 "Expected a correct structure size, got %d\n", size);
223 if (size == sizeof(WAVEFORMATEX)) {
224 rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,size,NULL);
225 } else if (size == sizeof(WAVEFORMATEXTENSIBLE)) {
226 WAVEFORMATEXTENSIBLE wfxe;
227 rc=IDirectSoundBuffer_GetFormat(*dsbo,(WAVEFORMATEX*)&wfxe,size,NULL);
228 wfx = wfxe.Format;
230 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
231 DXGetErrorString8(rc));
232 if (rc==DS_OK && winetest_debug > 1) {
233 trace(" Format: %s tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
234 is_primary ? "Primary" : "Secondary",
235 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
236 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
239 /* DSOUND: Error: Invalid frequency buffer */
240 rc=IDirectSoundBuffer_GetFrequency(*dsbo,0);
241 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetFrequency() should have "
242 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
244 /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
245 rc=IDirectSoundBuffer_GetFrequency(*dsbo,&freq);
246 ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
247 (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
248 "IDirectSoundBuffer_GetFrequency() failed: %s\n",DXGetErrorString8(rc));
249 if (rc==DS_OK) {
250 ok(freq==wfx.nSamplesPerSec,"The frequency returned by GetFrequency "
251 "%d does not match the format %d\n",freq,wfx.nSamplesPerSec);
254 /* DSOUND: Error: Invalid status pointer */
255 rc=IDirectSoundBuffer_GetStatus(*dsbo,0);
256 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetStatus() should have "
257 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
259 rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
260 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %s\n",
261 DXGetErrorString8(rc));
262 ok(status==0,"status=0x%x instead of 0\n",status);
264 if (is_primary) {
265 DSBCAPS new_dsbcaps;
266 /* We must call SetCooperativeLevel to be allowed to call SetFormat */
267 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
268 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
269 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) "
270 "failed: %s\n",DXGetErrorString8(rc));
271 if (rc!=DS_OK)
272 return;
274 /* DSOUND: Error: Invalid format pointer */
275 rc=IDirectSoundBuffer_SetFormat(*dsbo,0);
276 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_SetFormat() should have "
277 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
279 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
280 rc=IDirectSoundBuffer_SetFormat(*dsbo,&wfx2);
281 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %s\n",
282 format_string(&wfx2), DXGetErrorString8(rc));
284 /* There is no guarantee that SetFormat will actually change the
285 * format to what we asked for. It depends on what the soundcard
286 * supports. So we must re-query the format.
288 rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,sizeof(wfx),NULL);
289 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
290 DXGetErrorString8(rc));
291 if (rc==DS_OK &&
292 (wfx.wFormatTag!=wfx2.wFormatTag ||
293 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
294 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
295 wfx.nChannels!=wfx2.nChannels)) {
296 trace("Requested format tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
297 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
298 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
299 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
300 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
301 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
304 ZeroMemory(&new_dsbcaps, sizeof(new_dsbcaps));
305 new_dsbcaps.dwSize = sizeof(new_dsbcaps);
306 rc=IDirectSoundBuffer_GetCaps(*dsbo,&new_dsbcaps);
307 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %s\n",
308 DXGetErrorString8(rc));
309 if (rc==DS_OK && winetest_debug > 1) {
310 trace(" new Caps: flags=0x%08x size=%d\n",new_dsbcaps.dwFlags,
311 new_dsbcaps.dwBufferBytes);
314 /* Check for primary buffer size change */
315 ok(new_dsbcaps.dwBufferBytes == dsbcaps.dwBufferBytes,
316 " buffer size changed after SetFormat() - "
317 "previous size was %u, current size is %u\n",
318 dsbcaps.dwBufferBytes, new_dsbcaps.dwBufferBytes);
319 dsbcaps.dwBufferBytes = new_dsbcaps.dwBufferBytes;
321 /* Check for primary buffer flags change */
322 ok(new_dsbcaps.dwFlags == dsbcaps.dwFlags,
323 " flags changed after SetFormat() - "
324 "previous flags were %08x, current flags are %08x\n",
325 dsbcaps.dwFlags, new_dsbcaps.dwFlags);
327 /* Set the CooperativeLevel back to normal */
328 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
329 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
330 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
331 "failed: %s\n",DXGetErrorString8(rc));
334 if (play) {
335 play_state_t state;
336 DS3DLISTENER listener_param;
337 LPDIRECTSOUND3DBUFFER buffer=NULL;
338 DS3DBUFFER buffer_param;
339 DWORD start_time,now;
340 LPVOID buffer1;
341 DWORD length1;
343 if (winetest_interactive) {
344 trace(" Playing %g second 440Hz tone at %dx%dx%d\n", duration,
345 wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
348 if (is_primary) {
349 /* We must call SetCooperativeLevel to be allowed to call Lock */
350 /* DSOUND: Setting DirectSound cooperative level to
351 * DSSCL_WRITEPRIMARY */
352 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),
353 DSSCL_WRITEPRIMARY);
354 ok(rc==DS_OK,
355 "IDirectSound8_SetCooperativeLevel(DSSCL_WRITEPRIMARY) failed: "
356 "%s\n",DXGetErrorString8(rc));
357 if (rc!=DS_OK)
358 return;
360 if (buffer3d) {
361 LPDIRECTSOUNDBUFFER temp_buffer;
363 rc=IDirectSoundBuffer_QueryInterface(*dsbo,&IID_IDirectSound3DBuffer,
364 (LPVOID *)&buffer);
365 ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %s\n",
366 DXGetErrorString8(rc));
367 if (rc!=DS_OK)
368 return;
370 /* check the COM interface */
371 rc=IDirectSoundBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
372 (LPVOID *)&temp_buffer);
373 ok(rc==DS_OK && temp_buffer!=NULL,
374 "IDirectSoundBuffer_QueryInterface() failed: %s\n",
375 DXGetErrorString8(rc));
376 ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
377 temp_buffer,*dsbo);
378 ref=IDirectSoundBuffer_Release(temp_buffer);
379 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
380 "should have 1\n",ref);
382 temp_buffer=NULL;
383 rc=IDirectSound3DBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
384 (LPVOID *)&temp_buffer);
385 ok(rc==DS_OK && temp_buffer!=NULL,
386 "IDirectSound3DBuffer_QueryInterface() failed: %s\n",
387 DXGetErrorString8(rc));
388 ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
389 temp_buffer,*dsbo);
390 ref=IDirectSoundBuffer_Release(temp_buffer);
391 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
392 "should have 1\n",ref);
394 ref=IDirectSoundBuffer_Release(*dsbo);
395 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
396 "should have 0\n",ref);
398 rc=IDirectSound3DBuffer_QueryInterface(buffer,
399 &IID_IDirectSoundBuffer,
400 (LPVOID *)dsbo);
401 ok(rc==DS_OK && *dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface() "
402 "failed: %s\n",DXGetErrorString8(rc));
404 /* DSOUND: Error: Invalid buffer */
405 rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
406 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
407 "failed: %s\n",DXGetErrorString8(rc));
409 ZeroMemory(&buffer_param, sizeof(buffer_param));
411 /* DSOUND: Error: Invalid buffer */
412 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
413 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
414 "failed: %s\n",DXGetErrorString8(rc));
416 buffer_param.dwSize=sizeof(buffer_param);
417 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
418 ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters() failed: %s\n",
419 DXGetErrorString8(rc));
421 if (set_volume) {
422 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
423 LONG val;
424 rc=IDirectSoundBuffer_GetVolume(*dsbo,&val);
425 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
426 DXGetErrorString8(rc));
428 rc=IDirectSoundBuffer_SetVolume(*dsbo,volume);
429 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume() failed: %s\n",
430 DXGetErrorString8(rc));
431 } else {
432 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
433 rc=IDirectSoundBuffer_GetVolume(*dsbo,&volume);
434 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetVolume() "
435 "should have returned DSERR_CONTROLUNAVAIL, returned: %s\n",
436 DXGetErrorString8(rc));
440 if (set_pan) {
441 if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
442 LONG val;
443 rc=IDirectSoundBuffer_GetPan(*dsbo,&val);
444 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan() failed: %s\n",
445 DXGetErrorString8(rc));
447 rc=IDirectSoundBuffer_SetPan(*dsbo,pan);
448 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan() failed: %s\n",
449 DXGetErrorString8(rc));
450 } else {
451 /* DSOUND: Error: Buffer does not have CTRLPAN */
452 rc=IDirectSoundBuffer_GetPan(*dsbo,&pan);
453 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetPan() "
454 "should have returned DSERR_CONTROLUNAVAIL, returned: %s\n",
455 DXGetErrorString8(rc));
459 /* try an offset past the end of the buffer */
460 rc = IDirectSoundBuffer_Lock(*dsbo, dsbcaps.dwBufferBytes, 0, &buffer1,
461 &length1, NULL, NULL,
462 DSBLOCK_ENTIREBUFFER);
463 ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
464 "returned DSERR_INVALIDPARAM, returned %s\n", DXGetErrorString8(rc));
466 /* try a size larger than the buffer */
467 rc = IDirectSoundBuffer_Lock(*dsbo, 0, dsbcaps.dwBufferBytes + 1,
468 &buffer1, &length1, NULL, NULL,
469 DSBLOCK_FROMWRITECURSOR);
470 ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
471 "returned DSERR_INVALIDPARAM, returned %s\n", DXGetErrorString8(rc));
473 state.wave=wave_generate_la(&wfx,duration,&state.wave_len);
475 state.dsbo=*dsbo;
476 state.wfx=&wfx;
477 state.buffer_size=dsbcaps.dwBufferBytes;
478 state.played=state.written=state.offset=0;
479 buffer_refill8(&state,state.buffer_size);
481 rc=IDirectSoundBuffer_Play(*dsbo,0,0,DSBPLAY_LOOPING);
482 ok(rc==DS_OK,"IDirectSoundBuffer_Play() failed: %s\n",
483 DXGetErrorString8(rc));
485 rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
486 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %s\n",
487 DXGetErrorString8(rc));
488 ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
489 "GetStatus: bad status: %x\n",status);
491 if (listener) {
492 ZeroMemory(&listener_param,sizeof(listener_param));
493 listener_param.dwSize=sizeof(listener_param);
494 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
495 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
496 "failed: %s\n",DXGetErrorString8(rc));
497 if (move_listener) {
498 listener_param.vPosition.x = -5.0f;
499 listener_param.vVelocity.x = (float)(10.0/duration);
501 rc=IDirectSound3DListener_SetAllParameters(listener,
502 &listener_param,
503 DS3D_IMMEDIATE);
504 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %s\n",
505 DXGetErrorString8(rc));
507 if (buffer3d) {
508 if (move_sound) {
509 buffer_param.vPosition.x = 100.0f;
510 buffer_param.vVelocity.x = (float)(-200.0/duration);
512 buffer_param.flMinDistance = 10;
513 rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,
514 DS3D_IMMEDIATE);
515 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %s\n",
516 DXGetErrorString8(rc));
519 start_time=GetTickCount();
520 while (buffer_service8(&state)) {
521 WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
522 now=GetTickCount();
523 if (listener && move_listener) {
524 listener_param.vPosition.x = (float)(-5.0+10.0*(now-start_time)/1000/duration);
525 if (winetest_debug>2)
526 trace("listener position=%g\n",listener_param.vPosition.x);
527 rc=IDirectSound3DListener_SetPosition(listener,
528 listener_param.vPosition.x,listener_param.vPosition.y,
529 listener_param.vPosition.z,DS3D_IMMEDIATE);
530 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: "
531 "%s\n",DXGetErrorString8(rc));
533 if (buffer3d && move_sound) {
534 buffer_param.vPosition.x = (float)(100-200.0*(now-start_time)/1000/duration);
535 if (winetest_debug>2)
536 trace("sound position=%g\n",buffer_param.vPosition.x);
537 rc=IDirectSound3DBuffer_SetPosition(buffer,
538 buffer_param.vPosition.x,buffer_param.vPosition.y,
539 buffer_param.vPosition.z,DS3D_IMMEDIATE);
540 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %s\n",
541 DXGetErrorString8(rc));
544 /* Check the sound duration was within 10% of the expected value */
545 now=GetTickCount();
546 ok(fabs(1000*duration-now+start_time)<=100*duration,
547 "The sound played for %d ms instead of %g ms\n",
548 now-start_time,1000*duration);
550 free(state.wave);
551 if (is_primary) {
552 /* Set the CooperativeLevel back to normal */
553 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
554 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
555 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
556 "failed: %s\n",DXGetErrorString8(rc));
558 if (buffer3d) {
559 ref=IDirectSound3DBuffer_Release(buffer);
560 ok(ref==0,"IDirectSound3DBuffer_Release() has %d references, "
561 "should have 0\n",ref);
566 static HRESULT test_secondary8(LPGUID lpGuid, int play,
567 int has_3d, int has_3dbuffer,
568 int has_listener, int has_duplicate,
569 int move_listener, int move_sound)
571 HRESULT rc;
572 LPDIRECTSOUND8 dso=NULL;
573 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
574 LPDIRECTSOUND3DLISTENER listener=NULL;
575 DSBUFFERDESC bufdesc;
576 WAVEFORMATEX wfx, wfx1;
577 int ref;
579 /* Create the DirectSound object */
580 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
581 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %s\n",
582 DXGetErrorString8(rc));
583 if (rc!=DS_OK)
584 return rc;
586 /* We must call SetCooperativeLevel before creating primary buffer */
587 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
588 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
589 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: "
590 "%s\n",DXGetErrorString8(rc));
591 if (rc!=DS_OK)
592 goto EXIT;
594 ZeroMemory(&bufdesc, sizeof(bufdesc));
595 bufdesc.dwSize=sizeof(bufdesc);
596 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
597 if (has_3d)
598 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
599 else
600 bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
601 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
602 ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
603 "IDirectSound8_CreateSoundBuffer() failed to create a %sprimary buffer: "
604 "%s\n",has_3d?"3D ":"", DXGetErrorString8(rc));
605 if (rc == DSERR_CONTROLUNAVAIL)
606 trace(" No Primary\n");
607 else if (rc==DS_OK && primary!=NULL) {
608 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
609 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
610 DXGetErrorString8(rc));
611 if (rc!=DS_OK)
612 goto EXIT1;
614 if (has_listener) {
615 rc=IDirectSoundBuffer_QueryInterface(primary,
616 &IID_IDirectSound3DListener,
617 (void **)&listener);
618 ok(rc==DS_OK && listener!=NULL,
619 "IDirectSoundBuffer_QueryInterface() failed to get a 3D "
620 "listener %s\n",DXGetErrorString8(rc));
621 ref=IDirectSoundBuffer_Release(primary);
622 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
623 "should have 0\n",ref);
624 if (rc==DS_OK && listener!=NULL) {
625 DS3DLISTENER listener_param;
626 ZeroMemory(&listener_param,sizeof(listener_param));
627 /* DSOUND: Error: Invalid buffer */
628 rc=IDirectSound3DListener_GetAllParameters(listener,0);
629 ok(rc==DSERR_INVALIDPARAM,
630 "IDirectSound3dListener_GetAllParameters() should have "
631 "returned DSERR_INVALIDPARAM, returned: %s\n",
632 DXGetErrorString8(rc));
634 /* DSOUND: Error: Invalid buffer */
635 rc=IDirectSound3DListener_GetAllParameters(listener,
636 &listener_param);
637 ok(rc==DSERR_INVALIDPARAM,
638 "IDirectSound3dListener_GetAllParameters() should have "
639 "returned DSERR_INVALIDPARAM, returned: %s\n",
640 DXGetErrorString8(rc));
642 listener_param.dwSize=sizeof(listener_param);
643 rc=IDirectSound3DListener_GetAllParameters(listener,
644 &listener_param);
645 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
646 "failed: %s\n",DXGetErrorString8(rc));
647 } else {
648 ok(listener==NULL, "IDirectSoundBuffer_QueryInterface() "
649 "failed but returned a listener anyway\n");
650 ok(rc!=DS_OK, "IDirectSoundBuffer_QueryInterface() succeeded "
651 "but returned a NULL listener\n");
652 if (listener) {
653 ref=IDirectSound3DListener_Release(listener);
654 ok(ref==0,"IDirectSound3dListener_Release() listener has "
655 "%d references, should have 0\n",ref);
657 goto EXIT2;
661 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
662 secondary=NULL;
663 ZeroMemory(&bufdesc, sizeof(bufdesc));
664 bufdesc.dwSize=sizeof(bufdesc);
665 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
666 if (has_3d)
667 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
668 else
669 bufdesc.dwFlags|=
670 (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
671 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
672 wfx.nBlockAlign);
673 bufdesc.lpwfxFormat=&wfx;
674 if (has_3d) {
675 /* a stereo 3D buffer should fail */
676 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
677 ok(rc==DSERR_INVALIDPARAM,
678 "IDirectSound8_CreateSoundBuffer(secondary) should have "
679 "returned DSERR_INVALIDPARAM, returned %s\n",
680 DXGetErrorString8(rc));
681 if (secondary)
682 ref=IDirectSoundBuffer_Release(secondary);
683 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,1);
686 if (winetest_interactive) {
687 trace(" Testing a %s%ssecondary buffer %s%s%s%sat %dx%dx%d "
688 "with a primary buffer at %dx%dx%d\n",
689 has_3dbuffer?"3D ":"",
690 has_duplicate?"duplicated ":"",
691 listener!=NULL||move_sound?"with ":"",
692 move_listener?"moving ":"",
693 listener!=NULL?"listener ":"",
694 listener&&move_sound?"and moving sound ":move_sound?
695 "moving sound ":"",
696 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
697 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
699 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
700 ok(rc==DS_OK && secondary!=NULL,"IDirectSound8_CreateSoundBuffer() "
701 "failed to create a %s%ssecondary buffer %s%s%s%sat %dx%dx%d (%s): %s\n",
702 has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"",
703 listener!=NULL||move_sound?"with ":"", move_listener?"moving ":"",
704 listener!=NULL?"listener ":"",
705 listener&&move_sound?"and moving sound ":move_sound?
706 "moving sound ":"",
707 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
708 getDSBCAPS(bufdesc.dwFlags),DXGetErrorString8(rc));
709 if (rc==DS_OK && secondary!=NULL) {
710 if (!has_3d) {
711 LONG refvol,vol,refpan,pan;
713 /* Check the initial secondary buffer's volume and pan */
714 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
715 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(secondary) failed: "
716 "%s\n",DXGetErrorString8(rc));
717 ok(vol==0,"wrong volume for a new secondary buffer: %d\n",vol);
718 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
719 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: "
720 "%s\n",DXGetErrorString8(rc));
721 ok(pan==0,"wrong pan for a new secondary buffer: %d\n",pan);
723 /* Check that changing the secondary buffer's volume and pan
724 * does not impact the primary buffer's volume and pan
726 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
727 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: "
728 "%s\n",DXGetErrorString8(rc));
729 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
730 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: "
731 "%s\n",DXGetErrorString8(rc));
733 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
734 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: "
735 "%s\n",DXGetErrorString8(rc));
736 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
737 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: "
738 "%s\n",DXGetErrorString8(rc));
739 ok(vol==-1000,"secondary: wrong volume %d instead of -1000\n",
740 vol);
741 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
742 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: "
743 "%s\n",DXGetErrorString8(rc));
744 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
745 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: "
746 "%s\n",DXGetErrorString8(rc));
747 ok(pan==-1000,"secondary: wrong pan %d instead of -1000\n",
748 pan);
750 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
751 ok(rc==DS_OK,"IDirectSoundBuffer_`GetVolume(primary) failed: i"
752 "%s\n",DXGetErrorString8(rc));
753 ok(vol==refvol,"The primary volume changed from %d to %d\n",
754 refvol,vol);
755 rc=IDirectSoundBuffer_GetPan(primary,&pan);
756 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: "
757 "%s\n",DXGetErrorString8(rc));
758 ok(pan==refpan,"The primary pan changed from %d to %d\n",
759 refpan,pan);
761 rc=IDirectSoundBuffer_SetVolume(secondary,0);
762 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: "
763 "%s\n",DXGetErrorString8(rc));
764 rc=IDirectSoundBuffer_SetPan(secondary,0);
765 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: "
766 "%s\n",DXGetErrorString8(rc));
768 if (has_duplicate) {
769 LPDIRECTSOUNDBUFFER duplicated=NULL;
771 /* DSOUND: Error: Invalid source buffer */
772 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,0);
773 ok(rc==DSERR_INVALIDPARAM,
774 "IDirectSound8_DuplicateSoundBuffer() should have returned "
775 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
777 /* DSOUND: Error: Invalid dest buffer */
778 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,0);
779 ok(rc==DSERR_INVALIDPARAM,
780 "IDirectSound8_DuplicateSoundBuffer() should have returned "
781 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
783 /* DSOUND: Error: Invalid source buffer */
784 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,&duplicated);
785 ok(rc==DSERR_INVALIDPARAM,
786 "IDirectSound8_DuplicateSoundBuffer() should have returned "
787 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
789 duplicated=NULL;
790 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,
791 &duplicated);
792 ok(rc==DS_OK && duplicated!=NULL,
793 "IDirectSound8_DuplicateSoundBuffer() failed to duplicate "
794 "a secondary buffer: %s\n",DXGetErrorString8(rc));
796 if (rc==DS_OK && duplicated!=NULL) {
797 ref=IDirectSoundBuffer_Release(secondary);
798 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
799 "references, should have 0\n",ref);
800 secondary=duplicated;
804 if (rc==DS_OK && secondary!=NULL) {
805 double duration;
806 duration=(move_listener || move_sound?4.0:1.0);
807 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
808 winetest_interactive,duration,has_3dbuffer,
809 listener,move_listener,move_sound);
810 ref=IDirectSoundBuffer_Release(secondary);
811 ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, "
812 "should have 0\n",has_duplicate?"duplicated":"secondary",
813 ref);
816 EXIT1:
817 if (has_listener) {
818 ref=IDirectSound3DListener_Release(listener);
819 ok(ref==0,"IDirectSound3dListener_Release() listener has %d "
820 "references, should have 0\n",ref);
821 } else {
822 ref=IDirectSoundBuffer_Release(primary);
823 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
824 "should have 0\n",ref);
826 } else {
827 ok(primary==NULL,"IDirectSound8_CreateSoundBuffer(primary) failed "
828 "but primary created anyway\n");
829 ok(rc!=DS_OK,"IDirectSound8_CreateSoundBuffer(primary) succeeded "
830 "but primary not created\n");
831 if (primary) {
832 ref=IDirectSoundBuffer_Release(primary);
833 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
834 "should have 0\n",ref);
837 EXIT2:
838 /* Set the CooperativeLevel back to normal */
839 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
840 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
841 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: "
842 "%s\n",DXGetErrorString8(rc));
844 EXIT:
845 ref=IDirectSound8_Release(dso);
846 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
847 if (ref!=0)
848 return DSERR_GENERIC;
850 return rc;
853 static HRESULT test_for_driver8(LPGUID lpGuid)
855 HRESULT rc;
856 LPDIRECTSOUND8 dso=NULL;
857 int ref;
859 /* Create the DirectSound object */
860 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
861 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
862 "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
863 if (rc!=DS_OK)
864 return rc;
866 ref=IDirectSound8_Release(dso);
867 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
868 if (ref!=0)
869 return DSERR_GENERIC;
871 return rc;
874 static HRESULT test_primary8(LPGUID lpGuid)
876 HRESULT rc;
877 LPDIRECTSOUND8 dso=NULL;
878 LPDIRECTSOUNDBUFFER primary=NULL;
879 DSBUFFERDESC bufdesc;
880 DSCAPS dscaps;
881 int ref, i;
883 /* Create the DirectSound object */
884 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
885 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %s\n",
886 DXGetErrorString8(rc));
887 if (rc!=DS_OK)
888 return rc;
890 /* Get the device capabilities */
891 ZeroMemory(&dscaps, sizeof(dscaps));
892 dscaps.dwSize=sizeof(dscaps);
893 rc=IDirectSound8_GetCaps(dso,&dscaps);
894 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
895 if (rc!=DS_OK)
896 goto EXIT;
898 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
899 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
900 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
901 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: "
902 "%s\n",DXGetErrorString8(rc));
903 if (rc!=DS_OK)
904 goto EXIT;
906 /* Testing the primary buffer */
907 primary=NULL;
908 ZeroMemory(&bufdesc, sizeof(bufdesc));
909 bufdesc.dwSize=sizeof(bufdesc);
910 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
911 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
912 ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
913 "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: "
914 "%s\n",DXGetErrorString8(rc));
915 if (rc == DSERR_CONTROLUNAVAIL)
916 trace(" No Primary\n");
917 else if (rc==DS_OK && primary!=NULL) {
918 test_buffer8(dso,&primary,1,TRUE,0,TRUE,0,winetest_interactive &&
919 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
920 if (winetest_interactive) {
921 LONG volume,pan;
923 volume = DSBVOLUME_MAX;
924 for (i = 0; i < 6; i++) {
925 test_buffer8(dso,&primary,1,TRUE,volume,TRUE,0,
926 winetest_interactive &&
927 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
928 1.0,0,NULL,0,0);
929 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
932 pan = DSBPAN_LEFT;
933 for (i = 0; i < 7; i++) {
934 test_buffer8(dso,&primary,1,TRUE,0,TRUE,pan,
935 winetest_interactive &&
936 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
937 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
940 ref=IDirectSoundBuffer_Release(primary);
941 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
942 "should have 0\n",ref);
945 /* Set the CooperativeLevel back to normal */
946 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
947 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
948 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: "
949 "%s\n",DXGetErrorString8(rc));
951 EXIT:
952 ref=IDirectSound8_Release(dso);
953 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
954 if (ref!=0)
955 return DSERR_GENERIC;
957 return rc;
960 static HRESULT test_primary_3d8(LPGUID lpGuid)
962 HRESULT rc;
963 LPDIRECTSOUND8 dso=NULL;
964 LPDIRECTSOUNDBUFFER primary=NULL;
965 DSBUFFERDESC bufdesc;
966 DSCAPS dscaps;
967 int ref;
969 /* Create the DirectSound object */
970 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
971 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %s\n",
972 DXGetErrorString8(rc));
973 if (rc!=DS_OK)
974 return rc;
976 /* Get the device capabilities */
977 ZeroMemory(&dscaps, sizeof(dscaps));
978 dscaps.dwSize=sizeof(dscaps);
979 rc=IDirectSound8_GetCaps(dso,&dscaps);
980 ok(rc==DS_OK,"IDirectSound8_GetCaps failed: %s\n",DXGetErrorString8(rc));
981 if (rc!=DS_OK)
982 goto EXIT;
984 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
985 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
986 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
987 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: "
988 "%s\n",DXGetErrorString8(rc));
989 if (rc!=DS_OK)
990 goto EXIT;
992 primary=NULL;
993 ZeroMemory(&bufdesc, sizeof(bufdesc));
994 bufdesc.dwSize=sizeof(bufdesc);
995 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
996 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
997 ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
998 "to create a primary buffer: %s\n",DXGetErrorString8(rc));
999 if (rc==DS_OK && primary!=NULL) {
1000 ref=IDirectSoundBuffer_Release(primary);
1001 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1002 "should have 0\n",ref);
1003 primary=NULL;
1004 ZeroMemory(&bufdesc, sizeof(bufdesc));
1005 bufdesc.dwSize=sizeof(bufdesc);
1006 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
1007 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1008 ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() "
1009 "failed to create a 3D primary buffer: %s\n",DXGetErrorString8(rc));
1010 if (rc==DS_OK && primary!=NULL) {
1011 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
1012 winetest_interactive &&
1013 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
1014 ref=IDirectSoundBuffer_Release(primary);
1015 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1016 "should have 0\n",ref);
1019 /* Set the CooperativeLevel back to normal */
1020 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
1021 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
1022 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: "
1023 "%s\n",DXGetErrorString8(rc));
1025 EXIT:
1026 ref=IDirectSound8_Release(dso);
1027 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
1028 if (ref!=0)
1029 return DSERR_GENERIC;
1031 return rc;
1034 static HRESULT test_primary_3d_with_listener8(LPGUID lpGuid)
1036 HRESULT rc;
1037 LPDIRECTSOUND8 dso=NULL;
1038 LPDIRECTSOUNDBUFFER primary=NULL;
1039 DSBUFFERDESC bufdesc;
1040 DSCAPS dscaps;
1041 int ref;
1043 /* Create the DirectSound object */
1044 rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
1045 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %s\n",
1046 DXGetErrorString8(rc));
1047 if (rc!=DS_OK)
1048 return rc;
1050 /* Get the device capabilities */
1051 ZeroMemory(&dscaps, sizeof(dscaps));
1052 dscaps.dwSize=sizeof(dscaps);
1053 rc=IDirectSound8_GetCaps(dso,&dscaps);
1054 ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
1055 if (rc!=DS_OK)
1056 goto EXIT;
1058 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
1059 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1060 rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1061 ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: "
1062 "%s\n",DXGetErrorString8(rc));
1063 if (rc!=DS_OK)
1064 goto EXIT;
1065 primary=NULL;
1066 ZeroMemory(&bufdesc, sizeof(bufdesc));
1067 bufdesc.dwSize=sizeof(bufdesc);
1068 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
1069 rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1070 ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
1071 "to create a 3D primary buffer %s\n",DXGetErrorString8(rc));
1072 if (rc==DS_OK && primary!=NULL) {
1073 LPDIRECTSOUND3DLISTENER listener=NULL;
1074 rc=IDirectSoundBuffer_QueryInterface(primary,
1075 &IID_IDirectSound3DListener,
1076 (void **)&listener);
1077 ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface() "
1078 "failed to get a 3D listener: %s\n",DXGetErrorString8(rc));
1079 if (rc==DS_OK && listener!=NULL) {
1080 LPDIRECTSOUNDBUFFER temp_buffer=NULL;
1082 /* Checking the COM interface */
1083 rc=IDirectSoundBuffer_QueryInterface(primary,
1084 &IID_IDirectSoundBuffer,
1085 (LPVOID *)&temp_buffer);
1086 ok(rc==DS_OK && temp_buffer!=NULL,
1087 "IDirectSoundBuffer_QueryInterface() failed: %s\n",
1088 DXGetErrorString8(rc));
1089 ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1090 if (rc==DS_OK && temp_buffer!=NULL) {
1091 ref=IDirectSoundBuffer_Release(temp_buffer);
1092 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1093 "should have 1\n",ref);
1095 temp_buffer=NULL;
1096 rc=IDirectSound3DListener_QueryInterface(listener,
1097 &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
1098 ok(rc==DS_OK && temp_buffer!=NULL,
1099 "IDirectSoundBuffer_QueryInterface() failed: %s\n",
1100 DXGetErrorString8(rc));
1101 ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1102 ref=IDirectSoundBuffer_Release(temp_buffer);
1103 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1104 "should have 1\n",ref);
1106 /* Testing the buffer */
1107 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
1108 winetest_interactive &&
1109 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
1110 1.0,0,listener,0,0);
1113 /* Testing the reference counting */
1114 ref=IDirectSound3DListener_Release(listener);
1115 ok(ref==0,"IDirectSound3DListener_Release() listener has %d "
1116 "references, should have 0\n",ref);
1119 /* Testing the reference counting */
1120 ref=IDirectSoundBuffer_Release(primary);
1121 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1122 "should have 0\n",ref);
1125 EXIT:
1126 ref=IDirectSound8_Release(dso);
1127 ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
1128 if (ref!=0)
1129 return DSERR_GENERIC;
1131 return rc;
1134 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1135 LPCSTR lpcstrModule, LPVOID lpContext)
1137 HRESULT rc;
1138 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1140 rc = test_for_driver8(lpGuid);
1141 if (rc == DSERR_NODRIVER) {
1142 trace(" No Driver\n");
1143 return 1;
1144 } else if (rc == DSERR_ALLOCATED) {
1145 trace(" Already In Use\n");
1146 return 1;
1147 } else if (rc == E_FAIL) {
1148 trace(" No Device\n");
1149 return 1;
1152 trace(" Testing the primary buffer\n");
1153 test_primary8(lpGuid);
1155 trace(" Testing 3D primary buffer\n");
1156 test_primary_3d8(lpGuid);
1158 trace(" Testing 3D primary buffer with listener\n");
1159 test_primary_3d_with_listener8(lpGuid);
1161 /* Testing secondary buffers */
1162 test_secondary8(lpGuid,winetest_interactive,0,0,0,0,0,0);
1163 test_secondary8(lpGuid,winetest_interactive,0,0,0,1,0,0);
1165 /* Testing 3D secondary buffers */
1166 test_secondary8(lpGuid,winetest_interactive,1,0,0,0,0,0);
1167 test_secondary8(lpGuid,winetest_interactive,1,1,0,0,0,0);
1168 test_secondary8(lpGuid,winetest_interactive,1,1,0,1,0,0);
1169 test_secondary8(lpGuid,winetest_interactive,1,0,1,0,0,0);
1170 test_secondary8(lpGuid,winetest_interactive,1,0,1,1,0,0);
1171 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,0);
1172 test_secondary8(lpGuid,winetest_interactive,1,1,1,1,0,0);
1173 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,0);
1174 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,1);
1175 test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,1);
1177 return 1;
1180 static void ds3d8_tests(void)
1182 HRESULT rc;
1183 rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
1184 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
1187 START_TEST(ds3d8)
1189 HMODULE hDsound;
1191 CoInitialize(NULL);
1193 hDsound = LoadLibrary("dsound.dll");
1194 if (hDsound)
1196 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
1198 pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1199 "DirectSoundEnumerateA");
1200 pDirectSoundCreate8 = (void*)GetProcAddress(hDsound,
1201 "DirectSoundCreate8");
1202 if (pDirectSoundCreate8)
1203 ds3d8_tests();
1204 else
1205 skip("ds3d8 test skipped\n");
1207 FreeLibrary(hDsound);
1209 else
1210 skip("dsound.dll not found!\n");
1212 CoUninitialize();