1 /* 2 * Unit tests for capture functions 3 * 4 * Copyright (c) 2002 Francois Gouget 5 * Copyright (c) 2003 Robert Reif 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "dsound_test.h" 23 24 #include <stdio.h> 25 26 #define NOTIFICATIONS 5 27 28 static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID,LPDIRECTSOUNDCAPTURE*,LPUNKNOWN)=NULL; 29 static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL; 30 31 static const char * get_format_str(WORD format) 32 { 33 static char msg[32]; 34 #define WAVE_FORMAT(f) case f: return #f 35 switch (format) { 36 WAVE_FORMAT(WAVE_FORMAT_PCM); 37 WAVE_FORMAT(WAVE_FORMAT_ADPCM); 38 WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD); 39 WAVE_FORMAT(WAVE_FORMAT_ALAW); 40 WAVE_FORMAT(WAVE_FORMAT_MULAW); 41 WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM); 42 WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM); 43 WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM); 44 WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM); 45 WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM); 46 WAVE_FORMAT(WAVE_FORMAT_DIGISTD); 47 WAVE_FORMAT(WAVE_FORMAT_DIGIFIX); 48 WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM); 49 WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM); 50 WAVE_FORMAT(WAVE_FORMAT_SONARC); 51 WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH); 52 WAVE_FORMAT(WAVE_FORMAT_ECHOSC1); 53 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36); 54 WAVE_FORMAT(WAVE_FORMAT_APTX); 55 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10); 56 WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2); 57 WAVE_FORMAT(WAVE_FORMAT_GSM610); 58 WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME); 59 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC); 60 WAVE_FORMAT(WAVE_FORMAT_DIGIREAL); 61 WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM); 62 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10); 63 WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM); 64 WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM); 65 WAVE_FORMAT(WAVE_FORMAT_MPEG); 66 WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3); 67 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM); 68 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8); 69 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10); 70 WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND); 71 WAVE_FORMAT(WAVE_FORMAT_OLIGSM); 72 WAVE_FORMAT(WAVE_FORMAT_OLIADPCM); 73 WAVE_FORMAT(WAVE_FORMAT_OLICELP); 74 WAVE_FORMAT(WAVE_FORMAT_OLISBC); 75 WAVE_FORMAT(WAVE_FORMAT_OLIOPR); 76 WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT); 77 WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE); 78 } 79 #undef WAVE_FORMAT 80 sprintf(msg, "Unknown(0x%04x)", format); 81 return msg; 82 } 83 84 const char * format_string(const WAVEFORMATEX* wfx) 85 { 86 static char str[64]; 87 88 sprintf(str, "%5dx%2dx%d %s", 89 wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels, 90 get_format_str(wfx->wFormatTag)); 91 92 return str; 93 } 94 95 static void IDirectSoundCapture_test(LPDIRECTSOUNDCAPTURE dsco, 96 BOOL initialized, LPCGUID lpGuid) 97 { 98 HRESULT rc; 99 DSCCAPS dsccaps; 100 int ref; 101 IUnknown * unknown; 102 IDirectSoundCapture * dsc; 103 104 /* Try to Query for objects */ 105 rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IUnknown, 106 (LPVOID*)&unknown); 107 ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IUnknown) " 108 "failed: %08x\n", rc); 109 if (rc==DS_OK) 110 IDirectSoundCapture_Release(unknown); 111 112 rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IDirectSoundCapture, 113 (LPVOID*)&dsc); 114 ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IDirectSoundCapture) " 115 "failed: %08x\n", rc); 116 if (rc==DS_OK) 117 IDirectSoundCapture_Release(dsc); 118 119 if (initialized == FALSE) { 120 /* try uninitialized object */ 121 rc=IDirectSoundCapture_GetCaps(dsco,0); 122 ok(rc==DSERR_UNINITIALIZED||rc==E_INVALIDARG, 123 "IDirectSoundCapture_GetCaps(NULL) should have returned " 124 "DSERR_UNINITIALIZED or E_INVALIDARG, returned: %08x\n", rc); 125 126 rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps); 127 ok(rc==DSERR_UNINITIALIZED,"IDirectSoundCapture_GetCaps() " 128 "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc); 129 130 rc=IDirectSoundCapture_Initialize(dsco, lpGuid); 131 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED|| 132 rc==E_FAIL||rc==E_INVALIDARG, 133 "IDirectSoundCapture_Initialize() failed: %08x\n", rc); 134 if (rc==DSERR_NODRIVER||rc==E_INVALIDARG) { 135 trace(" No Driver\n"); 136 goto EXIT; 137 } else if (rc==E_FAIL) { 138 trace(" No Device\n"); 139 goto EXIT; 140 } else if (rc==DSERR_ALLOCATED) { 141 trace(" Already In Use\n"); 142 goto EXIT; 143 } 144 } 145 146 rc=IDirectSoundCapture_Initialize(dsco, lpGuid); 147 ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSoundCapture_Initialize() " 148 "should have returned DSERR_ALREADYINITIALIZED: %08x\n", rc); 149 150 /* DSOUND: Error: Invalid caps buffer */ 151 rc=IDirectSoundCapture_GetCaps(dsco, 0); 152 ok(rc==DSERR_INVALIDPARAM, "IDirectSoundCapture_GetCaps(NULL) " 153 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 154 155 ZeroMemory(&dsccaps, sizeof(dsccaps)); 156 157 /* DSOUND: Error: Invalid caps buffer */ 158 rc=IDirectSound_GetCaps(dsco, &dsccaps); 159 ok(rc==DSERR_INVALIDPARAM, "IDirectSound_GetCaps() " 160 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 161 162 dsccaps.dwSize=sizeof(dsccaps); 163 164 /* DSOUND: Running on a certified driver */ 165 rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps); 166 ok(rc==DS_OK, "IDirectSoundCapture_GetCaps() failed: %08x\n", rc); 167 168 EXIT: 169 ref=IDirectSoundCapture_Release(dsco); 170 ok(ref==0, "IDirectSoundCapture_Release() has %d references, " 171 "should have 0\n", ref); 172 } 173 174 static void test_capture(void) 175 { 176 HRESULT rc; 177 LPDIRECTSOUNDCAPTURE dsco=NULL; 178 LPCLASSFACTORY cf=NULL; 179 180 trace("Testing IDirectSoundCapture\n"); 181 182 rc=CoGetClassObject(&CLSID_DirectSoundCapture, CLSCTX_INPROC_SERVER, NULL, 183 &IID_IClassFactory, (void**)&cf); 184 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSoundCapture, IID_IClassFactory) " 185 "failed: %08x\n", rc); 186 187 rc=CoGetClassObject(&CLSID_DirectSoundCapture, CLSCTX_INPROC_SERVER, NULL, 188 &IID_IUnknown, (void**)&cf); 189 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSoundCapture, IID_IUnknown) " 190 "failed: %08x\n", rc); 191 192 /* try the COM class factory method of creation with no device specified */ 193 rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER, 194 &IID_IDirectSoundCapture, (void**)&dsco); 195 ok(rc==S_OK||rc==REGDB_E_CLASSNOTREG,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %08x\n", rc); 196 if (rc==REGDB_E_CLASSNOTREG) { 197 trace(" Class Not Registered\n"); 198 return; 199 } 200 if (dsco) 201 IDirectSoundCapture_test(dsco, FALSE, NULL); 202 203 /* try the COM class factory method of creation with default capture 204 * device specified */ 205 rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER, 206 &IID_IDirectSoundCapture, (void**)&dsco); 207 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %08x\n", rc); 208 if (dsco) 209 IDirectSoundCapture_test(dsco, FALSE, &DSDEVID_DefaultCapture); 210 211 /* try the COM class factory method of creation with default voice 212 * capture device specified */ 213 rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER, 214 &IID_IDirectSoundCapture, (void**)&dsco); 215 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %08x\n", rc); 216 if (dsco) 217 IDirectSoundCapture_test(dsco, FALSE, &DSDEVID_DefaultVoiceCapture); 218 219 /* try the COM class factory method of creation with a bad 220 * IID specified */ 221 rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER, 222 &CLSID_DirectSoundPrivate, (void**)&dsco); 223 ok(rc==E_NOINTERFACE, 224 "CoCreateInstance(CLSID_DirectSoundCapture,CLSID_DirectSoundPrivate) " 225 "should have failed: %08x\n",rc); 226 227 /* try with no device specified */ 228 rc=pDirectSoundCaptureCreate(NULL,&dsco,NULL); 229 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, 230 "DirectSoundCaptureCreate(NULL) failed: %08x\n",rc); 231 if (rc==S_OK && dsco) 232 IDirectSoundCapture_test(dsco, TRUE, NULL); 233 234 /* try with default capture device specified */ 235 rc=pDirectSoundCaptureCreate(&DSDEVID_DefaultCapture,&dsco,NULL); 236 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, 237 "DirectSoundCaptureCreate(DSDEVID_DefaultCapture) failed: %08x\n", rc); 238 if (rc==DS_OK && dsco) 239 IDirectSoundCapture_test(dsco, TRUE, NULL); 240 241 /* try with default voice capture device specified */ 242 rc=pDirectSoundCaptureCreate(&DSDEVID_DefaultVoiceCapture,&dsco,NULL); 243 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, 244 "DirectSoundCaptureCreate(DSDEVID_DefaultVoiceCapture) failed: %08x\n", rc); 245 if (rc==DS_OK && dsco) 246 IDirectSoundCapture_test(dsco, TRUE, NULL); 247 248 /* try with a bad device specified */ 249 rc=pDirectSoundCaptureCreate(&DSDEVID_DefaultVoicePlayback,&dsco,NULL); 250 ok(rc==DSERR_NODRIVER, 251 "DirectSoundCaptureCreate(DSDEVID_DefaultVoicePlatback) " 252 "should have failed: %08x\n",rc); 253 if (rc==DS_OK && dsco) 254 IDirectSoundCapture_Release(dsco); 255 } 256 257 typedef struct { 258 char* wave; 259 DWORD wave_len; 260 261 LPDIRECTSOUNDCAPTUREBUFFER dscbo; 262 LPWAVEFORMATEX wfx; 263 DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS]; 264 HANDLE event[NOTIFICATIONS]; 265 LPDIRECTSOUNDNOTIFY notify; 266 267 DWORD buffer_size; 268 DWORD read; 269 DWORD offset; 270 DWORD size; 271 272 DWORD last_pos; 273 } capture_state_t; 274 275 static int capture_buffer_service(capture_state_t* state) 276 { 277 HRESULT rc; 278 LPVOID ptr1,ptr2; 279 DWORD len1,len2; 280 DWORD capture_pos,read_pos; 281 282 rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos, 283 &read_pos); 284 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCurrentPosition() failed: %08x\n", rc); 285 if (rc!=DS_OK) 286 return 0; 287 288 rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size, 289 &ptr1,&len1,&ptr2,&len2,0); 290 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Lock() failed: %08x\n", rc); 291 if (rc!=DS_OK) 292 return 0; 293 294 rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2); 295 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Unlock() failed: %08x\n", rc); 296 if (rc!=DS_OK) 297 return 0; 298 299 state->offset = (state->offset + state->size) % state->buffer_size; 300 301 return 1; 302 } 303 304 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, 305 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record) 306 { 307 HRESULT rc; 308 DSCBCAPS dscbcaps; 309 WAVEFORMATEX wfx; 310 DWORD size,status; 311 capture_state_t state; 312 int i, ref; 313 314 /* Private dsound.dll: Error: Invalid caps pointer */ 315 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0); 316 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should " 317 "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 318 319 /* Private dsound.dll: Error: Invalid caps pointer */ 320 dscbcaps.dwSize=0; 321 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps); 322 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should " 323 "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 324 325 dscbcaps.dwSize=sizeof(dscbcaps); 326 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps); 327 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCaps() failed: %08x\n", rc); 328 if (rc==DS_OK && winetest_debug > 1) { 329 trace(" Caps: size = %d flags=0x%08x buffer size=%d\n", 330 dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes); 331 } 332 333 /* Query the format size. Note that it may not match sizeof(wfx) */ 334 /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must 335 * be non-NULL */ 336 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL); 337 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetFormat() should " 338 "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 339 340 size=0; 341 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size); 342 ok(rc==DS_OK && size!=0,"IDirectSoundCaptureBuffer_GetFormat() should " 343 "have returned the needed size: rc=%08x, size=%d\n", rc,size); 344 345 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL); 346 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetFormat() failed: %08x\n", rc); 347 if (rc==DS_OK && winetest_debug > 1) { 348 trace(" Format: tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n", 349 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, 350 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); 351 } 352 353 /* Private dsound.dll: Error: Invalid status pointer */ 354 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0); 355 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetStatus() should " 356 "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 357 358 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status); 359 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc); 360 if (rc==DS_OK && winetest_debug > 1) { 361 trace(" Status=0x%04x\n",status); 362 } 363 364 ZeroMemory(&state, sizeof(state)); 365 state.dscbo=dscbo; 366 state.wfx=&wfx; 367 state.buffer_size = dscbcaps.dwBufferBytes; 368 for (i = 0; i < NOTIFICATIONS; i++) 369 state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL ); 370 state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS; 371 372 rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify, 373 (void **)&(state.notify)); 374 ok((rc==DS_OK)&&(state.notify!=NULL), 375 "IDirectSoundCaptureBuffer_QueryInterface() failed: %08x\n", rc); 376 377 for (i = 0; i < NOTIFICATIONS; i++) { 378 state.posnotify[i].dwOffset = (i * state.size) + state.size - 1; 379 state.posnotify[i].hEventNotify = state.event[i]; 380 } 381 382 rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS, 383 state.posnotify); 384 ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions() failed: %08x\n", rc); 385 386 ref=IDirectSoundNotify_Release(state.notify); 387 ok(ref==0,"IDirectSoundNotify_Release(): has %d references, should have " 388 "0\n",ref); 389 390 rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING); 391 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %08x\n", rc); 392 393 rc=IDirectSoundCaptureBuffer_Start(dscbo,0); 394 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %08x\n", rc); 395 396 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status); 397 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc); 398 ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING) || broken(status==DSCBSTATUS_CAPTURING), 399 "GetStatus: bad status: %x\n",status); 400 401 if (record) { 402 /* wait for the notifications */ 403 for (i = 0; i < (NOTIFICATIONS * 2); i++) { 404 rc=WaitForMultipleObjects(NOTIFICATIONS,state.event,FALSE,3000); 405 ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)), 406 "WaitForMultipleObjects failed: 0x%x\n",rc); 407 if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) { 408 ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED), 409 "Wrong notification: should be %d, got %d\n", 410 i%NOTIFICATIONS,rc-WAIT_OBJECT_0); 411 } 412 if (!capture_buffer_service(&state)) 413 break; 414 } 415 416 } 417 rc=IDirectSoundCaptureBuffer_Stop(dscbo); 418 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %08x\n", rc); 419 420 rc=IDirectSoundCaptureBuffer_Stop(dscbo); 421 ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %08x\n", rc); 422 } 423 424 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, 425 LPCSTR lpcstrModule, LPVOID lpContext) 426 { 427 HRESULT rc; 428 LPDIRECTSOUNDCAPTURE dsco=NULL; 429 LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL; 430 DSCBUFFERDESC bufdesc; 431 WAVEFORMATEX wfx; 432 DSCCAPS dsccaps; 433 DWORD f; 434 int ref; 435 436 /* Private dsound.dll: Error: Invalid interface buffer */ 437 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule); 438 rc=pDirectSoundCaptureCreate(lpGuid,NULL,NULL); 439 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate() should have " 440 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 441 442 rc=pDirectSoundCaptureCreate(lpGuid,&dsco,NULL); 443 ok((rc==DS_OK)||(rc==DSERR_NODRIVER)||(rc==E_FAIL)||(rc==DSERR_ALLOCATED), 444 "DirectSoundCaptureCreate() failed: %08x\n",rc); 445 if (rc!=DS_OK) { 446 if (rc==DSERR_NODRIVER) 447 trace(" No Driver\n"); 448 else if (rc==E_FAIL) 449 trace(" No Device\n"); 450 else if (rc==DSERR_ALLOCATED) 451 trace(" Already In Use\n"); 452 goto EXIT; 453 } 454 455 /* Private dsound.dll: Error: Invalid caps buffer */ 456 rc=IDirectSoundCapture_GetCaps(dsco,NULL); 457 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have " 458 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 459 460 /* Private dsound.dll: Error: Invalid caps buffer */ 461 dsccaps.dwSize=0; 462 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps); 463 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have " 464 "returned DSERR_INVALIDPARAM, returned: %08x\n",rc); 465 466 dsccaps.dwSize=sizeof(dsccaps); 467 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps); 468 ok(rc==DS_OK,"IDirectSoundCapture_GetCaps() failed: %08x\n", rc); 469 if (rc==DS_OK && winetest_debug > 1) { 470 trace(" Caps: size=%d flags=0x%08x formats=%05x channels=%d\n", 471 dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats, 472 dsccaps.dwChannels); 473 } 474 475 /* Private dsound.dll: Error: Invalid size */ 476 /* Private dsound.dll: Error: Invalid capture buffer description */ 477 ZeroMemory(&bufdesc, sizeof(bufdesc)); 478 bufdesc.dwSize=0; 479 bufdesc.dwFlags=0; 480 bufdesc.dwBufferBytes=0; 481 bufdesc.dwReserved=0; 482 bufdesc.lpwfxFormat=NULL; 483 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); 484 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() " 485 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 486 if (rc==DS_OK) { 487 ref=IDirectSoundCaptureBuffer_Release(dscbo); 488 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, " 489 "should have 0\n",ref); 490 } 491 492 /* Private dsound.dll: Error: Invalid buffer size */ 493 /* Private dsound.dll: Error: Invalid capture buffer description */ 494 ZeroMemory(&bufdesc, sizeof(bufdesc)); 495 bufdesc.dwSize=sizeof(bufdesc); 496 bufdesc.dwFlags=0; 497 bufdesc.dwBufferBytes=0; 498 bufdesc.dwReserved=0; 499 bufdesc.lpwfxFormat=NULL; 500 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); 501 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() " 502 "should have returned DSERR_INVALIDPARAM, returned %08x\n", rc); 503 if (rc==DS_OK) { 504 ref=IDirectSoundCaptureBuffer_Release(dscbo); 505 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, " 506 "should have 0\n",ref); 507 } 508 509 /* Private dsound.dll: Error: Invalid buffer size */ 510 /* Private dsound.dll: Error: Invalid capture buffer description */ 511 ZeroMemory(&bufdesc, sizeof(bufdesc)); 512 ZeroMemory(&wfx, sizeof(wfx)); 513 bufdesc.dwSize=sizeof(bufdesc); 514 bufdesc.dwFlags=0; 515 bufdesc.dwBufferBytes=0; 516 bufdesc.dwReserved=0; 517 bufdesc.lpwfxFormat=&wfx; 518 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); 519 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() " 520 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 521 if (rc==DS_OK) { 522 ref=IDirectSoundCaptureBuffer_Release(dscbo); 523 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, " 524 "should have 0\n",ref); 525 } 526 527 /* Private dsound.dll: Error: Invalid buffer size */ 528 /* Private dsound.dll: Error: Invalid capture buffer description */ 529 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1); 530 ZeroMemory(&bufdesc, sizeof(bufdesc)); 531 bufdesc.dwSize=sizeof(bufdesc); 532 bufdesc.dwFlags=0; 533 bufdesc.dwBufferBytes=0; 534 bufdesc.dwReserved=0; 535 bufdesc.lpwfxFormat=&wfx; 536 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); 537 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() " 538 "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); 539 if (rc==DS_OK) { 540 ref=IDirectSoundCaptureBuffer_Release(dscbo); 541 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, " 542 "should have 0\n",ref); 543 } 544 545 for (f=0;f<NB_FORMATS;f++) { 546 dscbo=NULL; 547 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1], 548 formats[f][2]); 549 ZeroMemory(&bufdesc, sizeof(bufdesc)); 550 bufdesc.dwSize=sizeof(bufdesc); 551 bufdesc.dwFlags=0; 552 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; 553 bufdesc.dwReserved=0; 554 bufdesc.lpwfxFormat=&wfx; 555 if (winetest_interactive) 556 trace(" Testing the capture buffer at %s\n", format_string(&wfx)); 557 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); 558 ok(((rc==DS_OK)&&(dscbo!=NULL)) 559 || rc==DSERR_BADFORMAT || rc==DSERR_INVALIDCALL || rc==DSERR_NODRIVER 560 || rc==DSERR_ALLOCATED || rc==E_INVALIDARG || rc==E_FAIL, 561 "IDirectSoundCapture_CreateCaptureBuffer() failed to create a " 562 "%s capture buffer: %08x\n",format_string(&wfx),rc); 563 if (rc==DS_OK) { 564 test_capture_buffer(dsco, dscbo, winetest_interactive); 565 ref=IDirectSoundCaptureBuffer_Release(dscbo); 566 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, " 567 "should have 0\n",ref); 568 } else if (rc==DSERR_BADFORMAT) { 569 ok(!(dsccaps.dwFormats & formats[f][3]), 570 "IDirectSoundCapture_CreateCaptureBuffer() failed to create a " 571 "capture buffer: format listed as supported but using it failed\n"); 572 if (!(dsccaps.dwFormats & formats[f][3])) 573 trace(" Format not supported: %s\n", format_string(&wfx)); 574 } else if (rc==DSERR_NODRIVER) { 575 trace(" No Driver\n"); 576 } else if (rc==DSERR_ALLOCATED) { 577 trace(" Already In Use\n"); 578 } else if (rc==E_INVALIDARG) { /* try the old version struct */ 579 DSCBUFFERDESC1 bufdesc1; 580 ZeroMemory(&bufdesc1, sizeof(bufdesc1)); 581 bufdesc1.dwSize=sizeof(bufdesc1); 582 bufdesc1.dwFlags=0; 583 bufdesc1.dwBufferBytes=wfx.nAvgBytesPerSec; 584 bufdesc1.dwReserved=0; 585 bufdesc1.lpwfxFormat=&wfx; 586 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco, 587 (DSCBUFFERDESC*)&bufdesc1,&dscbo,NULL); 588 ok(rc==DS_OK || broken(rc==DSERR_INVALIDPARAM), 589 "IDirectSoundCapture_CreateCaptureBuffer() failed to create a " 590 "%s capture buffer: %08x\n",format_string(&wfx), rc); 591 if (rc==DSERR_INVALIDPARAM) { 592 skip("broken driver\n"); 593 goto EXIT; 594 } 595 if (rc==DS_OK) { 596 test_capture_buffer(dsco, dscbo, winetest_interactive); 597 ref=IDirectSoundCaptureBuffer_Release(dscbo); 598 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d " 599 "references, should have 0\n",ref); 600 } 601 } else if (rc==E_FAIL) { 602 /* WAVE_FORMAT_PCM only allows 8 and 16 bits per sample, so only 603 * report a failure if the bits per sample is 8 or 16 604 */ 605 if (wfx.wBitsPerSample == 8 || wfx.wBitsPerSample == 16) 606 ok(FALSE,"Should not fail for 8 or 16 bits per sample\n"); 607 } 608 } 609 610 /* try a non PCM format */ 611 if (0) 612 { 613 /* FIXME: Why is this commented out? */ 614 init_format(&wfx,WAVE_FORMAT_MULAW,8000,8,1); 615 ZeroMemory(&bufdesc, sizeof(bufdesc)); 616 bufdesc.dwSize=sizeof(bufdesc); 617 bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED; 618 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; 619 bufdesc.dwReserved=0; 620 bufdesc.lpwfxFormat=&wfx; 621 if (winetest_interactive) 622 trace(" Testing the capture buffer at %s\n", format_string(&wfx)); 623 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); 624 ok((rc==DS_OK)&&(dscbo!=NULL),"IDirectSoundCapture_CreateCaptureBuffer() " 625 "failed to create a capture buffer: %08x\n",rc); 626 if ((rc==DS_OK)&&(dscbo!=NULL)) { 627 test_capture_buffer(dsco, dscbo, winetest_interactive); 628 ref=IDirectSoundCaptureBuffer_Release(dscbo); 629 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, " 630 "should have 0\n",ref); 631 } 632 } 633 634 /* Try an invalid format to test error handling */ 635 if (0) 636 { 637 /* FIXME: Remove this test altogether? */ 638 init_format(&wfx,WAVE_FORMAT_PCM,2000000,16,2); 639 ZeroMemory(&bufdesc, sizeof(bufdesc)); 640 bufdesc.dwSize=sizeof(bufdesc); 641 bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED; 642 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; 643 bufdesc.dwReserved=0; 644 bufdesc.lpwfxFormat=&wfx; 645 if (winetest_interactive) 646 trace(" Testing the capture buffer at %s\n", format_string(&wfx)); 647 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); 648 ok(rc!=DS_OK,"IDirectSoundCapture_CreateCaptureBuffer() should have failed " 649 "at 2 MHz %08x\n",rc); 650 } 651 652 EXIT: 653 if (dsco!=NULL) { 654 ref=IDirectSoundCapture_Release(dsco); 655 ok(ref==0,"IDirectSoundCapture_Release() has %d references, should " 656 "have 0\n",ref); 657 } 658 659 return TRUE; 660 } 661 662 static void test_enumerate(void) 663 { 664 HRESULT rc; 665 rc=pDirectSoundCaptureEnumerateA(&dscenum_callback,NULL); 666 ok(rc==DS_OK,"DirectSoundCaptureEnumerateA() failed: %08x\n", rc); 667 } 668 669 static void test_COM(void) 670 { 671 IDirectSoundCapture *dsc = (IDirectSoundCapture*)0xdeadbeef; 672 IDirectSoundCaptureBuffer *buffer = (IDirectSoundCaptureBuffer*)0xdeadbeef; 673 IDirectSoundNotify *notify; 674 IUnknown *unk; 675 DSCBUFFERDESC bufdesc; 676 WAVEFORMATEX wfx; 677 HRESULT hr; 678 ULONG refcount; 679 680 hr = pDirectSoundCaptureCreate(NULL, &dsc, (IUnknown*)0xdeadbeef); 681 ok(hr == DSERR_NOAGGREGATION, 682 "DirectSoundCaptureCreate failed: %08x, expected DSERR_NOAGGREGATION\n", hr); 683 ok(dsc == (IDirectSoundCapture*)0xdeadbeef, "dsc = %p\n", dsc); 684 685 hr = pDirectSoundCaptureCreate(NULL, &dsc, NULL); 686 if (hr == DSERR_NODRIVER) { 687 skip("No driver\n"); 688 return; 689 } 690 ok(hr == DS_OK, "DirectSoundCaptureCreate failed: %08x, expected DS_OK\n", hr); 691 692 /* Different refcount for IDirectSoundCapture and for IUnknown */ 693 refcount = IDirectSoundCapture_AddRef(dsc); 694 ok(refcount == 2, "refcount == %u, expected 2\n", refcount); 695 hr = IDirectSoundCapture_QueryInterface(dsc, &IID_IUnknown, (void**)&unk); 696 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); 697 refcount = IUnknown_AddRef(unk); 698 ok(refcount == 2, "refcount == %u, expected 2\n", refcount); 699 IUnknown_Release(unk); 700 IUnknown_Release(unk); 701 IDirectSoundCapture_Release(dsc); 702 703 init_format(&wfx, WAVE_FORMAT_PCM, 44100, 16, 1); 704 ZeroMemory(&bufdesc, sizeof(bufdesc)); 705 bufdesc.dwSize = sizeof(bufdesc); 706 bufdesc.dwBufferBytes = wfx.nAvgBytesPerSec; 707 bufdesc.lpwfxFormat = &wfx; 708 709 hr = IDirectSoundCapture_CreateCaptureBuffer(dsc, &bufdesc, &buffer, (IUnknown*)0xdeadbeef); 710 if (hr == E_INVALIDARG) { 711 /* Old DirectX has only the 1st version of the DSCBUFFERDESC struct */ 712 bufdesc.dwSize = sizeof(DSCBUFFERDESC1); 713 hr = IDirectSoundCapture_CreateCaptureBuffer(dsc, &bufdesc, &buffer, (IUnknown*)0xdeadbeef); 714 } 715 ok(hr == DSERR_NOAGGREGATION, 716 "IDirectSoundCapture_CreateCaptureBuffer failed: %08x, expected DSERR_NOAGGREGATION\n", hr); 717 ok(buffer == (IDirectSoundCaptureBuffer*)0xdeadbeef || !buffer /* Win2k without DirectX9 */, 718 "buffer = %p\n", buffer); 719 720 hr = IDirectSoundCapture_CreateCaptureBuffer(dsc, &bufdesc, &buffer, NULL); 721 ok(hr == DS_OK, "IDirectSoundCapture_CreateCaptureBuffer failed: %08x, expected DS_OK\n", hr); 722 723 /* IDirectSoundCaptureBuffer and IDirectSoundNotify have separate refcounts */ 724 IDirectSoundCaptureBuffer_AddRef(buffer); 725 refcount = IDirectSoundCaptureBuffer_AddRef(buffer); 726 ok(refcount == 3, "IDirectSoundCaptureBuffer refcount is %u, expected 3\n", refcount); 727 hr = IDirectSoundCaptureBuffer_QueryInterface(buffer, &IID_IDirectSoundNotify, (void**)¬ify); 728 ok(hr == DS_OK, "IDirectSoundCapture_QueryInterface failed: %08x, expected DS_OK\n", hr); 729 refcount = IDirectSoundNotify_AddRef(notify); 730 ok(refcount == 2, "IDirectSoundNotify refcount is %u, expected 2\n", refcount); 731 IDirectSoundCaptureBuffer_AddRef(buffer); 732 refcount = IDirectSoundCaptureBuffer_Release(buffer); 733 ok(refcount == 3, "IDirectSoundCaptureBuffer refcount is %u, expected 3\n", refcount); 734 735 /* Release IDirectSoundCaptureBuffer while keeping IDirectSoundNotify alive */ 736 while (IDirectSoundCaptureBuffer_Release(buffer) > 0); 737 refcount = IDirectSoundNotify_AddRef(notify); 738 ok(refcount == 3, "IDirectSoundNotify refcount is %u, expected 3\n", refcount); 739 refcount = IDirectSoundCaptureBuffer_AddRef(buffer); 740 ok(refcount == 1, "IDirectSoundCaptureBuffer refcount is %u, expected 1\n", refcount); 741 742 while (IDirectSoundNotify_Release(notify) > 0); 743 refcount = IDirectSoundCaptureBuffer_Release(buffer); 744 ok(refcount == 0, "IDirectSoundCaptureBuffer refcount is %u, expected 0\n", refcount); 745 refcount = IDirectSoundCapture_Release(dsc); 746 ok(refcount == 0, "IDirectSoundCapture refcount is %u, expected 0\n", refcount); 747 } 748 749 START_TEST(capture) 750 { 751 HMODULE hDsound; 752 753 CoInitialize(NULL); 754 755 hDsound = LoadLibrary("dsound.dll"); 756 if (!hDsound) { 757 skip("dsound.dll not found - skipping all tests\n"); 758 return; 759 } 760 761 pDirectSoundCaptureCreate = (void*)GetProcAddress(hDsound, "DirectSoundCaptureCreate"); 762 pDirectSoundCaptureEnumerateA = (void*)GetProcAddress(hDsound, "DirectSoundCaptureEnumerateA"); 763 if (!pDirectSoundCaptureCreate || !pDirectSoundCaptureEnumerateA) { 764 skip("DirectSoundCapture{Create,Enumerate} missing - skipping all tests\n"); 765 return; 766 } 767 768 test_COM(); 769 test_capture(); 770 test_enumerate(); 771 772 FreeLibrary(hDsound); 773 CoUninitialize(); 774 } 775