Commit | Line | Data |
---|---|---|
935e3df3 OK |
1 | /* DirectSound |
2 | * | |
3 | * Copyright 1998 Marcus Meissner | |
4 | * Copyright 1998 Rob Riggs | |
5 | * Copyright 2000-2001 TransGaming Technologies, Inc. | |
22b09a10 | 6 | * Copyright 2002-2003 Rok Mandeljc <rok.mandeljc@gimb.org> |
935e3df3 OK |
7 | * |
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | * This library is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
935e3df3 OK |
21 | */ |
22 | /* | |
23 | * Most thread locking is complete. There may be a few race | |
24 | * conditions still lurking. | |
25 | * | |
26 | * Tested with a Soundblaster clone, a Gravis UltraSound Classic, | |
27 | * and a Turtle Beach Tropez+. | |
28 | * | |
29 | * TODO: | |
30 | * Implement SetCooperativeLevel properly (need to address focus issues) | |
31 | * Implement DirectSound3DBuffers (stubs in place) | |
32 | * Use hardware 3D support if available | |
33 | * Add critical section locking inside Release and AddRef methods | |
34 | * Handle static buffers - put those in hardware, non-static not in hardware | |
35 | * Hardware DuplicateSoundBuffer | |
36 | * Proper volume calculation, and setting volume in HEL primary buffer | |
37 | * Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN | |
38 | */ | |
39 | ||
e37c6e18 | 40 | #include <stdarg.h> |
935e3df3 OK |
41 | #include <math.h> /* Insomnia - pow() function */ |
42 | ||
297f3d89 DP |
43 | #define NONAMELESSUNION |
44 | #define NONAMELESSSTRUCT | |
935e3df3 OK |
45 | #include "windef.h" |
46 | #include "winbase.h" | |
6727c52f | 47 | #include "winuser.h" |
935e3df3 | 48 | #include "mmsystem.h" |
9c1de6de | 49 | #include "winternl.h" |
935e3df3 | 50 | #include "mmddk.h" |
935e3df3 OK |
51 | #include "wine/debug.h" |
52 | #include "dsound.h" | |
53 | #include "dsdriver.h" | |
54 | #include "dsound_private.h" | |
55 | ||
ce7a2bab RM |
56 | /* default velocity of sound in the air */ |
57 | #define DEFAULT_VELOCITY 340 | |
22b09a10 | 58 | |
1b3ce0d5 | 59 | WINE_DEFAULT_DEBUG_CHANNEL(dsound3d); |
935e3df3 | 60 | |
5b918db6 RM |
61 | /******************************************************************************* |
62 | * Auxiliary functions | |
63 | */ | |
64 | ||
65 | /* scalar product (i believe it's called dot product in english) */ | |
824c9c8e | 66 | static inline D3DVALUE ScalarProduct (const D3DVECTOR *a, const D3DVECTOR *b) |
5b918db6 RM |
67 | { |
68 | D3DVALUE c; | |
e37c6e18 | 69 | c = (a->x*b->x) + (a->y*b->y) + (a->z*b->z); |
3cf9f845 | 70 | TRACE("(%f,%f,%f) * (%f,%f,%f) = %f)\n", a->x, a->y, a->z, b->x, b->y, |
e37c6e18 | 71 | b->z, c); |
5b918db6 RM |
72 | return c; |
73 | } | |
74 | ||
75 | /* vector product (i believe it's called cross product in english */ | |
824c9c8e | 76 | static inline D3DVECTOR VectorProduct (const D3DVECTOR *a, const D3DVECTOR *b) |
5b918db6 | 77 | { |
7da6e5c9 | 78 | D3DVECTOR c; |
e37c6e18 AJ |
79 | c.x = (a->y*b->z) - (a->z*b->y); |
80 | c.y = (a->z*b->x) - (a->x*b->z); | |
81 | c.z = (a->x*b->y) - (a->y*b->x); | |
3cf9f845 | 82 | TRACE("(%f,%f,%f) x (%f,%f,%f) = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y, |
e37c6e18 | 83 | b->z, c.x, c.y, c.z); |
5b918db6 RM |
84 | return c; |
85 | } | |
86 | ||
56aaea2f | 87 | /* magnitude (length) of vector */ |
824c9c8e | 88 | static inline D3DVALUE VectorMagnitude (const D3DVECTOR *a) |
5b918db6 RM |
89 | { |
90 | D3DVALUE l; | |
91 | l = sqrt (ScalarProduct (a, a)); | |
e37c6e18 | 92 | TRACE("|(%f,%f,%f)| = %f\n", a->x, a->y, a->z, l); |
5b918db6 RM |
93 | return l; |
94 | } | |
95 | ||
96 | /* conversion between radians and degrees */ | |
7da6e5c9 | 97 | static inline D3DVALUE RadToDeg (D3DVALUE angle) |
5b918db6 | 98 | { |
7da6e5c9 | 99 | D3DVALUE newangle; |
5b918db6 | 100 | newangle = angle * (360/(2*M_PI)); |
7da6e5c9 | 101 | TRACE("%f rad = %f deg\n", angle, newangle); |
5b918db6 RM |
102 | return newangle; |
103 | } | |
104 | ||
545a774f ML |
105 | /* angle between vectors - rad version */ |
106 | static inline D3DVALUE AngleBetweenVectorsRad (const D3DVECTOR *a, const D3DVECTOR *b) | |
5b918db6 | 107 | { |
7da6e5c9 | 108 | D3DVALUE la, lb, product, angle, cos; |
b3bf746f | 109 | /* definition of scalar product: a*b = |a|*|b|*cos... therefore: */ |
5b918db6 RM |
110 | product = ScalarProduct (a,b); |
111 | la = VectorMagnitude (a); | |
112 | lb = VectorMagnitude (b); | |
3f965d58 ML |
113 | if (!la || !lb) |
114 | return 0; | |
115 | ||
5b918db6 | 116 | cos = product/(la*lb); |
7da6e5c9 | 117 | angle = acos(cos); |
545a774f ML |
118 | TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f radians (%f degrees)\n", a->x, a->y, a->z, b->x, |
119 | b->y, b->z, angle, RadToDeg(angle)); | |
7da6e5c9 RM |
120 | return angle; |
121 | } | |
122 | ||
545a774f | 123 | static inline D3DVALUE AngleBetweenVectorsDeg (const D3DVECTOR *a, const D3DVECTOR *b) |
7da6e5c9 | 124 | { |
545a774f | 125 | return RadToDeg(AngleBetweenVectorsRad(a, b)); |
5b918db6 RM |
126 | } |
127 | ||
1b3ce0d5 | 128 | /* calculates vector between two points */ |
824c9c8e | 129 | static inline D3DVECTOR VectorBetweenTwoPoints (const D3DVECTOR *a, const D3DVECTOR *b) |
1b3ce0d5 RM |
130 | { |
131 | D3DVECTOR c; | |
e37c6e18 AJ |
132 | c.x = b->x - a->x; |
133 | c.y = b->y - a->y; | |
134 | c.z = b->z - a->z; | |
135 | TRACE("A (%f,%f,%f), B (%f,%f,%f), AB = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y, | |
136 | b->z, c.x, c.y, c.z); | |
1b3ce0d5 RM |
137 | return c; |
138 | } | |
139 | ||
9dacf206 | 140 | /* calculates the length of vector's projection on another vector */ |
824c9c8e | 141 | static inline D3DVALUE ProjectVector (const D3DVECTOR *a, const D3DVECTOR *p) |
ce7a2bab RM |
142 | { |
143 | D3DVALUE prod, result; | |
144 | prod = ScalarProduct(a, p); | |
145 | result = prod/VectorMagnitude(p); | |
e37c6e18 AJ |
146 | TRACE("length projection of (%f,%f,%f) on (%f,%f,%f) = %f\n", a->x, a->y, a->z, p->x, |
147 | p->y, p->z, result); | |
ce7a2bab RM |
148 | return result; |
149 | } | |
150 | ||
5b918db6 RM |
151 | /******************************************************************************* |
152 | * 3D Buffer and Listener mixing | |
153 | */ | |
1b3ce0d5 | 154 | |
9dacf206 | 155 | void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) |
5b918db6 | 156 | { |
438985f3 | 157 | /* volume, at which the sound will be played after all calcs. */ |
7da6e5c9 | 158 | D3DVALUE lVolume = 0; |
438985f3 | 159 | /* stuff for distance related stuff calc. */ |
1b3ce0d5 | 160 | D3DVECTOR vDistance; |
7da6e5c9 RM |
161 | D3DVALUE flDistance = 0; |
162 | /* panning related stuff */ | |
163 | D3DVALUE flAngle; | |
164 | D3DVECTOR vLeft; | |
ce7a2bab | 165 | /* doppler shift related stuff */ |
c7bebba1 | 166 | #if 0 |
ce7a2bab | 167 | D3DVALUE flFreq, flBufferVel, flListenerVel; |
c7bebba1 AJ |
168 | #endif |
169 | ||
9dacf206 | 170 | TRACE("(%p)\n",dsb); |
22b09a10 | 171 | |
7da6e5c9 | 172 | /* initial buffer volume */ |
605cc1b0 | 173 | lVolume = dsb->ds3db_lVolume; |
1b3ce0d5 | 174 | |
9dacf206 | 175 | switch (dsb->ds3db_ds3db.dwMode) |
1b3ce0d5 | 176 | { |
53b5a474 | 177 | case DS3DMODE_DISABLE: |
7da6e5c9 RM |
178 | TRACE("3D processing disabled\n"); |
179 | /* this one is here only to eliminate annoying warning message */ | |
9dacf206 | 180 | DSOUND_RecalcVolPan (&dsb->volpan); |
53b5a474 | 181 | break; |
1b3ce0d5 | 182 | case DS3DMODE_NORMAL: |
53b5a474 RM |
183 | TRACE("Normal 3D processing mode\n"); |
184 | /* we need to calculate distance between buffer and listener*/ | |
e49a5c22 | 185 | vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->device->ds3dl.vPosition); |
22b09a10 | 186 | flDistance = VectorMagnitude (&vDistance); |
438985f3 | 187 | break; |
1b3ce0d5 | 188 | case DS3DMODE_HEADRELATIVE: |
53b5a474 RM |
189 | TRACE("Head-relative 3D processing mode\n"); |
190 | /* distance between buffer and listener is same as buffer's position */ | |
9dacf206 | 191 | flDistance = VectorMagnitude (&dsb->ds3db_ds3db.vPosition); |
7da6e5c9 RM |
192 | break; |
193 | } | |
53b5a474 | 194 | |
9dacf206 | 195 | if (flDistance > dsb->ds3db_ds3db.flMaxDistance) |
53b5a474 RM |
196 | { |
197 | /* some apps don't want you to hear too distant sounds... */ | |
9dacf206 | 198 | if (dsb->dsbd.dwFlags & DSBCAPS_MUTE3DATMAXDISTANCE) |
53b5a474 | 199 | { |
9dacf206 RR |
200 | dsb->volpan.lVolume = DSBVOLUME_MIN; |
201 | DSOUND_RecalcVolPan (&dsb->volpan); | |
53b5a474 RM |
202 | /* i guess mixing here would be a waste of power */ |
203 | return; | |
204 | } | |
205 | else | |
9dacf206 | 206 | flDistance = dsb->ds3db_ds3db.flMaxDistance; |
53b5a474 | 207 | } |
9dacf206 RR |
208 | |
209 | if (flDistance < dsb->ds3db_ds3db.flMinDistance) | |
210 | flDistance = dsb->ds3db_ds3db.flMinDistance; | |
53b5a474 | 211 | |
8de6b7da RI |
212 | /* attenuation proportional to the distance squared, converted to millibels as in lVolume*/ |
213 | lVolume -= log10(flDistance/dsb->ds3db_ds3db.flMinDistance * flDistance/dsb->ds3db_ds3db.flMinDistance)*1000; | |
26bd2ec9 | 214 | TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %d to %f\n", flDistance, dsb->ds3db_ds3db.flMinDistance, dsb->ds3db_lVolume, lVolume); |
7da6e5c9 RM |
215 | |
216 | /* conning */ | |
217 | /* sometimes it happens that vConeOrientation vector = (0,0,0); in this case angle is "nan" and it's useless*/ | |
e37c6e18 | 218 | if (dsb->ds3db_ds3db.vConeOrientation.x == 0 && dsb->ds3db_ds3db.vConeOrientation.y == 0 && dsb->ds3db_ds3db.vConeOrientation.z == 0) |
7da6e5c9 RM |
219 | { |
220 | TRACE("conning: cones not set\n"); | |
221 | } | |
222 | else | |
223 | { | |
224 | /* calculate angle */ | |
9dacf206 | 225 | flAngle = AngleBetweenVectorsDeg(&dsb->ds3db_ds3db.vConeOrientation, &vDistance); |
7da6e5c9 | 226 | /* if by any chance it happens that OutsideConeAngle = InsideConeAngle (that means that conning has no effect) */ |
9dacf206 | 227 | if (dsb->ds3db_ds3db.dwInsideConeAngle != dsb->ds3db_ds3db.dwOutsideConeAngle) |
7da6e5c9 RM |
228 | { |
229 | /* my test show that for my way of calc., we need only half of angles */ | |
9dacf206 RR |
230 | DWORD dwInsideConeAngle = dsb->ds3db_ds3db.dwInsideConeAngle/2; |
231 | DWORD dwOutsideConeAngle = dsb->ds3db_ds3db.dwOutsideConeAngle/2; | |
a6ab4c51 ML |
232 | if (dwOutsideConeAngle == dwInsideConeAngle) |
233 | ++dwOutsideConeAngle; | |
234 | ||
7da6e5c9 RM |
235 | /* full volume */ |
236 | if (flAngle < dwInsideConeAngle) | |
237 | flAngle = dwInsideConeAngle; | |
238 | /* min (app defined) volume */ | |
239 | if (flAngle > dwOutsideConeAngle) | |
240 | flAngle = dwOutsideConeAngle; | |
241 | /* this probably isn't the right thing, but it's ok for the time being */ | |
9dacf206 RR |
242 | lVolume += ((dsb->ds3db_ds3db.lConeOutsideVolume)/((dwOutsideConeAngle) - (dwInsideConeAngle))) * flAngle; |
243 | } | |
26bd2ec9 | 244 | TRACE("conning: Angle = %f deg; InsideConeAngle(/2) = %d deg; OutsideConeAngle(/2) = %d deg; ConeOutsideVolume = %d => adjusting volume to %f\n", |
9dacf206 | 245 | flAngle, dsb->ds3db_ds3db.dwInsideConeAngle/2, dsb->ds3db_ds3db.dwOutsideConeAngle/2, dsb->ds3db_ds3db.lConeOutsideVolume, lVolume); |
7da6e5c9 | 246 | } |
9dacf206 | 247 | dsb->volpan.lVolume = lVolume; |
7da6e5c9 RM |
248 | |
249 | /* panning */ | |
e49a5c22 RR |
250 | if (dsb->device->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x && |
251 | dsb->device->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y && | |
252 | dsb->device->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) { | |
9dacf206 RR |
253 | dsb->volpan.lPan = 0; |
254 | flAngle = 0.0; | |
255 | } | |
256 | else | |
257 | { | |
e49a5c22 RR |
258 | vDistance = VectorBetweenTwoPoints(&dsb->device->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition); |
259 | vLeft = VectorProduct(&dsb->device->ds3dl.vOrientFront, &dsb->device->ds3dl.vOrientTop); | |
9dacf206 RR |
260 | flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance); |
261 | /* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */ | |
262 | dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000; | |
263 | } | |
26bd2ec9 | 264 | TRACE("panning: Angle = %f rad, lPan = %d\n", flAngle, dsb->volpan.lPan); |
ce7a2bab RM |
265 | |
266 | /* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */ | |
267 | #if 0 | |
7da6e5c9 | 268 | /* doppler shift*/ |
684a121a | 269 | if ((VectorMagnitude(&ds3db_ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->device->ds3dl.vVelocity) == 0)) |
ce7a2bab RM |
270 | { |
271 | TRACE("doppler: Buffer and Listener don't have velocities\n"); | |
272 | } | |
36e90546 | 273 | else if (ds3db_ds3db.vVelocity != dsb->device->ds3dl.vVelocity) |
ce7a2bab | 274 | { |
684a121a | 275 | /* calculate length of ds3db_ds3db.vVelocity component which causes Doppler Effect |
ce7a2bab RM |
276 | NOTE: if buffer moves TOWARDS the listener, it's velocity component is NEGATIVE |
277 | if buffer moves AWAY from listener, it's velocity component is POSITIVE */ | |
9dacf206 | 278 | flBufferVel = ProjectVector(&dsb->ds3db_ds3db.vVelocity, &vDistance); |
56aaea2f | 279 | /* calculate length of ds3dl.vVelocity component which causes Doppler Effect |
ce7a2bab RM |
280 | NOTE: if listener moves TOWARDS the buffer, it's velocity component is POSITIVE |
281 | if listener moves AWAY from buffer, it's velocity component is NEGATIVE */ | |
e49a5c22 | 282 | flListenerVel = ProjectVector(&dsb->device->ds3dl.vVelocity, &vDistance); |
ce7a2bab | 283 | /* formula taken from Gianicoli D.: Physics, 4th edition: */ |
9dacf206 RR |
284 | /* FIXME: replace dsb->freq with appropriate frequency ! */ |
285 | flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel)); | |
3cf9f845 | 286 | TRACE("doppler: Buffer velocity (component) = %lf, Listener velocity (component) = %lf => Doppler shift: %ld Hz -> %lf Hz\n", flBufferVel, flListenerVel, |
9dacf206 | 287 | dsb->freq, flFreq); |
ce7a2bab | 288 | /* FIXME: replace following line with correct frequency setting ! */ |
9dacf206 | 289 | dsb->freq = flFreq; |
36e90546 ML |
290 | DSOUND_RecalcFormat(dsb); |
291 | DSOUND_MixToTemporary(dsb, 0, dsb->buflen); | |
ce7a2bab RM |
292 | } |
293 | #endif | |
7da6e5c9 | 294 | |
ce7a2bab | 295 | /* time for remix */ |
9dacf206 RR |
296 | DSOUND_RecalcVolPan(&dsb->volpan); |
297 | } | |
298 | ||
299 | static void DSOUND_Mix3DBuffer(IDirectSoundBufferImpl *dsb) | |
300 | { | |
301 | TRACE("(%p)\n",dsb); | |
302 | ||
303 | DSOUND_Calc3DBuffer(dsb); | |
5b918db6 RM |
304 | } |
305 | ||
0265676a | 306 | static void DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl) |
5b918db6 | 307 | { |
5b918db6 | 308 | int i; |
a4ed8e77 | 309 | TRACE("(%p)\n",ds3dl); |
e49a5c22 | 310 | for (i = 0; i < ds3dl->device->nrofbuffers; i++) |
5b918db6 | 311 | { |
a7d6ed8e | 312 | /* check if this buffer is waiting for recalculation */ |
e49a5c22 | 313 | if (ds3dl->device->buffers[i]->ds3db_need_recalc) |
1b3ce0d5 | 314 | { |
e49a5c22 | 315 | DSOUND_Mix3DBuffer(ds3dl->device->buffers[i]); |
1b3ce0d5 | 316 | } |
5b918db6 RM |
317 | } |
318 | } | |
935e3df3 OK |
319 | |
320 | /******************************************************************************* | |
321 | * IDirectSound3DBuffer | |
322 | */ | |
323 | ||
324 | /* IUnknown methods */ | |
325 | static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface( | |
326 | LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj) | |
327 | { | |
314b99c4 | 328 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
935e3df3 OK |
329 | |
330 | TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); | |
331 | return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj); | |
332 | } | |
333 | ||
334 | static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface) | |
335 | { | |
f8833dae RR |
336 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
337 | ULONG ref = InterlockedIncrement(&(This->ref)); | |
26bd2ec9 | 338 | TRACE("(%p) ref was %d\n", This, ref - 1); |
f8833dae | 339 | return ref; |
935e3df3 OK |
340 | } |
341 | ||
342 | static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface) | |
343 | { | |
f8833dae RR |
344 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
345 | ULONG ref = InterlockedDecrement(&(This->ref)); | |
26bd2ec9 | 346 | TRACE("(%p) ref was %d\n", This, ref + 1); |
935e3df3 | 347 | |
f8833dae RR |
348 | if (!ref) { |
349 | This->dsb->ds3db = NULL; | |
350 | IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb); | |
351 | HeapFree(GetProcessHeap(), 0, This); | |
352 | TRACE("(%p) released\n", This); | |
353 | } | |
354 | return ref; | |
935e3df3 OK |
355 | } |
356 | ||
357 | /* IDirectSound3DBuffer methods */ | |
358 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters( | |
359 | LPDIRECTSOUND3DBUFFER iface, | |
360 | LPDS3DBUFFER lpDs3dBuffer) | |
361 | { | |
314b99c4 | 362 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
9dacf206 RR |
363 | TRACE("(%p,%p)\n",This,lpDs3dBuffer); |
364 | ||
365 | if (lpDs3dBuffer == NULL) { | |
14a5d168 | 366 | WARN("invalid parameter: lpDs3dBuffer == NULL\n"); |
9dacf206 RR |
367 | return DSERR_INVALIDPARAM; |
368 | } | |
369 | ||
370 | if (lpDs3dBuffer->dwSize < sizeof(*lpDs3dBuffer)) { | |
26bd2ec9 | 371 | WARN("invalid parameter: lpDs3dBuffer->dwSize = %d\n",lpDs3dBuffer->dwSize); |
9dacf206 RR |
372 | return DSERR_INVALIDPARAM; |
373 | } | |
374 | ||
e9ebbfc0 RR |
375 | TRACE("returning: all parameters\n"); |
376 | *lpDs3dBuffer = This->dsb->ds3db_ds3db; | |
935e3df3 OK |
377 | return DS_OK; |
378 | } | |
379 | ||
380 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles( | |
381 | LPDIRECTSOUND3DBUFFER iface, | |
382 | LPDWORD lpdwInsideConeAngle, | |
383 | LPDWORD lpdwOutsideConeAngle) | |
384 | { | |
314b99c4 | 385 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 386 | TRACE("returning: Inside Cone Angle = %d degrees; Outside Cone Angle = %d degrees\n", |
e9ebbfc0 RR |
387 | This->dsb->ds3db_ds3db.dwInsideConeAngle, This->dsb->ds3db_ds3db.dwOutsideConeAngle); |
388 | *lpdwInsideConeAngle = This->dsb->ds3db_ds3db.dwInsideConeAngle; | |
389 | *lpdwOutsideConeAngle = This->dsb->ds3db_ds3db.dwOutsideConeAngle; | |
935e3df3 OK |
390 | return DS_OK; |
391 | } | |
392 | ||
393 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation( | |
394 | LPDIRECTSOUND3DBUFFER iface, | |
395 | LPD3DVECTOR lpvConeOrientation) | |
396 | { | |
314b99c4 | 397 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
e9ebbfc0 | 398 | TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n", |
605cc1b0 RR |
399 | This->dsb->ds3db_ds3db.vConeOrientation.x, |
400 | This->dsb->ds3db_ds3db.vConeOrientation.y, | |
e37c6e18 | 401 | This->dsb->ds3db_ds3db.vConeOrientation.z); |
e9ebbfc0 | 402 | *lpvConeOrientation = This->dsb->ds3db_ds3db.vConeOrientation; |
935e3df3 OK |
403 | return DS_OK; |
404 | } | |
405 | ||
406 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume( | |
407 | LPDIRECTSOUND3DBUFFER iface, | |
408 | LPLONG lplConeOutsideVolume) | |
409 | { | |
314b99c4 | 410 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 411 | TRACE("returning: Cone Outside Volume = %d\n", This->dsb->ds3db_ds3db.lConeOutsideVolume); |
e9ebbfc0 | 412 | *lplConeOutsideVolume = This->dsb->ds3db_ds3db.lConeOutsideVolume; |
935e3df3 OK |
413 | return DS_OK; |
414 | } | |
415 | ||
416 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance( | |
417 | LPDIRECTSOUND3DBUFFER iface, | |
418 | LPD3DVALUE lpfMaxDistance) | |
419 | { | |
314b99c4 | 420 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
e9ebbfc0 RR |
421 | TRACE("returning: Max Distance = %f\n", This->dsb->ds3db_ds3db.flMaxDistance); |
422 | *lpfMaxDistance = This->dsb->ds3db_ds3db.flMaxDistance; | |
935e3df3 OK |
423 | return DS_OK; |
424 | } | |
425 | ||
426 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance( | |
427 | LPDIRECTSOUND3DBUFFER iface, | |
428 | LPD3DVALUE lpfMinDistance) | |
429 | { | |
314b99c4 | 430 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
e9ebbfc0 RR |
431 | TRACE("returning: Min Distance = %f\n", This->dsb->ds3db_ds3db.flMinDistance); |
432 | *lpfMinDistance = This->dsb->ds3db_ds3db.flMinDistance; | |
935e3df3 OK |
433 | return DS_OK; |
434 | } | |
435 | ||
436 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode( | |
437 | LPDIRECTSOUND3DBUFFER iface, | |
438 | LPDWORD lpdwMode) | |
439 | { | |
314b99c4 | 440 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 441 | TRACE("returning: Mode = %d\n", This->dsb->ds3db_ds3db.dwMode); |
e9ebbfc0 | 442 | *lpdwMode = This->dsb->ds3db_ds3db.dwMode; |
935e3df3 OK |
443 | return DS_OK; |
444 | } | |
445 | ||
446 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition( | |
447 | LPDIRECTSOUND3DBUFFER iface, | |
448 | LPD3DVECTOR lpvPosition) | |
449 | { | |
314b99c4 | 450 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
e9ebbfc0 | 451 | TRACE("returning: Position vector = (%f,%f,%f)\n", |
e37c6e18 AJ |
452 | This->dsb->ds3db_ds3db.vPosition.x, |
453 | This->dsb->ds3db_ds3db.vPosition.y, | |
454 | This->dsb->ds3db_ds3db.vPosition.z); | |
e9ebbfc0 | 455 | *lpvPosition = This->dsb->ds3db_ds3db.vPosition; |
935e3df3 OK |
456 | return DS_OK; |
457 | } | |
458 | ||
459 | static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity( | |
460 | LPDIRECTSOUND3DBUFFER iface, | |
461 | LPD3DVECTOR lpvVelocity) | |
462 | { | |
314b99c4 | 463 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
e9ebbfc0 | 464 | TRACE("returning: Velocity vector = (%f,%f,%f)\n", |
e37c6e18 AJ |
465 | This->dsb->ds3db_ds3db.vVelocity.x, |
466 | This->dsb->ds3db_ds3db.vVelocity.y, | |
467 | This->dsb->ds3db_ds3db.vVelocity.z); | |
e9ebbfc0 | 468 | *lpvVelocity = This->dsb->ds3db_ds3db.vVelocity; |
935e3df3 OK |
469 | return DS_OK; |
470 | } | |
471 | ||
472 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters( | |
473 | LPDIRECTSOUND3DBUFFER iface, | |
474 | LPCDS3DBUFFER lpcDs3dBuffer, | |
475 | DWORD dwApply) | |
476 | { | |
314b99c4 | 477 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
9dacf206 | 478 | DWORD status = DSERR_INVALIDPARAM; |
26bd2ec9 | 479 | TRACE("(%p,%p,%x)\n",iface,lpcDs3dBuffer,dwApply); |
9dacf206 RR |
480 | |
481 | if (lpcDs3dBuffer == NULL) { | |
482 | WARN("invalid parameter: lpcDs3dBuffer == NULL\n"); | |
483 | return status; | |
553dded4 | 484 | } |
9dacf206 RR |
485 | |
486 | if (lpcDs3dBuffer->dwSize != sizeof(DS3DBUFFER)) { | |
26bd2ec9 | 487 | WARN("invalid parameter: lpcDs3dBuffer->dwSize = %d\n", lpcDs3dBuffer->dwSize); |
9dacf206 RR |
488 | return status; |
489 | } | |
490 | ||
26bd2ec9 | 491 | TRACE("setting: all parameters; dwApply = %d\n", dwApply); |
e9ebbfc0 | 492 | This->dsb->ds3db_ds3db = *lpcDs3dBuffer; |
9dacf206 | 493 | |
e9ebbfc0 RR |
494 | if (dwApply == DS3D_IMMEDIATE) |
495 | { | |
496 | DSOUND_Mix3DBuffer(This->dsb); | |
497 | } | |
498 | This->dsb->ds3db_need_recalc = TRUE; | |
499 | status = DS_OK; | |
9dacf206 RR |
500 | |
501 | return status; | |
935e3df3 OK |
502 | } |
503 | ||
504 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles( | |
505 | LPDIRECTSOUND3DBUFFER iface, | |
506 | DWORD dwInsideConeAngle, | |
507 | DWORD dwOutsideConeAngle, | |
508 | DWORD dwApply) | |
509 | { | |
314b99c4 | 510 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 511 | TRACE("setting: Inside Cone Angle = %d; Outside Cone Angle = %d; dwApply = %d\n", |
9dacf206 | 512 | dwInsideConeAngle, dwOutsideConeAngle, dwApply); |
e9ebbfc0 RR |
513 | This->dsb->ds3db_ds3db.dwInsideConeAngle = dwInsideConeAngle; |
514 | This->dsb->ds3db_ds3db.dwOutsideConeAngle = dwOutsideConeAngle; | |
515 | if (dwApply == DS3D_IMMEDIATE) | |
516 | { | |
517 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 518 | } |
e9ebbfc0 | 519 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
520 | return DS_OK; |
521 | } | |
522 | ||
523 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation( | |
524 | LPDIRECTSOUND3DBUFFER iface, | |
525 | D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
526 | DWORD dwApply) | |
527 | { | |
314b99c4 | 528 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 529 | TRACE("setting: Cone Orientation vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply); |
e37c6e18 AJ |
530 | This->dsb->ds3db_ds3db.vConeOrientation.x = x; |
531 | This->dsb->ds3db_ds3db.vConeOrientation.y = y; | |
532 | This->dsb->ds3db_ds3db.vConeOrientation.z = z; | |
e9ebbfc0 RR |
533 | if (dwApply == DS3D_IMMEDIATE) |
534 | { | |
535 | This->dsb->ds3db_need_recalc = FALSE; | |
536 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 537 | } |
e9ebbfc0 | 538 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
539 | return DS_OK; |
540 | } | |
541 | ||
542 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume( | |
543 | LPDIRECTSOUND3DBUFFER iface, | |
544 | LONG lConeOutsideVolume, | |
545 | DWORD dwApply) | |
546 | { | |
314b99c4 | 547 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 548 | TRACE("setting: ConeOutsideVolume = %d; dwApply = %d\n", lConeOutsideVolume, dwApply); |
e9ebbfc0 RR |
549 | This->dsb->ds3db_ds3db.lConeOutsideVolume = lConeOutsideVolume; |
550 | if (dwApply == DS3D_IMMEDIATE) | |
551 | { | |
552 | This->dsb->ds3db_need_recalc = FALSE; | |
553 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 554 | } |
e9ebbfc0 | 555 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
556 | return DS_OK; |
557 | } | |
558 | ||
559 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance( | |
560 | LPDIRECTSOUND3DBUFFER iface, | |
561 | D3DVALUE fMaxDistance, | |
562 | DWORD dwApply) | |
563 | { | |
314b99c4 | 564 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 565 | TRACE("setting: MaxDistance = %f; dwApply = %d\n", fMaxDistance, dwApply); |
e9ebbfc0 RR |
566 | This->dsb->ds3db_ds3db.flMaxDistance = fMaxDistance; |
567 | if (dwApply == DS3D_IMMEDIATE) | |
568 | { | |
569 | This->dsb->ds3db_need_recalc = FALSE; | |
570 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 571 | } |
e9ebbfc0 | 572 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
573 | return DS_OK; |
574 | } | |
575 | ||
576 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance( | |
577 | LPDIRECTSOUND3DBUFFER iface, | |
578 | D3DVALUE fMinDistance, | |
579 | DWORD dwApply) | |
580 | { | |
314b99c4 | 581 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 582 | TRACE("setting: MinDistance = %f; dwApply = %d\n", fMinDistance, dwApply); |
e9ebbfc0 RR |
583 | This->dsb->ds3db_ds3db.flMinDistance = fMinDistance; |
584 | if (dwApply == DS3D_IMMEDIATE) | |
585 | { | |
586 | This->dsb->ds3db_need_recalc = FALSE; | |
587 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 588 | } |
e9ebbfc0 | 589 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
590 | return DS_OK; |
591 | } | |
592 | ||
593 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode( | |
594 | LPDIRECTSOUND3DBUFFER iface, | |
595 | DWORD dwMode, | |
596 | DWORD dwApply) | |
597 | { | |
314b99c4 | 598 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 599 | TRACE("setting: Mode = %d; dwApply = %d\n", dwMode, dwApply); |
e9ebbfc0 RR |
600 | This->dsb->ds3db_ds3db.dwMode = dwMode; |
601 | if (dwApply == DS3D_IMMEDIATE) | |
602 | { | |
603 | This->dsb->ds3db_need_recalc = FALSE; | |
604 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 605 | } |
e9ebbfc0 | 606 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
607 | return DS_OK; |
608 | } | |
609 | ||
610 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition( | |
611 | LPDIRECTSOUND3DBUFFER iface, | |
612 | D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
613 | DWORD dwApply) | |
614 | { | |
314b99c4 | 615 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 616 | TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply); |
e37c6e18 AJ |
617 | This->dsb->ds3db_ds3db.vPosition.x = x; |
618 | This->dsb->ds3db_ds3db.vPosition.y = y; | |
619 | This->dsb->ds3db_ds3db.vPosition.z = z; | |
e9ebbfc0 RR |
620 | if (dwApply == DS3D_IMMEDIATE) |
621 | { | |
622 | This->dsb->ds3db_need_recalc = FALSE; | |
623 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 624 | } |
e9ebbfc0 | 625 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
626 | return DS_OK; |
627 | } | |
628 | ||
629 | static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity( | |
630 | LPDIRECTSOUND3DBUFFER iface, | |
631 | D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
632 | DWORD dwApply) | |
633 | { | |
314b99c4 | 634 | IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; |
26bd2ec9 | 635 | TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply); |
e37c6e18 AJ |
636 | This->dsb->ds3db_ds3db.vVelocity.x = x; |
637 | This->dsb->ds3db_ds3db.vVelocity.y = y; | |
638 | This->dsb->ds3db_ds3db.vVelocity.z = z; | |
e9ebbfc0 RR |
639 | if (dwApply == DS3D_IMMEDIATE) |
640 | { | |
641 | This->dsb->ds3db_need_recalc = FALSE; | |
642 | DSOUND_Mix3DBuffer(This->dsb); | |
553dded4 | 643 | } |
e9ebbfc0 | 644 | This->dsb->ds3db_need_recalc = TRUE; |
935e3df3 OK |
645 | return DS_OK; |
646 | } | |
647 | ||
b67da5b9 | 648 | static const IDirectSound3DBufferVtbl ds3dbvt = |
935e3df3 | 649 | { |
935e3df3 OK |
650 | /* IUnknown methods */ |
651 | IDirectSound3DBufferImpl_QueryInterface, | |
652 | IDirectSound3DBufferImpl_AddRef, | |
653 | IDirectSound3DBufferImpl_Release, | |
654 | /* IDirectSound3DBuffer methods */ | |
655 | IDirectSound3DBufferImpl_GetAllParameters, | |
656 | IDirectSound3DBufferImpl_GetConeAngles, | |
657 | IDirectSound3DBufferImpl_GetConeOrientation, | |
658 | IDirectSound3DBufferImpl_GetConeOutsideVolume, | |
659 | IDirectSound3DBufferImpl_GetMaxDistance, | |
660 | IDirectSound3DBufferImpl_GetMinDistance, | |
661 | IDirectSound3DBufferImpl_GetMode, | |
662 | IDirectSound3DBufferImpl_GetPosition, | |
663 | IDirectSound3DBufferImpl_GetVelocity, | |
664 | IDirectSound3DBufferImpl_SetAllParameters, | |
665 | IDirectSound3DBufferImpl_SetConeAngles, | |
666 | IDirectSound3DBufferImpl_SetConeOrientation, | |
667 | IDirectSound3DBufferImpl_SetConeOutsideVolume, | |
668 | IDirectSound3DBufferImpl_SetMaxDistance, | |
669 | IDirectSound3DBufferImpl_SetMinDistance, | |
670 | IDirectSound3DBufferImpl_SetMode, | |
671 | IDirectSound3DBufferImpl_SetPosition, | |
672 | IDirectSound3DBufferImpl_SetVelocity, | |
673 | }; | |
674 | ||
0265676a | 675 | HRESULT IDirectSound3DBufferImpl_Create( |
5ec32cec | 676 | IDirectSoundBufferImpl *dsb, |
935e3df3 OK |
677 | IDirectSound3DBufferImpl **pds3db) |
678 | { | |
679 | IDirectSound3DBufferImpl *ds3db; | |
5ec32cec | 680 | TRACE("(%p,%p)\n",dsb,pds3db); |
a4ed8e77 | 681 | |
dfe3c1c5 | 682 | ds3db = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*ds3db)); |
a4ed8e77 RR |
683 | |
684 | if (ds3db == NULL) { | |
685 | WARN("out of memory\n"); | |
9dacf206 | 686 | *pds3db = 0; |
a4ed8e77 RR |
687 | return DSERR_OUTOFMEMORY; |
688 | } | |
935e3df3 | 689 | |
935e3df3 | 690 | ds3db->ref = 0; |
5ec32cec | 691 | ds3db->dsb = dsb; |
c2ebe1ff | 692 | ds3db->lpVtbl = &ds3dbvt; |
9dacf206 RR |
693 | |
694 | ds3db->dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER); | |
e37c6e18 AJ |
695 | ds3db->dsb->ds3db_ds3db.vPosition.x = 0.0; |
696 | ds3db->dsb->ds3db_ds3db.vPosition.y = 0.0; | |
697 | ds3db->dsb->ds3db_ds3db.vPosition.z = 0.0; | |
698 | ds3db->dsb->ds3db_ds3db.vVelocity.x = 0.0; | |
699 | ds3db->dsb->ds3db_ds3db.vVelocity.y = 0.0; | |
700 | ds3db->dsb->ds3db_ds3db.vVelocity.z = 0.0; | |
9dacf206 RR |
701 | ds3db->dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE; |
702 | ds3db->dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE; | |
e37c6e18 AJ |
703 | ds3db->dsb->ds3db_ds3db.vConeOrientation.x = 0.0; |
704 | ds3db->dsb->ds3db_ds3db.vConeOrientation.y = 0.0; | |
705 | ds3db->dsb->ds3db_ds3db.vConeOrientation.z = 0.0; | |
9dacf206 RR |
706 | ds3db->dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME; |
707 | ds3db->dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE; | |
708 | ds3db->dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE; | |
709 | ds3db->dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL; | |
710 | ||
711 | ds3db->dsb->ds3db_need_recalc = TRUE; | |
712 | ||
5ec32cec RR |
713 | IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb); |
714 | ||
935e3df3 OK |
715 | *pds3db = ds3db; |
716 | return S_OK; | |
717 | } | |
718 | ||
0265676a | 719 | HRESULT IDirectSound3DBufferImpl_Destroy( |
605cc1b0 RR |
720 | IDirectSound3DBufferImpl *pds3db) |
721 | { | |
722 | TRACE("(%p)\n",pds3db); | |
723 | ||
724 | while (IDirectSound3DBufferImpl_Release((LPDIRECTSOUND3DBUFFER)pds3db) > 0); | |
725 | ||
726 | return S_OK; | |
727 | } | |
728 | ||
935e3df3 OK |
729 | /******************************************************************************* |
730 | * IDirectSound3DListener | |
731 | */ | |
732 | ||
733 | /* IUnknown methods */ | |
734 | static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface( | |
735 | LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj) | |
736 | { | |
314b99c4 | 737 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
935e3df3 OK |
738 | |
739 | TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); | |
9dacf206 | 740 | |
f5080c86 RR |
741 | if (ppobj == NULL) { |
742 | WARN("invalid parameter\n"); | |
743 | return E_INVALIDARG; | |
744 | } | |
745 | ||
746 | *ppobj = NULL; /* assume failure */ | |
747 | ||
9dacf206 RR |
748 | if ( IsEqualGUID(riid, &IID_IUnknown) || |
749 | IsEqualGUID(riid, &IID_IDirectSound3DListener ) ) { | |
750 | IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)This); | |
751 | *ppobj = This; | |
752 | return S_OK; | |
753 | } | |
754 | ||
755 | if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) { | |
e49a5c22 RR |
756 | if (!This->device->primary) |
757 | PrimaryBufferImpl_Create(This->device, &(This->device->primary), &(This->device->dsbd)); | |
758 | if (This->device->primary) { | |
759 | *ppobj = This->device->primary; | |
5ec32cec RR |
760 | IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj); |
761 | return S_OK; | |
762 | } | |
9dacf206 RR |
763 | } |
764 | ||
765 | FIXME( "Unknown IID %s\n", debugstr_guid( riid ) ); | |
9dacf206 | 766 | return E_NOINTERFACE; |
935e3df3 OK |
767 | } |
768 | ||
769 | static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface) | |
770 | { | |
f8833dae RR |
771 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
772 | ULONG ref = InterlockedIncrement(&(This->ref)); | |
26bd2ec9 | 773 | TRACE("(%p) ref was %d\n", This, ref - 1); |
f8833dae | 774 | return ref; |
935e3df3 OK |
775 | } |
776 | ||
777 | static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface) | |
778 | { | |
f8833dae RR |
779 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
780 | ULONG ref = InterlockedDecrement(&(This->ref)); | |
26bd2ec9 | 781 | TRACE("(%p) ref was %d\n", This, ref + 1); |
935e3df3 | 782 | |
f8833dae | 783 | if (!ref) { |
e49a5c22 | 784 | This->device->listener = 0; |
f8833dae RR |
785 | HeapFree(GetProcessHeap(), 0, This); |
786 | TRACE("(%p) released\n", This); | |
787 | } | |
788 | return ref; | |
935e3df3 OK |
789 | } |
790 | ||
791 | /* IDirectSound3DListener methods */ | |
792 | static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter( | |
793 | LPDIRECTSOUND3DLISTENER iface, | |
794 | LPDS3DLISTENER lpDS3DL) | |
795 | { | |
314b99c4 | 796 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
9dacf206 RR |
797 | TRACE("(%p,%p)\n",This,lpDS3DL); |
798 | ||
799 | if (lpDS3DL == NULL) { | |
14a5d168 | 800 | WARN("invalid parameter: lpDS3DL == NULL\n"); |
9dacf206 RR |
801 | return DSERR_INVALIDPARAM; |
802 | } | |
803 | ||
804 | if (lpDS3DL->dwSize < sizeof(*lpDS3DL)) { | |
26bd2ec9 | 805 | WARN("invalid parameter: lpDS3DL->dwSize = %d\n",lpDS3DL->dwSize); |
9dacf206 RR |
806 | return DSERR_INVALIDPARAM; |
807 | } | |
808 | ||
17c8b8e2 | 809 | TRACE("returning: all parameters\n"); |
e49a5c22 | 810 | *lpDS3DL = This->device->ds3dl; |
935e3df3 OK |
811 | return DS_OK; |
812 | } | |
813 | ||
814 | static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor( | |
815 | LPDIRECTSOUND3DLISTENER iface, | |
816 | LPD3DVALUE lpfDistanceFactor) | |
817 | { | |
314b99c4 | 818 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
e49a5c22 RR |
819 | TRACE("returning: Distance Factor = %f\n", This->device->ds3dl.flDistanceFactor); |
820 | *lpfDistanceFactor = This->device->ds3dl.flDistanceFactor; | |
935e3df3 OK |
821 | return DS_OK; |
822 | } | |
823 | ||
824 | static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor( | |
825 | LPDIRECTSOUND3DLISTENER iface, | |
826 | LPD3DVALUE lpfDopplerFactor) | |
827 | { | |
314b99c4 | 828 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
e49a5c22 RR |
829 | TRACE("returning: Doppler Factor = %f\n", This->device->ds3dl.flDopplerFactor); |
830 | *lpfDopplerFactor = This->device->ds3dl.flDopplerFactor; | |
935e3df3 OK |
831 | return DS_OK; |
832 | } | |
833 | ||
834 | static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation( | |
835 | LPDIRECTSOUND3DLISTENER iface, | |
836 | LPD3DVECTOR lpvOrientFront, | |
837 | LPD3DVECTOR lpvOrientTop) | |
838 | { | |
314b99c4 | 839 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
3cf9f845 MS |
840 | TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->device->ds3dl.vOrientFront.x, |
841 | This->device->ds3dl.vOrientFront.y, This->device->ds3dl.vOrientFront.z, This->device->ds3dl.vOrientTop.x, This->device->ds3dl.vOrientTop.y, | |
e49a5c22 RR |
842 | This->device->ds3dl.vOrientTop.z); |
843 | *lpvOrientFront = This->device->ds3dl.vOrientFront; | |
844 | *lpvOrientTop = This->device->ds3dl.vOrientTop; | |
935e3df3 OK |
845 | return DS_OK; |
846 | } | |
847 | ||
848 | static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition( | |
849 | LPDIRECTSOUND3DLISTENER iface, | |
850 | LPD3DVECTOR lpvPosition) | |
851 | { | |
314b99c4 | 852 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
e49a5c22 RR |
853 | TRACE("returning: Position vector = (%f,%f,%f)\n", This->device->ds3dl.vPosition.x, This->device->ds3dl.vPosition.y, This->device->ds3dl.vPosition.z); |
854 | *lpvPosition = This->device->ds3dl.vPosition; | |
935e3df3 OK |
855 | return DS_OK; |
856 | } | |
857 | ||
858 | static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor( | |
859 | LPDIRECTSOUND3DLISTENER iface, | |
860 | LPD3DVALUE lpfRolloffFactor) | |
861 | { | |
314b99c4 | 862 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
e49a5c22 RR |
863 | TRACE("returning: RolloffFactor = %f\n", This->device->ds3dl.flRolloffFactor); |
864 | *lpfRolloffFactor = This->device->ds3dl.flRolloffFactor; | |
935e3df3 OK |
865 | return DS_OK; |
866 | } | |
867 | ||
868 | static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity( | |
869 | LPDIRECTSOUND3DLISTENER iface, | |
870 | LPD3DVECTOR lpvVelocity) | |
871 | { | |
314b99c4 | 872 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
e49a5c22 RR |
873 | TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->device->ds3dl.vVelocity.x, This->device->ds3dl.vVelocity.y, This->device->ds3dl.vVelocity.z); |
874 | *lpvVelocity = This->device->ds3dl.vVelocity; | |
935e3df3 OK |
875 | return DS_OK; |
876 | } | |
877 | ||
878 | static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters( | |
879 | LPDIRECTSOUND3DLISTENER iface, | |
880 | LPCDS3DLISTENER lpcDS3DL, | |
881 | DWORD dwApply) | |
882 | { | |
314b99c4 | 883 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
26bd2ec9 | 884 | TRACE("setting: all parameters; dwApply = %d\n", dwApply); |
e49a5c22 | 885 | This->device->ds3dl = *lpcDS3DL; |
f3128dad RM |
886 | if (dwApply == DS3D_IMMEDIATE) |
887 | { | |
e49a5c22 | 888 | This->device->ds3dl_need_recalc = FALSE; |
5b918db6 | 889 | DSOUND_ChangeListener(This); |
f3128dad | 890 | } |
e49a5c22 | 891 | This->device->ds3dl_need_recalc = TRUE; |
935e3df3 OK |
892 | return DS_OK; |
893 | } | |
894 | ||
895 | static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor( | |
896 | LPDIRECTSOUND3DLISTENER iface, | |
897 | D3DVALUE fDistanceFactor, | |
898 | DWORD dwApply) | |
899 | { | |
314b99c4 | 900 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
26bd2ec9 | 901 | TRACE("setting: Distance Factor = %f; dwApply = %d\n", fDistanceFactor, dwApply); |
e49a5c22 | 902 | This->device->ds3dl.flDistanceFactor = fDistanceFactor; |
f3128dad RM |
903 | if (dwApply == DS3D_IMMEDIATE) |
904 | { | |
e49a5c22 | 905 | This->device->ds3dl_need_recalc = FALSE; |
5b918db6 | 906 | DSOUND_ChangeListener(This); |
f3128dad | 907 | } |
e49a5c22 | 908 | This->device->ds3dl_need_recalc = TRUE; |
935e3df3 OK |
909 | return DS_OK; |
910 | } | |
911 | ||
912 | static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor( | |
913 | LPDIRECTSOUND3DLISTENER iface, | |
914 | D3DVALUE fDopplerFactor, | |
915 | DWORD dwApply) | |
916 | { | |
314b99c4 | 917 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
26bd2ec9 | 918 | TRACE("setting: Doppler Factor = %f; dwApply = %d\n", fDopplerFactor, dwApply); |
e49a5c22 | 919 | This->device->ds3dl.flDopplerFactor = fDopplerFactor; |
f3128dad RM |
920 | if (dwApply == DS3D_IMMEDIATE) |
921 | { | |
e49a5c22 | 922 | This->device->ds3dl_need_recalc = FALSE; |
5b918db6 | 923 | DSOUND_ChangeListener(This); |
f3128dad | 924 | } |
e49a5c22 | 925 | This->device->ds3dl_need_recalc = TRUE; |
935e3df3 OK |
926 | return DS_OK; |
927 | } | |
928 | ||
929 | static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation( | |
930 | LPDIRECTSOUND3DLISTENER iface, | |
931 | D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront, | |
932 | D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, | |
933 | DWORD dwApply) | |
934 | { | |
314b99c4 | 935 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
3cf9f845 | 936 | TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %d\n", |
f3128dad | 937 | xFront, yFront, zFront, xTop, yTop, zTop, dwApply); |
e49a5c22 RR |
938 | This->device->ds3dl.vOrientFront.x = xFront; |
939 | This->device->ds3dl.vOrientFront.y = yFront; | |
940 | This->device->ds3dl.vOrientFront.z = zFront; | |
941 | This->device->ds3dl.vOrientTop.x = xTop; | |
942 | This->device->ds3dl.vOrientTop.y = yTop; | |
943 | This->device->ds3dl.vOrientTop.z = zTop; | |
f3128dad RM |
944 | if (dwApply == DS3D_IMMEDIATE) |
945 | { | |
e49a5c22 | 946 | This->device->ds3dl_need_recalc = FALSE; |
5b918db6 | 947 | DSOUND_ChangeListener(This); |
f3128dad | 948 | } |
e49a5c22 | 949 | This->device->ds3dl_need_recalc = TRUE; |
935e3df3 OK |
950 | return DS_OK; |
951 | } | |
952 | ||
953 | static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition( | |
954 | LPDIRECTSOUND3DLISTENER iface, | |
955 | D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
956 | DWORD dwApply) | |
957 | { | |
314b99c4 | 958 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
26bd2ec9 | 959 | TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply); |
e49a5c22 RR |
960 | This->device->ds3dl.vPosition.x = x; |
961 | This->device->ds3dl.vPosition.y = y; | |
962 | This->device->ds3dl.vPosition.z = z; | |
f3128dad RM |
963 | if (dwApply == DS3D_IMMEDIATE) |
964 | { | |
e49a5c22 | 965 | This->device->ds3dl_need_recalc = FALSE; |
5b918db6 | 966 | DSOUND_ChangeListener(This); |
f3128dad | 967 | } |
e49a5c22 | 968 | This->device->ds3dl_need_recalc = TRUE; |
935e3df3 OK |
969 | return DS_OK; |
970 | } | |
971 | ||
972 | static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor( | |
973 | LPDIRECTSOUND3DLISTENER iface, | |
974 | D3DVALUE fRolloffFactor, | |
975 | DWORD dwApply) | |
976 | { | |
314b99c4 | 977 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
26bd2ec9 | 978 | TRACE("setting: Rolloff Factor = %f; dwApply = %d\n", fRolloffFactor, dwApply); |
e49a5c22 | 979 | This->device->ds3dl.flRolloffFactor = fRolloffFactor; |
f3128dad RM |
980 | if (dwApply == DS3D_IMMEDIATE) |
981 | { | |
e49a5c22 | 982 | This->device->ds3dl_need_recalc = FALSE; |
5b918db6 | 983 | DSOUND_ChangeListener(This); |
f3128dad | 984 | } |
e49a5c22 | 985 | This->device->ds3dl_need_recalc = TRUE; |
935e3df3 OK |
986 | return DS_OK; |
987 | } | |
988 | ||
989 | static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity( | |
990 | LPDIRECTSOUND3DLISTENER iface, | |
991 | D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
992 | DWORD dwApply) | |
993 | { | |
314b99c4 | 994 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
26bd2ec9 | 995 | TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply); |
e49a5c22 RR |
996 | This->device->ds3dl.vVelocity.x = x; |
997 | This->device->ds3dl.vVelocity.y = y; | |
998 | This->device->ds3dl.vVelocity.z = z; | |
f3128dad RM |
999 | if (dwApply == DS3D_IMMEDIATE) |
1000 | { | |
e49a5c22 | 1001 | This->device->ds3dl_need_recalc = FALSE; |
5b918db6 | 1002 | DSOUND_ChangeListener(This); |
f3128dad | 1003 | } |
e49a5c22 | 1004 | This->device->ds3dl_need_recalc = TRUE; |
935e3df3 OK |
1005 | return DS_OK; |
1006 | } | |
1007 | ||
1008 | static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings( | |
1009 | LPDIRECTSOUND3DLISTENER iface) | |
935e3df3 | 1010 | { |
314b99c4 | 1011 | IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; |
5b918db6 RM |
1012 | TRACE("\n"); |
1013 | DSOUND_ChangeListener(This); | |
935e3df3 OK |
1014 | return DS_OK; |
1015 | } | |
1016 | ||
b67da5b9 | 1017 | static const IDirectSound3DListenerVtbl ds3dlvt = |
935e3df3 | 1018 | { |
935e3df3 OK |
1019 | /* IUnknown methods */ |
1020 | IDirectSound3DListenerImpl_QueryInterface, | |
1021 | IDirectSound3DListenerImpl_AddRef, | |
1022 | IDirectSound3DListenerImpl_Release, | |
1023 | /* IDirectSound3DListener methods */ | |
1024 | IDirectSound3DListenerImpl_GetAllParameter, | |
1025 | IDirectSound3DListenerImpl_GetDistanceFactor, | |
1026 | IDirectSound3DListenerImpl_GetDopplerFactor, | |
1027 | IDirectSound3DListenerImpl_GetOrientation, | |
1028 | IDirectSound3DListenerImpl_GetPosition, | |
1029 | IDirectSound3DListenerImpl_GetRolloffFactor, | |
1030 | IDirectSound3DListenerImpl_GetVelocity, | |
1031 | IDirectSound3DListenerImpl_SetAllParameters, | |
1032 | IDirectSound3DListenerImpl_SetDistanceFactor, | |
1033 | IDirectSound3DListenerImpl_SetDopplerFactor, | |
1034 | IDirectSound3DListenerImpl_SetOrientation, | |
1035 | IDirectSound3DListenerImpl_SetPosition, | |
1036 | IDirectSound3DListenerImpl_SetRolloffFactor, | |
1037 | IDirectSound3DListenerImpl_SetVelocity, | |
1038 | IDirectSound3DListenerImpl_CommitDeferredSettings, | |
1039 | }; | |
1040 | ||
0265676a | 1041 | HRESULT IDirectSound3DListenerImpl_Create( |
e49a5c22 RR |
1042 | DirectSoundDevice * device, |
1043 | IDirectSound3DListenerImpl ** ppdsl) | |
935e3df3 | 1044 | { |
e49a5c22 RR |
1045 | IDirectSound3DListenerImpl *pdsl; |
1046 | TRACE("(%p,%p)\n",device,ppdsl); | |
a4ed8e77 | 1047 | |
e49a5c22 | 1048 | pdsl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*pdsl)); |
a4ed8e77 | 1049 | |
e49a5c22 | 1050 | if (pdsl == NULL) { |
a4ed8e77 | 1051 | WARN("out of memory\n"); |
e49a5c22 | 1052 | *ppdsl = 0; |
a4ed8e77 RR |
1053 | return DSERR_OUTOFMEMORY; |
1054 | } | |
935e3df3 | 1055 | |
e49a5c22 RR |
1056 | pdsl->ref = 0; |
1057 | pdsl->lpVtbl = &ds3dlvt; | |
1058 | ||
1059 | pdsl->device = device; | |
1060 | ||
1061 | pdsl->device->ds3dl.dwSize = sizeof(DS3DLISTENER); | |
1062 | pdsl->device->ds3dl.vPosition.x = 0.0; | |
1063 | pdsl->device->ds3dl.vPosition.y = 0.0; | |
1064 | pdsl->device->ds3dl.vPosition.z = 0.0; | |
1065 | pdsl->device->ds3dl.vVelocity.x = 0.0; | |
1066 | pdsl->device->ds3dl.vVelocity.y = 0.0; | |
1067 | pdsl->device->ds3dl.vVelocity.z = 0.0; | |
1068 | pdsl->device->ds3dl.vOrientFront.x = 0.0; | |
1069 | pdsl->device->ds3dl.vOrientFront.y = 0.0; | |
1070 | pdsl->device->ds3dl.vOrientFront.z = 1.0; | |
1071 | pdsl->device->ds3dl.vOrientTop.x = 0.0; | |
1072 | pdsl->device->ds3dl.vOrientTop.y = 1.0; | |
1073 | pdsl->device->ds3dl.vOrientTop.z = 0.0; | |
1074 | pdsl->device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; | |
1075 | pdsl->device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; | |
1076 | pdsl->device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; | |
1077 | ||
1078 | pdsl->device->ds3dl_need_recalc = TRUE; | |
1079 | ||
1080 | *ppdsl = pdsl; | |
935e3df3 OK |
1081 | return S_OK; |
1082 | } |