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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define NONAMELESSSTRUCT
23 #define NONAMELESSUNION
30 #include "wine/test.h"
37 #include "dsound_test.h"
39 #define NOTIFICATIONS 5
42 static const char * get_format_str(WORD format
)
45 #define WAVE_FORMAT(f) case f: return #f
47 WAVE_FORMAT(WAVE_FORMAT_PCM
);
48 WAVE_FORMAT(WAVE_FORMAT_ADPCM
);
49 WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD
);
50 WAVE_FORMAT(WAVE_FORMAT_ALAW
);
51 WAVE_FORMAT(WAVE_FORMAT_MULAW
);
52 WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM
);
53 WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM
);
54 WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM
);
55 WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM
);
56 WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM
);
57 WAVE_FORMAT(WAVE_FORMAT_DIGISTD
);
58 WAVE_FORMAT(WAVE_FORMAT_DIGIFIX
);
59 WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM
);
60 WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM
);
61 WAVE_FORMAT(WAVE_FORMAT_SONARC
);
62 WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH
);
63 WAVE_FORMAT(WAVE_FORMAT_ECHOSC1
);
64 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36
);
65 WAVE_FORMAT(WAVE_FORMAT_APTX
);
66 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10
);
67 WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2
);
68 WAVE_FORMAT(WAVE_FORMAT_GSM610
);
69 WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME
);
70 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC
);
71 WAVE_FORMAT(WAVE_FORMAT_DIGIREAL
);
72 WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM
);
73 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10
);
74 WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM
);
75 WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM
);
76 WAVE_FORMAT(WAVE_FORMAT_MPEG
);
77 WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3
);
78 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM
);
79 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8
);
80 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10
);
81 WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND
);
82 WAVE_FORMAT(WAVE_FORMAT_OLIGSM
);
83 WAVE_FORMAT(WAVE_FORMAT_OLIADPCM
);
84 WAVE_FORMAT(WAVE_FORMAT_OLICELP
);
85 WAVE_FORMAT(WAVE_FORMAT_OLISBC
);
86 WAVE_FORMAT(WAVE_FORMAT_OLIOPR
);
87 WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT
);
88 WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE
);
91 sprintf(msg
, "Unknown(0x%04x)", format
);
95 static char * format_string(WAVEFORMATEX
* wfx
)
99 sprintf(str
, "%5ldx%2dx%d %s",
100 wfx
->nSamplesPerSec
, wfx
->wBitsPerSample
, wfx
->nChannels
,
101 get_format_str(wfx
->wFormatTag
));
110 LPDIRECTSOUNDCAPTUREBUFFER dscbo
;
112 DSBPOSITIONNOTIFY posnotify
[NOTIFICATIONS
];
113 HANDLE event
[NOTIFICATIONS
];
114 LPDIRECTSOUNDNOTIFY notify
;
124 static int capture_buffer_service(capture_state_t
* state
)
129 DWORD capture_pos
,read_pos
;
131 rc
=IDirectSoundCaptureBuffer_GetCurrentPosition(state
->dscbo
,&capture_pos
,
133 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_GetCurrentPosition() failed: %s\n",
134 DXGetErrorString8(rc
));
138 rc
=IDirectSoundCaptureBuffer_Lock(state
->dscbo
,state
->offset
,state
->size
,
139 &ptr1
,&len1
,&ptr2
,&len2
,0);
140 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_Lock() failed: %s\n",
141 DXGetErrorString8(rc
));
145 rc
=IDirectSoundCaptureBuffer_Unlock(state
->dscbo
,ptr1
,len1
,ptr2
,len2
);
146 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_Unlock() failed: %s\n",
147 DXGetErrorString8(rc
));
151 state
->offset
= (state
->offset
+ state
->size
) % state
->buffer_size
;
156 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco
,
157 LPDIRECTSOUNDCAPTUREBUFFER dscbo
, int record
)
163 capture_state_t state
;
166 /* Private dsound.dll: Error: Invalid caps pointer */
167 rc
=IDirectSoundCaptureBuffer_GetCaps(dscbo
,0);
168 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCaptureBuffer_GetCaps() should "
169 "have returned DSERR_INVALIDPARAM, returned: %s\n",
170 DXGetErrorString8(rc
));
172 /* Private dsound.dll: Error: Invalid caps pointer */
174 rc
=IDirectSoundCaptureBuffer_GetCaps(dscbo
,&dscbcaps
);
175 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCaptureBuffer_GetCaps() should "
176 "have returned DSERR_INVALIDPARAM, returned: %s\n",
177 DXGetErrorString8(rc
));
179 dscbcaps
.dwSize
=sizeof(dscbcaps
);
180 rc
=IDirectSoundCaptureBuffer_GetCaps(dscbo
,&dscbcaps
);
181 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_GetCaps() failed: %s\n",
182 DXGetErrorString8(rc
));
183 if (rc
==DS_OK
&& winetest_debug
> 1) {
184 trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
185 dscbcaps
.dwSize
,dscbcaps
.dwFlags
,dscbcaps
.dwBufferBytes
);
188 /* Query the format size. Note that it may not match sizeof(wfx) */
189 /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must
191 rc
=IDirectSoundCaptureBuffer_GetFormat(dscbo
,NULL
,0,NULL
);
192 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCaptureBuffer_GetFormat() should "
193 "have returned DSERR_INVALIDPARAM, returned: %s\n",
194 DXGetErrorString8(rc
));
197 rc
=IDirectSoundCaptureBuffer_GetFormat(dscbo
,NULL
,0,&size
);
198 ok(rc
==DS_OK
&& size
!=0,"IDirectSoundCaptureBuffer_GetFormat() should "
199 "have returned the needed size: rc=%s, size=%ld\n",
200 DXGetErrorString8(rc
),size
);
202 rc
=IDirectSoundCaptureBuffer_GetFormat(dscbo
,&wfx
,sizeof(wfx
),NULL
);
203 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_GetFormat() failed: %s\n",
204 DXGetErrorString8(rc
));
205 if (rc
==DS_OK
&& winetest_debug
> 1) {
206 trace(" Format: tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
207 wfx
.wFormatTag
,wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,
208 wfx
.nChannels
,wfx
.nAvgBytesPerSec
,wfx
.nBlockAlign
);
211 /* Private dsound.dll: Error: Invalid status pointer */
212 rc
=IDirectSoundCaptureBuffer_GetStatus(dscbo
,0);
213 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCaptureBuffer_GetStatus() should "
214 "have returned DSERR_INVALIDPARAM, returned: %s\n",
215 DXGetErrorString8(rc
));
217 rc
=IDirectSoundCaptureBuffer_GetStatus(dscbo
,&status
);
218 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
219 DXGetErrorString8(rc
));
220 if (rc
==DS_OK
&& winetest_debug
> 1) {
221 trace(" Status=0x%04lx\n",status
);
224 ZeroMemory(&state
, sizeof(state
));
227 state
.buffer_size
= dscbcaps
.dwBufferBytes
;
228 for (i
= 0; i
< NOTIFICATIONS
; i
++)
229 state
.event
[i
] = CreateEvent( NULL
, FALSE
, FALSE
, NULL
);
230 state
.size
= dscbcaps
.dwBufferBytes
/ NOTIFICATIONS
;
232 rc
=IDirectSoundCaptureBuffer_QueryInterface(dscbo
,&IID_IDirectSoundNotify
,
233 (void **)&(state
.notify
));
234 ok((rc
==DS_OK
)&&(state
.notify
!=NULL
),
235 "IDirectSoundCaptureBuffer_QueryInterface() failed: %s\n",
236 DXGetErrorString8(rc
));
240 for (i
= 0; i
< NOTIFICATIONS
; i
++) {
241 state
.posnotify
[i
].dwOffset
= (i
* state
.size
) + state
.size
- 1;
242 state
.posnotify
[i
].hEventNotify
= state
.event
[i
];
245 rc
=IDirectSoundNotify_SetNotificationPositions(state
.notify
,NOTIFICATIONS
,
247 ok(rc
==DS_OK
,"IDirectSoundNotify_SetNotificationPositions() failed: %s\n",
248 DXGetErrorString8(rc
));
252 ref
=IDirectSoundNotify_Release(state
.notify
);
253 ok(ref
==0,"IDirectSoundNotify_Release(): has %d references, should have "
259 rc
=IDirectSoundCaptureBuffer_Start(dscbo
,DSCBSTART_LOOPING
);
260 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_Start() failed: %s\n",
261 DXGetErrorString8(rc
));
265 rc
=IDirectSoundCaptureBuffer_GetStatus(dscbo
,&status
);
266 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
267 DXGetErrorString8(rc
));
268 ok(status
==(DSCBSTATUS_CAPTURING
|DSCBSTATUS_LOOPING
),
269 "GetStatus: bad status: %lx\n",status
);
273 /* wait for the notifications */
274 for (i
= 0; i
< (NOTIFICATIONS
* 2); i
++) {
275 rc
=MsgWaitForMultipleObjects(NOTIFICATIONS
,state
.event
,FALSE
,
277 ok(rc
==(WAIT_OBJECT_0
+(i
%NOTIFICATIONS
)),
278 "MsgWaitForMultipleObjects failed: 0x%lx\n",rc
);
279 if (rc
!=(WAIT_OBJECT_0
+(i
%NOTIFICATIONS
))) {
280 ok((rc
==WAIT_TIMEOUT
)||(rc
==WAIT_FAILED
),
281 "Wrong notification: should be %d, got %ld\n",
282 i
%NOTIFICATIONS
,rc
-WAIT_OBJECT_0
);
284 if (!capture_buffer_service(&state
))
288 rc
=IDirectSoundCaptureBuffer_Stop(dscbo
);
289 ok(rc
==DS_OK
,"IDirectSoundCaptureBuffer_Stop() failed: %s\n",
290 DXGetErrorString8(rc
));
296 static BOOL WINAPI
dscenum_callback(LPGUID lpGuid
, LPCSTR lpcstrDescription
,
297 LPCSTR lpcstrModule
, LPVOID lpContext
)
300 LPDIRECTSOUNDCAPTURE dsco
=NULL
;
301 LPDIRECTSOUNDCAPTUREBUFFER dscbo
=NULL
;
302 DSCBUFFERDESC bufdesc
;
308 /* Private dsound.dll: Error: Invalid interface buffer */
309 trace("*** Testing %s - %s ***\n",lpcstrDescription
,lpcstrModule
);
310 rc
=DirectSoundCaptureCreate(lpGuid
,NULL
,NULL
);
311 ok(rc
==DSERR_INVALIDPARAM
,"DirectSoundCaptureCreate() should have "
312 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc
));
314 ref
=IDirectSoundCapture_Release(dsco
);
315 ok(ref
==0,"IDirectSoundCapture_Release() has %d references, should "
319 rc
=DirectSoundCaptureCreate(lpGuid
,&dsco
,NULL
);
320 ok((rc
==DS_OK
)||(rc
==DSERR_NODRIVER
),"DirectSoundCaptureCreate() failed: "
321 "%s\n",DXGetErrorString8(rc
));
325 /* Private dsound.dll: Error: Invalid caps buffer */
326 rc
=IDirectSoundCapture_GetCaps(dsco
,NULL
);
327 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCapture_GetCaps() should have "
328 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc
));
330 /* Private dsound.dll: Error: Invalid caps buffer */
332 rc
=IDirectSoundCapture_GetCaps(dsco
,&dsccaps
);
333 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCapture_GetCaps() should have "
334 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc
));
336 dsccaps
.dwSize
=sizeof(dsccaps
);
337 rc
=IDirectSoundCapture_GetCaps(dsco
,&dsccaps
);
338 ok(rc
==DS_OK
,"IDirectSoundCapture_GetCaps() failed: %s\n",
339 DXGetErrorString8(rc
));
340 if (rc
==DS_OK
&& winetest_debug
> 1) {
341 trace(" Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
342 dsccaps
.dwSize
,dsccaps
.dwFlags
,dsccaps
.dwFormats
,
346 /* Private dsound.dll: Error: Invalid size */
347 /* Private dsound.dll: Error: Invalid capture buffer description */
348 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
351 bufdesc
.dwBufferBytes
=0;
352 bufdesc
.dwReserved
=0;
353 bufdesc
.lpwfxFormat
=NULL
;
354 rc
=IDirectSoundCapture_CreateCaptureBuffer(dsco
,&bufdesc
,&dscbo
,NULL
);
355 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCapture_CreateCaptureBuffer() "
356 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
357 DXGetErrorString8(rc
));
359 ref
=IDirectSoundCaptureBuffer_Release(dscbo
);
360 ok(ref
==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
361 "should have 0\n",ref
);
364 /* Private dsound.dll: Error: Invalid buffer size */
365 /* Private dsound.dll: Error: Invalid capture buffer description */
366 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
367 bufdesc
.dwSize
=sizeof(bufdesc
);
369 bufdesc
.dwBufferBytes
=0;
370 bufdesc
.dwReserved
=0;
371 bufdesc
.lpwfxFormat
=NULL
;
372 rc
=IDirectSoundCapture_CreateCaptureBuffer(dsco
,&bufdesc
,&dscbo
,NULL
);
373 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCapture_CreateCaptureBuffer() "
374 "should have returned DSERR_INVALIDPARAM, returned %s\n",
375 DXGetErrorString8(rc
));
377 ref
=IDirectSoundCaptureBuffer_Release(dscbo
);
378 ok(ref
==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
379 "should have 0\n",ref
);
382 /* Private dsound.dll: Error: Invalid buffer size */
383 /* Private dsound.dll: Error: Invalid capture buffer description */
384 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
385 ZeroMemory(&wfx
, sizeof(wfx
));
386 bufdesc
.dwSize
=sizeof(bufdesc
);
388 bufdesc
.dwBufferBytes
=0;
389 bufdesc
.dwReserved
=0;
390 bufdesc
.lpwfxFormat
=&wfx
;
391 rc
=IDirectSoundCapture_CreateCaptureBuffer(dsco
,&bufdesc
,&dscbo
,NULL
);
392 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCapture_CreateCaptureBuffer() "
393 "should have returned DSERR_INVALIDPARAM, returned :%s\n",
394 DXGetErrorString8(rc
));
396 ref
=IDirectSoundCaptureBuffer_Release(dscbo
);
397 ok(ref
==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
398 "should have 0\n",ref
);
401 /* Private dsound.dll: Error: Invalid buffer size */
402 /* Private dsound.dll: Error: Invalid capture buffer description */
403 init_format(&wfx
,WAVE_FORMAT_PCM
,11025,8,1);
404 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
405 bufdesc
.dwSize
=sizeof(bufdesc
);
407 bufdesc
.dwBufferBytes
=0;
408 bufdesc
.dwReserved
=0;
409 bufdesc
.lpwfxFormat
=&wfx
;
410 rc
=IDirectSoundCapture_CreateCaptureBuffer(dsco
,&bufdesc
,&dscbo
,NULL
);
411 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundCapture_CreateCaptureBuffer() "
412 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
413 DXGetErrorString8(rc
));
415 ref
=IDirectSoundCaptureBuffer_Release(dscbo
);
416 ok(ref
==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
417 "should have 0\n",ref
);
420 for (f
=0;f
<NB_FORMATS
;f
++) {
422 init_format(&wfx
,WAVE_FORMAT_PCM
,formats
[f
][0],formats
[f
][1],
424 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
425 bufdesc
.dwSize
=sizeof(bufdesc
);
427 bufdesc
.dwBufferBytes
=wfx
.nAvgBytesPerSec
;
428 bufdesc
.dwReserved
=0;
429 bufdesc
.lpwfxFormat
=&wfx
;
430 if (winetest_interactive
)
431 trace(" Testing the capture buffer at %s\n", format_string(&wfx
));
432 rc
=IDirectSoundCapture_CreateCaptureBuffer(dsco
,&bufdesc
,&dscbo
,NULL
);
433 ok((rc
==DS_OK
)&&(dscbo
!=NULL
),
434 "IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
435 "capture buffer: %s\n",DXGetErrorString8(rc
));
437 test_capture_buffer(dsco
, dscbo
, winetest_interactive
);
438 ref
=IDirectSoundCaptureBuffer_Release(dscbo
);
439 ok(ref
==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
440 "should have 0\n",ref
);
444 /* try a non PCM format */
446 init_format(&wfx
,WAVE_FORMAT_MULAW
,8000,8,1);
447 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
448 bufdesc
.dwSize
=sizeof(bufdesc
);
449 bufdesc
.dwFlags
=DSCBCAPS_WAVEMAPPED
;
450 bufdesc
.dwBufferBytes
=wfx
.nAvgBytesPerSec
;
451 bufdesc
.dwReserved
=0;
452 bufdesc
.lpwfxFormat
=&wfx
;
453 if (winetest_interactive
)
454 trace(" Testing the capture buffer at %s\n", format_string(&wfx
));
455 rc
=IDirectSoundCapture_CreateCaptureBuffer(dsco
,&bufdesc
,&dscbo
,NULL
);
456 ok((rc
==DS_OK
)&&(dscbo
!=NULL
),"IDirectSoundCapture_CreateCaptureBuffer() "
457 "failed to create a capture buffer: %s\n",DXGetErrorString8(rc
));
458 if ((rc
==DS_OK
)&&(dscbo
!=NULL
)) {
459 test_capture_buffer(dsco
, dscbo
, winetest_interactive
);
460 ref
=IDirectSoundCaptureBuffer_Release(dscbo
);
461 ok(ref
==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
462 "should have 0\n",ref
);
466 /* Try an invalid format to test error handling */
468 init_format(&wfx
,WAVE_FORMAT_PCM
,2000000,16,2);
469 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
470 bufdesc
.dwSize
=sizeof(bufdesc
);
471 bufdesc
.dwFlags
=DSCBCAPS_WAVEMAPPED
;
472 bufdesc
.dwBufferBytes
=wfx
.nAvgBytesPerSec
;
473 bufdesc
.dwReserved
=0;
474 bufdesc
.lpwfxFormat
=&wfx
;
475 if (winetest_interactive
)
476 trace(" Testing the capture buffer at %s\n", format_string(&wfx
));
477 rc
=IDirectSoundCapture_CreateCaptureBuffer(dsco
,&bufdesc
,&dscbo
,NULL
);
478 ok(rc
!=DS_OK
,"IDirectSoundCapture_CreateCaptureBuffer() should have failed "
479 "at 2 MHz %s\n",DXGetErrorString8(rc
));
484 ref
=IDirectSoundCapture_Release(dsco
);
485 ok(ref
==0,"IDirectSoundCapture_Release() has %d references, should "
492 static void capture_tests()
495 rc
=DirectSoundCaptureEnumerateA(&dscenum_callback
,NULL
);
496 ok(rc
==DS_OK
,"DirectSoundCaptureEnumerateA() failed: %s\n",
497 DXGetErrorString8(rc
));