2 * Unit tests for dsound functions
4 * Copyright (c) 2002 Francois Gouget
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSSTRUCT
22 #define NONAMELESSUNION
28 #include "wine/test.h"
33 static const unsigned int formats[][3]={
59 #define NB_FORMATS (sizeof(formats)/sizeof(*formats))
61 /* The time slice determines how often we will service the buffer and the
62 * buffer will be four time slices long
64 #define TIME_SLICE 100
65 #define BUFFER_LEN (4*TIME_SLICE)
66 #define TONE_DURATION (6*TIME_SLICE)
68 /* This test can play a test tone. But this only makes sense if someone
69 * is going to carefully listen to it, and would only bother everyone else.
70 * So this is only done if the test is being run in interactive mode.
73 #define PI 3.14159265358979323846
74 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
81 nb_samples=(int)(duration*wfx->nSamplesPerSec);
82 *size=nb_samples*wfx->nBlockAlign;
84 for (i=0;i<nb_samples;i++) {
85 double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
86 if (wfx->wBitsPerSample==8) {
87 unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
89 if (wfx->nChannels==2)
92 signed short sample=(signed short)((double)32767.5*y-0.5);
96 if (wfx->nChannels==2) {
106 static HWND get_hwnd()
108 HWND hwnd=GetForegroundWindow();
110 hwnd=GetDesktopWindow();
114 static void init_format(WAVEFORMATEX* wfx, int rate, int depth, int channels)
116 wfx->wFormatTag=WAVE_FORMAT_PCM;
117 wfx->nChannels=channels;
118 wfx->wBitsPerSample=depth;
119 wfx->nSamplesPerSec=rate;
120 wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
121 wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
129 LPDIRECTSOUNDBUFFER dsbo;
138 static int buffer_refill(play_state_t* state, DWORD size)
144 if (size>state->wave_len-state->written)
145 size=state->wave_len-state->written;
147 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
148 &ptr1,&len1,&ptr2,&len2,0);
149 ok(rc==DS_OK,"Lock: 0x%lx",rc);
153 memcpy(ptr1,state->wave+state->written,len1);
154 state->written+=len1;
156 memcpy(ptr2,state->wave+state->written,len2);
157 state->written+=len2;
159 state->offset=state->written % state->buffer_size;
160 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
161 ok(rc==DS_OK,"Unlock: 0x%lx",rc);
167 static int buffer_silence(play_state_t* state, DWORD size)
174 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
175 &ptr1,&len1,&ptr2,&len2,0);
176 ok(rc==DS_OK,"Lock: 0x%lx",rc);
180 s=(state->wfx->wBitsPerSample==8?0x80:0);
185 state->offset=(state->offset+size) % state->buffer_size;
186 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
187 ok(rc==DS_OK,"Unlock: 0x%lx",rc);
193 static int buffer_service(play_state_t* state)
195 DWORD play_pos,write_pos,buf_free;
198 rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,&write_pos);
199 ok(rc==DS_OK,"GetCurrentPosition: %lx",rc);
204 /* Refill the buffer */
205 if (state->offset<=play_pos) {
206 buf_free=play_pos-state->offset;
208 buf_free=state->buffer_size-state->offset+play_pos;
210 if (winetest_debug > 1)
211 trace("buf pos=%ld free=%ld written=%ld / %ld\n",
212 play_pos,buf_free,state->written,state->wave_len);
216 if (state->written<state->wave_len) {
217 int w=buffer_refill(state,buf_free);
221 if (state->written==state->wave_len) {
222 state->last_pos=(state->offset<play_pos)?play_pos:0;
223 if (winetest_debug > 1)
224 trace("last sound byte at %ld\n",
225 (state->written % state->buffer_size));
228 if (state->last_pos!=0 && play_pos<state->last_pos) {
229 /* We wrapped around the end of the buffer */
232 if (state->last_pos==0 &&
233 play_pos>(state->written % state->buffer_size)) {
234 /* Now everything has been played */
240 /* Fill with silence */
241 if (winetest_debug > 1)
242 trace("writing %ld bytes of silence\n",buf_free);
243 if (buffer_silence(state,buf_free)==-1)
249 if (winetest_debug > 1)
250 trace("stopping playback\n");
251 rc=IDirectSoundBuffer_Stop(state->dsbo);
252 ok(rc==DS_OK,"Stop failed: rc=%ld",rc);
256 static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
257 int is_primary, int play, int buffer3d,
258 LPDIRECTSOUND3DLISTENER listener,
259 int move_listener, int move_sound)
263 WAVEFORMATEX wfx,wfx2;
264 DWORD size,status,freq;
267 /* DSOUND: Error: Invalid caps pointer */
268 rc=IDirectSoundBuffer_GetCaps(dsbo,0);
269 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
271 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
273 /* DSOUND: Error: Invalid caps pointer */
274 rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
275 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
277 dsbcaps.dwSize=sizeof(dsbcaps);
278 rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
279 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
281 trace(" Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
282 dsbcaps.dwBufferBytes);
285 /* Query the format size. Note that it may not match sizeof(wfx) */
287 rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
288 ok(rc==DS_OK && size!=0,
289 "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
292 rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
293 ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
295 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
296 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
297 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
300 /* DSOUND: Error: Invalid frequency buffer */
301 rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
302 ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
304 /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
305 rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
306 ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
307 (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
308 "GetFrequency failed: 0x%lx\n",rc);
310 ok(freq==wfx.nSamplesPerSec,
311 "The frequency returned by GetFrequency %ld does not match the format %ld\n",
312 freq,wfx.nSamplesPerSec);
315 /* DSOUND: Error: Invalid status pointer */
316 rc=IDirectSoundBuffer_GetStatus(dsbo,0);
317 ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
319 rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
320 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
322 trace(" status=0x%04lx\n",status);
326 /* We must call SetCooperativeLevel to be allowed to call SetFormat */
327 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
328 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
329 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
333 /* DSOUND: Error: Invalid format pointer */
334 rc=IDirectSoundBuffer_SetFormat(dsbo,0);
335 ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
337 init_format(&wfx2,11025,16,2);
338 rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
339 ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
341 /* There is no garantee that SetFormat will actually change the
342 * format to what we asked for. It depends on what the soundcard
343 * supports. So we must re-query the format.
345 rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
346 ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
348 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
349 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
350 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
353 /* Set the CooperativeLevel back to normal */
354 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
355 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
356 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
362 LPDIRECTSOUND3DBUFFER buffer=NULL;
363 DS3DBUFFER buffer_param;
364 DS3DLISTENER listener_param;
365 trace(" Playing 440Hz LA at %ldx%dx%d\n",
366 wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
369 /* We must call SetCooperativeLevel to be allowed to call Lock */
370 /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
371 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
372 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
377 LPDIRECTSOUNDBUFFER temp_buffer;
379 rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
380 ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
384 /* check the COM interface */
385 rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
386 ok(rc==DS_OK&&temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
387 ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
388 ref=IDirectSoundBuffer_Release(temp_buffer);
389 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
392 rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
393 ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
394 ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
395 ref=IDirectSoundBuffer_Release(temp_buffer);
396 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
398 #if 0 /* FIXME: this works on windows */
399 ref=IDirectSoundBuffer_Release(dsbo);
400 ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
402 rc=IDirectSound3DBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer,(LPVOID *)&dsbo);
403 ok(rc==DS_OK&&dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
406 /* DSOUND: Error: Invalid buffer */
407 rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
408 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
410 ZeroMemory(&buffer_param, sizeof(buffer_param));
412 /* DSOUND: Error: Invalid buffer */
413 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
414 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
416 buffer_param.dwSize=sizeof(buffer_param);
417 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
418 ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
420 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
421 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
422 ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
424 rc=IDirectSoundBuffer_SetVolume(dsbo,-300);
425 ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
427 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
428 trace(" volume=%ld\n",volume);
430 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
431 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
432 ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc);
435 if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
436 rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
437 ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc);
439 rc=IDirectSoundBuffer_SetPan(dsbo,0);
440 ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
442 rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
443 trace(" pan=%ld\n",pan);
445 /* DSOUND: Error: Buffer does not have CTRLPAN */
446 rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
447 ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc);
450 state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len);
454 state.buffer_size=dsbcaps.dwBufferBytes;
455 state.written=state.offset=0;
456 buffer_refill(&state,state.buffer_size);
458 rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
459 ok(rc==DS_OK,"Play: 0x%lx\n",rc);
461 rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
462 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
463 ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
464 "GetStatus: bad status: %lx",status);
467 ZeroMemory(&listener_param,sizeof(listener_param));
468 listener_param.dwSize=sizeof(listener_param);
469 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
470 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
472 listener_param.vPosition.x = -5.0;
474 listener_param.vPosition.x = 0.0;
475 listener_param.vPosition.y = 0.0;
476 listener_param.vPosition.z = 0.0;
477 rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
478 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
482 buffer_param.vPosition.x = 5.0;
484 buffer_param.vPosition.x = 0.0;
485 buffer_param.vPosition.y = 0.0;
486 buffer_param.vPosition.z = 0.0;
487 rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
488 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
491 while (buffer_service(&state)) {
492 WaitForSingleObject(GetCurrentProcess(),TIME_SLICE/2);
493 if (listener&&move_listener) {
494 listener_param.vPosition.x += 0.5;
495 rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
496 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
498 if (buffer3d&&move_sound) {
499 buffer_param.vPosition.x -= 0.5;
500 rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
501 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
505 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
506 rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
507 ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
512 /* Set the CooperativeLevel back to normal */
513 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
514 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
515 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
518 ref=IDirectSound3DBuffer_Release(buffer);
519 ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref);
524 static HRESULT test_secondary(LPGUID lpGuid, int play,
525 int has_3d, int has_3dbuffer,
526 int has_listener, int has_duplicate,
527 int move_listener, int move_sound)
530 LPDIRECTSOUND dso=NULL;
531 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
532 LPDIRECTSOUND3DLISTENER listener=NULL;
533 DSBUFFERDESC bufdesc;
538 /* Create the DirectSound object */
539 rc=DirectSoundCreate(lpGuid,&dso,NULL);
540 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
544 /* Get the device capabilities */
545 ZeroMemory(&dscaps, sizeof(dscaps));
546 dscaps.dwSize=sizeof(dscaps);
547 rc=IDirectSound_GetCaps(dso,&dscaps);
548 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
552 /* We must call SetCooperativeLevel before creating primary buffer */
553 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
554 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
555 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
559 ZeroMemory(&bufdesc, sizeof(bufdesc));
560 bufdesc.dwSize=sizeof(bufdesc);
561 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
563 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
565 bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
566 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
567 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a %sprimary buffer 0x%lx\n",has_3d?"3D ":"", rc);
568 if (rc==DS_OK&&primary!=NULL) {
570 rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
571 ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
572 ref=IDirectSoundBuffer_Release(primary);
573 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
574 if(rc==DS_OK&&listener!=NULL) {
575 DS3DLISTENER listener_param;
576 ZeroMemory(&listener_param,sizeof(listener_param));
577 /* DSOUND: Error: Invalid buffer */
578 rc=IDirectSound3DListener_GetAllParameters(listener,0);
579 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
581 /* DSOUND: Error: Invalid buffer */
582 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
583 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
585 listener_param.dwSize=sizeof(listener_param);
586 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
587 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
592 for (f=0;f<NB_FORMATS;f++) {
593 init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
595 ZeroMemory(&bufdesc, sizeof(bufdesc));
596 bufdesc.dwSize=sizeof(bufdesc);
597 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
599 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
601 bufdesc.dwFlags|=(DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
602 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
603 bufdesc.lpwfxFormat=&wfx;
604 trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
605 has_3dbuffer?"3D ":"",
606 has_duplicate?"duplicated ":"",
607 listener!=NULL||move_sound?"with ":"",
608 move_listener?"moving ":"",
609 listener!=NULL?"listener ":"",
610 listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
611 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
612 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
613 ok(rc==DS_OK&&secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
614 if (rc==DS_OK&&secondary!=NULL) {
616 LPDIRECTSOUNDBUFFER duplicated=NULL;
618 /* DSOUND: Error: Invalid source buffer */
619 rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
620 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
622 /* DSOUND: Error: Invalid dest buffer */
623 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
624 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
626 /* DSOUND: Error: Invalid source buffer */
627 rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
628 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
631 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
632 ok(rc==DS_OK&&duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
634 if (rc==DS_OK&&duplicated!=NULL) {
635 ref=IDirectSoundBuffer_Release(secondary);
636 ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
637 secondary=duplicated;
641 if (rc==DS_OK&&secondary!=NULL) {
642 test_buffer(dso,secondary,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound);
643 ref=IDirectSoundBuffer_Release(secondary);
644 ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
649 ref=IDirectSound3DListener_Release(listener);
650 ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
652 ref=IDirectSoundBuffer_Release(primary);
653 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
656 /* Set the CooperativeLevel back to normal */
657 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
658 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
659 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
662 ref=IDirectSound_Release(dso);
663 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
665 return DSERR_GENERIC;
670 static HRESULT test_dsound(LPGUID lpGuid)
673 LPDIRECTSOUND dso=NULL;
675 DWORD speaker_config, new_speaker_config;
678 /* DSOUND: Error: Invalid interface buffer */
679 rc=DirectSoundCreate(lpGuid,0,NULL);
680 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate should have failed: 0x%lx\n",rc);
682 /* Create the DirectSound object */
683 rc=DirectSoundCreate(lpGuid,&dso,NULL);
684 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
688 /* DSOUND: Error: Invalid caps buffer */
689 rc=IDirectSound_GetCaps(dso,0);
690 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
692 ZeroMemory(&dscaps, sizeof(dscaps));
694 /* DSOUND: Error: Invalid caps buffer */
695 rc=IDirectSound_GetCaps(dso,&dscaps);
696 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
698 dscaps.dwSize=sizeof(dscaps);
700 /* DSOUND: Running on a certified driver */
701 rc=IDirectSound_GetCaps(dso,&dscaps);
702 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
704 trace(" DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
705 dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
706 dscaps.dwMaxSecondarySampleRate);
709 rc=IDirectSound_GetSpeakerConfig(dso,0);
710 ok(rc==DSERR_INVALIDPARAM,"GetSpeakerConfig should have failed: 0x%lx\n",rc);
712 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
713 ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
715 trace(" DirectSound SpeakerConfig: 0x%08lx\n", speaker_config);
718 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,DSSPEAKER_GEOMETRY_WIDE);
719 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
720 ok(rc==DS_OK,"SetSpeakerConfig failed: 0x%lx\n",rc);
722 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
723 ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
725 ok(speaker_config==new_speaker_config,"SetSpeakerConfig failed to set speaker config: expected 0x%08lx, got 0x%08lx\n",
726 speaker_config,new_speaker_config);
729 /* Release the DirectSound object */
730 ref=IDirectSound_Release(dso);
731 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
733 return DSERR_GENERIC;
735 #if 0 /* FIXME: this works on windows */
736 /* Create a DirectSound object */
737 rc=DirectSoundCreate(lpGuid,&dso,NULL);
738 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
740 LPDIRECTSOUND dso1=NULL;
742 /* Create a second DirectSound object */
743 rc=DirectSoundCreate(lpGuid,&dso1,NULL);
744 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
746 /* Release the second DirectSound object */
747 ref=IDirectSound_Release(dso1);
748 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
749 ok(dso!=dso1,"DirectSound objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
752 /* Release the first DirectSound object */
753 ref=IDirectSound_Release(dso);
754 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
756 return DSERR_GENERIC;
764 static HRESULT test_primary(LPGUID lpGuid)
767 LPDIRECTSOUND dso=NULL;
768 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
769 DSBUFFERDESC bufdesc;
773 /* Create the DirectSound object */
774 rc=DirectSoundCreate(lpGuid,&dso,NULL);
775 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
779 /* Get the device capabilities */
780 ZeroMemory(&dscaps, sizeof(dscaps));
781 dscaps.dwSize=sizeof(dscaps);
782 rc=IDirectSound_GetCaps(dso,&dscaps);
783 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
787 /* DSOUND: Error: Invalid buffer description pointer */
788 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
789 ok(rc==DSERR_INVALIDPARAM,"CreateSoundBuffer should have failed: 0x%lx\n",rc);
791 /* DSOUND: Error: Invalid buffer description pointer */
792 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
793 ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
795 /* DSOUND: Error: Invalid buffer description pointer */
796 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
797 ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
799 ZeroMemory(&bufdesc, sizeof(bufdesc));
801 /* DSOUND: Error: Invalid size */
802 /* DSOUND: Error: Invalid buffer description */
803 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
804 ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,primary=0x%lx\n",rc,(DWORD)primary);
806 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
807 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
808 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
809 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
813 /* Testing the primary buffer */
815 ZeroMemory(&bufdesc, sizeof(bufdesc));
816 bufdesc.dwSize=sizeof(bufdesc);
817 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
818 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
819 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
820 if (rc==DS_OK&&primary!=NULL) {
821 /* Try to create a second primary buffer */
822 /* DSOUND: Error: The primary buffer already exists. Any changes made to the buffer description will be ignored. */
823 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
824 ok(rc==DS_OK&&second==primary,"CreateSoundBuffer should have returned original primary buffer: 0x%lx\n",rc);
825 ref=IDirectSoundBuffer_Release(second);
826 ok(ref==1,"IDirectSoundBuffer_Release primary has %d references, should have 1\n",ref);
827 /* Try to duplicate a primary buffer */
828 /* DSOUND: Error: Can't duplicate primary buffers */
829 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
831 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc);
832 test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
833 ref=IDirectSoundBuffer_Release(primary);
834 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
837 /* Set the CooperativeLevel back to normal */
838 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
839 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
840 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
843 ref=IDirectSound_Release(dso);
844 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
846 return DSERR_GENERIC;
851 static HRESULT test_primary_3d(LPGUID lpGuid)
854 LPDIRECTSOUND dso=NULL;
855 LPDIRECTSOUNDBUFFER primary=NULL;
856 DSBUFFERDESC bufdesc;
860 /* Create the DirectSound object */
861 rc=DirectSoundCreate(lpGuid,&dso,NULL);
862 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
866 /* Get the device capabilities */
867 ZeroMemory(&dscaps, sizeof(dscaps));
868 dscaps.dwSize=sizeof(dscaps);
869 rc=IDirectSound_GetCaps(dso,&dscaps);
870 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
874 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
875 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
876 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
877 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
882 ZeroMemory(&bufdesc, sizeof(bufdesc));
883 bufdesc.dwSize=sizeof(bufdesc);
884 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
885 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
886 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
887 if (rc==DS_OK&&primary!=NULL) {
888 ref=IDirectSoundBuffer_Release(primary);
889 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
891 ZeroMemory(&bufdesc, sizeof(bufdesc));
892 bufdesc.dwSize=sizeof(bufdesc);
893 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
894 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
895 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
896 if (rc==DS_OK&&primary!=NULL) {
897 test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
898 ref=IDirectSoundBuffer_Release(primary);
899 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
902 /* Set the CooperativeLevel back to normal */
903 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
904 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
905 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
908 ref=IDirectSound_Release(dso);
909 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
911 return DSERR_GENERIC;
916 static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
919 LPDIRECTSOUND dso=NULL;
920 LPDIRECTSOUNDBUFFER primary=NULL;
921 DSBUFFERDESC bufdesc;
925 /* Create the DirectSound object */
926 rc=DirectSoundCreate(lpGuid,&dso,NULL);
927 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
931 /* Get the device capabilities */
932 ZeroMemory(&dscaps, sizeof(dscaps));
933 dscaps.dwSize=sizeof(dscaps);
934 rc=IDirectSound_GetCaps(dso,&dscaps);
935 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
939 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
940 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
941 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
942 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
946 ZeroMemory(&bufdesc, sizeof(bufdesc));
947 bufdesc.dwSize=sizeof(bufdesc);
948 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
949 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
950 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
951 if (rc==DS_OK&&primary!=NULL) {
952 LPDIRECTSOUND3DLISTENER listener=NULL;
953 rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
954 ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
955 if (rc==DS_OK&&listener!=NULL) {
956 LPDIRECTSOUNDBUFFER temp_buffer=NULL;
958 /* Checking the COM interface */
959 rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
960 ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
961 ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
962 if(rc==DS_OK&&temp_buffer!=NULL) {
963 ref=IDirectSoundBuffer_Release(temp_buffer);
964 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
967 rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
968 ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
969 ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
970 ref=IDirectSoundBuffer_Release(temp_buffer);
971 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
973 /* Testing the buffer */
974 test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
977 /* Testing the reference counting */
978 ref=IDirectSound3DListener_Release(listener);
979 ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
982 /* Testing the reference counting */
983 ref=IDirectSoundBuffer_Release(primary);
984 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
988 ref=IDirectSound_Release(dso);
989 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
991 return DSERR_GENERIC;
996 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
997 LPCSTR lpcstrModule, LPVOID lpContext)
1001 trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
1002 rc=test_dsound(lpGuid);
1003 ok(rc==DS_OK,"DirectSound test failed\n");
1005 trace(" Testing the primary buffer\n");
1006 rc=test_primary(lpGuid);
1007 ok(rc==DS_OK,"Primary Buffer test failed\n");
1009 trace(" Testing 3D primary buffer\n");
1010 rc=test_primary_3d(lpGuid);
1011 ok(rc==DS_OK,"3D Primary Buffer test failed\n");
1013 trace(" Testing 3D primary buffer with listener\n");
1014 rc=test_primary_3d_with_listener(lpGuid);
1015 ok(rc==DS_OK,"3D Primary Buffer with listener test failed\n");
1017 /* Testing secondary buffers */
1018 test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0);
1019 test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0);
1021 /* Testing 3D secondary buffers */
1022 test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0);
1023 test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0);
1024 test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0);
1025 test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0);
1026 test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0);
1027 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0);
1028 test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0);
1029 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0);
1030 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1);
1031 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
1036 static void dsound_out_tests()
1039 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
1040 ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc);
1043 #define NOTIFICATIONS 5
1049 LPDIRECTSOUNDCAPTUREBUFFER dscbo;
1051 DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
1052 HANDLE event[NOTIFICATIONS];
1053 LPDIRECTSOUNDNOTIFY notify;
1063 static int capture_buffer_service(capture_state_t* state)
1068 DWORD capture_pos,read_pos;
1070 rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos);
1071 ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx\n",rc);
1075 rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0);
1076 ok(rc==DS_OK,"Lock failed: 0x%lx\n",rc);
1080 rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
1081 ok(rc==DS_OK,"Unlock failed: 0x%lx\n",rc);
1085 state->offset = (state->offset + state->size) % state->buffer_size;
1090 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
1091 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
1097 capture_state_t state;
1100 /* Private dsound.dll: Error: Invalid caps pointer */
1101 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
1102 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1104 /* Private dsound.dll: Error: Invalid caps pointer */
1106 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
1107 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1109 dscbcaps.dwSize=sizeof(dscbcaps);
1110 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
1111 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
1113 trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
1114 dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
1117 /* Query the format size. Note that it may not match sizeof(wfx) */
1118 /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must be non-NULL */
1119 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
1120 ok(rc==DSERR_INVALIDPARAM,
1121 "GetFormat should have returned an error: rc=0x%lx\n",rc);
1124 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
1125 ok(rc==DS_OK && size!=0,
1126 "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
1129 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
1130 ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
1132 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
1133 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
1134 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
1137 /* Private dsound.dll: Error: Invalid status pointer */
1138 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
1139 ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
1141 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
1142 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
1144 trace(" status=0x%04lx\n",status);
1147 ZeroMemory(&state, sizeof(state));
1150 state.buffer_size = dscbcaps.dwBufferBytes;
1151 for (i = 0; i < NOTIFICATIONS; i++)
1152 state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
1153 state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
1155 rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify));
1156 ok((rc==DS_OK)&&(state.notify!=NULL),"QueryInterface failed: 0x%lx\n",rc);
1160 for (i = 0; i < NOTIFICATIONS; i++) {
1161 state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
1162 state.posnotify[i].hEventNotify = state.event[i];
1165 rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify);
1166 ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx\n",rc);
1170 rc=IDirectSoundNotify_Release(state.notify);
1171 ok(rc==0,"Release: 0x%lx\n",rc);
1176 rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
1177 ok(rc==DS_OK,"Start: 0x%lx\n",rc);
1181 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
1182 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
1183 ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
1184 "GetStatus: bad status: %lx",status);
1188 /* wait for the notifications */
1189 for (i = 0; i < (NOTIFICATIONS * 2); i++) {
1190 rc=MsgWaitForMultipleObjects( NOTIFICATIONS, state.event, FALSE, 3000, QS_ALLEVENTS );
1191 ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
1192 if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
1193 ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),"Wrong notification: should be %d, got %ld\n",
1194 i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
1197 if (!capture_buffer_service(&state))
1201 rc=IDirectSoundCaptureBuffer_Stop(dscbo);
1202 ok(rc==DS_OK,"Stop: 0x%lx\n",rc);
1208 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1209 LPCSTR lpcstrModule, LPVOID lpContext)
1212 LPDIRECTSOUNDCAPTURE dsco=NULL;
1213 LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
1214 DSCBUFFERDESC bufdesc;
1219 /* Private dsound.dll: Error: Invalid interface buffer */
1220 trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
1221 rc=DirectSoundCaptureCreate(lpGuid,NULL,NULL);
1222 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx\n",rc);
1224 ref=IDirectSoundCapture_Release(dsco);
1225 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
1228 rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL);
1229 ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx\n",rc);
1233 /* Private dsound.dll: Error: Invalid caps buffer */
1234 rc=IDirectSoundCapture_GetCaps(dsco,NULL);
1235 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1237 /* Private dsound.dll: Error: Invalid caps buffer */
1239 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
1240 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1242 dsccaps.dwSize=sizeof(dsccaps);
1243 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
1244 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
1246 trace(" DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
1247 dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels);
1250 /* Private dsound.dll: Error: Invalid size */
1251 /* Private dsound.dll: Error: Invalid capture buffer description */
1252 ZeroMemory(&bufdesc, sizeof(bufdesc));
1255 bufdesc.dwBufferBytes=0;
1256 bufdesc.dwReserved=0;
1257 bufdesc.lpwfxFormat=NULL;
1258 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1259 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1261 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1262 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1265 /* Private dsound.dll: Error: Invalid buffer size */
1266 /* Private dsound.dll: Error: Invalid capture buffer description */
1267 ZeroMemory(&bufdesc, sizeof(bufdesc));
1268 bufdesc.dwSize=sizeof(bufdesc);
1270 bufdesc.dwBufferBytes=0;
1271 bufdesc.dwReserved=0;
1272 bufdesc.lpwfxFormat=NULL;
1273 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1274 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1276 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1277 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1280 /* Private dsound.dll: Error: Invalid buffer size */
1281 /* Private dsound.dll: Error: Invalid capture buffer description */
1282 ZeroMemory(&bufdesc, sizeof(bufdesc));
1283 ZeroMemory(&wfx, sizeof(wfx));
1284 bufdesc.dwSize=sizeof(bufdesc);
1286 bufdesc.dwBufferBytes=0;
1287 bufdesc.dwReserved=0;
1288 bufdesc.lpwfxFormat=&wfx;
1289 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1290 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1292 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1293 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1296 /* Private dsound.dll: Error: Invalid buffer size */
1297 /* Private dsound.dll: Error: Invalid capture buffer description */
1298 init_format(&wfx,11025,8,1);
1299 ZeroMemory(&bufdesc, sizeof(bufdesc));
1300 bufdesc.dwSize=sizeof(bufdesc);
1302 bufdesc.dwBufferBytes=0;
1303 bufdesc.dwReserved=0;
1304 bufdesc.lpwfxFormat=&wfx;
1305 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1306 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1308 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1309 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1312 for (f=0;f<NB_FORMATS;f++) {
1314 init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
1315 ZeroMemory(&bufdesc, sizeof(bufdesc));
1316 bufdesc.dwSize=sizeof(bufdesc);
1318 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
1319 bufdesc.dwReserved=0;
1320 bufdesc.lpwfxFormat=&wfx;
1321 trace(" Testing the capture buffer at %ldx%dx%d\n",
1322 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
1323 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1324 ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc);
1326 test_capture_buffer(dsco, dscbo, winetest_interactive);
1327 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1328 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1332 /* Try an invalid format to test error handling */
1334 init_format(&wfx,2000000,16,2);
1335 ZeroMemory(&bufdesc, sizeof(bufdesc));
1336 bufdesc.dwSize=sizeof(bufdesc);
1337 bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
1338 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
1339 bufdesc.dwReserved=0;
1340 bufdesc.lpwfxFormat=&wfx;
1341 trace(" Testing the capture buffer at %ldx%dx%d\n",
1342 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
1343 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1344 ok(rc!=DS_OK,"CreateCaptureBuffer should have failed at 2 MHz 0x%lx\n",rc);
1349 ref=IDirectSoundCapture_Release(dsco);
1350 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
1356 static void dsound_in_tests()
1359 rc=DirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
1360 ok(rc==DS_OK,"DirectSoundCaptureEnumerate failed: %ld\n",rc);