Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / dsound / sound3d.c
1 /*                      DirectSound
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998 Rob Riggs
5  * Copyright 2000-2001 TransGaming Technologies, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 /*
22  * Most thread locking is complete. There may be a few race
23  * conditions still lurking.
24  *
25  * Tested with a Soundblaster clone, a Gravis UltraSound Classic,
26  * and a Turtle Beach Tropez+.
27  *
28  * TODO:
29  *      Implement SetCooperativeLevel properly (need to address focus issues)
30  *      Implement DirectSound3DBuffers (stubs in place)
31  *      Use hardware 3D support if available
32  *      Add critical section locking inside Release and AddRef methods
33  *      Handle static buffers - put those in hardware, non-static not in hardware
34  *      Hardware DuplicateSoundBuffer
35  *      Proper volume calculation, and setting volume in HEL primary buffer
36  *      Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN
37  */
38
39 #include "config.h"
40 #include <assert.h>
41 #include <stdio.h>
42 #include <sys/types.h>
43 #include <sys/fcntl.h>
44 #include <unistd.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <math.h>       /* Insomnia - pow() function */
48
49 #include "windef.h"
50 #include "winbase.h"
51 #include "wingdi.h"
52 #include "winuser.h"
53 #include "winerror.h"
54 #include "mmsystem.h"
55 #include "ntddk.h"
56 #include "mmddk.h"
57 #include "wine/windef16.h"
58 #include "wine/debug.h"
59 #include "dsound.h"
60 #include "dsdriver.h"
61 #include "dsound_private.h"
62
63 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
64
65
66 /*******************************************************************************
67  *              IDirectSound3DBuffer
68  */
69
70 /* IUnknown methods */
71 static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
72         LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj)
73 {
74         ICOM_THIS(IDirectSound3DBufferImpl,iface);
75
76         TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
77         return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
78 }
79
80 static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
81 {
82         ICOM_THIS(IDirectSound3DBufferImpl,iface);
83         ULONG ulReturn;
84
85         TRACE("(%p) ref was %ld\n", This, This->ref);
86         ulReturn = InterlockedIncrement(&This->ref);
87         if (ulReturn == 1)
88                 IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
89         return ulReturn;
90 }
91
92 static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
93 {
94         ICOM_THIS(IDirectSound3DBufferImpl,iface);
95         ULONG ulReturn;
96
97         TRACE("(%p) ref was %ld\n", This, This->ref);
98
99         ulReturn = InterlockedDecrement(&This->ref);
100         if(ulReturn)
101                 return ulReturn;
102
103         if (This->dsb) {
104                 BOOL std = (This->dsb->dsbd.dwFlags & DSBCAPS_CTRL3D);
105
106                 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
107
108                 if (std)
109                         return 0; /* leave it to IDirectSoundBufferImpl_Release */
110         }
111
112         if (This->dsb->ds3db == This) This->dsb->ds3db = NULL;
113
114         DeleteCriticalSection(&This->lock);
115
116         HeapFree(GetProcessHeap(),0,This);
117
118         return 0;
119 }
120
121 /* IDirectSound3DBuffer methods */
122 static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
123         LPDIRECTSOUND3DBUFFER iface,
124         LPDS3DBUFFER lpDs3dBuffer)
125 {
126         FIXME("stub\n");
127         return DS_OK;
128 }
129
130 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
131         LPDIRECTSOUND3DBUFFER iface,
132         LPDWORD lpdwInsideConeAngle,
133         LPDWORD lpdwOutsideConeAngle)
134 {
135         FIXME("stub\n");
136         return DS_OK;
137 }
138
139 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
140         LPDIRECTSOUND3DBUFFER iface,
141         LPD3DVECTOR lpvConeOrientation)
142 {
143         FIXME("stub\n");
144         return DS_OK;
145 }
146
147 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
148         LPDIRECTSOUND3DBUFFER iface,
149         LPLONG lplConeOutsideVolume)
150 {
151         FIXME("stub\n");
152         return DS_OK;
153 }
154
155 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
156         LPDIRECTSOUND3DBUFFER iface,
157         LPD3DVALUE lpfMaxDistance)
158 {
159         FIXME("stub\n");
160         return DS_OK;
161 }
162
163 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
164         LPDIRECTSOUND3DBUFFER iface,
165         LPD3DVALUE lpfMinDistance)
166 {
167         FIXME("stub\n");
168         return DS_OK;
169 }
170
171 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
172         LPDIRECTSOUND3DBUFFER iface,
173         LPDWORD lpdwMode)
174 {
175         FIXME("stub\n");
176         return DS_OK;
177 }
178
179 static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
180         LPDIRECTSOUND3DBUFFER iface,
181         LPD3DVECTOR lpvPosition)
182 {
183         FIXME("stub\n");
184         return DS_OK;
185 }
186
187 static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
188         LPDIRECTSOUND3DBUFFER iface,
189         LPD3DVECTOR lpvVelocity)
190 {
191         FIXME("stub\n");
192         return DS_OK;
193 }
194
195 static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
196         LPDIRECTSOUND3DBUFFER iface,
197         LPCDS3DBUFFER lpcDs3dBuffer,
198         DWORD dwApply)
199 {
200         FIXME("stub\n");
201         return DS_OK;
202 }
203
204 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
205         LPDIRECTSOUND3DBUFFER iface,
206         DWORD dwInsideConeAngle,
207         DWORD dwOutsideConeAngle,
208         DWORD dwApply)
209 {
210         FIXME("stub\n");
211         return DS_OK;
212 }
213
214 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
215         LPDIRECTSOUND3DBUFFER iface,
216         D3DVALUE x, D3DVALUE y, D3DVALUE z,
217         DWORD dwApply)
218 {
219         FIXME("stub\n");
220         return DS_OK;
221 }
222
223 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
224         LPDIRECTSOUND3DBUFFER iface,
225         LONG lConeOutsideVolume,
226         DWORD dwApply)
227 {
228         FIXME("stub\n");
229         return DS_OK;
230 }
231
232 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
233         LPDIRECTSOUND3DBUFFER iface,
234         D3DVALUE fMaxDistance,
235         DWORD dwApply)
236 {
237         FIXME("stub\n");
238         return DS_OK;
239 }
240
241 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
242         LPDIRECTSOUND3DBUFFER iface,
243         D3DVALUE fMinDistance,
244         DWORD dwApply)
245 {
246         FIXME("stub\n");
247         return DS_OK;
248 }
249
250 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
251         LPDIRECTSOUND3DBUFFER iface,
252         DWORD dwMode,
253         DWORD dwApply)
254 {
255         ICOM_THIS(IDirectSound3DBufferImpl,iface);
256         TRACE("mode = %lx\n", dwMode);
257         This->ds3db.dwMode = dwMode;
258         return DS_OK;
259 }
260
261 static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
262         LPDIRECTSOUND3DBUFFER iface,
263         D3DVALUE x, D3DVALUE y, D3DVALUE z,
264         DWORD dwApply)
265 {
266         FIXME("stub\n");
267         return DS_OK;
268 }
269
270 static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
271         LPDIRECTSOUND3DBUFFER iface,
272         D3DVALUE x, D3DVALUE y, D3DVALUE z,
273         DWORD dwApply)
274 {
275         FIXME("stub\n");
276         return DS_OK;
277 }
278
279 static ICOM_VTABLE(IDirectSound3DBuffer) ds3dbvt =
280 {
281         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
282         /* IUnknown methods */
283         IDirectSound3DBufferImpl_QueryInterface,
284         IDirectSound3DBufferImpl_AddRef,
285         IDirectSound3DBufferImpl_Release,
286         /* IDirectSound3DBuffer methods */
287         IDirectSound3DBufferImpl_GetAllParameters,
288         IDirectSound3DBufferImpl_GetConeAngles,
289         IDirectSound3DBufferImpl_GetConeOrientation,
290         IDirectSound3DBufferImpl_GetConeOutsideVolume,
291         IDirectSound3DBufferImpl_GetMaxDistance,
292         IDirectSound3DBufferImpl_GetMinDistance,
293         IDirectSound3DBufferImpl_GetMode,
294         IDirectSound3DBufferImpl_GetPosition,
295         IDirectSound3DBufferImpl_GetVelocity,
296         IDirectSound3DBufferImpl_SetAllParameters,
297         IDirectSound3DBufferImpl_SetConeAngles,
298         IDirectSound3DBufferImpl_SetConeOrientation,
299         IDirectSound3DBufferImpl_SetConeOutsideVolume,
300         IDirectSound3DBufferImpl_SetMaxDistance,
301         IDirectSound3DBufferImpl_SetMinDistance,
302         IDirectSound3DBufferImpl_SetMode,
303         IDirectSound3DBufferImpl_SetPosition,
304         IDirectSound3DBufferImpl_SetVelocity,
305 };
306
307 HRESULT WINAPI IDirectSound3DBufferImpl_Create(
308         IDirectSoundBufferImpl *This,
309         IDirectSound3DBufferImpl **pds3db)
310 {
311         IDirectSound3DBufferImpl *ds3db;
312
313         ds3db = (IDirectSound3DBufferImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*ds3db));
314         ds3db->ref = 0;
315         ds3db->dsb = This;
316         ICOM_VTBL(ds3db) = &ds3dbvt;
317         InitializeCriticalSection(&ds3db->lock);
318
319         ds3db->ds3db.dwSize = sizeof(DS3DBUFFER);
320         ds3db->ds3db.vPosition.u1.x = 0.0;
321         ds3db->ds3db.vPosition.u2.y = 0.0;
322         ds3db->ds3db.vPosition.u3.z = 0.0;
323         ds3db->ds3db.vVelocity.u1.x = 0.0;
324         ds3db->ds3db.vVelocity.u2.y = 0.0;
325         ds3db->ds3db.vVelocity.u3.z = 0.0;
326         ds3db->ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
327         ds3db->ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
328         ds3db->ds3db.vConeOrientation.u1.x = 0.0;
329         ds3db->ds3db.vConeOrientation.u2.y = 0.0;
330         ds3db->ds3db.vConeOrientation.u3.z = 0.0;
331         ds3db->ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
332         ds3db->ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
333         ds3db->ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
334         ds3db->ds3db.dwMode = DS3DMODE_NORMAL;
335
336         *pds3db = ds3db;
337         return S_OK;
338 }
339
340 /*******************************************************************************
341  *            IDirectSound3DListener
342  */
343
344 /* IUnknown methods */
345 static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
346         LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj)
347 {
348         ICOM_THIS(IDirectSound3DListenerImpl,iface);
349
350         TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
351         return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
352 }
353
354 static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
355 {
356         ICOM_THIS(IDirectSound3DListenerImpl,iface);
357         return InterlockedIncrement(&This->ref);
358 }
359
360 static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
361 {
362         ICOM_THIS(IDirectSound3DListenerImpl,iface);
363         ULONG ulReturn;
364
365         TRACE("(%p) ref was %ld\n", This, This->ref);
366
367         ulReturn = InterlockedDecrement(&This->ref);
368
369         /* Free all resources */
370         if( ulReturn == 0 ) {
371                 if(This->dsb)
372                         IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
373                 DeleteCriticalSection(&This->lock);
374                 HeapFree(GetProcessHeap(),0,This);
375         }
376
377         return ulReturn;
378 }
379
380 /* IDirectSound3DListener methods */
381 static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
382         LPDIRECTSOUND3DLISTENER iface,
383         LPDS3DLISTENER lpDS3DL)
384 {
385         FIXME("stub\n");
386         return DS_OK;
387 }
388
389 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
390         LPDIRECTSOUND3DLISTENER iface,
391         LPD3DVALUE lpfDistanceFactor)
392 {
393         FIXME("stub\n");
394         return DS_OK;
395 }
396
397 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
398         LPDIRECTSOUND3DLISTENER iface,
399         LPD3DVALUE lpfDopplerFactor)
400 {
401         FIXME("stub\n");
402         return DS_OK;
403 }
404
405 static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
406         LPDIRECTSOUND3DLISTENER iface,
407         LPD3DVECTOR lpvOrientFront,
408         LPD3DVECTOR lpvOrientTop)
409 {
410         FIXME("stub\n");
411         return DS_OK;
412 }
413
414 static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
415         LPDIRECTSOUND3DLISTENER iface,
416         LPD3DVECTOR lpvPosition)
417 {
418         FIXME("stub\n");
419         return DS_OK;
420 }
421
422 static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
423         LPDIRECTSOUND3DLISTENER iface,
424         LPD3DVALUE lpfRolloffFactor)
425 {
426         FIXME("stub\n");
427         return DS_OK;
428 }
429
430 static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
431         LPDIRECTSOUND3DLISTENER iface,
432         LPD3DVECTOR lpvVelocity)
433 {
434         FIXME("stub\n");
435         return DS_OK;
436 }
437
438 static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
439         LPDIRECTSOUND3DLISTENER iface,
440         LPCDS3DLISTENER lpcDS3DL,
441         DWORD dwApply)
442 {
443         FIXME("stub\n");
444         return DS_OK;
445 }
446
447 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
448         LPDIRECTSOUND3DLISTENER iface,
449         D3DVALUE fDistanceFactor,
450         DWORD dwApply)
451 {
452         FIXME("stub\n");
453         return DS_OK;
454 }
455
456 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
457         LPDIRECTSOUND3DLISTENER iface,
458         D3DVALUE fDopplerFactor,
459         DWORD dwApply)
460 {
461         FIXME("stub\n");
462         return DS_OK;
463 }
464
465 static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
466         LPDIRECTSOUND3DLISTENER iface,
467         D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
468         D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
469         DWORD dwApply)
470 {
471         FIXME("stub\n");
472         return DS_OK;
473 }
474
475 static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
476         LPDIRECTSOUND3DLISTENER iface,
477         D3DVALUE x, D3DVALUE y, D3DVALUE z,
478         DWORD dwApply)
479 {
480         FIXME("stub\n");
481         return DS_OK;
482 }
483
484 static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
485         LPDIRECTSOUND3DLISTENER iface,
486         D3DVALUE fRolloffFactor,
487         DWORD dwApply)
488 {
489         FIXME("stub\n");
490         return DS_OK;
491 }
492
493 static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
494         LPDIRECTSOUND3DLISTENER iface,
495         D3DVALUE x, D3DVALUE y, D3DVALUE z,
496         DWORD dwApply)
497 {
498         FIXME("stub\n");
499         return DS_OK;
500 }
501
502 static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
503         LPDIRECTSOUND3DLISTENER iface)
504
505 {
506         FIXME("stub\n");
507         return DS_OK;
508 }
509
510 static ICOM_VTABLE(IDirectSound3DListener) ds3dlvt =
511 {
512         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
513         /* IUnknown methods */
514         IDirectSound3DListenerImpl_QueryInterface,
515         IDirectSound3DListenerImpl_AddRef,
516         IDirectSound3DListenerImpl_Release,
517         /* IDirectSound3DListener methods */
518         IDirectSound3DListenerImpl_GetAllParameter,
519         IDirectSound3DListenerImpl_GetDistanceFactor,
520         IDirectSound3DListenerImpl_GetDopplerFactor,
521         IDirectSound3DListenerImpl_GetOrientation,
522         IDirectSound3DListenerImpl_GetPosition,
523         IDirectSound3DListenerImpl_GetRolloffFactor,
524         IDirectSound3DListenerImpl_GetVelocity,
525         IDirectSound3DListenerImpl_SetAllParameters,
526         IDirectSound3DListenerImpl_SetDistanceFactor,
527         IDirectSound3DListenerImpl_SetDopplerFactor,
528         IDirectSound3DListenerImpl_SetOrientation,
529         IDirectSound3DListenerImpl_SetPosition,
530         IDirectSound3DListenerImpl_SetRolloffFactor,
531         IDirectSound3DListenerImpl_SetVelocity,
532         IDirectSound3DListenerImpl_CommitDeferredSettings,
533 };
534
535 HRESULT WINAPI IDirectSound3DListenerImpl_Create(
536         PrimaryBufferImpl *This,
537         IDirectSound3DListenerImpl **pdsl)
538 {
539         IDirectSound3DListenerImpl *dsl;
540
541         dsl = (IDirectSound3DListenerImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsl));
542         dsl->ref = 1;
543         ICOM_VTBL(dsl) = &ds3dlvt;
544
545         dsl->ds3dl.dwSize = sizeof(DS3DLISTENER);
546         dsl->ds3dl.vPosition.u1.x = 0.0;
547         dsl->ds3dl.vPosition.u2.y = 0.0;
548         dsl->ds3dl.vPosition.u3.z = 0.0;
549         dsl->ds3dl.vVelocity.u1.x = 0.0;
550         dsl->ds3dl.vVelocity.u2.y = 0.0;
551         dsl->ds3dl.vVelocity.u3.z = 0.0;
552         dsl->ds3dl.vOrientFront.u1.x = 0.0;
553         dsl->ds3dl.vOrientFront.u2.y = 0.0;
554         dsl->ds3dl.vOrientFront.u3.z = 1.0;
555         dsl->ds3dl.vOrientTop.u1.x = 0.0;
556         dsl->ds3dl.vOrientTop.u2.y = 1.0;
557         dsl->ds3dl.vOrientTop.u3.z = 0.0;
558         dsl->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
559         dsl->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
560
561         InitializeCriticalSection(&dsl->lock);
562
563         dsl->dsb = This;
564         IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This);
565
566         *pdsl = dsl;
567         return S_OK;
568 }