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 #define PI 3.14159265358979323846 29 30 31 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL; 32 static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID,LPDIRECTSOUND*, 33 LPUNKNOWN)=NULL; 34 35 char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size, BOOL ieee) 36 { 37 int i; 38 int nb_samples; 39 char* buf; 40 char* b; 41 42 nb_samples=(int)(duration*wfx->nSamplesPerSec); 43 *size=nb_samples*wfx->nBlockAlign; 44 b=buf=HeapAlloc(GetProcessHeap(), 0, *size); 45 for (i=0;i<nb_samples;i++) { 46 double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec); 47 if (wfx->wBitsPerSample==8) { 48 unsigned char sample=127.5*(y+1.0); 49 *b++=sample; 50 if (wfx->nChannels==2) 51 *b++=sample; 52 } else if (wfx->wBitsPerSample == 16) { 53 signed short sample=32767.5*y-0.5; 54 b[0]=sample & 0xff; 55 b[1]=sample >> 8; 56 b+=2; 57 if (wfx->nChannels==2) { 58 b[0]=sample & 0xff; 59 b[1]=sample >> 8; 60 b+=2; 61 } 62 } else if (wfx->wBitsPerSample == 24) { 63 signed int sample=8388607.5*y-0.5; 64 b[0]=sample & 0xff; 65 b[1]=(sample >> 8)&0xff; 66 b[2]=sample >> 16; 67 b+=3; 68 if (wfx->nChannels==2) { 69 b[0]=sample & 0xff; 70 b[1]=(sample >> 8)&0xff; 71 b[2]=sample >> 16; 72 b+=3; 73 } 74 } else if (wfx->wBitsPerSample == 32) { 75 if (ieee) { 76 float *ptr = (float *) b; 77 *ptr = y; 78 79 ptr++; 80 b+=4; 81 82 if (wfx->nChannels==2) { 83 *ptr = y; 84 b+=4; 85 } 86 } else { 87 signed int sample=2147483647.5*y-0.5; 88 b[0]=sample & 0xff; 89 b[1]=(sample >> 8)&0xff; 90 b[2]=(sample >> 16)&0xff; 91 b[3]=sample >> 24; 92 b+=4; 93 if (wfx->nChannels==2) { 94 b[0]=sample & 0xff; 95 b[1]=(sample >> 8)&0xff; 96 b[2]=(sample >> 16)&0xff; 97 b[3]=sample >> 24; 98 b+=4; 99 } 100 } 101 } 102 } 103 return buf; 104 } 105 106 const char * getDSBCAPS(DWORD xmask) { 107 static struct { 108 DWORD mask; 109 const char *name; 110 } flags[] = { 111 #define FE(x) { x, #x }, 112 FE(DSBCAPS_PRIMARYBUFFER) 113 FE(DSBCAPS_STATIC) 114 FE(DSBCAPS_LOCHARDWARE) 115 FE(DSBCAPS_LOCSOFTWARE) 116 FE(DSBCAPS_CTRL3D) 117 FE(DSBCAPS_CTRLFREQUENCY) 118 FE(DSBCAPS_CTRLPAN) 119 FE(DSBCAPS_CTRLVOLUME) 120 FE(DSBCAPS_CTRLPOSITIONNOTIFY) 121 FE(DSBCAPS_STICKYFOCUS) 122 FE(DSBCAPS_GLOBALFOCUS) 123 FE(DSBCAPS_GETCURRENTPOSITION2) 124 FE(DSBCAPS_MUTE3DATMAXDISTANCE) 125 #undef FE 126 }; 127 static char buffer[512]; 128 unsigned int i; 129 BOOL first = TRUE; 130 131 buffer[0] = 0; 132 133 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++) { 134 if ((flags[i].mask & xmask) == flags[i].mask) { 135 if (first) 136 first = FALSE; 137 else 138 strcat(buffer, "|"); 139 strcat(buffer, flags[i].name); 140 } 141 } 142 143 return buffer; 144 } 145 146 HWND get_hwnd(void) 147 { 148 HWND hwnd=GetForegroundWindow(); 149 if (!hwnd) 150 hwnd=GetDesktopWindow(); 151 return hwnd; 152 } 153 154 void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth, 155 int channels) 156 { 157 wfx->wFormatTag=format; 158 wfx->nChannels=channels; 159 wfx->wBitsPerSample=depth; 160 wfx->nSamplesPerSec=rate; 161 wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8; 162 /* FIXME: Shouldn't this test be if (format!=WAVE_FORMAT_PCM) */ 163 if (wfx->nBlockAlign==0) 164 { 165 /* align compressed formats to byte boundary */ 166 wfx->nBlockAlign=1; 167 } 168 wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign; 169 wfx->cbSize=0; 170 } 171 172 typedef struct { 173 char* wave; 174 DWORD wave_len; 175 176 LPDIRECTSOUNDBUFFER dsbo; 177 LPWAVEFORMATEX wfx; 178 DWORD buffer_size; 179 DWORD written; 180 DWORD played; 181 DWORD offset; 182 } play_state_t; 183 184 static int buffer_refill(play_state_t* state, DWORD size) 185 { 186 LPVOID ptr1,ptr2; 187 DWORD len1,len2; 188 HRESULT rc; 189 190 if (size>state->wave_len-state->written) 191 size=state->wave_len-state->written; 192 193 /* some broken apps like Navyfield mistakenly pass NULL for a ppValue */ 194 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size, 195 &ptr1,NULL,&ptr2,&len2,0); 196 ok(rc==DSERR_INVALIDPARAM,"expected %08x got %08x\n",DSERR_INVALIDPARAM, rc); 197 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size, 198 &ptr1,&len1,&ptr2,&len2,0); 199 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc); 200 if (rc!=DS_OK) 201 return -1; 202 203 memcpy(ptr1,state->wave+state->written,len1); 204 state->written+=len1; 205 if (ptr2!=NULL) { 206 memcpy(ptr2,state->wave+state->written,len2); 207 state->written+=len2; 208 } 209 state->offset=state->written % state->buffer_size; 210 /* some apps blindly pass &ptr1 instead of ptr1 */ 211 rc=IDirectSoundBuffer_Unlock(state->dsbo,&ptr1,len1,ptr2,len2); 212 ok(rc==DSERR_INVALIDPARAM, "IDDirectSoundBuffer_Unlock(): expected %08x got %08x, %p %p\n",DSERR_INVALIDPARAM, rc, &ptr1, ptr1); 213 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2); 214 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc); 215 if (rc!=DS_OK) 216 return -1; 217 return size; 218 } 219 220 static int buffer_silence(play_state_t* state, DWORD size) 221 { 222 LPVOID ptr1,ptr2; 223 DWORD len1,len2; 224 HRESULT rc; 225 BYTE s; 226 227 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size, 228 &ptr1,&len1,&ptr2,&len2,0); 229 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc); 230 if (rc!=DS_OK) 231 return -1; 232 233 s=(state->wfx->wBitsPerSample==8?0x80:0); 234 memset(ptr1,s,len1); 235 if (ptr2!=NULL) { 236 memset(ptr2,s,len2); 237 } 238 state->offset=(state->offset+size) % state->buffer_size; 239 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2); 240 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc); 241 if (rc!=DS_OK) 242 return -1; 243 return size; 244 } 245 246 static int buffer_service(play_state_t* state) 247 { 248 DWORD last_play_pos,play_pos,buf_free; 249 HRESULT rc; 250 251 rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL); 252 ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %08x\n", rc); 253 if (rc!=DS_OK) { 254 goto STOP; 255 } 256 257 /* Update the amount played */ 258 last_play_pos=state->played % state->buffer_size; 259 if (play_pos<last_play_pos) 260 state->played+=state->buffer_size-last_play_pos+play_pos; 261 else 262 state->played+=play_pos-last_play_pos; 263 264 if (winetest_debug > 1) 265 trace("buf size=%d last_play_pos=%d play_pos=%d played=%d / %d\n", 266 state->buffer_size,last_play_pos,play_pos,state->played, 267 state->wave_len); 268 269 if (state->played>state->wave_len) 270 { 271 /* Everything has been played */ 272 goto STOP; 273 } 274 275 /* Refill the buffer */ 276 if (state->offset<=play_pos) 277 buf_free=play_pos-state->offset; 278 else 279 buf_free=state->buffer_size-state->offset+play_pos; 280 281 if (winetest_debug > 1) 282 trace("offset=%d free=%d written=%d / %d\n", 283 state->offset,buf_free,state->written,state->wave_len); 284 if (buf_free==0) 285 return 1; 286 287 if (state->written<state->wave_len) 288 { 289 int w=buffer_refill(state,buf_free); 290 if (w==-1) 291 goto STOP; 292 buf_free-=w; 293 if (state->written==state->wave_len && winetest_debug > 1) 294 trace("last sound byte at %d\n", 295 (state->written % state->buffer_size)); 296 } 297 298 if (buf_free>0) { 299 /* Fill with silence */ 300 if (winetest_debug > 1) 301 trace("writing %d bytes of silence\n",buf_free); 302 if (buffer_silence(state,buf_free)==-1) 303 goto STOP; 304 } 305 return 1; 306 307 STOP: 308 if (winetest_debug > 1) 309 trace("stopping playback\n"); 310 rc=IDirectSoundBuffer_Stop(state->dsbo); 311 ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %08x\n", rc); 312 return 0; 313 } 314 315 void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER *dsbo, 316 BOOL is_primary, BOOL set_volume, LONG volume, 317 BOOL set_pan, LONG pan, BOOL play, double duration, 318 BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener, 319 BOOL move_listener, BOOL move_sound, 320 BOOL set_frequency, DWORD frequency) 321 { 322 HRESULT rc; 323 DSBCAPS dsbcaps; 324 WAVEFORMATEX wfx,wfx2; 325 DWORD size,status,freq; 326 BOOL ieee = FALSE; 327 int ref; 328 329 if (set_frequency) { 330 rc=IDirectSoundBuffer_SetFrequency(*dsbo,frequency); 331 ok(rc==DS_OK||rc==DSERR_CONTROLUNAVAIL, 332 "IDirectSoundBuffer_SetFrequency() failed to set frequency %08x\n",rc); 333 if (rc!=DS_OK) 334 return; 335 } 336 337 /* DSOUND: Error: Invalid caps pointer */ 338 rc=IDirectSoundBuffer_GetCaps(*dsbo,0); 339 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have " 340 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 341 342 ZeroMemory(&dsbcaps, sizeof(dsbcaps)); 343 344 /* DSOUND: Error: Invalid caps pointer */ 345 rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps); 346 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have " 347 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 348 349 dsbcaps.dwSize=sizeof(dsbcaps); 350 rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps); 351 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc); 352 if (rc==DS_OK && winetest_debug > 1) { 353 trace(" Caps: flags=0x%08x size=%d\n",dsbcaps.dwFlags, 354 dsbcaps.dwBufferBytes); 355 } 356 357 /* Query the format size. */ 358 size=0; 359 rc=IDirectSoundBuffer_GetFormat(*dsbo,NULL,0,&size); 360 ok(rc==DS_OK && size!=0,"IDirectSoundBuffer_GetFormat() should have " 361 "returned the needed size: rc=%08x size=%d\n",rc,size); 362 363 ok(size == sizeof(WAVEFORMATEX) || size == sizeof(WAVEFORMATEXTENSIBLE), 364 "Expected a correct structure size, got %d\n", size); 365 366 if (size == sizeof(WAVEFORMATEX)) { 367 rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,size,NULL); 368 ieee = (wfx.wFormatTag == WAVE_FORMAT_IEEE_FLOAT); 369 } 370 else if (size == sizeof(WAVEFORMATEXTENSIBLE)) { 371 WAVEFORMATEXTENSIBLE wfxe; 372 rc=IDirectSoundBuffer_GetFormat(*dsbo,(WAVEFORMATEX*)&wfxe,size,NULL); 373 wfx = wfxe.Format; 374 ieee = IsEqualGUID(&wfxe.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT); 375 } else 376 return; 377 378 ok(rc==DS_OK, 379 "IDirectSoundBuffer_GetFormat() failed: %08x\n", rc); 380 if (rc==DS_OK && winetest_debug > 1) { 381 trace(" Format: %s tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n", 382 is_primary ? "Primary" : "Secondary", 383 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, 384 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); 385 } 386 387 /* DSOUND: Error: Invalid frequency buffer */ 388 rc=IDirectSoundBuffer_GetFrequency(*dsbo,0); 389 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetFrequency() should have " 390 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 391 392 /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */ 393 rc=IDirectSoundBuffer_GetFrequency(*dsbo,&freq); 394 ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) || 395 (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)), 396 "IDirectSoundBuffer_GetFrequency() failed: %08x\n",rc); 397 if (rc==DS_OK) { 398 DWORD f = set_frequency?frequency:wfx.nSamplesPerSec; 399 ok(freq==f,"The frequency returned by GetFrequency " 400 "%d does not match the format %d\n",freq,f); 401 } 402 403 /* DSOUND: Error: Invalid status pointer */ 404 rc=IDirectSoundBuffer_GetStatus(*dsbo,0); 405 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetStatus() should have " 406 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 407 408 rc=IDirectSoundBuffer_GetStatus(*dsbo,&status); 409 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc); 410 ok(status==0,"status=0x%x instead of 0\n",status); 411 412 if (is_primary) { 413 DSBCAPS new_dsbcaps; 414 /* We must call SetCooperativeLevel to be allowed to call SetFormat */ 415 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ 416 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); 417 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc); 418 if (rc!=DS_OK) 419 return; 420 421 /* DSOUND: Error: Invalid format pointer */ 422 rc=IDirectSoundBuffer_SetFormat(*dsbo,0); 423 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_SetFormat() should have " 424 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 425 426 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2); 427 rc=IDirectSoundBuffer_SetFormat(*dsbo,&wfx2); 428 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %08x\n", 429 format_string(&wfx2), rc); 430 431 /* There is no guarantee that SetFormat will actually change the 432 * format to what we asked for. It depends on what the soundcard 433 * supports. So we must re-query the format. 434 */ 435 rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,sizeof(wfx),NULL); 436 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc); 437 if (rc==DS_OK && 438 (wfx.wFormatTag!=wfx2.wFormatTag || 439 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec || 440 wfx.wBitsPerSample!=wfx2.wBitsPerSample || 441 wfx.nChannels!=wfx2.nChannels)) { 442 trace("Requested format tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n", 443 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample, 444 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign); 445 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n", 446 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, 447 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); 448 } 449 450 ZeroMemory(&new_dsbcaps, sizeof(new_dsbcaps)); 451 new_dsbcaps.dwSize = sizeof(new_dsbcaps); 452 rc=IDirectSoundBuffer_GetCaps(*dsbo,&new_dsbcaps); 453 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc); 454 if (rc==DS_OK && winetest_debug > 1) { 455 trace(" new Caps: flags=0x%08x size=%d\n",new_dsbcaps.dwFlags, 456 new_dsbcaps.dwBufferBytes); 457 } 458 459 /* Check for primary buffer size change */ 460 ok(new_dsbcaps.dwBufferBytes == dsbcaps.dwBufferBytes, 461 " buffer size changed after SetFormat() - " 462 "previous size was %u, current size is %u\n", 463 dsbcaps.dwBufferBytes, new_dsbcaps.dwBufferBytes); 464 dsbcaps.dwBufferBytes = new_dsbcaps.dwBufferBytes; 465 466 /* Check for primary buffer flags change */ 467 ok(new_dsbcaps.dwFlags == dsbcaps.dwFlags, 468 " flags changed after SetFormat() - " 469 "previous flags were %08x, current flags are %08x\n", 470 dsbcaps.dwFlags, new_dsbcaps.dwFlags); 471 472 /* Set the CooperativeLevel back to normal */ 473 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ 474 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); 475 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc); 476 } 477 478 if (play) { 479 play_state_t state; 480 DS3DLISTENER listener_param; 481 LPDIRECTSOUND3DBUFFER buffer=NULL; 482 DS3DBUFFER buffer_param; 483 DWORD start_time,now; 484 LPVOID buffer1; 485 DWORD length1; 486 487 if (winetest_interactive) { 488 if (set_frequency) 489 trace(" Playing %g second 440Hz tone at %dx%dx%d with a " 490 "frequency of %d (%dHz)\n", duration, 491 wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nChannels, 492 frequency, (440 * frequency) / wfx.nSamplesPerSec); 493 else 494 trace(" Playing %g second 440Hz tone at %dx%dx%d\n", duration, 495 wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nChannels); 496 } 497 498 if (is_primary) { 499 /* We must call SetCooperativeLevel to be allowed to call Lock */ 500 /* DSOUND: Setting DirectSound cooperative level to 501 * DSSCL_WRITEPRIMARY */ 502 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(), 503 DSSCL_WRITEPRIMARY); 504 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_WRITEPRIMARY) " 505 "failed: %08x\n",rc); 506 if (rc!=DS_OK) 507 return; 508 } 509 if (buffer3d) { 510 LPDIRECTSOUNDBUFFER temp_buffer; 511 512 rc=IDirectSoundBuffer_QueryInterface(*dsbo,&IID_IDirectSound3DBuffer, 513 (LPVOID *)&buffer); 514 ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc); 515 if (rc!=DS_OK) 516 return; 517 518 /* check the COM interface */ 519 rc=IDirectSoundBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer, 520 (LPVOID *)&temp_buffer); 521 ok(rc==DS_OK && temp_buffer!=NULL, 522 "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc); 523 ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n", 524 temp_buffer,*dsbo); 525 ref=IDirectSoundBuffer_Release(temp_buffer); 526 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, " 527 "should have 1\n",ref); 528 529 temp_buffer=NULL; 530 rc=IDirectSound3DBuffer_QueryInterface(*dsbo, 531 &IID_IDirectSoundBuffer, 532 (LPVOID *)&temp_buffer); 533 ok(rc==DS_OK && temp_buffer!=NULL, 534 "IDirectSound3DBuffer_QueryInterface() failed: %08x\n", rc); 535 ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n", 536 temp_buffer,*dsbo); 537 ref=IDirectSoundBuffer_Release(temp_buffer); 538 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, " 539 "should have 1\n",ref); 540 541 ref=IDirectSoundBuffer_Release(*dsbo); 542 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, " 543 "should have 0\n",ref); 544 545 rc=IDirectSound3DBuffer_QueryInterface(buffer, 546 &IID_IDirectSoundBuffer, 547 (LPVOID *)dsbo); 548 ok(rc==DS_OK && *dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface() " 549 "failed: %08x\n",rc); 550 551 /* DSOUND: Error: Invalid buffer */ 552 rc=IDirectSound3DBuffer_GetAllParameters(buffer,0); 553 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() " 554 "failed: %08x\n",rc); 555 556 ZeroMemory(&buffer_param, sizeof(buffer_param)); 557 558 /* DSOUND: Error: Invalid buffer */ 559 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param); 560 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() " 561 "failed: %08x\n",rc); 562 563 buffer_param.dwSize=sizeof(buffer_param); 564 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param); 565 ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters() failed: %08x\n", rc); 566 } 567 if (set_volume) { 568 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) { 569 LONG val; 570 rc=IDirectSoundBuffer_GetVolume(*dsbo,&val); 571 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc); 572 573 rc=IDirectSoundBuffer_SetVolume(*dsbo,volume); 574 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume() failed: %08x\n", rc); 575 } else { 576 /* DSOUND: Error: Buffer does not have CTRLVOLUME */ 577 rc=IDirectSoundBuffer_GetVolume(*dsbo,&volume); 578 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetVolume() " 579 "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc); 580 } 581 } 582 583 if (set_pan) { 584 if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) { 585 LONG val; 586 rc=IDirectSoundBuffer_GetPan(*dsbo,&val); 587 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan() failed: %08x\n", rc); 588 589 rc=IDirectSoundBuffer_SetPan(*dsbo,pan); 590 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan() failed: %08x\n", rc); 591 } else { 592 /* DSOUND: Error: Buffer does not have CTRLPAN */ 593 rc=IDirectSoundBuffer_GetPan(*dsbo,&pan); 594 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetPan() " 595 "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc); 596 } 597 } 598 599 /* try an offset past the end of the buffer */ 600 rc = IDirectSoundBuffer_Lock(*dsbo, dsbcaps.dwBufferBytes, 0, &buffer1, 601 &length1, NULL, NULL, 602 DSBLOCK_ENTIREBUFFER); 603 ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have " 604 "returned DSERR_INVALIDPARAM, returned %08x\n", rc); 605 606 /* try a size larger than the buffer */ 607 rc = IDirectSoundBuffer_Lock(*dsbo, 0, dsbcaps.dwBufferBytes + 1, 608 &buffer1, &length1, NULL, NULL, 609 DSBLOCK_FROMWRITECURSOR); 610 ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have " 611 "returned DSERR_INVALIDPARAM, returned %08x\n", rc); 612 613 if (set_frequency) 614 state.wave=wave_generate_la(&wfx,(duration*frequency)/wfx.nSamplesPerSec,&state.wave_len,ieee); 615 else 616 state.wave=wave_generate_la(&wfx,duration,&state.wave_len,ieee); 617 618 state.dsbo=*dsbo; 619 state.wfx=&wfx; 620 state.buffer_size=dsbcaps.dwBufferBytes; 621 state.played=state.written=state.offset=0; 622 buffer_refill(&state,state.buffer_size); 623 624 rc=IDirectSoundBuffer_Play(*dsbo,0,0,DSBPLAY_LOOPING); 625 ok(rc==DS_OK,"IDirectSoundBuffer_Play() failed: %08x\n", rc); 626 627 rc=IDirectSoundBuffer_GetStatus(*dsbo,&status); 628 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc); 629 ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING), 630 "GetStatus: bad status: %x\n",status); 631 632 if (listener) { 633 ZeroMemory(&listener_param,sizeof(listener_param)); 634 listener_param.dwSize=sizeof(listener_param); 635 rc=IDirectSound3DListener_GetAllParameters(listener, 636 &listener_param); 637 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() " 638 "failed: %08x\n",rc); 639 if (move_listener) { 640 listener_param.vPosition.x = -5.0f; 641 listener_param.vVelocity.x = (float)(10.0/duration); 642 } 643 rc=IDirectSound3DListener_SetAllParameters(listener, 644 &listener_param, 645 DS3D_IMMEDIATE); 646 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n", rc); 647 } 648 if (buffer3d) { 649 if (move_sound) { 650 buffer_param.vPosition.x = 100.0f; 651 buffer_param.vVelocity.x = (float)(-200.0/duration); 652 } 653 buffer_param.flMinDistance = 10; 654 rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param, 655 DS3D_IMMEDIATE); 656 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc); 657 } 658 659 start_time=GetTickCount(); 660 while (buffer_service(&state)) { 661 WaitForSingleObject(GetCurrentProcess(),TIME_SLICE); 662 now=GetTickCount(); 663 if (listener && move_listener) { 664 listener_param.vPosition.x = (float)(-5.0+10.0*(now-start_time)/1000/duration); 665 if (winetest_debug>2) 666 trace("listener position=%g\n",listener_param.vPosition.x); 667 rc=IDirectSound3DListener_SetPosition(listener, 668 listener_param.vPosition.x,listener_param.vPosition.y, 669 listener_param.vPosition.z,DS3D_IMMEDIATE); 670 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n",rc); 671 } 672 if (buffer3d && move_sound) { 673 buffer_param.vPosition.x = (float)(100-200.0*(now-start_time)/1000/duration); 674 if (winetest_debug>2) 675 trace("sound position=%g\n",buffer_param.vPosition.x); 676 rc=IDirectSound3DBuffer_SetPosition(buffer, 677 buffer_param.vPosition.x,buffer_param.vPosition.y, 678 buffer_param.vPosition.z,DS3D_IMMEDIATE); 679 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc); 680 } 681 } 682 /* Check the sound duration was within 10% of the expected value */ 683 now=GetTickCount(); 684 ok(fabs(1000*duration-now+start_time)<=100*duration, 685 "The sound played for %d ms instead of %g ms\n", 686 now-start_time,1000*duration); 687 688 HeapFree(GetProcessHeap(), 0, state.wave); 689 if (is_primary) { 690 /* Set the CooperativeLevel back to normal */ 691 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ 692 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); 693 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) " 694 "failed: %08x\n",rc); 695 } 696 if (buffer3d) { 697 ref=IDirectSound3DBuffer_Release(buffer); 698 ok(ref==0,"IDirectSound3DBuffer_Release() has %d references, " 699 "should have 0\n",ref); 700 } 701 } 702 } 703 704 static HRESULT test_secondary(LPGUID lpGuid, int play, 705 int has_3d, int has_3dbuffer, 706 int has_listener, int has_duplicate, 707 int move_listener, int move_sound) 708 { 709 HRESULT rc; 710 LPDIRECTSOUND dso=NULL; 711 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; 712 LPDIRECTSOUND3DLISTENER listener=NULL; 713 DSBUFFERDESC bufdesc; 714 WAVEFORMATEX wfx, wfx1; 715 int ref; 716 717 /* Create the DirectSound object */ 718 rc=pDirectSoundCreate(lpGuid,&dso,NULL); 719 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08x\n", rc); 720 if (rc!=DS_OK) 721 return rc; 722 723 /* We must call SetCooperativeLevel before creating primary buffer */ 724 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ 725 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); 726 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc); 727 if (rc!=DS_OK) 728 goto EXIT; 729 730 ZeroMemory(&bufdesc, sizeof(bufdesc)); 731 bufdesc.dwSize=sizeof(bufdesc); 732 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; 733 if (has_3d) 734 bufdesc.dwFlags|=DSBCAPS_CTRL3D; 735 else 736 bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN); 737 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); 738 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL), 739 "IDirectSound_CreateSoundBuffer() failed to create a %sprimary buffer: %08x\n",has_3d?"3D ":"", rc); 740 if (rc==DSERR_CONTROLUNAVAIL) 741 trace(" No Primary\n"); 742 else if (rc==DS_OK && primary!=NULL) { 743 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL); 744 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc); 745 if (rc!=DS_OK) 746 goto EXIT1; 747 748 if (has_listener) { 749 rc=IDirectSoundBuffer_QueryInterface(primary, 750 &IID_IDirectSound3DListener, 751 (void **)&listener); 752 ok(rc==DS_OK && listener!=NULL, 753 "IDirectSoundBuffer_QueryInterface() failed to get a 3D listener: %08x\n",rc); 754 ref=IDirectSoundBuffer_Release(primary); 755 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " 756 "should have 0\n",ref); 757 if (rc==DS_OK && listener!=NULL) { 758 DS3DLISTENER listener_param; 759 ZeroMemory(&listener_param,sizeof(listener_param)); 760 /* DSOUND: Error: Invalid buffer */ 761 rc=IDirectSound3DListener_GetAllParameters(listener,0); 762 ok(rc==DSERR_INVALIDPARAM, 763 "IDirectSound3dListener_GetAllParameters() should have " 764 "returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 765 766 /* DSOUND: Error: Invalid buffer */ 767 rc=IDirectSound3DListener_GetAllParameters(listener, 768 &listener_param); 769 ok(rc==DSERR_INVALIDPARAM, 770 "IDirectSound3dListener_GetAllParameters() should have " 771 "returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 772 773 listener_param.dwSize=sizeof(listener_param); 774 rc=IDirectSound3DListener_GetAllParameters(listener, 775 &listener_param); 776 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() " 777 "failed: %08x\n",rc); 778 } else { 779 ok(listener==NULL, "IDirectSoundBuffer_QueryInterface() " 780 "failed but returned a listener anyway\n"); 781 ok(rc!=DS_OK, "IDirectSoundBuffer_QueryInterface() succeeded " 782 "but returned a NULL listener\n"); 783 if (listener) { 784 ref=IDirectSound3DListener_Release(listener); 785 ok(ref==0,"IDirectSound3dListener_Release() listener has " 786 "%d references, should have 0\n",ref); 787 } 788 goto EXIT2; 789 } 790 } 791 792 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2); 793 secondary=NULL; 794 ZeroMemory(&bufdesc, sizeof(bufdesc)); 795 bufdesc.dwSize=sizeof(bufdesc); 796 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; 797 if (has_3dbuffer) 798 bufdesc.dwFlags|=DSBCAPS_CTRL3D; 799 else 800 bufdesc.dwFlags|= 801 (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN); 802 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, 803 wfx.nBlockAlign); 804 bufdesc.lpwfxFormat=&wfx; 805 if (winetest_interactive) { 806 trace(" Testing a %s%ssecondary buffer %s%s%s%sat %dx%dx%d " 807 "with a primary buffer at %dx%dx%d\n", 808 has_3dbuffer?"3D ":"", 809 has_duplicate?"duplicated ":"", 810 listener!=NULL||move_sound?"with ":"", 811 move_listener?"moving ":"", 812 listener!=NULL?"listener ":"", 813 listener&&move_sound?"and moving sound ":move_sound? 814 "moving sound ":"", 815 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels, 816 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels); 817 } 818 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); 819 ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */ 820 "IDirectSound_CreateSoundBuffer() failed to create a %s%ssecondary buffer %s%s%s%sat %dx%dx%d (%s): %08x\n", 821 has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"", 822 listener!=NULL||move_sound?"with ":"", move_listener?"moving ":"", 823 listener!=NULL?"listener ":"", 824 listener&&move_sound?"and moving sound ":move_sound? 825 "moving sound ":"", 826 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels, 827 getDSBCAPS(bufdesc.dwFlags),rc); 828 if (rc==DS_OK && secondary!=NULL) { 829 IDirectSound3DBuffer *ds3d; 830 831 rc=IDirectSoundBuffer_QueryInterface(secondary, &IID_IDirectSound3DBuffer, (void**)&ds3d); 832 ok((has_3dbuffer && rc==DS_OK) || (!has_3dbuffer && rc==E_NOINTERFACE), 833 "Wrong return trying to get 3D buffer on %s3D secondary interface: %08x\n", has_3dbuffer ? "" : "non-", rc); 834 if(rc==DS_OK) 835 IDirectSound3DBuffer_Release(ds3d); 836 837 if (!has_3d) { 838 LONG refvol,vol,refpan,pan; 839 840 /* Check the initial secondary buffer's volume and pan */ 841 rc=IDirectSoundBuffer_GetVolume(secondary,&vol); 842 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(secondary) failed: %08x\n",rc); 843 ok(vol==0,"wrong volume for a new secondary buffer: %d\n",vol); 844 rc=IDirectSoundBuffer_GetPan(secondary,&pan); 845 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: %08x\n",rc); 846 ok(pan==0,"wrong pan for a new secondary buffer: %d\n",pan); 847 848 /* Check that changing the secondary buffer's volume and pan 849 * does not impact the primary buffer's volume and pan 850 */ 851 rc=IDirectSoundBuffer_GetVolume(primary,&refvol); 852 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: %08x\n",rc); 853 rc=IDirectSoundBuffer_GetPan(primary,&refpan); 854 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n", rc); 855 856 rc=IDirectSoundBuffer_SetVolume(secondary,-1000); 857 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc); 858 rc=IDirectSoundBuffer_GetVolume(secondary,&vol); 859 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc); 860 ok(vol==-1000,"secondary: wrong volume %d instead of -1000\n", 861 vol); 862 rc=IDirectSoundBuffer_SetPan(secondary,-1000); 863 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc); 864 rc=IDirectSoundBuffer_GetPan(secondary,&pan); 865 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc); 866 ok(pan==-1000,"secondary: wrong pan %d instead of -1000\n", 867 pan); 868 869 rc=IDirectSoundBuffer_GetVolume(primary,&vol); 870 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: %08x\n",rc); 871 ok(vol==refvol,"The primary volume changed from %d to %d\n", 872 refvol,vol); 873 rc=IDirectSoundBuffer_GetPan(primary,&pan); 874 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n", rc); 875 ok(pan==refpan,"The primary pan changed from %d to %d\n", 876 refpan,pan); 877 878 rc=IDirectSoundBuffer_SetVolume(secondary,0); 879 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc); 880 rc=IDirectSoundBuffer_SetPan(secondary,0); 881 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc); 882 } 883 if (has_duplicate) { 884 LPDIRECTSOUNDBUFFER duplicated=NULL; 885 886 /* DSOUND: Error: Invalid source buffer */ 887 rc=IDirectSound_DuplicateSoundBuffer(dso,0,0); 888 ok(rc==DSERR_INVALIDPARAM, 889 "IDirectSound_DuplicateSoundBuffer() should have returned " 890 "DSERR_INVALIDPARAM, returned: %08x\n",rc); 891 892 /* DSOUND: Error: Invalid dest buffer */ 893 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0); 894 ok(rc==DSERR_INVALIDPARAM, 895 "IDirectSound_DuplicateSoundBuffer() should have returned " 896 "DSERR_INVALIDPARAM, returned: %08x\n",rc); 897 898 /* DSOUND: Error: Invalid source buffer */ 899 rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated); 900 ok(rc==DSERR_INVALIDPARAM, 901 "IDirectSound_DuplicateSoundBuffer() should have returned " 902 "DSERR_INVALIDPARAM, returned: %08x\n",rc); 903 904 duplicated=NULL; 905 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary, 906 &duplicated); 907 ok(rc==DS_OK && duplicated!=NULL, 908 "IDirectSound_DuplicateSoundBuffer() failed to duplicate " 909 "a secondary buffer: %08x\n",rc); 910 911 if (rc==DS_OK && duplicated!=NULL) { 912 ref=IDirectSoundBuffer_Release(secondary); 913 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d " 914 "references, should have 0\n",ref); 915 secondary=duplicated; 916 } 917 } 918 919 if (rc==DS_OK && secondary!=NULL) { 920 double duration; 921 duration=(move_listener || move_sound?4.0:1.0); 922 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0, 923 winetest_interactive,duration,has_3dbuffer, 924 listener,move_listener,move_sound,FALSE,0); 925 ref=IDirectSoundBuffer_Release(secondary); 926 ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, " 927 "should have 0\n",has_duplicate?"duplicated":"secondary", 928 ref); 929 } 930 } 931 EXIT1: 932 if (has_listener) { 933 ref=IDirectSound3DListener_Release(listener); 934 ok(ref==0,"IDirectSound3dListener_Release() listener has %d " 935 "references, should have 0\n",ref); 936 } else { 937 ref=IDirectSoundBuffer_Release(primary); 938 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " 939 "should have 0\n",ref); 940 } 941 } else { 942 ok(primary==NULL,"IDirectSound_CreateSoundBuffer(primary) failed " 943 "but primary created anyway\n"); 944 ok(rc!=DS_OK,"IDirectSound_CreateSoundBuffer(primary) succeeded " 945 "but primary not created\n"); 946 if (primary) { 947 ref=IDirectSoundBuffer_Release(primary); 948 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " 949 "should have 0\n",ref); 950 } 951 } 952 EXIT2: 953 /* Set the CooperativeLevel back to normal */ 954 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ 955 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); 956 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n", rc); 957 958 EXIT: 959 ref=IDirectSound_Release(dso); 960 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); 961 if (ref!=0) 962 return DSERR_GENERIC; 963 964 return rc; 965 } 966 967 static HRESULT test_for_driver(LPGUID lpGuid) 968 { 969 HRESULT rc; 970 LPDIRECTSOUND dso=NULL; 971 int ref; 972 973 /* Create the DirectSound object */ 974 rc=pDirectSoundCreate(lpGuid,&dso,NULL); 975 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, 976 "DirectSoundCreate() failed: %08x\n",rc); 977 if (rc!=DS_OK) 978 return rc; 979 980 ref=IDirectSound_Release(dso); 981 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); 982 if (ref!=0) 983 return DSERR_GENERIC; 984 985 return rc; 986 } 987 988 static HRESULT test_primary(LPGUID lpGuid) 989 { 990 HRESULT rc; 991 LPDIRECTSOUND dso=NULL; 992 LPDIRECTSOUNDBUFFER primary=NULL; 993 DSBUFFERDESC bufdesc; 994 DSCAPS dscaps; 995 int ref, i; 996 997 /* Create the DirectSound object */ 998 rc=pDirectSoundCreate(lpGuid,&dso,NULL); 999 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08x\n", rc); 1000 if (rc!=DS_OK) 1001 return rc; 1002 1003 /* Get the device capabilities */ 1004 ZeroMemory(&dscaps, sizeof(dscaps)); 1005 dscaps.dwSize=sizeof(dscaps); 1006 rc=IDirectSound_GetCaps(dso,&dscaps); 1007 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc); 1008 if (rc!=DS_OK) 1009 goto EXIT; 1010 1011 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */ 1012 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ 1013 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); 1014 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc); 1015 if (rc!=DS_OK) 1016 goto EXIT; 1017 1018 /* Testing the primary buffer */ 1019 primary=NULL; 1020 ZeroMemory(&bufdesc, sizeof(bufdesc)); 1021 bufdesc.dwSize=sizeof(bufdesc); 1022 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN; 1023 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); 1024 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL), 1025 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: %08x\n",rc); 1026 if (rc==DSERR_CONTROLUNAVAIL) 1027 trace(" No Primary\n"); 1028 else if (rc==DS_OK && primary!=NULL) { 1029 test_buffer(dso,&primary,1,TRUE,0,TRUE,0,winetest_interactive && 1030 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0, 1031 FALSE,0); 1032 if (winetest_interactive) { 1033 LONG volume,pan; 1034 1035 volume = DSBVOLUME_MAX; 1036 for (i = 0; i < 6; i++) { 1037 test_buffer(dso,&primary,1,TRUE,volume,TRUE,0, 1038 winetest_interactive && 1039 !(dscaps.dwFlags & DSCAPS_EMULDRIVER), 1040 1.0,0,NULL,0,0,FALSE,0); 1041 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40); 1042 } 1043 1044 pan = DSBPAN_LEFT; 1045 for (i = 0; i < 7; i++) { 1046 test_buffer(dso,&primary,1,TRUE,0,TRUE,pan, 1047 winetest_interactive && 1048 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0,FALSE,0); 1049 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6); 1050 } 1051 } 1052 ref=IDirectSoundBuffer_Release(primary); 1053 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " 1054 "should have 0\n",ref); 1055 } 1056 1057 /* Set the CooperativeLevel back to normal */ 1058 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ 1059 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); 1060 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n", rc); 1061 1062 EXIT: 1063 ref=IDirectSound_Release(dso); 1064 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); 1065 if (ref!=0) 1066 return DSERR_GENERIC; 1067 1068 return rc; 1069 } 1070 1071 static HRESULT test_primary_3d(LPGUID lpGuid) 1072 { 1073 HRESULT rc; 1074 LPDIRECTSOUND dso=NULL; 1075 LPDIRECTSOUNDBUFFER primary=NULL; 1076 DSBUFFERDESC bufdesc; 1077 DSCAPS dscaps; 1078 int ref; 1079 1080 /* Create the DirectSound object */ 1081 rc=pDirectSoundCreate(lpGuid,&dso,NULL); 1082 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08x\n", rc); 1083 if (rc!=DS_OK) 1084 return rc; 1085 1086 /* Get the device capabilities */ 1087 ZeroMemory(&dscaps, sizeof(dscaps)); 1088 dscaps.dwSize=sizeof(dscaps); 1089 rc=IDirectSound_GetCaps(dso,&dscaps); 1090 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc); 1091 if (rc!=DS_OK) 1092 goto EXIT; 1093 1094 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */ 1095 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ 1096 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); 1097 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc); 1098 if (rc!=DS_OK) 1099 goto EXIT; 1100 1101 primary=NULL; 1102 ZeroMemory(&bufdesc, sizeof(bufdesc)); 1103 bufdesc.dwSize=sizeof(bufdesc); 1104 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; 1105 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); 1106 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed " 1107 "to create a primary buffer: %08x\n",rc); 1108 if (rc==DS_OK && primary!=NULL) { 1109 ref=IDirectSoundBuffer_Release(primary); 1110 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " 1111 "should have 0\n",ref); 1112 primary=NULL; 1113 ZeroMemory(&bufdesc, sizeof(bufdesc)); 1114 bufdesc.dwSize=sizeof(bufdesc); 1115 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D; 1116 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); 1117 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() " 1118 "failed to create a 3D primary buffer: %08x\n",rc); 1119 if (rc==DS_OK && primary!=NULL) { 1120 test_buffer(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive && 1121 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0, 1122 FALSE,0); 1123 ref=IDirectSoundBuffer_Release(primary); 1124 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " 1125 "should have 0\n",ref); 1126 } 1127 } 1128 /* Set the CooperativeLevel back to normal */ 1129 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ 1130 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); 1131 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n", rc); 1132 1133 EXIT: 1134 ref=IDirectSound_Release(dso); 1135 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); 1136 if (ref!=0) 1137 return DSERR_GENERIC; 1138 1139 return rc; 1140 } 1141 1142 static HRESULT test_primary_3d_with_listener(LPGUID lpGuid) 1143 { 1144 HRESULT rc; 1145 LPDIRECTSOUND dso=NULL; 1146 LPDIRECTSOUNDBUFFER primary=NULL; 1147 DSBUFFERDESC bufdesc; 1148 DSCAPS dscaps; 1149 int ref; 1150 1151 /* Create the DirectSound object */ 1152 rc=pDirectSoundCreate(lpGuid,&dso,NULL); 1153 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08x\n", rc); 1154 if (rc!=DS_OK) 1155 return rc; 1156 1157 /* Get the device capabilities */ 1158 ZeroMemory(&dscaps, sizeof(dscaps)); 1159 dscaps.dwSize=sizeof(dscaps); 1160 rc=IDirectSound_GetCaps(dso,&dscaps); 1161 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc); 1162 if (rc!=DS_OK) 1163 goto EXIT; 1164 1165 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */ 1166 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ 1167 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); 1168 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc); 1169 if (rc!=DS_OK) 1170 goto EXIT; 1171 primary=NULL; 1172 ZeroMemory(&bufdesc, sizeof(bufdesc)); 1173 bufdesc.dwSize=sizeof(bufdesc); 1174 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D; 1175 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); 1176 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed " 1177 "to create a 3D primary buffer: %08x\n",rc); 1178 if (rc==DS_OK && primary!=NULL) { 1179 LPDIRECTSOUND3DLISTENER listener=NULL; 1180 LPDIRECTSOUNDBUFFER temp_buffer=NULL; 1181 rc=IDirectSoundBuffer_QueryInterface(primary, 1182 &IID_IDirectSound3DListener,(void **)&listener); 1183 ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface() " 1184 "failed to get a 3D listener: %08x\n",rc); 1185 if (rc==DS_OK && listener!=NULL) { 1186 /* Checking the COM interface */ 1187 rc=IDirectSoundBuffer_QueryInterface(primary, 1188 &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer); 1189 ok(rc==DS_OK && temp_buffer!=NULL, 1190 "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc); 1191 ok(temp_buffer==primary, 1192 "COM interface broken: %p != %p\n", 1193 temp_buffer,primary); 1194 if (rc==DS_OK && temp_buffer!=NULL) { 1195 ref=IDirectSoundBuffer_Release(temp_buffer); 1196 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, " 1197 "should have 1\n",ref); 1198 1199 temp_buffer=NULL; 1200 rc=IDirectSound3DListener_QueryInterface(listener, 1201 &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer); 1202 ok(rc==DS_OK && temp_buffer!=NULL, 1203 "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc); 1204 ok(temp_buffer==primary, 1205 "COM interface broken: %p != %p\n", 1206 temp_buffer,primary); 1207 ref=IDirectSoundBuffer_Release(temp_buffer); 1208 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, " 1209 "should have 1\n",ref); 1210 1211 /* Testing the buffer */ 1212 test_buffer(dso,&primary,1,FALSE,0,FALSE,0, 1213 winetest_interactive && 1214 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0, 1215 listener,0,0,FALSE,0); 1216 1217 temp_buffer = NULL; 1218 rc = IDirectSound3DListener_QueryInterface(listener, &IID_IKsPropertySet, 1219 (void **)&temp_buffer); 1220 ok(rc==DS_OK && temp_buffer!=NULL, 1221 "IDirectSound3DListener_QueryInterface didn't handle IKsPropertySet: ret = %08x\n", rc); 1222 if(temp_buffer) 1223 IKsPropertySet_Release(temp_buffer); 1224 } 1225 1226 /* Testing the reference counting */ 1227 ref=IDirectSound3DListener_Release(listener); 1228 ok(ref==0,"IDirectSound3DListener_Release() listener has %d " 1229 "references, should have 0\n",ref); 1230 } 1231 1232 temp_buffer = NULL; 1233 rc = IDirectSoundBuffer_QueryInterface(primary, &IID_IKsPropertySet, (void **)&temp_buffer); 1234 ok(rc==DS_OK && temp_buffer!=NULL, 1235 "IDirectSoundBuffer_QueryInterface didn't handle IKsPropertySet on primary buffer: ret = %08x\n", rc); 1236 if(temp_buffer) 1237 IKsPropertySet_Release(temp_buffer); 1238 1239 /* Testing the reference counting */ 1240 ref=IDirectSoundBuffer_Release(primary); 1241 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " 1242 "should have 0\n",ref); 1243 } 1244 1245 EXIT: 1246 ref=IDirectSound_Release(dso); 1247 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); 1248 if (ref!=0) 1249 return DSERR_GENERIC; 1250 1251 return rc; 1252 } 1253 1254 static unsigned driver_count = 0; 1255 1256 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, 1257 LPCSTR lpcstrModule, LPVOID lpContext) 1258 { 1259 HRESULT rc; 1260 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule); 1261 driver_count++; 1262 1263 rc = test_for_driver(lpGuid); 1264 if (rc == DSERR_NODRIVER) { 1265 trace(" No Driver\n"); 1266 return 1; 1267 } else if (rc == DSERR_ALLOCATED) { 1268 trace(" Already In Use\n"); 1269 return 1; 1270 } else if (rc == E_FAIL) { 1271 trace(" No Device\n"); 1272 return 1; 1273 } 1274 1275 trace(" Testing the primary buffer\n"); 1276 test_primary(lpGuid); 1277 1278 trace(" Testing 3D primary buffer\n"); 1279 test_primary_3d(lpGuid); 1280 1281 trace(" Testing 3D primary buffer with listener\n"); 1282 test_primary_3d_with_listener(lpGuid); 1283 1284 /* Testing secondary buffers */ 1285 test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0); 1286 test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0); 1287 1288 /* Testing 3D secondary buffers */ 1289 test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0); 1290 test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0); 1291 test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0); 1292 test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0); 1293 test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0); 1294 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0); 1295 test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0); 1296 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0); 1297 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1); 1298 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1); 1299 1300 return 1; 1301 } 1302 1303 static void ds3d_tests(void) 1304 { 1305 HRESULT rc; 1306 rc=pDirectSoundEnumerateA(&dsenum_callback,NULL); 1307 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc); 1308 trace("tested %u DirectSound drivers\n", driver_count); 1309 } 1310 1311 START_TEST(ds3d) 1312 { 1313 HMODULE hDsound; 1314 1315 CoInitialize(NULL); 1316 1317 hDsound = LoadLibrary("dsound.dll"); 1318 if (hDsound) 1319 { 1320 1321 pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound, 1322 "DirectSoundEnumerateA"); 1323 pDirectSoundCreate = (void*)GetProcAddress(hDsound, 1324 "DirectSoundCreate"); 1325 1326 ds3d_tests(); 1327 1328 FreeLibrary(hDsound); 1329 } 1330 else 1331 skip("dsound.dll not found - skipping all tests\n"); 1332 1333 CoUninitialize(); 1334 } 1335