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 #ifndef DSBCAPS_CTRLDEFAULT
34 #define DSBCAPS_CTRLDEFAULT 0x000000E0
37 static const unsigned int formats[][3]={
63 #define NB_FORMATS (sizeof(formats)/sizeof(*formats))
65 /* The time slice determines how often we will service the buffer and the
66 * buffer will be four time slices long
68 #define TIME_SLICE 100
69 #define BUFFER_LEN (4*TIME_SLICE)
70 #define TONE_DURATION (6*TIME_SLICE)
72 /* This test can play a test tone. But this only makes sense if someone
73 * is going to carefully listen to it, and would only bother everyone else.
74 * So this is only done if the test is being run in interactive mode.
77 #define PI 3.14159265358979323846
78 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
85 nb_samples=(int)(duration*wfx->nSamplesPerSec);
86 *size=nb_samples*wfx->nBlockAlign;
88 for (i=0;i<nb_samples;i++) {
89 double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
90 if (wfx->wBitsPerSample==8) {
91 unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
93 if (wfx->nChannels==2)
96 signed short sample=(signed short)((double)32767.5*y-0.5);
100 if (wfx->nChannels==2) {
110 static HWND get_hwnd()
112 HWND hwnd=GetForegroundWindow();
114 hwnd=GetDesktopWindow();
118 static void init_format(WAVEFORMATEX* wfx, int rate, int depth, int channels)
120 wfx->wFormatTag=WAVE_FORMAT_PCM;
121 wfx->nChannels=channels;
122 wfx->wBitsPerSample=depth;
123 wfx->nSamplesPerSec=rate;
124 wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
125 wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
133 LPDIRECTSOUNDBUFFER dsbo;
142 static int buffer_refill(play_state_t* state, DWORD size)
148 if (size>state->wave_len-state->written)
149 size=state->wave_len-state->written;
151 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
152 &ptr1,&len1,&ptr2,&len2,0);
153 ok(rc==DS_OK,"Lock: 0x%lx",rc);
157 memcpy(ptr1,state->wave+state->written,len1);
158 state->written+=len1;
160 memcpy(ptr2,state->wave+state->written,len2);
161 state->written+=len2;
163 state->offset=state->written % state->buffer_size;
164 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
165 ok(rc==DS_OK,"Unlock: 0x%lx",rc);
171 static int buffer_silence(play_state_t* state, DWORD size)
178 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
179 &ptr1,&len1,&ptr2,&len2,0);
180 ok(rc==DS_OK,"Lock: 0x%lx",rc);
184 s=(state->wfx->wBitsPerSample==8?0x80:0);
189 state->offset=(state->offset+size) % state->buffer_size;
190 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
191 ok(rc==DS_OK,"Unlock: 0x%lx",rc);
197 static int buffer_service(play_state_t* state)
199 DWORD play_pos,write_pos,buf_free;
202 rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,&write_pos);
203 ok(rc==DS_OK,"GetCurrentPosition: %lx",rc);
208 /* Refill the buffer */
209 if (state->offset<=play_pos) {
210 buf_free=play_pos-state->offset;
212 buf_free=state->buffer_size-state->offset+play_pos;
214 if (winetest_debug > 1)
215 trace("buf pos=%ld free=%ld written=%ld / %ld\n",
216 play_pos,buf_free,state->written,state->wave_len);
220 if (state->written<state->wave_len) {
221 int w=buffer_refill(state,buf_free);
225 if (state->written==state->wave_len) {
226 state->last_pos=(state->offset<play_pos)?play_pos:0;
227 if (winetest_debug > 1)
228 trace("last sound byte at %ld\n",
229 (state->written % state->buffer_size));
232 if (state->last_pos!=0 && play_pos<state->last_pos) {
233 /* We wrapped around the end of the buffer */
236 if (state->last_pos==0 &&
237 play_pos>(state->written % state->buffer_size)) {
238 /* Now everything has been played */
244 /* Fill with silence */
245 if (winetest_debug > 1)
246 trace("writing %ld bytes of silence\n",buf_free);
247 if (buffer_silence(state,buf_free)==-1)
253 if (winetest_debug > 1)
254 trace("stopping playback\n");
255 rc=IDirectSoundBuffer_Stop(state->dsbo);
256 ok(rc==DS_OK,"Stop failed: rc=%ld",rc);
260 static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
261 int is_primary, int play, int buffer3d,
262 LPDIRECTSOUND3DLISTENER listener,
263 int move_listener, int move_sound)
267 WAVEFORMATEX wfx,wfx2;
268 DWORD size,status,freq;
271 /* DSOUND: Error: Invalid caps pointer */
272 rc=IDirectSoundBuffer_GetCaps(dsbo,0);
273 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
275 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
277 /* DSOUND: Error: Invalid caps pointer */
278 rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
279 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
281 dsbcaps.dwSize=sizeof(dsbcaps);
282 rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
283 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
285 trace(" Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
286 dsbcaps.dwBufferBytes);
289 /* Query the format size. Note that it may not match sizeof(wfx) */
291 rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
292 ok(rc==DS_OK && size!=0,
293 "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
296 rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
297 ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
299 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
300 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
301 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
304 /* DSOUND: Error: Invalid frequency buffer */
305 rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
306 ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
308 /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
309 rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
310 ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary),
311 "GetFrequency failed: 0x%lx\n",rc);
313 ok(freq==wfx.nSamplesPerSec,
314 "The frequency returned by GetFrequency %ld does not match the format %ld\n",
315 freq,wfx.nSamplesPerSec);
318 /* DSOUND: Error: Invalid status pointer */
319 rc=IDirectSoundBuffer_GetStatus(dsbo,0);
320 ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
322 rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
323 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
325 trace(" status=0x%04lx\n",status);
329 /* We must call SetCooperativeLevel to be allowed to call SetFormat */
330 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
331 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
332 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
336 /* DSOUND: Error: Invalid format pointer */
337 rc=IDirectSoundBuffer_SetFormat(dsbo,0);
338 ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
340 init_format(&wfx2,11025,16,2);
341 rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
342 ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
344 /* There is no garantee that SetFormat will actually change the
345 * format to what we asked for. It depends on what the soundcard
346 * supports. So we must re-query the format.
348 rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
349 ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
351 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
352 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
353 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
356 /* Set the CooperativeLevel back to normal */
357 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
358 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
359 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
365 LPDIRECTSOUND3DBUFFER buffer=NULL;
366 DS3DBUFFER buffer_param;
367 DS3DLISTENER listener_param;
368 trace(" Playing 440Hz LA at %ldx%dx%d\n",
369 wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
372 /* We must call SetCooperativeLevel to be allowed to call Lock */
373 /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
374 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
375 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
380 LPDIRECTSOUNDBUFFER temp_buffer;
382 rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
383 ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
387 /* check the COM interface */
388 rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
389 ok(rc==DS_OK&&temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
390 ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
391 ref=IDirectSoundBuffer_Release(temp_buffer);
392 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
395 rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
396 ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
397 ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
398 ref=IDirectSoundBuffer_Release(temp_buffer);
399 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
401 #if 0 /* FIXME: this works on windows */
402 ref=IDirectSoundBuffer_Release(dsbo);
403 ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
405 rc=IDirectSound3DBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer,(LPVOID *)&dsbo);
406 ok(rc==DS_OK&&dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
409 /* DSOUND: Error: Invalid buffer */
410 rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
411 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
413 ZeroMemory(&buffer_param, sizeof(buffer_param));
415 /* DSOUND: Error: Invalid buffer */
416 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
417 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
419 buffer_param.dwSize=sizeof(buffer_param);
420 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
421 ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
423 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
424 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
425 ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
427 rc=IDirectSoundBuffer_SetVolume(dsbo,-300);
428 ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
431 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
432 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
433 ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary),"GetVolume failed: 0x%lx\n",rc);
435 trace(" volume=%ld\n",volume);
438 state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len);
442 state.buffer_size=dsbcaps.dwBufferBytes;
443 state.written=state.offset=0;
444 buffer_refill(&state,state.buffer_size);
446 rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
447 ok(rc==DS_OK,"Play: 0x%lx\n",rc);
449 rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
450 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
451 ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
452 "GetStatus: bad status: %lx",status);
455 ZeroMemory(&listener_param,sizeof(listener_param));
456 listener_param.dwSize=sizeof(listener_param);
457 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
458 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
460 listener_param.vPosition.x = -5.0;
462 listener_param.vPosition.x = 0.0;
463 listener_param.vPosition.y = 0.0;
464 listener_param.vPosition.z = 0.0;
465 rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
466 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
470 buffer_param.vPosition.x = 5.0;
472 buffer_param.vPosition.x = 0.0;
473 buffer_param.vPosition.y = 0.0;
474 buffer_param.vPosition.z = 0.0;
475 rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
476 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
479 while (buffer_service(&state)) {
480 WaitForSingleObject(GetCurrentProcess(),TIME_SLICE/2);
481 if (listener&&move_listener) {
482 listener_param.vPosition.x += 0.5;
483 rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
484 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
486 if (buffer3d&&move_sound) {
487 buffer_param.vPosition.x -= 0.5;
488 rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
489 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
493 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
494 rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
495 ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
500 /* Set the CooperativeLevel back to normal */
501 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
502 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
503 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
506 ref=IDirectSound3DBuffer_Release(buffer);
507 ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref);
512 static HRESULT test_secondary(LPGUID lpGuid, int play,
513 int has_3d, int has_3dbuffer,
514 int has_listener, int has_duplicate,
515 int move_listener, int move_sound)
518 LPDIRECTSOUND dso=NULL;
519 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
520 LPDIRECTSOUND3DLISTENER listener=NULL;
521 DSBUFFERDESC bufdesc;
526 /* Create the DirectSound object */
527 rc=DirectSoundCreate(lpGuid,&dso,NULL);
528 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
532 /* Get the device capabilities */
533 ZeroMemory(&dscaps, sizeof(dscaps));
534 dscaps.dwSize=sizeof(dscaps);
535 rc=IDirectSound_GetCaps(dso,&dscaps);
536 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
540 /* We must call SetCooperativeLevel before creating primary buffer */
541 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
542 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
543 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
547 ZeroMemory(&bufdesc, sizeof(bufdesc));
548 bufdesc.dwSize=sizeof(bufdesc);
549 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
551 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
552 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
553 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a %sprimary buffer 0x%lx\n",has_3d?"3D ":"", rc);
554 if (rc==DS_OK&&primary!=NULL) {
556 rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
557 ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
558 ref=IDirectSoundBuffer_Release(primary);
559 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
560 if(rc==DS_OK&&listener!=NULL) {
561 DS3DLISTENER listener_param;
562 ZeroMemory(&listener_param,sizeof(listener_param));
563 /* DSOUND: Error: Invalid buffer */
564 rc=IDirectSound3DListener_GetAllParameters(listener,0);
565 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
567 /* DSOUND: Error: Invalid buffer */
568 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
569 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
571 listener_param.dwSize=sizeof(listener_param);
572 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
573 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
578 for (f=0;f<NB_FORMATS;f++) {
579 init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
581 ZeroMemory(&bufdesc, sizeof(bufdesc));
582 bufdesc.dwSize=sizeof(bufdesc);
583 bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRL3D;
585 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
586 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
587 bufdesc.lpwfxFormat=&wfx;
588 trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
589 has_3dbuffer?"3D ":"",
590 has_duplicate?"duplicated ":"",
591 listener!=NULL||move_sound?"with ":"",
592 move_listener?"moving ":"",
593 listener!=NULL?"listener ":"",
594 listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
595 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
596 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
597 ok(rc==DS_OK&&secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
598 if (rc==DS_OK&&secondary!=NULL) {
600 LPDIRECTSOUNDBUFFER duplicated=NULL;
602 /* DSOUND: Error: Invalid source buffer */
603 rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
604 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
606 /* DSOUND: Error: Invalid dest buffer */
607 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
608 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
610 /* DSOUND: Error: Invalid source buffer */
611 rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
612 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
615 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
616 ok(rc==DS_OK&&duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
618 if (rc==DS_OK&&duplicated!=NULL) {
619 ref=IDirectSoundBuffer_Release(secondary);
620 ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
621 secondary=duplicated;
625 if (rc==DS_OK&&secondary!=NULL) {
626 test_buffer(dso,secondary,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound);
627 ref=IDirectSoundBuffer_Release(secondary);
628 ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
633 ref=IDirectSound3DListener_Release(listener);
634 ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
636 ref=IDirectSoundBuffer_Release(primary);
637 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
640 /* Set the CooperativeLevel back to normal */
641 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
642 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
643 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
646 ref=IDirectSound_Release(dso);
647 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
649 return DSERR_GENERIC;
654 static HRESULT test_dsound(LPGUID lpGuid)
657 LPDIRECTSOUND dso=NULL;
659 DWORD speaker_config, new_speaker_config;
662 /* DSOUND: Error: Invalid interface buffer */
663 rc=DirectSoundCreate(lpGuid,0,NULL);
664 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate should have failed: 0x%lx\n",rc);
666 /* Create the DirectSound object */
667 rc=DirectSoundCreate(lpGuid,&dso,NULL);
668 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
672 /* DSOUND: Error: Invalid caps buffer */
673 rc=IDirectSound_GetCaps(dso,0);
674 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
676 ZeroMemory(&dscaps, sizeof(dscaps));
678 /* DSOUND: Error: Invalid caps buffer */
679 rc=IDirectSound_GetCaps(dso,&dscaps);
680 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
682 dscaps.dwSize=sizeof(dscaps);
684 /* DSOUND: Running on a certified driver */
685 rc=IDirectSound_GetCaps(dso,&dscaps);
686 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
688 trace(" DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
689 dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
690 dscaps.dwMaxSecondarySampleRate);
693 rc=IDirectSound_GetSpeakerConfig(dso,0);
694 ok(rc==DSERR_INVALIDPARAM,"GetSpeakerConfig should have failed: 0x%lx\n",rc);
696 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
697 ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
699 trace(" DirectSound SpeakerConfig: 0x%08lx\n", speaker_config);
702 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,DSSPEAKER_GEOMETRY_WIDE);
703 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
704 ok(rc==DS_OK,"SetSpeakerConfig failed: 0x%lx\n",rc);
706 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
707 ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
709 ok(speaker_config==new_speaker_config,"SetSpeakerConfig failed to set speaker config: expected 0x%08lx, got 0x%08lx\n",
710 speaker_config,new_speaker_config);
713 /* Release the DirectSound object */
714 ref=IDirectSound_Release(dso);
715 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
717 return DSERR_GENERIC;
719 #if 0 /* FIXME: this works on windows */
720 /* Create a DirectSound object */
721 rc=DirectSoundCreate(lpGuid,&dso,NULL);
722 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
724 LPDIRECTSOUND dso1=NULL;
726 /* Create a second DirectSound object */
727 rc=DirectSoundCreate(lpGuid,&dso1,NULL);
728 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
730 /* Release the second DirectSound object */
731 ref=IDirectSound_Release(dso1);
732 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
733 ok(dso!=dso1,"DirectSound objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
736 /* Release the first DirectSound object */
737 ref=IDirectSound_Release(dso);
738 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
740 return DSERR_GENERIC;
748 static HRESULT test_primary(LPGUID lpGuid)
751 LPDIRECTSOUND dso=NULL;
752 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
753 DSBUFFERDESC bufdesc;
757 /* Create the DirectSound object */
758 rc=DirectSoundCreate(lpGuid,&dso,NULL);
759 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
763 /* Get the device capabilities */
764 ZeroMemory(&dscaps, sizeof(dscaps));
765 dscaps.dwSize=sizeof(dscaps);
766 rc=IDirectSound_GetCaps(dso,&dscaps);
767 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
771 /* DSOUND: Error: Invalid buffer description pointer */
772 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
773 ok(rc==DSERR_INVALIDPARAM,"CreateSoundBuffer should have failed: 0x%lx\n",rc);
775 /* DSOUND: Error: Invalid buffer description pointer */
776 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
777 ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
779 /* DSOUND: Error: Invalid buffer description pointer */
780 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
781 ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
783 ZeroMemory(&bufdesc, sizeof(bufdesc));
785 /* DSOUND: Error: Invalid size */
786 /* DSOUND: Error: Invalid buffer description */
787 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
788 ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,primary=0x%lx\n",rc,(DWORD)primary);
790 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
791 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
792 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
793 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
797 /* Testing the primary buffer */
799 ZeroMemory(&bufdesc, sizeof(bufdesc));
800 bufdesc.dwSize=sizeof(bufdesc);
801 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
802 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
803 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
804 if (rc==DS_OK&&primary!=NULL) {
805 /* Try to create a second primary buffer */
806 /* DSOUND: Error: The primary buffer already exists. Any changes made to the buffer description will be ignored. */
807 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
808 ok(rc==DS_OK&&second==primary,"CreateSoundBuffer should have returned original primary buffer: 0x%lx\n",rc);
809 ref=IDirectSoundBuffer_Release(second);
810 ok(ref==1,"IDirectSoundBuffer_Release primary has %d references, should have 1\n",ref);
811 /* Try to duplicate a primary buffer */
812 /* DSOUND: Error: Can't duplicate primary buffers */
813 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
815 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc);
816 test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
817 ref=IDirectSoundBuffer_Release(primary);
818 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
820 /* Set the CooperativeLevel back to normal */
821 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
822 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
823 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
826 ref=IDirectSound_Release(dso);
827 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
829 return DSERR_GENERIC;
834 static HRESULT test_primary_3d(LPGUID lpGuid)
837 LPDIRECTSOUND dso=NULL;
838 LPDIRECTSOUNDBUFFER primary=NULL;
839 DSBUFFERDESC bufdesc;
843 /* Create the DirectSound object */
844 rc=DirectSoundCreate(lpGuid,&dso,NULL);
845 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
849 /* Get the device capabilities */
850 ZeroMemory(&dscaps, sizeof(dscaps));
851 dscaps.dwSize=sizeof(dscaps);
852 rc=IDirectSound_GetCaps(dso,&dscaps);
853 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
857 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
858 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
859 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
860 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
864 ZeroMemory(&bufdesc, sizeof(bufdesc));
865 bufdesc.dwSize=sizeof(bufdesc);
866 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
867 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
868 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
869 if (rc==DS_OK&&primary!=NULL) {
870 ref=IDirectSoundBuffer_Release(primary);
871 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
873 ZeroMemory(&bufdesc, sizeof(bufdesc));
874 bufdesc.dwSize=sizeof(bufdesc);
875 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
876 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
877 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
878 if (rc==DS_OK&&primary!=NULL) {
879 test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
880 ref=IDirectSoundBuffer_Release(primary);
881 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
884 /* Set the CooperativeLevel back to normal */
885 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
886 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
887 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
890 ref=IDirectSound_Release(dso);
891 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
893 return DSERR_GENERIC;
898 static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
901 LPDIRECTSOUND dso=NULL;
902 LPDIRECTSOUNDBUFFER primary=NULL;
903 DSBUFFERDESC bufdesc;
907 /* Create the DirectSound object */
908 rc=DirectSoundCreate(lpGuid,&dso,NULL);
909 ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
913 /* Get the device capabilities */
914 ZeroMemory(&dscaps, sizeof(dscaps));
915 dscaps.dwSize=sizeof(dscaps);
916 rc=IDirectSound_GetCaps(dso,&dscaps);
917 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
921 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
922 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
923 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
924 ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
928 ZeroMemory(&bufdesc, sizeof(bufdesc));
929 bufdesc.dwSize=sizeof(bufdesc);
930 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
931 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
932 ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
933 if (rc==DS_OK&&primary!=NULL) {
934 LPDIRECTSOUND3DLISTENER listener=NULL;
935 rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
936 ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
937 if (rc==DS_OK&&listener!=NULL) {
938 LPDIRECTSOUNDBUFFER temp_buffer=NULL;
940 /* Checking the COM interface */
941 rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
942 ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
943 ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
944 if(rc==DS_OK&&temp_buffer!=NULL) {
945 ref=IDirectSoundBuffer_Release(temp_buffer);
946 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
949 rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
950 ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
951 ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
952 ref=IDirectSoundBuffer_Release(temp_buffer);
953 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
955 /* Testing the buffer */
956 test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
959 /* Testing the reference counting */
960 ref=IDirectSound3DListener_Release(listener);
961 ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
964 /* Testing the reference counting */
965 ref=IDirectSoundBuffer_Release(primary);
966 ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
970 ref=IDirectSound_Release(dso);
971 ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
973 return DSERR_GENERIC;
978 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
979 LPCSTR lpcstrModule, LPVOID lpContext)
983 trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
984 rc=test_dsound(lpGuid);
985 ok(rc==DS_OK,"DirectSound test failed\n");
987 trace(" Testing the primary buffer\n");
988 rc=test_primary(lpGuid);
989 ok(rc==DS_OK,"Primary Buffer test failed\n");
991 trace(" Testing 3D primary buffer\n");
992 rc=test_primary_3d(lpGuid);
993 ok(rc==DS_OK,"3D Primary Buffer test failed\n");
995 trace(" Testing 3D primary buffer with listener\n");
996 rc=test_primary_3d_with_listener(lpGuid);
997 ok(rc==DS_OK,"3D Primary Buffer with listener test failed\n");
999 /* Testing secondary buffers */
1000 test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0);
1001 test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0);
1003 /* Testing 3D secondary buffers */
1004 test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0);
1005 test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0);
1006 test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0);
1007 test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0);
1008 test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0);
1009 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0);
1010 test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0);
1011 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0);
1012 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1);
1013 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
1018 static void dsound_out_tests()
1021 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
1022 ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc);
1025 #define NOTIFICATIONS 5
1031 LPDIRECTSOUNDCAPTUREBUFFER dscbo;
1033 DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
1035 LPDIRECTSOUNDNOTIFY notify;
1045 static int capture_buffer_service(capture_state_t* state)
1050 DWORD capture_pos,read_pos;
1052 rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos);
1053 ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx\n",rc);
1057 rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0);
1058 ok(rc==DS_OK,"Lock failed: 0x%lx\n",rc);
1062 rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
1063 ok(rc==DS_OK,"Unlock failed: 0x%lx\n",rc);
1067 state->offset = (state->offset + state->size) % state->buffer_size;
1072 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
1073 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
1079 capture_state_t state;
1082 /* Private dsound.dll: Error: Invalid caps pointer */
1083 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
1084 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1086 /* Private dsound.dll: Error: Invalid caps pointer */
1088 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
1089 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1091 dscbcaps.dwSize=sizeof(dscbcaps);
1092 rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
1093 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
1095 trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
1096 dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
1099 /* Query the format size. Note that it may not match sizeof(wfx) */
1100 /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must be non-NULL */
1101 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
1102 ok(rc==DSERR_INVALIDPARAM,
1103 "GetFormat should have returned an error: rc=0x%lx\n",rc);
1106 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
1107 ok(rc==DS_OK && size!=0,
1108 "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
1111 rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
1112 ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
1114 trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
1115 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
1116 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
1119 /* Private dsound.dll: Error: Invalid status pointer */
1120 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
1121 ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
1123 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
1124 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
1126 trace(" status=0x%04lx\n",status);
1129 ZeroMemory(&state, sizeof(state));
1132 state.buffer_size = dscbcaps.dwBufferBytes;
1133 state.event = CreateEvent( NULL, FALSE, FALSE, NULL );
1134 state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
1136 rc=IDirectSoundCapture_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify));
1137 ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
1141 for (i = 0; i < NOTIFICATIONS; i++) {
1142 state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
1143 state.posnotify[i].hEventNotify = state.event;
1146 rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify);
1147 ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx\n",rc);
1152 rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
1153 ok(rc==DS_OK,"Start: 0x%lx\n",rc);
1157 rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
1158 ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
1159 ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
1160 "GetStatus: bad status: %lx",status);
1164 /* wait for the notifications */
1165 for (i = 0; i < (NOTIFICATIONS * 2); i++) {
1166 rc=MsgWaitForMultipleObjects( 1, &(state.event), FALSE, 3000, QS_ALLEVENTS );
1167 ok(rc==WAIT_OBJECT_0,"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
1168 if (rc!=WAIT_OBJECT_0)
1170 if (!capture_buffer_service(&state))
1174 rc=IDirectSoundCaptureBuffer_Stop(dscbo);
1175 ok(rc==DS_OK,"Stop: 0x%lx\n",rc);
1180 rc=IDirectSoundNotify_Release(state.notify);
1181 ok(rc==0,"Release: 0x%lx\n",rc);
1186 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1187 LPCSTR lpcstrModule, LPVOID lpContext)
1190 LPDIRECTSOUNDCAPTURE dsco=NULL;
1191 LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
1192 DSCBUFFERDESC bufdesc;
1197 /* Private dsound.dll: Error: Invalid interface buffer */
1198 trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
1199 rc=DirectSoundCaptureCreate(lpGuid,NULL,NULL);
1200 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx\n",rc);
1202 ref=IDirectSoundCapture_Release(dsco);
1203 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
1206 rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL);
1207 ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx\n",rc);
1211 /* Private dsound.dll: Error: Invalid caps buffer */
1212 rc=IDirectSoundCapture_GetCaps(dsco,NULL);
1213 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1215 /* Private dsound.dll: Error: Invalid caps buffer */
1217 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
1218 ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1220 dsccaps.dwSize=sizeof(dsccaps);
1221 rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
1222 ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
1224 trace(" DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
1225 dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels);
1228 /* Private dsound.dll: Error: Invalid size */
1229 /* Private dsound.dll: Error: Invalid capture buffer description */
1230 ZeroMemory(&bufdesc, sizeof(bufdesc));
1233 bufdesc.dwBufferBytes=0;
1234 bufdesc.dwReserved=0;
1235 bufdesc.lpwfxFormat=NULL;
1236 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1237 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1239 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1240 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1243 /* Private dsound.dll: Error: Invalid buffer size */
1244 /* Private dsound.dll: Error: Invalid capture buffer description */
1245 ZeroMemory(&bufdesc, sizeof(bufdesc));
1246 bufdesc.dwSize=sizeof(bufdesc);
1248 bufdesc.dwBufferBytes=0;
1249 bufdesc.dwReserved=0;
1250 bufdesc.lpwfxFormat=NULL;
1251 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1252 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1254 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1255 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1258 /* Private dsound.dll: Error: Invalid buffer size */
1259 /* Private dsound.dll: Error: Invalid capture buffer description */
1260 ZeroMemory(&bufdesc, sizeof(bufdesc));
1261 ZeroMemory(&wfx, sizeof(wfx));
1262 bufdesc.dwSize=sizeof(bufdesc);
1264 bufdesc.dwBufferBytes=0;
1265 bufdesc.dwReserved=0;
1266 bufdesc.lpwfxFormat=&wfx;
1267 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1268 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1270 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1271 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1274 /* Private dsound.dll: Error: Invalid buffer size */
1275 /* Private dsound.dll: Error: Invalid capture buffer description */
1276 init_format(&wfx,11025,8,1);
1277 ZeroMemory(&bufdesc, sizeof(bufdesc));
1278 bufdesc.dwSize=sizeof(bufdesc);
1280 bufdesc.dwBufferBytes=0;
1281 bufdesc.dwReserved=0;
1282 bufdesc.lpwfxFormat=&wfx;
1283 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1284 ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1286 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1287 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1290 for (f=0;f<NB_FORMATS;f++) {
1291 init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
1292 ZeroMemory(&bufdesc, sizeof(bufdesc));
1293 bufdesc.dwSize=sizeof(bufdesc);
1295 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
1296 bufdesc.dwReserved=0;
1297 bufdesc.lpwfxFormat=&wfx;
1298 trace(" Testing the capture buffer at %ldx%dx%d\n",
1299 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
1300 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1301 ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc);
1303 test_capture_buffer(dsco, dscbo, winetest_interactive);
1304 ref=IDirectSoundCaptureBuffer_Release(dscbo);
1305 ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1309 /* Try an invalid format to test error handling */
1311 init_format(&wfx,2000000,16,2);
1312 ZeroMemory(&bufdesc, sizeof(bufdesc));
1313 bufdesc.dwSize=sizeof(bufdesc);
1314 bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
1315 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
1316 bufdesc.dwReserved=0;
1317 bufdesc.lpwfxFormat=&wfx;
1318 trace(" Testing the capture buffer at %ldx%dx%d\n",
1319 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
1320 rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1321 ok(rc!=DS_OK,"CreateCaptureBuffer should have failed at 2 MHz 0x%lx\n",rc);
1326 ref=IDirectSoundCapture_Release(dsco);
1327 ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
1333 static void dsound_in_tests()
1336 rc=DirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
1337 ok(rc==DS_OK,"DirectSoundCaptureEnumerate failed: %ld\n",rc);