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
29 #include "wine/test.h"
34 static const unsigned int formats[][3]={
60 #define NB_FORMATS (sizeof(formats)/sizeof(*formats))
62 #define NOTIFICATIONS 5
64 static void init_format(WAVEFORMATEX* wfx, int rate, int depth, int channels)
66 wfx->wFormatTag=WAVE_FORMAT_PCM;
67 wfx->nChannels=channels;
68 wfx->wBitsPerSample=depth;
69 wfx->nSamplesPerSec=rate;
70 wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
71 wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
79 LPDIRECTSOUNDCAPTUREBUFFER dscbo;
81 DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
82 HANDLE event[NOTIFICATIONS];
83 LPDIRECTSOUNDNOTIFY notify;
93 static int capture_buffer_service(capture_state_t* state)
98 DWORD capture_pos,read_pos;
100 rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos);
101 ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx\n",rc);
105 rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0);
106 ok(rc==DS_OK,"Lock failed: 0x%lx\n",rc);
110 rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
111 ok(rc==DS_OK,"Unlock failed: 0x%lx\n",rc);
115 state->offset = (state->offset + state->size) % state->buffer_size;
120 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
121 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
127 capture_state_t state;
130 /* Private dsound.dll: Error: Invalid caps pointer */
131 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
132 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
134 /* Private dsound.dll: Error: Invalid caps pointer */
136 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
137 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
139 dscbcaps.dwSize=sizeof(dscbcaps);
140 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
141 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
143 trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
144 dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
147 /* Query the format size. Note that it may not match sizeof(wfx) */
148 /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must be non-NULL */
149 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
150 ok(rc==DSERR_INVALIDPARAM,
151 "GetFormat should have returned an error: rc=0x%lx\n",rc);
154 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
155 ok(rc==DS_OK && size!=0,
156 "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
159 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
160 ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
162 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
163 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
164 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
167 /* Private dsound.dll: Error: Invalid status pointer */
168 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
169 ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
171 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
172 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
174 trace(" status=0x%04lx\n",status);
177 ZeroMemory(&state, sizeof(state));
180 state.buffer_size = dscbcaps.dwBufferBytes;
181 for (i = 0; i < NOTIFICATIONS; i++)
182 state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
183 state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
185 rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify));
186 ok((rc==DS_OK)&&(state.notify!=NULL),"QueryInterface failed: 0x%lx\n",rc);
190 for (i = 0; i < NOTIFICATIONS; i++) {
191 state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
192 state.posnotify[i].hEventNotify = state.event[i];
195 rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify);
196 ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx\n",rc);
200 rc=IDirectSoundNotify_Release(state.notify);
201 ok(rc==0,"Release: 0x%lx\n",rc);
206 rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
207 ok(rc==DS_OK,"Start: 0x%lx\n",rc);
211 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
212 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
213 ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
214 "GetStatus: bad status: %lx",status);
218 /* wait for the notifications */
219 for (i = 0; i < (NOTIFICATIONS * 2); i++) {
220 rc=MsgWaitForMultipleObjects( NOTIFICATIONS, state.event, FALSE, 3000, QS_ALLEVENTS );
221 ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
222 if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
223 ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),"Wrong notification: should be %d, got %ld\n",
224 i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
227 if (!capture_buffer_service(&state))
231 rc=IDirectSoundCaptureBuffer_Stop(dscbo);
232 ok(rc==DS_OK,"Stop: 0x%lx\n",rc);
238 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
239 LPCSTR lpcstrModule, LPVOID lpContext)
242 LPDIRECTSOUNDCAPTURE dsco=NULL;
243 LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
244 DSCBUFFERDESC bufdesc;
249 /* Private dsound.dll: Error: Invalid interface buffer */
250 trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
251 rc=DirectSoundCaptureCreate(lpGuid,NULL,NULL);
252 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx\n",rc);
254 ref=IDirectSoundCapture_Release(dsco);
255 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
258 rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL);
259 ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx\n",rc);
263 /* Private dsound.dll: Error: Invalid caps buffer */
264 rc=IDirectSoundCapture_GetCaps(dsco,NULL);
265 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
267 /* Private dsound.dll: Error: Invalid caps buffer */
269 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
270 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
272 dsccaps.dwSize=sizeof(dsccaps);
273 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
274 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
276 trace(" DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
277 dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels);
280 /* Private dsound.dll: Error: Invalid size */
281 /* Private dsound.dll: Error: Invalid capture buffer description */
282 ZeroMemory(&bufdesc, sizeof(bufdesc));
285 bufdesc.dwBufferBytes=0;
286 bufdesc.dwReserved=0;
287 bufdesc.lpwfxFormat=NULL;
288 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
289 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
291 ref=IDirectSoundCaptureBuffer_Release(dscbo);
292 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
295 /* Private dsound.dll: Error: Invalid buffer size */
296 /* Private dsound.dll: Error: Invalid capture buffer description */
297 ZeroMemory(&bufdesc, sizeof(bufdesc));
298 bufdesc.dwSize=sizeof(bufdesc);
300 bufdesc.dwBufferBytes=0;
301 bufdesc.dwReserved=0;
302 bufdesc.lpwfxFormat=NULL;
303 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
304 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
306 ref=IDirectSoundCaptureBuffer_Release(dscbo);
307 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
310 /* Private dsound.dll: Error: Invalid buffer size */
311 /* Private dsound.dll: Error: Invalid capture buffer description */
312 ZeroMemory(&bufdesc, sizeof(bufdesc));
313 ZeroMemory(&wfx, sizeof(wfx));
314 bufdesc.dwSize=sizeof(bufdesc);
316 bufdesc.dwBufferBytes=0;
317 bufdesc.dwReserved=0;
318 bufdesc.lpwfxFormat=&wfx;
319 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
320 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
322 ref=IDirectSoundCaptureBuffer_Release(dscbo);
323 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
326 /* Private dsound.dll: Error: Invalid buffer size */
327 /* Private dsound.dll: Error: Invalid capture buffer description */
328 init_format(&wfx,11025,8,1);
329 ZeroMemory(&bufdesc, sizeof(bufdesc));
330 bufdesc.dwSize=sizeof(bufdesc);
332 bufdesc.dwBufferBytes=0;
333 bufdesc.dwReserved=0;
334 bufdesc.lpwfxFormat=&wfx;
335 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
336 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
338 ref=IDirectSoundCaptureBuffer_Release(dscbo);
339 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
342 for (f=0;f<NB_FORMATS;f++) {
344 init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
345 ZeroMemory(&bufdesc, sizeof(bufdesc));
346 bufdesc.dwSize=sizeof(bufdesc);
348 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
349 bufdesc.dwReserved=0;
350 bufdesc.lpwfxFormat=&wfx;
351 trace(" Testing the capture buffer at %ldx%dx%d\n",
352 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
353 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
354 ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc);
356 test_capture_buffer(dsco, dscbo, winetest_interactive);
357 ref=IDirectSoundCaptureBuffer_Release(dscbo);
358 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
362 /* Try an invalid format to test error handling */
364 init_format(&wfx,2000000,16,2);
365 ZeroMemory(&bufdesc, sizeof(bufdesc));
366 bufdesc.dwSize=sizeof(bufdesc);
367 bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
368 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
369 bufdesc.dwReserved=0;
370 bufdesc.lpwfxFormat=&wfx;
371 trace(" Testing the capture buffer at %ldx%dx%d\n",
372 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
373 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
374 ok(rc!=DS_OK,"CreateCaptureBuffer should have failed at 2 MHz 0x%lx\n",rc);
379 ref=IDirectSoundCapture_Release(dsco);
380 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
386 static void capture_tests()
389 rc=DirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
390 ok(rc==DS_OK,"DirectSoundCaptureEnumerate failed: %ld\n",rc);