Implement A->W call for GetNamedSecurityInfo.
[wine] / dlls / dsound / tests / ds3d8.c
1 /*
2  * Tests the panning and 3D functions of DirectSound
3  *
4  * Part of this test involves playing test tones. But this only makes
5  * sense if someone is going to carefully listen to it, and would only
6  * bother everyone else.
7  * So this is only done if the test is being run in interactive mode.
8  *
9  * Copyright (c) 2002-2004 Francois Gouget
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28 #include <windows.h>
29
30 #include <math.h>
31 #include <stdlib.h>
32
33 #include "wine/test.h"
34 #include "windef.h"
35 #include "wingdi.h"
36 #include "dsound.h"
37 #include "dxerr8.h"
38
39 #include "dsound_test.h"
40
41 typedef struct {
42     char* wave;
43     DWORD wave_len;
44
45     LPDIRECTSOUNDBUFFER dsbo;
46     LPWAVEFORMATEX wfx;
47     DWORD buffer_size;
48     DWORD written;
49     DWORD played;
50     DWORD offset;
51 } play_state_t;
52
53 static int buffer_refill8(play_state_t* state, DWORD size)
54 {
55     LPVOID ptr1,ptr2;
56     DWORD len1,len2;
57     HRESULT rc;
58
59     if (size>state->wave_len-state->written)
60         size=state->wave_len-state->written;
61
62     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
63                                &ptr1,&len1,&ptr2,&len2,0);
64     ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
65     if (rc!=DS_OK)
66         return -1;
67
68     memcpy(ptr1,state->wave+state->written,len1);
69     state->written+=len1;
70     if (ptr2!=NULL) {
71         memcpy(ptr2,state->wave+state->written,len2);
72         state->written+=len2;
73     }
74     state->offset=state->written % state->buffer_size;
75     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
76     ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
77     if (rc!=DS_OK)
78         return -1;
79     return size;
80 }
81
82 static int buffer_silence8(play_state_t* state, DWORD size)
83 {
84     LPVOID ptr1,ptr2;
85     DWORD len1,len2;
86     HRESULT rc;
87     BYTE s;
88
89     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
90                                &ptr1,&len1,&ptr2,&len2,0);
91     ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
92     if (rc!=DS_OK)
93         return -1;
94
95     s=(state->wfx->wBitsPerSample==8?0x80:0);
96     memset(ptr1,s,len1);
97     if (ptr2!=NULL) {
98         memset(ptr2,s,len2);
99     }
100     state->offset=(state->offset+size) % state->buffer_size;
101     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
102     ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
103     if (rc!=DS_OK)
104         return -1;
105     return size;
106 }
107
108 static int buffer_service8(play_state_t* state)
109 {
110     DWORD last_play_pos,play_pos,buf_free;
111     HRESULT rc;
112
113     rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
114     ok(rc==DS_OK,"GetCurrentPosition: %lx\n",rc);
115     if (rc!=DS_OK) {
116         goto STOP;
117     }
118
119     /* Update the amount played */
120     last_play_pos=state->played % state->buffer_size;
121     if (play_pos<last_play_pos)
122         state->played+=state->buffer_size-last_play_pos+play_pos;
123     else
124         state->played+=play_pos-last_play_pos;
125
126     if (winetest_debug > 1)
127         trace("buf size=%ld last_play_pos=%ld play_pos=%ld played=%ld / %ld\n",
128               state->buffer_size,last_play_pos,play_pos,state->played,state->wave_len);
129
130     if (state->played>state->wave_len)
131     {
132         /* Everything has been played */
133         goto STOP;
134     }
135
136     /* Refill the buffer */
137     if (state->offset<=play_pos)
138         buf_free=play_pos-state->offset;
139     else
140         buf_free=state->buffer_size-state->offset+play_pos;
141
142     if (winetest_debug > 1)
143         trace("offset=%ld free=%ld written=%ld / %ld\n",
144               state->offset,buf_free,state->written,state->wave_len);
145     if (buf_free==0)
146         return 1;
147
148     if (state->written<state->wave_len)
149     {
150         int w=buffer_refill8(state,buf_free);
151         if (w==-1)
152             goto STOP;
153         buf_free-=w;
154         if (state->written==state->wave_len && winetest_debug > 1)
155             trace("last sound byte at %ld\n",
156                   (state->written % state->buffer_size));
157     }
158
159     if (buf_free>0) {
160         /* Fill with silence */
161         if (winetest_debug > 1)
162             trace("writing %ld bytes of silence\n",buf_free);
163         if (buffer_silence8(state,buf_free)==-1)
164             goto STOP;
165     }
166     return 1;
167
168 STOP:
169     if (winetest_debug > 1)
170         trace("stopping playback\n");
171     rc=IDirectSoundBuffer_Stop(state->dsbo);
172     ok(rc==DS_OK,"Stop failed: rc=%ld\n",rc);
173     return 0;
174 }
175
176 void test_buffer8(LPDIRECTSOUND8 dso, LPDIRECTSOUNDBUFFER dsbo,
177                   BOOL is_primary, BOOL set_volume, LONG volume,
178                   BOOL set_pan, LONG pan, BOOL play, double duration,
179                   BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
180                   BOOL move_listener, BOOL move_sound)
181 {
182     HRESULT rc;
183     DSBCAPS dsbcaps;
184     WAVEFORMATEX wfx,wfx2;
185     DWORD size,status,freq;
186     int ref;
187
188     /* DSOUND: Error: Invalid caps pointer */
189     rc=IDirectSoundBuffer_GetCaps(dsbo,0);
190     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
191
192     ZeroMemory(&dsbcaps, sizeof(dsbcaps));
193
194     /* DSOUND: Error: Invalid caps pointer */
195     rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
196     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
197
198     dsbcaps.dwSize=sizeof(dsbcaps);
199     rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
200     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
201     if (rc==DS_OK) {
202         trace("    Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
203               dsbcaps.dwBufferBytes);
204     }
205
206     /* Query the format size. Note that it may not match sizeof(wfx) */
207     size=0;
208     rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
209     ok(rc==DS_OK && size!=0,
210        "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
211        rc,size);
212
213     rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
214     ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
215     if (rc==DS_OK && is_primary) {
216         trace("Primary buffer default format: tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
217               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
218               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
219     }
220
221     /* DSOUND: Error: Invalid frequency buffer */
222     rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
223     ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
224
225     /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
226     rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
227     ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
228        (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
229        "GetFrequency failed: 0x%lx\n",rc);
230     if (rc==DS_OK) {
231         ok(freq==wfx.nSamplesPerSec,
232            "The frequency returned by GetFrequency %ld does not match the format %ld\n",
233            freq,wfx.nSamplesPerSec);
234     }
235
236     /* DSOUND: Error: Invalid status pointer */
237     rc=IDirectSoundBuffer_GetStatus(dsbo,0);
238     ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
239
240     rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
241     ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
242     ok(status==0,"status=0x%lx instead of 0\n",status);
243
244     if (is_primary) {
245         /* We must call SetCooperativeLevel to be allowed to call SetFormat */
246         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
247         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
248         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
249         if (rc!=DS_OK)
250             return;
251
252         /* DSOUND: Error: Invalid format pointer */
253         rc=IDirectSoundBuffer_SetFormat(dsbo,0);
254         ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
255
256         init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
257         rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
258         ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
259
260         /* There is no garantee that SetFormat will actually change the
261          * format to what we asked for. It depends on what the soundcard
262          * supports. So we must re-query the format.
263          */
264         rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
265         ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
266         if (rc==DS_OK &&
267             (wfx.wFormatTag!=wfx2.wFormatTag ||
268              wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
269              wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
270              wfx.nChannels!=wfx2.nChannels)) {
271             trace("Requested format tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
272                   wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
273                   wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
274             trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
275                   wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
276                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
277         }
278
279         /* Set the CooperativeLevel back to normal */
280         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
281         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
282         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
283     }
284
285     if (play) {
286         play_state_t state;
287         DS3DLISTENER listener_param;
288         LPDIRECTSOUND3DBUFFER buffer=NULL;
289         DS3DBUFFER buffer_param;
290         DWORD start_time,now;
291
292         trace("    Playing %g second 440Hz tone at %ldx%dx%d\n", duration,
293               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
294
295         if (is_primary) {
296             /* We must call SetCooperativeLevel to be allowed to call Lock */
297             /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
298             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
299             ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
300             if (rc!=DS_OK)
301                 return;
302         }
303         if (buffer3d) {
304             LPDIRECTSOUNDBUFFER temp_buffer;
305
306             rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
307             ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
308             if (rc!=DS_OK)
309                 return;
310
311             /* check the COM interface */
312             rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
313             ok(rc==DS_OK && temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
314             ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
315             ref=IDirectSoundBuffer_Release(temp_buffer);
316             ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
317
318             temp_buffer=NULL;
319             rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
320             ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
321             ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
322             ref=IDirectSoundBuffer_Release(temp_buffer);
323             ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
324
325 #if 0
326             /* FIXME: this works on windows */
327             ref=IDirectSoundBuffer_Release(dsbo);
328             ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
329
330             rc=IDirectSound3DBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer,(LPVOID *)&dsbo);
331             ok(rc==DS_OK && dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
332 #endif
333
334             /* DSOUND: Error: Invalid buffer */
335             rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
336             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
337
338             ZeroMemory(&buffer_param, sizeof(buffer_param));
339
340             /* DSOUND: Error: Invalid buffer */
341             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
342             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
343
344             buffer_param.dwSize=sizeof(buffer_param);
345             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
346             ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
347         }
348         if (set_volume) {
349             if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
350                 LONG val;
351                 rc=IDirectSoundBuffer_GetVolume(dsbo,&val);
352                 ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
353
354                 rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
355                 ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
356             } else {
357                 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
358                 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
359                 ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc);
360             }
361         }
362
363         if (set_pan) {
364             if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
365                 LONG val;
366                 rc=IDirectSoundBuffer_GetPan(dsbo,&val);
367                 ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc);
368
369                 rc=IDirectSoundBuffer_SetPan(dsbo,pan);
370                 ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
371             } else {
372                 /* DSOUND: Error: Buffer does not have CTRLPAN */
373                 rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
374                 ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc);
375             }
376         }
377
378         state.wave=wave_generate_la(&wfx,duration,&state.wave_len);
379
380         state.dsbo=dsbo;
381         state.wfx=&wfx;
382         state.buffer_size=dsbcaps.dwBufferBytes;
383         state.played=state.written=state.offset=0;
384         buffer_refill8(&state,state.buffer_size);
385
386         rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
387         ok(rc==DS_OK,"Play: 0x%lx\n",rc);
388
389         rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
390         ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
391         ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
392            "GetStatus: bad status: %lx\n",status);
393
394         if (listener) {
395             ZeroMemory(&listener_param,sizeof(listener_param));
396             listener_param.dwSize=sizeof(listener_param);
397             rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
398             ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
399             if (move_listener)
400             {
401                 listener_param.vPosition.x = -5.0;
402                 listener_param.vVelocity.x = 10.0/duration;
403             }
404             rc=IDirectSound3DListener_SetAllParameters(listener,&listener_param,DS3D_IMMEDIATE);
405             ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
406         }
407         if (buffer3d) {
408             if (move_sound)
409             {
410                 buffer_param.vPosition.x = 100.0;
411                 buffer_param.vVelocity.x = -200.0/duration;
412             }
413             buffer_param.flMinDistance = 10;
414             rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,DS3D_IMMEDIATE);
415             ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
416         }
417
418         start_time=GetTickCount();
419         while (buffer_service8(&state)) {
420             WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
421             now=GetTickCount();
422             if (listener && move_listener) {
423                 listener_param.vPosition.x = -5.0+10.0*(now-start_time)/1000/duration;
424                 if (winetest_debug>2)
425                     trace("listener position=%g\n",listener_param.vPosition.x);
426                 rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
427                 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
428             }
429             if (buffer3d && move_sound) {
430                 buffer_param.vPosition.x = 100-200.0*(now-start_time)/1000/duration;
431                 if (winetest_debug>2)
432                     trace("sound position=%g\n",buffer_param.vPosition.x);
433                 rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
434                 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
435             }
436         }
437         /* Check the sound duration was within 10% of the expected value */
438         now=GetTickCount();
439         ok(fabs(1000*duration-now+start_time)<=100*duration,"The sound played for %ld ms instead of %g ms\n",now-start_time,1000*duration);
440
441         free(state.wave);
442         if (is_primary) {
443             /* Set the CooperativeLevel back to normal */
444             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
445             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
446             ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
447         }
448         if (buffer3d) {
449             ref=IDirectSound3DBuffer_Release(buffer);
450             ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref);
451         }
452     }
453 }
454
455 static HRESULT test_secondary8(LPGUID lpGuid, int play,
456                               int has_3d, int has_3dbuffer,
457                               int has_listener, int has_duplicate,
458                               int move_listener, int move_sound)
459 {
460     HRESULT rc;
461     LPDIRECTSOUND8 dso=NULL;
462     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
463     LPDIRECTSOUND3DLISTENER listener=NULL;
464     DSBUFFERDESC bufdesc;
465     WAVEFORMATEX wfx;
466     int ref;
467
468     /* Create the DirectSound object */
469     rc=DirectSoundCreate8(lpGuid,&dso,NULL);
470     ok(rc==DS_OK,"DirectSoundCreate8 failed: 0x%08lx\n",rc);
471     if (rc!=DS_OK)
472         return rc;
473
474     /* We must call SetCooperativeLevel before creating primary buffer */
475     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
476     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
477     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
478     if (rc!=DS_OK)
479         goto EXIT;
480
481     ZeroMemory(&bufdesc, sizeof(bufdesc));
482     bufdesc.dwSize=sizeof(bufdesc);
483     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
484     if (has_3d)
485         bufdesc.dwFlags|=DSBCAPS_CTRL3D;
486     else
487         bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
488     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
489     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a %sprimary buffer 0x%lx\n",has_3d?"3D ":"", rc);
490
491     if (rc==DS_OK && primary!=NULL) {
492         if (has_listener) {
493             rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
494             ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
495             ref=IDirectSoundBuffer_Release(primary);
496             ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
497             if (rc==DS_OK && listener!=NULL) {
498                 DS3DLISTENER listener_param;
499                 ZeroMemory(&listener_param,sizeof(listener_param));
500                 /* DSOUND: Error: Invalid buffer */
501                 rc=IDirectSound3DListener_GetAllParameters(listener,0);
502                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
503
504                 /* DSOUND: Error: Invalid buffer */
505                 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
506                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
507
508                 listener_param.dwSize=sizeof(listener_param);
509                 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
510                 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
511             }
512             else
513                 goto EXIT;
514         }
515
516         init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
517         secondary=NULL;
518         ZeroMemory(&bufdesc, sizeof(bufdesc));
519         bufdesc.dwSize=sizeof(bufdesc);
520         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
521         if (has_3d)
522             bufdesc.dwFlags|=DSBCAPS_CTRL3D;
523         else
524             bufdesc.dwFlags|=(DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
525         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
526         bufdesc.lpwfxFormat=&wfx;
527         trace("  Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
528               has_3dbuffer?"3D ":"",
529               has_duplicate?"duplicated ":"",
530               listener!=NULL||move_sound?"with ":"",
531               move_listener?"moving ":"",
532               listener!=NULL?"listener ":"",
533               listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
534               wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
535         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
536         ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
537         if (rc==DS_OK && secondary!=NULL) {
538             if (!has_3d)
539             {
540                 DWORD refvol,refpan,vol,pan;
541
542                 /* Check the initial secondary buffer's volume and pan */
543                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
544                 ok(rc==DS_OK,"GetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
545                 ok(vol==0,"wrong volume for a new secondary buffer: %ld\n",vol);
546                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
547                 ok(rc==DS_OK,"GetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
548                 ok(pan==0,"wrong pan for a new secondary buffer: %ld\n",pan);
549
550                 /* Check that changing the secondary buffer's volume and pan
551                  * does not impact the primary buffer's volume and pan
552                  */
553                 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
554                 ok(rc==DS_OK,"GetVolume(primary) failed: %s\n",DXGetErrorString8(rc));
555                 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
556                 ok(rc==DS_OK,"GetPan(primary) failed: %s\n",DXGetErrorString8(rc));
557
558                 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
559                 ok(rc==DS_OK,"SetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
560                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
561                 ok(rc==DS_OK,"SetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
562                 ok(vol==-1000,"secondary: wrong volume %ld instead of -1000\n",vol);
563                 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
564                 ok(rc==DS_OK,"SetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
565                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
566                 ok(rc==DS_OK,"SetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
567                 ok(vol==-1000,"secondary: wrong pan %ld instead of -1000\n",pan);
568
569                 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
570                 ok(rc==DS_OK,"GetVolume(primary) failed: %s\n",DXGetErrorString8(rc));
571                 ok(vol==refvol,"The primary volume changed from %ld to %ld\n",refvol,vol);
572                 rc=IDirectSoundBuffer_GetPan(primary,&pan);
573                 ok(rc==DS_OK,"GetPan(primary) failed: %s\n",DXGetErrorString8(rc));
574                 ok(pan==refpan,"The primary pan changed from %ld to %ld\n",refpan,pan);
575
576                 rc=IDirectSoundBuffer_SetVolume(secondary,0);
577                 ok(rc==DS_OK,"SetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
578                 rc=IDirectSoundBuffer_SetPan(secondary,0);
579                 ok(rc==DS_OK,"SetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
580             }
581             if (has_duplicate) {
582                 LPDIRECTSOUNDBUFFER duplicated=NULL;
583
584                 /* DSOUND: Error: Invalid source buffer */
585                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,0);
586                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
587
588                 /* DSOUND: Error: Invalid dest buffer */
589                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,0);
590                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
591
592                 /* DSOUND: Error: Invalid source buffer */
593                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,&duplicated);
594                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
595
596                 duplicated=NULL;
597                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,&duplicated);
598                 ok(rc==DS_OK && duplicated!=NULL,"IDirectSound8_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
599
600                 if (rc==DS_OK && duplicated!=NULL) {
601                     ref=IDirectSoundBuffer_Release(secondary);
602                     ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
603                     secondary=duplicated;
604                 }
605             }
606
607             if (rc==DS_OK && secondary!=NULL) {
608                 double duration;
609                 duration=(move_listener || move_sound?4.0:1.0);
610                 test_buffer8(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,duration,has_3dbuffer,listener,move_listener,move_sound);
611                 ref=IDirectSoundBuffer_Release(secondary);
612                 ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
613             }
614         }
615     }
616     if (has_listener) {
617         ref=IDirectSound3DListener_Release(listener);
618         ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
619     } else {
620         ref=IDirectSoundBuffer_Release(primary);
621         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
622     }
623
624     /* Set the CooperativeLevel back to normal */
625     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
626     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
627     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
628
629 EXIT:
630     ref=IDirectSound8_Release(dso);
631     ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
632     if (ref!=0)
633         return DSERR_GENERIC;
634
635     return rc;
636 }
637
638 static HRESULT test_primary8(LPGUID lpGuid)
639 {
640     HRESULT rc;
641     LPDIRECTSOUND8 dso=NULL;
642     LPDIRECTSOUNDBUFFER primary=NULL;
643     DSBUFFERDESC bufdesc;
644     DSCAPS dscaps;
645     int ref, i;
646
647     /* Create the DirectSound object */
648     rc=DirectSoundCreate8(lpGuid,&dso,NULL);
649     ok(rc==DS_OK,"DirectSoundCreate8 failed: 0x%lx\n",rc);
650     if (rc!=DS_OK)
651         return rc;
652
653     /* Get the device capabilities */
654     ZeroMemory(&dscaps, sizeof(dscaps));
655     dscaps.dwSize=sizeof(dscaps);
656     rc=IDirectSound8_GetCaps(dso,&dscaps);
657     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
658     if (rc!=DS_OK)
659         goto EXIT;
660
661     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
662     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
663     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
664     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
665     if (rc!=DS_OK)
666         goto EXIT;
667
668     /* Testing the primary buffer */
669     primary=NULL;
670     ZeroMemory(&bufdesc, sizeof(bufdesc));
671     bufdesc.dwSize=sizeof(bufdesc);
672     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
673     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
674     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
675     if (rc==DS_OK && primary!=NULL) {
676         test_buffer8(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
677         if (winetest_interactive) {
678             LONG volume,pan;
679
680             volume = DSBVOLUME_MAX;
681             for (i = 0; i < 6; i++) {
682                 test_buffer8(dso,primary,1,TRUE,volume,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
683                 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
684             }
685
686             pan = DSBPAN_LEFT;
687             for (i = 0; i < 7; i++) {
688                 test_buffer8(dso,primary,1,TRUE,0,TRUE,pan,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
689                 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
690             }
691         }
692         ref=IDirectSoundBuffer_Release(primary);
693         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
694     }
695
696     /* Set the CooperativeLevel back to normal */
697     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
698     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
699     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
700
701 EXIT:
702     ref=IDirectSound8_Release(dso);
703     ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
704     if (ref!=0)
705         return DSERR_GENERIC;
706
707     return rc;
708 }
709
710 static HRESULT test_primary_3d8(LPGUID lpGuid)
711 {
712     HRESULT rc;
713     LPDIRECTSOUND8 dso=NULL;
714     LPDIRECTSOUNDBUFFER primary=NULL;
715     DSBUFFERDESC bufdesc;
716     DSCAPS dscaps;
717     int ref;
718
719     /* Create the DirectSound object */
720     rc=DirectSoundCreate8(lpGuid,&dso,NULL);
721     ok(rc==DS_OK,"DirectSoundCreate8 failed: 0x%lx\n",rc);
722     if (rc!=DS_OK)
723         return rc;
724
725     /* Get the device capabilities */
726     ZeroMemory(&dscaps, sizeof(dscaps));
727     dscaps.dwSize=sizeof(dscaps);
728     rc=IDirectSound8_GetCaps(dso,&dscaps);
729     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
730     if (rc!=DS_OK)
731         goto EXIT;
732
733     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
734     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
735     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
736     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
737     if (rc!=DS_OK)
738         goto EXIT;
739
740     primary=NULL;
741     ZeroMemory(&bufdesc, sizeof(bufdesc));
742     bufdesc.dwSize=sizeof(bufdesc);
743     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
744     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
745     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
746     if (rc==DS_OK && primary!=NULL) {
747         ref=IDirectSoundBuffer_Release(primary);
748         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
749         primary=NULL;
750         ZeroMemory(&bufdesc, sizeof(bufdesc));
751         bufdesc.dwSize=sizeof(bufdesc);
752         bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
753         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
754         ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
755         if (rc==DS_OK && primary!=NULL) {
756             test_buffer8(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
757             ref=IDirectSoundBuffer_Release(primary);
758             ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
759         }
760     }
761     /* Set the CooperativeLevel back to normal */
762     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
763     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
764     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
765
766 EXIT:
767     ref=IDirectSound8_Release(dso);
768     ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
769     if (ref!=0)
770         return DSERR_GENERIC;
771
772     return rc;
773 }
774
775 static HRESULT test_primary_3d_with_listener8(LPGUID lpGuid)
776 {
777     HRESULT rc;
778     LPDIRECTSOUND8 dso=NULL;
779     LPDIRECTSOUNDBUFFER primary=NULL;
780     DSBUFFERDESC bufdesc;
781     DSCAPS dscaps;
782     int ref;
783
784     /* Create the DirectSound object */
785     rc=DirectSoundCreate8(lpGuid,&dso,NULL);
786     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
787     if (rc!=DS_OK)
788         return rc;
789
790     /* Get the device capabilities */
791     ZeroMemory(&dscaps, sizeof(dscaps));
792     dscaps.dwSize=sizeof(dscaps);
793     rc=IDirectSound8_GetCaps(dso,&dscaps);
794     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
795     if (rc!=DS_OK)
796         goto EXIT;
797
798     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
799     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
800     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
801     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
802     if (rc!=DS_OK)
803         goto EXIT;
804     primary=NULL;
805     ZeroMemory(&bufdesc, sizeof(bufdesc));
806     bufdesc.dwSize=sizeof(bufdesc);
807     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
808     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
809     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
810     if (rc==DS_OK && primary!=NULL) {
811         LPDIRECTSOUND3DLISTENER listener=NULL;
812         rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
813         ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
814         if (rc==DS_OK && listener!=NULL) {
815             LPDIRECTSOUNDBUFFER temp_buffer=NULL;
816
817             /* Checking the COM interface */
818             rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
819             ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
820             ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
821             if (rc==DS_OK && temp_buffer!=NULL) {
822                 ref=IDirectSoundBuffer_Release(temp_buffer);
823                 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
824
825                 temp_buffer=NULL;
826                 rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
827                 ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
828                 ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
829                 ref=IDirectSoundBuffer_Release(temp_buffer);
830                 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
831
832                 /* Testing the buffer */
833                 test_buffer8(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,listener,0,0);
834             }
835
836             /* Testing the reference counting */
837             ref=IDirectSound3DListener_Release(listener);
838             ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
839         }
840
841         /* Testing the reference counting */
842         ref=IDirectSoundBuffer_Release(primary);
843         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
844     }
845
846 EXIT:
847     ref=IDirectSound8_Release(dso);
848     ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
849     if (ref!=0)
850 return DSERR_GENERIC;
851
852     return rc;
853 }
854
855 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
856                                    LPCSTR lpcstrModule, LPVOID lpContext)
857 {
858     trace("*** Testing %s - %s\n",lpcstrDescription,lpcstrModule);
859
860     trace("  Testing the primary buffer\n");
861     test_primary8(lpGuid);
862
863     trace("  Testing 3D primary buffer\n");
864     test_primary_3d8(lpGuid);
865
866     trace("  Testing 3D primary buffer with listener\n");
867     test_primary_3d_with_listener8(lpGuid);
868
869     /* Testing secondary buffers */
870     test_secondary8(lpGuid,winetest_interactive,0,0,0,0,0,0);
871     test_secondary8(lpGuid,winetest_interactive,0,0,0,1,0,0);
872
873     /* Testing 3D secondary buffers */
874     test_secondary8(lpGuid,winetest_interactive,1,0,0,0,0,0);
875     test_secondary8(lpGuid,winetest_interactive,1,1,0,0,0,0);
876     test_secondary8(lpGuid,winetest_interactive,1,1,0,1,0,0);
877     test_secondary8(lpGuid,winetest_interactive,1,0,1,0,0,0);
878     test_secondary8(lpGuid,winetest_interactive,1,0,1,1,0,0);
879     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,0);
880     test_secondary8(lpGuid,winetest_interactive,1,1,1,1,0,0);
881     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,0);
882     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,1);
883     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,1);
884
885     return 1;
886 }
887
888 static void ds3d8_tests()
889 {
890     HRESULT rc;
891     rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
892     ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc);
893 }
894
895 START_TEST(ds3d8)
896 {
897     HMODULE hDsound;
898     FARPROC pFunc;
899
900     CoInitialize(NULL);
901
902     hDsound = LoadLibraryA("dsound.dll");
903     if (!hDsound) {
904         trace("dsound.dll not found\n");
905         return;
906     }
907
908     pFunc = (void*)GetProcAddress(hDsound, "DirectSoundCreate8");
909     if (!pFunc) {
910         trace("ds3d8 test skipped\n");
911         return;
912     }
913
914     ds3d8_tests();
915 }