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 static const unsigned int formats[][3]={
63 #define NB_FORMATS (sizeof(formats)/sizeof(*formats))
65 #define NOTIFICATIONS 5
67 static void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth, int channels)
69 wfx->wFormatTag=format;
70 wfx->nChannels=channels;
71 wfx->wBitsPerSample=depth;
72 wfx->nSamplesPerSec=rate;
73 wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
74 if (wfx->nBlockAlign==0) /* align compressed formats to byte boundry */
76 wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nChannels*wfx->wBitsPerSample/8;
80 static char * format_string(WAVEFORMATEX* wfx)
84 sprintf(str, "%ldx%dx%d %s",
85 wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels,
86 wfx->wFormatTag == WAVE_FORMAT_PCM ? "PCM" :
87 wfx->wFormatTag == WAVE_FORMAT_MULAW ? "MULAW" :
88 wfx->wFormatTag == WAVE_FORMAT_IMA_ADPCM ? "IMA ADPCM" : "Unknown");
97 LPDIRECTSOUNDCAPTUREBUFFER dscbo;
99 DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
100 HANDLE event[NOTIFICATIONS];
101 LPDIRECTSOUNDNOTIFY notify;
111 static int capture_buffer_service(capture_state_t* state)
116 DWORD capture_pos,read_pos;
118 rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos);
119 ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
123 rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0);
124 ok(rc==DS_OK,"Lock failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
128 rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
129 ok(rc==DS_OK,"Unlock failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
133 state->offset = (state->offset + state->size) % state->buffer_size;
138 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
139 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
145 capture_state_t state;
148 /* Private dsound.dll: Error: Invalid caps pointer */
149 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
150 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
152 /* Private dsound.dll: Error: Invalid caps pointer */
154 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
155 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
157 dscbcaps.dwSize=sizeof(dscbcaps);
158 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
159 ok(rc==DS_OK,"GetCaps failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
161 trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
162 dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
165 /* Query the format size. Note that it may not match sizeof(wfx) */
166 /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must be non-NULL */
167 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
168 ok(rc==DSERR_INVALIDPARAM,
169 "GetFormat should have returned an error: rc=0x%lx(%s)\n",rc,DXGetErrorString9(rc));
172 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
173 ok(rc==DS_OK && size!=0,
174 "GetFormat should have returned the needed size: rc=0x%lx(%s) size=%ld\n",
175 rc,DXGetErrorString9(rc),size);
177 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
178 ok(rc==DS_OK,"GetFormat failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
180 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
181 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
182 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
185 /* Private dsound.dll: Error: Invalid status pointer */
186 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
187 ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
189 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
190 ok(rc==DS_OK,"GetStatus failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
192 trace(" status=0x%04lx\n",status);
195 ZeroMemory(&state, sizeof(state));
198 state.buffer_size = dscbcaps.dwBufferBytes;
199 for (i = 0; i < NOTIFICATIONS; i++)
200 state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
201 state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
203 rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify));
204 ok((rc==DS_OK)&&(state.notify!=NULL),"QueryInterface failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
208 for (i = 0; i < NOTIFICATIONS; i++) {
209 state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
210 state.posnotify[i].hEventNotify = state.event[i];
213 rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify);
214 ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
218 rc=IDirectSoundNotify_Release(state.notify);
219 ok(rc==0,"Release: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
224 rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
225 ok(rc==DS_OK,"Start: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
229 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
230 ok(rc==DS_OK,"GetStatus failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
231 ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
232 "GetStatus: bad status: %lx\n",status);
236 /* wait for the notifications */
237 for (i = 0; i < (NOTIFICATIONS * 2); i++) {
238 rc=MsgWaitForMultipleObjects( NOTIFICATIONS, state.event, FALSE, 3000, QS_ALLEVENTS );
239 ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
240 if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
241 ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),"Wrong notification: should be %d, got %ld\n",
242 i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
244 if (!capture_buffer_service(&state))
248 rc=IDirectSoundCaptureBuffer_Stop(dscbo);
249 ok(rc==DS_OK,"Stop: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
255 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
256 LPCSTR lpcstrModule, LPVOID lpContext)
259 LPDIRECTSOUNDCAPTURE dsco=NULL;
260 LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
261 DSCBUFFERDESC bufdesc;
266 /* Private dsound.dll: Error: Invalid interface buffer */
267 trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
268 rc=DirectSoundCaptureCreate(lpGuid,NULL,NULL);
269 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
271 ref=IDirectSoundCapture_Release(dsco);
272 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
275 rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL);
276 ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
280 /* Private dsound.dll: Error: Invalid caps buffer */
281 rc=IDirectSoundCapture_GetCaps(dsco,NULL);
282 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
284 /* Private dsound.dll: Error: Invalid caps buffer */
286 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
287 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
289 dsccaps.dwSize=sizeof(dsccaps);
290 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
291 ok(rc==DS_OK,"GetCaps failed: 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
293 trace(" DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
294 dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels);
297 /* Private dsound.dll: Error: Invalid size */
298 /* Private dsound.dll: Error: Invalid capture buffer description */
299 ZeroMemory(&bufdesc, sizeof(bufdesc));
302 bufdesc.dwBufferBytes=0;
303 bufdesc.dwReserved=0;
304 bufdesc.lpwfxFormat=NULL;
305 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
306 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
308 ref=IDirectSoundCaptureBuffer_Release(dscbo);
309 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
312 /* Private dsound.dll: Error: Invalid buffer size */
313 /* Private dsound.dll: Error: Invalid capture buffer description */
314 ZeroMemory(&bufdesc, sizeof(bufdesc));
315 bufdesc.dwSize=sizeof(bufdesc);
317 bufdesc.dwBufferBytes=0;
318 bufdesc.dwReserved=0;
319 bufdesc.lpwfxFormat=NULL;
320 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
321 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
323 ref=IDirectSoundCaptureBuffer_Release(dscbo);
324 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
327 /* Private dsound.dll: Error: Invalid buffer size */
328 /* Private dsound.dll: Error: Invalid capture buffer description */
329 ZeroMemory(&bufdesc, sizeof(bufdesc));
330 ZeroMemory(&wfx, sizeof(wfx));
331 bufdesc.dwSize=sizeof(bufdesc);
333 bufdesc.dwBufferBytes=0;
334 bufdesc.dwReserved=0;
335 bufdesc.lpwfxFormat=&wfx;
336 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
337 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
339 ref=IDirectSoundCaptureBuffer_Release(dscbo);
340 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
343 /* Private dsound.dll: Error: Invalid buffer size */
344 /* Private dsound.dll: Error: Invalid capture buffer description */
345 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
346 ZeroMemory(&bufdesc, sizeof(bufdesc));
347 bufdesc.dwSize=sizeof(bufdesc);
349 bufdesc.dwBufferBytes=0;
350 bufdesc.dwReserved=0;
351 bufdesc.lpwfxFormat=&wfx;
352 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
353 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
355 ref=IDirectSoundCaptureBuffer_Release(dscbo);
356 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
359 for (f=0;f<NB_FORMATS;f++) {
361 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],formats[f][2]);
362 ZeroMemory(&bufdesc, sizeof(bufdesc));
363 bufdesc.dwSize=sizeof(bufdesc);
365 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
366 bufdesc.dwReserved=0;
367 bufdesc.lpwfxFormat=&wfx;
368 trace(" Testing the capture buffer at %s\n", format_string(&wfx));
369 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
370 ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
372 test_capture_buffer(dsco, dscbo, winetest_interactive);
373 ref=IDirectSoundCaptureBuffer_Release(dscbo);
374 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
378 /* try a non PCM format */
380 init_format(&wfx,WAVE_FORMAT_MULAW,8000,8,1);
381 ZeroMemory(&bufdesc, sizeof(bufdesc));
382 bufdesc.dwSize=sizeof(bufdesc);
383 bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
384 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
385 bufdesc.dwReserved=0;
386 bufdesc.lpwfxFormat=&wfx;
387 trace(" Testing the capture buffer at %s\n", format_string(&wfx));
388 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
389 ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
390 if ((rc==DS_OK)&&(dscbo!=NULL)) {
391 test_capture_buffer(dsco, dscbo, winetest_interactive);
392 ref=IDirectSoundCaptureBuffer_Release(dscbo);
393 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
397 /* Try an invalid format to test error handling */
399 init_format(&wfx,WAVE_FORMAT_PCM,2000000,16,2);
400 ZeroMemory(&bufdesc, sizeof(bufdesc));
401 bufdesc.dwSize=sizeof(bufdesc);
402 bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
403 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
404 bufdesc.dwReserved=0;
405 bufdesc.lpwfxFormat=&wfx;
406 trace(" Testing the capture buffer at %s\n", format_string(&wfx));
407 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
408 ok(rc!=DS_OK,"CreateCaptureBuffer should have failed at 2 MHz 0x%lx(%s)\n",rc,DXGetErrorString9(rc));
413 ref=IDirectSoundCapture_Release(dsco);
414 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
420 static void capture_tests()
423 rc=DirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
424 ok(rc==DS_OK,"DirectSoundCaptureEnumerate failed: 0x%08lx(%s)\n",rc,DXGetErrorString9(rc));