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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include "dsound_test.h"
27 
28 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
29 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
30 
31 typedef struct {
32     char* wave;
33     DWORD wave_len;
34 
35     LPDIRECTSOUNDBUFFER dsbo;
36     LPWAVEFORMATEX wfx;
37     DWORD buffer_size;
38     DWORD written;
39     DWORD played;
40     DWORD offset;
41 } play_state_t;
42 
buffer_refill8(play_state_t * state,DWORD size)43 static int buffer_refill8(play_state_t* state, DWORD size)
44 {
45     LPVOID ptr1,ptr2;
46     DWORD len1,len2;
47     HRESULT rc;
48 
49     if (size>state->wave_len-state->written)
50         size=state->wave_len-state->written;
51 
52     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
53                                &ptr1,&len1,&ptr2,&len2,0);
54     ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
55     if (rc!=DS_OK)
56         return -1;
57 
58     memcpy(ptr1,state->wave+state->written,len1);
59     state->written+=len1;
60     if (ptr2!=NULL) {
61         memcpy(ptr2,state->wave+state->written,len2);
62         state->written+=len2;
63     }
64     state->offset=state->written % state->buffer_size;
65     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
66     ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
67     if (rc!=DS_OK)
68         return -1;
69     return size;
70 }
71 
buffer_silence8(play_state_t * state,DWORD size)72 static int buffer_silence8(play_state_t* state, DWORD size)
73 {
74     LPVOID ptr1,ptr2;
75     DWORD len1,len2;
76     HRESULT rc;
77     BYTE s;
78 
79     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
80                                &ptr1,&len1,&ptr2,&len2,0);
81     ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
82     if (rc!=DS_OK)
83         return -1;
84 
85     s=(state->wfx->wBitsPerSample==8?0x80:0);
86     memset(ptr1,s,len1);
87     if (ptr2!=NULL) {
88         memset(ptr2,s,len2);
89     }
90     state->offset=(state->offset+size) % state->buffer_size;
91     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
92     ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
93     if (rc!=DS_OK)
94         return -1;
95     return size;
96 }
97 
buffer_service8(play_state_t * state)98 static int buffer_service8(play_state_t* state)
99 {
100     DWORD last_play_pos,play_pos,buf_free;
101     HRESULT rc;
102 
103     rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
104     ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %08x\n", rc);
105     if (rc!=DS_OK) {
106         goto STOP;
107     }
108 
109     /* Update the amount played */
110     last_play_pos=state->played % state->buffer_size;
111     if (play_pos<last_play_pos)
112         state->played+=state->buffer_size-last_play_pos+play_pos;
113     else
114         state->played+=play_pos-last_play_pos;
115 
116     if (winetest_debug > 1)
117         trace("buf size=%d last_play_pos=%d play_pos=%d played=%d / %d\n",
118               state->buffer_size,last_play_pos,play_pos,state->played,
119               state->wave_len);
120 
121     if (state->played>state->wave_len)
122     {
123         /* Everything has been played */
124         goto STOP;
125     }
126 
127     /* Refill the buffer */
128     if (state->offset<=play_pos)
129         buf_free=play_pos-state->offset;
130     else
131         buf_free=state->buffer_size-state->offset+play_pos;
132 
133     if (winetest_debug > 1)
134         trace("offset=%d free=%d written=%d / %d\n",
135               state->offset,buf_free,state->written,state->wave_len);
136     if (buf_free==0)
137         return 1;
138 
139     if (state->written<state->wave_len)
140     {
141         int w=buffer_refill8(state,buf_free);
142         if (w==-1)
143             goto STOP;
144         buf_free-=w;
145         if (state->written==state->wave_len && winetest_debug > 1)
146             trace("last sound byte at %d\n",
147                   (state->written % state->buffer_size));
148     }
149 
150     if (buf_free>0) {
151         /* Fill with silence */
152         if (winetest_debug > 1)
153             trace("writing %d bytes of silence\n",buf_free);
154         if (buffer_silence8(state,buf_free)==-1)
155             goto STOP;
156     }
157     return 1;
158 
159 STOP:
160     if (winetest_debug > 1)
161         trace("stopping playback\n");
162     rc=IDirectSoundBuffer_Stop(state->dsbo);
163     ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %08x\n", rc);
164     return 0;
165 }
166 
test_buffer8(LPDIRECTSOUND8 dso,LPDIRECTSOUNDBUFFER * dsbo,BOOL is_primary,BOOL set_volume,LONG volume,BOOL set_pan,LONG pan,BOOL play,double duration,BOOL buffer3d,LPDIRECTSOUND3DLISTENER listener,BOOL move_listener,BOOL move_sound)167 void test_buffer8(LPDIRECTSOUND8 dso, LPDIRECTSOUNDBUFFER * dsbo,
168                   BOOL is_primary, BOOL set_volume, LONG volume,
169                   BOOL set_pan, LONG pan, BOOL play, double duration,
170                   BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
171                   BOOL move_listener, BOOL move_sound)
172 {
173     HRESULT rc;
174     DSBCAPS dsbcaps;
175     WAVEFORMATEX wfx,wfx2;
176     DWORD size,status,freq;
177     BOOL ieee = FALSE;
178     int ref;
179 
180     /* DSOUND: Error: Invalid caps pointer */
181     rc=IDirectSoundBuffer_GetCaps(*dsbo,0);
182     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
183        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
184 
185     ZeroMemory(&dsbcaps, sizeof(dsbcaps));
186 
187     /* DSOUND: Error: Invalid caps pointer */
188     rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
189     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
190        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
191 
192     dsbcaps.dwSize=sizeof(dsbcaps);
193     rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
194     ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
195     if (rc==DS_OK && winetest_debug > 1) {
196         trace("    Caps: flags=0x%08x size=%d\n",dsbcaps.dwFlags,
197               dsbcaps.dwBufferBytes);
198     }
199 
200     /* Query the format size. */
201     size=0;
202     rc=IDirectSoundBuffer_GetFormat(*dsbo,NULL,0,&size);
203     ok(rc==DS_OK && size!=0,"IDirectSoundBuffer_GetFormat() should have "
204        "returned the needed size: rc=%08x size=%d\n",rc,size);
205 
206     ok(size == sizeof(WAVEFORMATEX) || size == sizeof(WAVEFORMATEXTENSIBLE),
207        "Expected a correct structure size, got %d\n", size);
208 
209     if (size == sizeof(WAVEFORMATEX)) {
210         rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,size,NULL);
211         ieee = (wfx.wFormatTag == WAVE_FORMAT_IEEE_FLOAT);
212     } else if (size == sizeof(WAVEFORMATEXTENSIBLE)) {
213         WAVEFORMATEXTENSIBLE wfxe;
214         rc=IDirectSoundBuffer_GetFormat(*dsbo,(WAVEFORMATEX*)&wfxe,size,NULL);
215         wfx = wfxe.Format;
216         ieee = IsEqualGUID(&wfxe.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
217     } else
218         return;
219 
220     ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
221     if (rc==DS_OK && winetest_debug > 1) {
222         trace("    Format: %s tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
223               is_primary ? "Primary" : "Secondary",
224               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
225               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
226     }
227 
228     /* DSOUND: Error: Invalid frequency buffer */
229     rc=IDirectSoundBuffer_GetFrequency(*dsbo,0);
230     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetFrequency() should have "
231        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
232 
233     /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
234     rc=IDirectSoundBuffer_GetFrequency(*dsbo,&freq);
235     ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
236        (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
237        "IDirectSoundBuffer_GetFrequency() failed: %08x\n",rc);
238     if (rc==DS_OK) {
239         ok(freq==wfx.nSamplesPerSec,"The frequency returned by GetFrequency "
240            "%d does not match the format %d\n",freq,wfx.nSamplesPerSec);
241     }
242 
243     /* DSOUND: Error: Invalid status pointer */
244     rc=IDirectSoundBuffer_GetStatus(*dsbo,0);
245     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetStatus() should have "
246        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
247 
248     rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
249     ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
250     ok(status==0,"status=0x%x instead of 0\n",status);
251 
252     if (is_primary) {
253         DSBCAPS new_dsbcaps;
254         /* We must call SetCooperativeLevel to be allowed to call SetFormat */
255         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
256         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
257         ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) "
258            "failed: %08x\n",rc);
259         if (rc!=DS_OK)
260             return;
261 
262         /* DSOUND: Error: Invalid format pointer */
263         rc=IDirectSoundBuffer_SetFormat(*dsbo,0);
264         ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_SetFormat() should have "
265            "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
266 
267         init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
268         rc=IDirectSoundBuffer_SetFormat(*dsbo,&wfx2);
269         ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
270            format_string(&wfx2), rc);
271 
272         /* There is no guarantee that SetFormat will actually change the
273 	 * format to what we asked for. It depends on what the soundcard
274 	 * supports. So we must re-query the format.
275 	 */
276         rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,sizeof(wfx),NULL);
277         ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
278         if (rc==DS_OK &&
279             (wfx.wFormatTag!=wfx2.wFormatTag ||
280              wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
281              wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
282              wfx.nChannels!=wfx2.nChannels)) {
283             trace("Requested format tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
284                   wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
285                   wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
286             trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
287                   wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
288                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
289         }
290 
291         ZeroMemory(&new_dsbcaps, sizeof(new_dsbcaps));
292         new_dsbcaps.dwSize = sizeof(new_dsbcaps);
293         rc=IDirectSoundBuffer_GetCaps(*dsbo,&new_dsbcaps);
294         ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
295         if (rc==DS_OK && winetest_debug > 1) {
296             trace("    new Caps: flags=0x%08x size=%d\n",new_dsbcaps.dwFlags,
297                   new_dsbcaps.dwBufferBytes);
298         }
299 
300         /* Check for primary buffer size change */
301         ok(new_dsbcaps.dwBufferBytes == dsbcaps.dwBufferBytes,
302            "    buffer size changed after SetFormat() - "
303            "previous size was %u, current size is %u\n",
304            dsbcaps.dwBufferBytes, new_dsbcaps.dwBufferBytes);
305         dsbcaps.dwBufferBytes = new_dsbcaps.dwBufferBytes;
306 
307         /* Check for primary buffer flags change */
308         ok(new_dsbcaps.dwFlags == dsbcaps.dwFlags,
309            "    flags changed after SetFormat() - "
310            "previous flags were %08x, current flags are %08x\n",
311            dsbcaps.dwFlags, new_dsbcaps.dwFlags);
312 
313         /* Set the CooperativeLevel back to normal */
314         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
315         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
316         ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
317            "failed: %08x\n",rc);
318     }
319 
320     if (play) {
321         play_state_t state;
322         DS3DLISTENER listener_param;
323         LPDIRECTSOUND3DBUFFER buffer=NULL;
324         DS3DBUFFER buffer_param;
325         DWORD start_time,now;
326         LPVOID buffer1;
327         DWORD length1;
328 
329         if (winetest_interactive) {
330             trace("    Playing %g second 440Hz tone at %dx%dx%d\n", duration,
331                   wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
332         }
333 
334         if (is_primary) {
335             /* We must call SetCooperativeLevel to be allowed to call Lock */
336             /* DSOUND: Setting DirectSound cooperative level to
337              * DSSCL_WRITEPRIMARY */
338             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),
339                                                  DSSCL_WRITEPRIMARY);
340             ok(rc==DS_OK,
341                "IDirectSound8_SetCooperativeLevel(DSSCL_WRITEPRIMARY) failed: %08x\n",rc);
342             if (rc!=DS_OK)
343                 return;
344         }
345         if (buffer3d) {
346             LPDIRECTSOUNDBUFFER temp_buffer;
347 
348             rc=IDirectSoundBuffer_QueryInterface(*dsbo,&IID_IDirectSound3DBuffer,
349                                                  (LPVOID *)&buffer);
350             ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
351             if (rc!=DS_OK)
352                 return;
353 
354             /* check the COM interface */
355             rc=IDirectSoundBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
356                                                  (LPVOID *)&temp_buffer);
357             ok(rc==DS_OK && temp_buffer!=NULL,
358                "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
359             ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
360                temp_buffer,*dsbo);
361             ref=IDirectSoundBuffer_Release(temp_buffer);
362             ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
363                "should have 1\n",ref);
364 
365             temp_buffer=NULL;
366             rc=IDirectSound3DBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
367                                                    (LPVOID *)&temp_buffer);
368             ok(rc==DS_OK && temp_buffer!=NULL,
369                "IDirectSound3DBuffer_QueryInterface() failed: %08x\n", rc);
370             ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
371                temp_buffer,*dsbo);
372             ref=IDirectSoundBuffer_Release(temp_buffer);
373             ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
374                "should have 1\n",ref);
375 
376             ref=IDirectSoundBuffer_Release(*dsbo);
377             ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
378                "should have 0\n",ref);
379 
380             rc=IDirectSound3DBuffer_QueryInterface(buffer,
381                                                    &IID_IDirectSoundBuffer,
382                                                    (LPVOID *)dsbo);
383             ok(rc==DS_OK && *dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface() "
384                "failed: %08x\n",rc);
385 
386             /* DSOUND: Error: Invalid buffer */
387             rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
388             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
389                "failed: %08x\n",rc);
390 
391             ZeroMemory(&buffer_param, sizeof(buffer_param));
392 
393             /* DSOUND: Error: Invalid buffer */
394             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
395             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
396                "failed: %08x\n",rc);
397 
398             buffer_param.dwSize=sizeof(buffer_param);
399             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
400             ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters() failed: %08x\n", rc);
401         }
402         if (set_volume) {
403             if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
404                 LONG val;
405                 rc=IDirectSoundBuffer_GetVolume(*dsbo,&val);
406                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc);
407 
408                 rc=IDirectSoundBuffer_SetVolume(*dsbo,volume);
409                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume() failed: %08x\n", rc);
410             } else {
411                 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
412                 rc=IDirectSoundBuffer_GetVolume(*dsbo,&volume);
413                 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetVolume() "
414                    "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
415             }
416         }
417 
418         if (set_pan) {
419             if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
420                 LONG val;
421                 rc=IDirectSoundBuffer_GetPan(*dsbo,&val);
422                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan() failed: %08x\n", rc);
423 
424                 rc=IDirectSoundBuffer_SetPan(*dsbo,pan);
425                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan() failed: %08x\n", rc);
426             } else {
427                 /* DSOUND: Error: Buffer does not have CTRLPAN */
428                 rc=IDirectSoundBuffer_GetPan(*dsbo,&pan);
429                 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetPan() "
430                    "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
431             }
432         }
433 
434         /* try an offset past the end of the buffer */
435         rc = IDirectSoundBuffer_Lock(*dsbo, dsbcaps.dwBufferBytes, 0, &buffer1,
436                                       &length1, NULL, NULL,
437                                       DSBLOCK_ENTIREBUFFER);
438         ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
439            "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
440 
441         /* try a size larger than the buffer */
442         rc = IDirectSoundBuffer_Lock(*dsbo, 0, dsbcaps.dwBufferBytes + 1,
443                                      &buffer1, &length1, NULL, NULL,
444                                      DSBLOCK_FROMWRITECURSOR);
445         ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
446            "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
447 
448         state.wave=wave_generate_la(&wfx,duration,&state.wave_len,ieee);
449 
450         state.dsbo=*dsbo;
451         state.wfx=&wfx;
452         state.buffer_size=dsbcaps.dwBufferBytes;
453         state.played=state.written=state.offset=0;
454         buffer_refill8(&state,state.buffer_size);
455 
456         rc=IDirectSoundBuffer_Play(*dsbo,0,0,DSBPLAY_LOOPING);
457         ok(rc==DS_OK,"IDirectSoundBuffer_Play() failed: %08x\n", rc);
458 
459         rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
460         ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
461         ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
462            "GetStatus: bad status: %x\n",status);
463 
464         if (listener) {
465             ZeroMemory(&listener_param,sizeof(listener_param));
466             listener_param.dwSize=sizeof(listener_param);
467             rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
468             ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
469                "failed: %08x\n",rc);
470             if (move_listener) {
471                 listener_param.vPosition.x = -5.0f;
472                 listener_param.vVelocity.x = (float)(10.0/duration);
473             }
474             rc=IDirectSound3DListener_SetAllParameters(listener,
475                                                        &listener_param,
476                                                        DS3D_IMMEDIATE);
477             ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n", rc);
478         }
479         if (buffer3d) {
480             if (move_sound) {
481                 buffer_param.vPosition.x = 100.0f;
482                 buffer_param.vVelocity.x = (float)(-200.0/duration);
483             }
484             buffer_param.flMinDistance = 10;
485             rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,
486                                                      DS3D_IMMEDIATE);
487             ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
488         }
489 
490         start_time=GetTickCount();
491         while (buffer_service8(&state)) {
492             WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
493             now=GetTickCount();
494             if (listener && move_listener) {
495                 listener_param.vPosition.x = (float)(-5.0+10.0*(now-start_time)/1000/duration);
496                 if (winetest_debug>2)
497                     trace("listener position=%g\n",listener_param.vPosition.x);
498                 rc=IDirectSound3DListener_SetPosition(listener,
499                     listener_param.vPosition.x,listener_param.vPosition.y,
500                     listener_param.vPosition.z,DS3D_IMMEDIATE);
501                 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n",rc);
502             }
503             if (buffer3d && move_sound) {
504                 buffer_param.vPosition.x = (float)(100-200.0*(now-start_time)/1000/duration);
505                 if (winetest_debug>2)
506                     trace("sound position=%g\n",buffer_param.vPosition.x);
507                 rc=IDirectSound3DBuffer_SetPosition(buffer,
508                     buffer_param.vPosition.x,buffer_param.vPosition.y,
509                     buffer_param.vPosition.z,DS3D_IMMEDIATE);
510                 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
511             }
512         }
513         /* Check the sound duration was within 10% of the expected value */
514         now=GetTickCount();
515         ok(fabs(1000*duration-now+start_time)<=100*duration,
516            "The sound played for %d ms instead of %g ms\n",
517            now-start_time,1000*duration);
518 
519         HeapFree(GetProcessHeap(), 0, state.wave);
520         if (is_primary) {
521             /* Set the CooperativeLevel back to normal */
522             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
523             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
524             ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
525                "failed: %08x\n",rc);
526         }
527         if (buffer3d) {
528             ref=IDirectSound3DBuffer_Release(buffer);
529             ok(ref==0,"IDirectSound3DBuffer_Release() has %d references, "
530                "should have 0\n",ref);
531         }
532     }
533 }
534 
test_secondary8(LPGUID lpGuid,int play,int has_3d,int has_3dbuffer,int has_listener,int has_duplicate,int move_listener,int move_sound)535 static HRESULT test_secondary8(LPGUID lpGuid, int play,
536                                int has_3d, int has_3dbuffer,
537                                int has_listener, int has_duplicate,
538                                int move_listener, int move_sound)
539 {
540     HRESULT rc;
541     LPDIRECTSOUND8 dso=NULL;
542     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
543     LPDIRECTSOUND3DLISTENER listener=NULL;
544     DSBUFFERDESC bufdesc;
545     WAVEFORMATEX wfx, wfx1;
546     int ref;
547 
548     /* Create the DirectSound object */
549     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
550     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
551     if (rc!=DS_OK)
552         return rc;
553 
554     /* We must call SetCooperativeLevel before creating primary buffer */
555     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
556     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
557     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
558     if (rc!=DS_OK)
559         goto EXIT;
560 
561     ZeroMemory(&bufdesc, sizeof(bufdesc));
562     bufdesc.dwSize=sizeof(bufdesc);
563     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
564     if (has_3d)
565         bufdesc.dwFlags|=DSBCAPS_CTRL3D;
566     else
567         bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
568     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
569     ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
570        "IDirectSound8_CreateSoundBuffer() failed to create a %sprimary buffer: %08x\n",has_3d?"3D ":"", rc);
571     if (rc == DSERR_CONTROLUNAVAIL)
572         trace("  No Primary\n");
573     else if (rc==DS_OK && primary!=NULL) {
574         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
575         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
576         if (rc!=DS_OK)
577             goto EXIT1;
578 
579         if (has_listener) {
580             rc=IDirectSoundBuffer_QueryInterface(primary,
581                                                  &IID_IDirectSound3DListener,
582                                                  (void **)&listener);
583             ok(rc==DS_OK && listener!=NULL,
584                "IDirectSoundBuffer_QueryInterface() failed to get a 3D "
585                "listener %08x\n",rc);
586             ref=IDirectSoundBuffer_Release(primary);
587             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
588                "should have 0\n",ref);
589             if (rc==DS_OK && listener!=NULL) {
590                 DS3DLISTENER listener_param;
591                 ZeroMemory(&listener_param,sizeof(listener_param));
592                 /* DSOUND: Error: Invalid buffer */
593                 rc=IDirectSound3DListener_GetAllParameters(listener,0);
594                 ok(rc==DSERR_INVALIDPARAM,
595                    "IDirectSound3dListener_GetAllParameters() should have "
596                    "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
597 
598                 /* DSOUND: Error: Invalid buffer */
599                 rc=IDirectSound3DListener_GetAllParameters(listener,
600                                                            &listener_param);
601                 ok(rc==DSERR_INVALIDPARAM,
602                    "IDirectSound3dListener_GetAllParameters() should have "
603                    "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
604 
605                 listener_param.dwSize=sizeof(listener_param);
606                 rc=IDirectSound3DListener_GetAllParameters(listener,
607                                                            &listener_param);
608                 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
609                    "failed: %08x\n",rc);
610             } else {
611                 ok(listener==NULL, "IDirectSoundBuffer_QueryInterface() "
612                    "failed but returned a listener anyway\n");
613                 ok(rc!=DS_OK, "IDirectSoundBuffer_QueryInterface() succeeded "
614                    "but returned a NULL listener\n");
615                 if (listener) {
616                     ref=IDirectSound3DListener_Release(listener);
617                     ok(ref==0,"IDirectSound3dListener_Release() listener has "
618                        "%d references, should have 0\n",ref);
619                 }
620                 goto EXIT2;
621             }
622         }
623 
624         init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
625         secondary=NULL;
626         ZeroMemory(&bufdesc, sizeof(bufdesc));
627         bufdesc.dwSize=sizeof(bufdesc);
628         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
629         if (has_3d)
630             bufdesc.dwFlags|=DSBCAPS_CTRL3D;
631         else
632             bufdesc.dwFlags|=
633                 (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
634         bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
635                                     wfx.nBlockAlign);
636         bufdesc.lpwfxFormat=&wfx;
637         if (has_3d) {
638             /* a stereo 3D buffer should fail */
639             rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
640             ok(rc==DSERR_INVALIDPARAM,
641                "IDirectSound8_CreateSoundBuffer(secondary) should have "
642                "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
643             if (secondary)
644             {
645                 ref=IDirectSoundBuffer_Release(secondary);
646                 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, should have 0\n",ref);
647             }
648             init_format(&wfx,WAVE_FORMAT_PCM,22050,16,1);
649         }
650 
651         if (winetest_interactive) {
652             trace("  Testing a %s%ssecondary buffer %s%s%s%sat %dx%dx%d "
653                   "with a primary buffer at %dx%dx%d\n",
654                   has_3dbuffer?"3D ":"",
655                   has_duplicate?"duplicated ":"",
656                   listener!=NULL||move_sound?"with ":"",
657                   move_listener?"moving ":"",
658                   listener!=NULL?"listener ":"",
659                   listener&&move_sound?"and moving sound ":move_sound?
660                   "moving sound ":"",
661                   wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
662                   wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
663         }
664         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
665         ok(rc==DS_OK && secondary!=NULL,"IDirectSound8_CreateSoundBuffer() "
666            "failed to create a %s%ssecondary buffer %s%s%s%sat %dx%dx%d (%s): %08x\n",
667            has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"",
668            listener!=NULL||move_sound?"with ":"", move_listener?"moving ":"",
669            listener!=NULL?"listener ":"",
670            listener&&move_sound?"and moving sound ":move_sound?
671            "moving sound ":"",
672            wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
673            getDSBCAPS(bufdesc.dwFlags),rc);
674         if (rc==DS_OK && secondary!=NULL) {
675             if (!has_3d) {
676                 LONG refvol,vol,refpan,pan;
677 
678                 /* Check the initial secondary buffer's volume and pan */
679                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
680                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(secondary) failed: %08x\n",rc);
681                 ok(vol==0,"wrong volume for a new secondary buffer: %d\n",vol);
682                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
683                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: %08x\n",rc);
684                 ok(pan==0,"wrong pan for a new secondary buffer: %d\n",pan);
685 
686                 /* Check that changing the secondary buffer's volume and pan
687                  * does not impact the primary buffer's volume and pan
688                  */
689                 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
690                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: %08x\n",rc);
691                 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
692                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
693 
694                 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
695                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
696                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
697                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
698                 ok(vol==-1000,"secondary: wrong volume %d instead of -1000\n",
699                    vol);
700                 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
701                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
702                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
703                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: %08x\n",rc);
704                 ok(pan==-1000,"secondary: wrong pan %d instead of -1000\n",
705                    pan);
706 
707                 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
708                 ok(rc==DS_OK,"IDirectSoundBuffer_`GetVolume(primary) failed: i%08x\n",rc);
709                 ok(vol==refvol,"The primary volume changed from %d to %d\n",
710                    refvol,vol);
711                 rc=IDirectSoundBuffer_GetPan(primary,&pan);
712                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
713                 ok(pan==refpan,"The primary pan changed from %d to %d\n",
714                    refpan,pan);
715 
716                 rc=IDirectSoundBuffer_SetVolume(secondary,0);
717                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
718                 rc=IDirectSoundBuffer_SetPan(secondary,0);
719                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
720             }
721             if (has_duplicate) {
722                 LPDIRECTSOUNDBUFFER duplicated=NULL;
723 
724                 /* DSOUND: Error: Invalid source buffer */
725                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,0);
726                 ok(rc==DSERR_INVALIDPARAM,
727                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
728                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
729 
730                 /* DSOUND: Error: Invalid dest buffer */
731                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,0);
732                 ok(rc==DSERR_INVALIDPARAM,
733                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
734                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
735 
736                 /* DSOUND: Error: Invalid source buffer */
737                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,&duplicated);
738                 ok(rc==DSERR_INVALIDPARAM,
739                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
740                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
741 
742                 duplicated=NULL;
743                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,
744                                                       &duplicated);
745                 ok(rc==DS_OK && duplicated!=NULL,
746                    "IDirectSound8_DuplicateSoundBuffer() failed to duplicate "
747                    "a secondary buffer: %08x\n",rc);
748 
749                 if (rc==DS_OK && duplicated!=NULL) {
750                     ref=IDirectSoundBuffer_Release(secondary);
751                     ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
752                        "references, should have 0\n",ref);
753                     secondary=duplicated;
754                 }
755             }
756 
757             if (rc==DS_OK && secondary!=NULL) {
758                 double duration;
759                 duration=(move_listener || move_sound?4.0:1.0);
760                 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
761                              winetest_interactive,duration,has_3dbuffer,
762                              listener,move_listener,move_sound);
763                 ref=IDirectSoundBuffer_Release(secondary);
764                 ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, "
765                    "should have 0\n",has_duplicate?"duplicated":"secondary",
766                    ref);
767             }
768         }
769 EXIT1:
770         if (has_listener) {
771             if (listener) {
772                 ref=IDirectSound3DListener_Release(listener);
773                 ok(ref==0,"IDirectSound3dListener_Release() listener has %d "
774                    "references, should have 0\n",ref);
775             }
776         } else {
777             ref=IDirectSoundBuffer_Release(primary);
778             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
779                "should have 0\n",ref);
780         }
781     } else {
782         ok(primary==NULL,"IDirectSound8_CreateSoundBuffer(primary) failed "
783            "but primary created anyway\n");
784         ok(rc!=DS_OK,"IDirectSound8_CreateSoundBuffer(primary) succeeded "
785            "but primary not created\n");
786         if (primary) {
787             ref=IDirectSoundBuffer_Release(primary);
788             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
789                "should have 0\n",ref);
790         }
791     }
792 EXIT2:
793     /* Set the CooperativeLevel back to normal */
794     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
795     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
796     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
797 
798 EXIT:
799     ref=IDirectSound8_Release(dso);
800     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
801     if (ref!=0)
802         return DSERR_GENERIC;
803 
804     return rc;
805 }
806 
test_for_driver8(LPGUID lpGuid)807 static HRESULT test_for_driver8(LPGUID lpGuid)
808 {
809     HRESULT rc;
810     LPDIRECTSOUND8 dso=NULL;
811     int ref;
812 
813     /* Create the DirectSound object */
814     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
815     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
816        "DirectSoundCreate8() failed: %08x\n",rc);
817     if (rc!=DS_OK)
818         return rc;
819 
820     ref=IDirectSound8_Release(dso);
821     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
822     if (ref!=0)
823         return DSERR_GENERIC;
824 
825     return rc;
826 }
827 
test_primary8(LPGUID lpGuid)828 static HRESULT test_primary8(LPGUID lpGuid)
829 {
830     HRESULT rc;
831     LPDIRECTSOUND8 dso=NULL;
832     LPDIRECTSOUNDBUFFER primary=NULL;
833     DSBUFFERDESC bufdesc;
834     DSCAPS dscaps;
835     int ref, i;
836 
837     /* Create the DirectSound object */
838     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
839     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
840     if (rc!=DS_OK)
841         return rc;
842 
843     /* Get the device capabilities */
844     ZeroMemory(&dscaps, sizeof(dscaps));
845     dscaps.dwSize=sizeof(dscaps);
846     rc=IDirectSound8_GetCaps(dso,&dscaps);
847     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
848     if (rc!=DS_OK)
849         goto EXIT;
850 
851     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
852     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
853     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
854     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
855     if (rc!=DS_OK)
856         goto EXIT;
857 
858     /* Testing the primary buffer */
859     primary=NULL;
860     ZeroMemory(&bufdesc, sizeof(bufdesc));
861     bufdesc.dwSize=sizeof(bufdesc);
862     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
863     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
864     ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
865        "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: %08x\n",rc);
866     if (rc == DSERR_CONTROLUNAVAIL)
867         trace("  No Primary\n");
868     else if (rc==DS_OK && primary!=NULL) {
869         test_buffer8(dso,&primary,1,TRUE,0,TRUE,0,winetest_interactive &&
870                      !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
871         if (winetest_interactive) {
872             LONG volume,pan;
873 
874             volume = DSBVOLUME_MAX;
875             for (i = 0; i < 6; i++) {
876                 test_buffer8(dso,&primary,1,TRUE,volume,TRUE,0,
877                              winetest_interactive &&
878                              !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
879                              1.0,0,NULL,0,0);
880                 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
881             }
882 
883             pan = DSBPAN_LEFT;
884             for (i = 0; i < 7; i++) {
885                 test_buffer8(dso,&primary,1,TRUE,0,TRUE,pan,
886                              winetest_interactive &&
887                              !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
888                 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
889             }
890         }
891         ref=IDirectSoundBuffer_Release(primary);
892         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
893            "should have 0\n",ref);
894     }
895 
896     /* Set the CooperativeLevel back to normal */
897     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
898     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
899     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
900 
901 EXIT:
902     ref=IDirectSound8_Release(dso);
903     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
904     if (ref!=0)
905         return DSERR_GENERIC;
906 
907     return rc;
908 }
909 
test_primary_3d8(LPGUID lpGuid)910 static HRESULT test_primary_3d8(LPGUID lpGuid)
911 {
912     HRESULT rc;
913     LPDIRECTSOUND8 dso=NULL;
914     LPDIRECTSOUNDBUFFER primary=NULL;
915     DSBUFFERDESC bufdesc;
916     DSCAPS dscaps;
917     int ref;
918 
919     /* Create the DirectSound object */
920     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
921     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
922     if (rc!=DS_OK)
923         return rc;
924 
925     /* Get the device capabilities */
926     ZeroMemory(&dscaps, sizeof(dscaps));
927     dscaps.dwSize=sizeof(dscaps);
928     rc=IDirectSound8_GetCaps(dso,&dscaps);
929     ok(rc==DS_OK,"IDirectSound8_GetCaps failed: %08x\n",rc);
930     if (rc!=DS_OK)
931         goto EXIT;
932 
933     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
934     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
935     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
936     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
937     if (rc!=DS_OK)
938         goto EXIT;
939 
940     primary=NULL;
941     ZeroMemory(&bufdesc, sizeof(bufdesc));
942     bufdesc.dwSize=sizeof(bufdesc);
943     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
944     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
945     ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
946        "to create a primary buffer: %08x\n",rc);
947     if (rc==DS_OK && primary!=NULL) {
948         ref=IDirectSoundBuffer_Release(primary);
949         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
950            "should have 0\n",ref);
951         primary=NULL;
952         ZeroMemory(&bufdesc, sizeof(bufdesc));
953         bufdesc.dwSize=sizeof(bufdesc);
954         bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
955         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
956         ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() "
957            "failed to create a 3D primary buffer: %08x\n",rc);
958         if (rc==DS_OK && primary!=NULL) {
959             test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
960                          winetest_interactive &&
961                          !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
962             ref=IDirectSoundBuffer_Release(primary);
963             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
964                "should have 0\n",ref);
965         }
966     }
967     /* Set the CooperativeLevel back to normal */
968     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
969     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
970     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
971 
972 EXIT:
973     ref=IDirectSound8_Release(dso);
974     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
975     if (ref!=0)
976         return DSERR_GENERIC;
977 
978     return rc;
979 }
980 
test_primary_3d_with_listener8(LPGUID lpGuid)981 static HRESULT test_primary_3d_with_listener8(LPGUID lpGuid)
982 {
983     HRESULT rc;
984     LPDIRECTSOUND8 dso=NULL;
985     LPDIRECTSOUNDBUFFER primary=NULL;
986     DSBUFFERDESC bufdesc;
987     DSCAPS dscaps;
988     int ref;
989 
990     /* Create the DirectSound object */
991     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
992     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
993     if (rc!=DS_OK)
994         return rc;
995 
996     /* Get the device capabilities */
997     ZeroMemory(&dscaps, sizeof(dscaps));
998     dscaps.dwSize=sizeof(dscaps);
999     rc=IDirectSound8_GetCaps(dso,&dscaps);
1000     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
1001     if (rc!=DS_OK)
1002         goto EXIT;
1003 
1004     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
1005     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1006     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1007     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
1008     if (rc!=DS_OK)
1009         goto EXIT;
1010     primary=NULL;
1011     ZeroMemory(&bufdesc, sizeof(bufdesc));
1012     bufdesc.dwSize=sizeof(bufdesc);
1013     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
1014     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1015     ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
1016        "to create a 3D primary buffer %08x\n",rc);
1017     if (rc==DS_OK && primary!=NULL) {
1018         LPDIRECTSOUND3DLISTENER listener=NULL;
1019         rc=IDirectSoundBuffer_QueryInterface(primary,
1020                                              &IID_IDirectSound3DListener,
1021                                              (void **)&listener);
1022         ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface() "
1023            "failed to get a 3D listener: %08x\n",rc);
1024         if (rc==DS_OK && listener!=NULL) {
1025             LPDIRECTSOUNDBUFFER temp_buffer=NULL;
1026 
1027             /* Checking the COM interface */
1028             rc=IDirectSoundBuffer_QueryInterface(primary,
1029                                                  &IID_IDirectSoundBuffer,
1030                                                  (LPVOID *)&temp_buffer);
1031             ok(rc==DS_OK && temp_buffer!=NULL,
1032                "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
1033             ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1034             if (rc==DS_OK && temp_buffer!=NULL) {
1035                 ref=IDirectSoundBuffer_Release(temp_buffer);
1036                 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1037                    "should have 1\n",ref);
1038 
1039                 temp_buffer=NULL;
1040                 rc=IDirectSound3DListener_QueryInterface(listener,
1041                     &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
1042                 ok(rc==DS_OK && temp_buffer!=NULL,
1043                    "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
1044                 ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1045                 ref=IDirectSoundBuffer_Release(temp_buffer);
1046                 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1047                    "should have 1\n",ref);
1048 
1049                 /* Testing the buffer */
1050                 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
1051                              winetest_interactive &&
1052                              !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
1053                              1.0,0,listener,0,0);
1054             }
1055 
1056             /* Testing the reference counting */
1057             ref=IDirectSound3DListener_Release(listener);
1058             ok(ref==0,"IDirectSound3DListener_Release() listener has %d "
1059                "references, should have 0\n",ref);
1060         }
1061 
1062         /* Testing the reference counting */
1063         ref=IDirectSoundBuffer_Release(primary);
1064         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1065            "should have 0\n",ref);
1066     }
1067 
1068 EXIT:
1069     ref=IDirectSound8_Release(dso);
1070     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
1071     if (ref!=0)
1072 return DSERR_GENERIC;
1073 
1074     return rc;
1075 }
1076 
1077 static unsigned driver_count = 0;
1078 
dsenum_callback(LPGUID lpGuid,LPCSTR lpcstrDescription,LPCSTR lpcstrModule,LPVOID lpContext)1079 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1080                                    LPCSTR lpcstrModule, LPVOID lpContext)
1081 {
1082     HRESULT rc;
1083     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1084     driver_count++;
1085 
1086     rc = test_for_driver8(lpGuid);
1087     if (rc == DSERR_NODRIVER) {
1088         trace("  No Driver\n");
1089         return 1;
1090     } else if (rc == DSERR_ALLOCATED) {
1091         trace("  Already In Use\n");
1092         return 1;
1093     } else if (rc == E_FAIL) {
1094         trace("  No Device\n");
1095         return 1;
1096     }
1097 
1098     trace("  Testing the primary buffer\n");
1099     test_primary8(lpGuid);
1100 
1101     trace("  Testing 3D primary buffer\n");
1102     test_primary_3d8(lpGuid);
1103 
1104     trace("  Testing 3D primary buffer with listener\n");
1105     test_primary_3d_with_listener8(lpGuid);
1106 
1107     /* Testing secondary buffers */
1108     test_secondary8(lpGuid,winetest_interactive,0,0,0,0,0,0);
1109     test_secondary8(lpGuid,winetest_interactive,0,0,0,1,0,0);
1110 
1111     /* Testing 3D secondary buffers */
1112     test_secondary8(lpGuid,winetest_interactive,1,0,0,0,0,0);
1113     test_secondary8(lpGuid,winetest_interactive,1,1,0,0,0,0);
1114     test_secondary8(lpGuid,winetest_interactive,1,1,0,1,0,0);
1115     test_secondary8(lpGuid,winetest_interactive,1,0,1,0,0,0);
1116     test_secondary8(lpGuid,winetest_interactive,1,0,1,1,0,0);
1117     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,0);
1118     test_secondary8(lpGuid,winetest_interactive,1,1,1,1,0,0);
1119     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,0);
1120     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,1);
1121     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,1);
1122 
1123     return 1;
1124 }
1125 
ds3d8_tests(void)1126 static void ds3d8_tests(void)
1127 {
1128     HRESULT rc;
1129     rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
1130     ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc);
1131     trace("tested %u DirectSound drivers\n", driver_count);
1132 }
1133 
START_TEST(ds3d8)1134 START_TEST(ds3d8)
1135 {
1136     HMODULE hDsound;
1137 
1138     CoInitialize(NULL);
1139 
1140     hDsound = LoadLibrary("dsound.dll");
1141     if (hDsound)
1142     {
1143 
1144         pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1145             "DirectSoundEnumerateA");
1146         pDirectSoundCreate8 = (void*)GetProcAddress(hDsound,
1147             "DirectSoundCreate8");
1148         if (pDirectSoundCreate8)
1149             ds3d8_tests();
1150         else
1151             skip("DirectSoundCreate8 missing - skipping all tests\n");
1152 
1153         FreeLibrary(hDsound);
1154     }
1155     else
1156         skip("dsound.dll not found - skipping all tests\n");
1157 
1158     CoUninitialize();
1159 }
1160