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