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
get_format_str(WORD format)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
format_string(const WAVEFORMATEX * wfx)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
IDirectSoundCapture_test(LPDIRECTSOUNDCAPTURE dsco,BOOL initialized,LPCGUID lpGuid)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
test_capture(void)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
capture_buffer_service(capture_state_t * state)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
test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,LPDIRECTSOUNDCAPTUREBUFFER dscbo,int record)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
dscenum_callback(LPGUID lpGuid,LPCSTR lpcstrDescription,LPCSTR lpcstrModule,LPVOID lpContext)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
test_enumerate(void)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
test_COM(void)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
START_TEST(capture)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