1 /* DirectSound COM interface
3 * Copyright 2009 Maarten Lankhorst
5 * Some code taken from the original dsound-openal implementation
6 * Copyright 2007-2009 Chris Robinson
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.
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.
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
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include <devpropdef.h>
33 #include "dsound_private.h"
37 #define DS_INCOMPLETE ((HRESULT)0x08780020)
40 #ifndef WAVE_FORMAT_IEEE_FLOAT
41 #define WAVE_FORMAT_IEEE_FLOAT 3
45 /* TODO: when bufferlost is set, return from all calls except initialize with
48 static IDirectSoundBuffer8Vtbl DSBuffer_Vtbl
;
49 static IDirectSound3DBufferVtbl DSBuffer3d_Vtbl
;
50 static IDirectSoundNotifyVtbl DSBufferNot_Vtbl
;
51 static IKsPropertySetVtbl DSBufferProp_Vtbl
;
54 static inline DSBuffer
*impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8
*iface
)
56 return CONTAINING_RECORD(iface
, DSBuffer
, IDirectSoundBuffer8_iface
);
59 static inline DSBuffer
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
61 return CONTAINING_RECORD(iface
, DSBuffer
, IDirectSoundBuffer8_iface
);
64 static inline DSBuffer
*impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer
*iface
)
66 return CONTAINING_RECORD(iface
, DSBuffer
, IDirectSound3DBuffer_iface
);
69 static inline DSBuffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
71 return CONTAINING_RECORD(iface
, DSBuffer
, IDirectSoundNotify_iface
);
74 static inline DSBuffer
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
76 return CONTAINING_RECORD(iface
, DSBuffer
, IKsPropertySet_iface
);
80 /* Should be called with critsect held and context set.. */
81 static void DSBuffer_addnotify(DSBuffer
*buf
)
83 DSPrimary
*prim
= buf
->primary
;
87 list
= prim
->notifies
;
88 for(i
= 0; i
< prim
->nnotifies
; ++i
)
92 ERR("Buffer %p already in notification list\n", buf
);
96 if(prim
->nnotifies
== prim
->sizenotifies
)
98 list
= HeapReAlloc(GetProcessHeap(), 0, list
, (prim
->nnotifies
+ 1) * sizeof(*list
));
100 prim
->sizenotifies
++;
102 list
[prim
->nnotifies
++] = buf
;
103 prim
->notifies
= list
;
107 static const char *get_fmtstr_PCM(const DSPrimary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
109 out
->Format
= *format
;
110 out
->Format
.cbSize
= 0;
112 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
113 !HAS_EXTENSION(prim
->share
, EXT_MCFORMATS
))
115 WARN("Multi-channel not available\n");
119 if(format
->wBitsPerSample
== 8)
121 switch(format
->nChannels
)
123 case 1: return "AL_FORMAT_MONO8";
124 case 2: return "AL_FORMAT_STEREO8";
125 case 4: return "AL_FORMAT_QUAD8";
126 case 6: return "AL_FORMAT_51CHN8";
127 case 7: return "AL_FORMAT_61CHN8";
128 case 8: return "AL_FORMAT_71CHN8";
131 else if(format
->wBitsPerSample
== 16)
133 switch(format
->nChannels
)
135 case 1: return "AL_FORMAT_MONO16";
136 case 2: return "AL_FORMAT_STEREO16";
137 case 4: return "AL_FORMAT_QUAD16";
138 case 6: return "AL_FORMAT_51CHN16";
139 case 7: return "AL_FORMAT_61CHN16";
140 case 8: return "AL_FORMAT_71CHN16";
144 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
145 format
->wBitsPerSample
, format
->nChannels
);
149 static const char *get_fmtstr_FLOAT(const DSPrimary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
151 out
->Format
= *format
;
152 out
->Format
.cbSize
= 0;
154 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
155 !HAS_EXTENSION(prim
->share
, EXT_MCFORMATS
))
157 WARN("Multi-channel not available\n");
161 if(format
->wBitsPerSample
== 32 && HAS_EXTENSION(prim
->share
, EXT_FLOAT32
))
163 switch(format
->nChannels
)
165 case 1: return "AL_FORMAT_MONO_FLOAT32";
166 case 2: return "AL_FORMAT_STEREO_FLOAT32";
167 case 4: return "AL_FORMAT_QUAD32";
168 case 6: return "AL_FORMAT_51CHN32";
169 case 7: return "AL_FORMAT_61CHN32";
170 case 8: return "AL_FORMAT_71CHN32";
174 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
175 format
->wBitsPerSample
, format
->nChannels
);
179 /* Speaker configs */
180 #define MONO SPEAKER_FRONT_CENTER
181 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
182 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
183 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
184 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
185 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
186 #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
188 static const char *get_fmtstr_EXT(const DSPrimary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
190 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
191 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
193 if(!out
->Samples
.wValidBitsPerSample
)
194 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
195 else if(out
->Samples
.wValidBitsPerSample
> out
->Format
.wBitsPerSample
)
197 WARN("Invalid ValidBitsPerSample (%u > %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
200 else if(out
->Samples
.wValidBitsPerSample
< out
->Format
.wBitsPerSample
)
202 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
206 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
207 !HAS_EXTENSION(prim
->share
, EXT_MCFORMATS
))
209 WARN("Multi-channel not available\n");
213 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
215 if(out
->Samples
.wValidBitsPerSample
== 8)
217 switch(out
->dwChannelMask
)
219 case MONO
: return "AL_FORMAT_MONO8";
220 case STEREO
: return "AL_FORMAT_STEREO8";
221 case REAR
: return "AL_FORMAT_REAR8";
222 case QUAD
: return "AL_FORMAT_QUAD8";
223 case X5DOT1
: return "AL_FORMAT_51CHN8";
224 case X6DOT1
: return "AL_FORMAT_61CHN8";
225 case X7DOT1
: return "AL_FORMAT_71CHN8";
228 else if(out
->Samples
.wValidBitsPerSample
== 16)
230 switch(out
->dwChannelMask
)
232 case MONO
: return "AL_FORMAT_MONO16";
233 case STEREO
: return "AL_FORMAT_STEREO16";
234 case REAR
: return "AL_FORMAT_REAR16";
235 case QUAD
: return "AL_FORMAT_QUAD16";
236 case X5DOT1
: return "AL_FORMAT_51CHN16";
237 case X6DOT1
: return "AL_FORMAT_61CHN16";
238 case X7DOT1
: return "AL_FORMAT_71CHN16";
242 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#lx)\n",
243 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
246 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
247 HAS_EXTENSION(prim
->share
, EXT_FLOAT32
))
249 if(out
->Samples
.wValidBitsPerSample
== 32)
251 switch(out
->dwChannelMask
)
253 case MONO
: return "AL_FORMAT_MONO_FLOAT32";
254 case STEREO
: return "AL_FORMAT_STEREO_FLOAT32";
255 case REAR
: return "AL_FORMAT_REAR32";
256 case QUAD
: return "AL_FORMAT_QUAD32";
257 case X5DOT1
: return "AL_FORMAT_51CHN32";
258 case X6DOT1
: return "AL_FORMAT_61CHN32";
259 case X7DOT1
: return "AL_FORMAT_71CHN32";
264 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
268 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#lx)\n",
269 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
272 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
273 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
277 static void DSData_Release(DSData
*This
);
278 static HRESULT
DSData_Create(DSData
**ppv
, const DSBUFFERDESC
*desc
, DSPrimary
*prim
)
280 HRESULT hr
= DSERR_INVALIDPARAM
;
281 const WAVEFORMATEX
*format
;
282 const char *fmt_str
= NULL
;
286 format
= desc
->lpwfxFormat
;
287 TRACE("Requested buffer format:\n"
288 " FormatTag = 0x%04x\n"
290 " SamplesPerSec = %lu\n"
291 " AvgBytesPerSec = %lu\n"
293 " BitsPerSample = %d\n",
294 format
->wFormatTag
, format
->nChannels
,
295 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
296 format
->nBlockAlign
, format
->wBitsPerSample
);
298 if(format
->nChannels
<= 0)
300 WARN("Invalid Channels %d\n", format
->nChannels
);
301 return DSERR_INVALIDPARAM
;
303 if(format
->nSamplesPerSec
< DSBFREQUENCY_MIN
|| format
->nSamplesPerSec
> DSBFREQUENCY_MAX
)
305 WARN("Invalid SamplesPerSec %lu\n", format
->nSamplesPerSec
);
306 return DSERR_INVALIDPARAM
;
308 if(format
->nBlockAlign
<= 0)
310 WARN("Invalid BlockAlign %d\n", format
->nBlockAlign
);
311 return DSERR_INVALIDPARAM
;
313 if(format
->wBitsPerSample
== 0 || (format
->wBitsPerSample
%8) != 0)
315 WARN("Invalid BitsPerSample %d\n", format
->wBitsPerSample
);
316 return DSERR_INVALIDPARAM
;
318 if(format
->nBlockAlign
!= format
->nChannels
*format
->wBitsPerSample
/8)
320 WARN("Invalid BlockAlign %d (expected %u = %u*%u/8)\n",
321 format
->nBlockAlign
, format
->nChannels
*format
->wBitsPerSample
/8,
322 format
->nChannels
, format
->wBitsPerSample
);
323 return DSERR_INVALIDPARAM
;
325 /* HACK: Some games provide an incorrect value here and expect to work.
326 * This is clearly not supposed to succeed with just anything, but until
327 * the amount of leeway allowed is discovered, be very lenient.
329 if(format
->nAvgBytesPerSec
== 0)
331 WARN("Invalid AvgBytesPerSec %lu (expected %lu = %lu*%u)\n",
332 format
->nAvgBytesPerSec
, format
->nSamplesPerSec
*format
->nBlockAlign
,
333 format
->nSamplesPerSec
, format
->nBlockAlign
);
334 return DSERR_INVALIDPARAM
;
336 if(format
->nAvgBytesPerSec
!= format
->nBlockAlign
*format
->nSamplesPerSec
)
337 WARN("Unexpected AvgBytesPerSec %lu (expected %lu = %lu*%u)\n",
338 format
->nAvgBytesPerSec
, format
->nSamplesPerSec
*format
->nBlockAlign
,
339 format
->nSamplesPerSec
, format
->nBlockAlign
);
341 if((desc
->dwFlags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
343 WARN("Hardware and software location requested\n");
344 return DSERR_INVALIDPARAM
;
347 buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
348 buf_size
-= buf_size
%format
->nBlockAlign
;
349 if(buf_size
< DSBSIZE_MIN
) return DSERR_BUFFERTOOSMALL
;
350 if(buf_size
> DSBSIZE_MAX
) return DSERR_INVALIDPARAM
;
352 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
353 * will need the EAX-RAM extension. Currently, we just tell the app it
354 * gets what it wanted. */
355 if(!HAS_EXTENSION(prim
->share
, SOFTX_MAP_BUFFER
))
356 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
)+buf_size
);
358 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
359 if(!pBuffer
) return E_OUTOFMEMORY
;
361 pBuffer
->primary
= prim
;
363 pBuffer
->dsbflags
= desc
->dwFlags
;
364 pBuffer
->buf_size
= buf_size
;
366 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
367 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
368 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
369 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
370 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
372 const WAVEFORMATEXTENSIBLE
*wfe
;
374 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
375 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
378 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
379 TRACE("Extensible values:\n"
381 " ChannelMask = 0x%lx\n"
383 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
384 debugstr_guid(&wfe
->SubFormat
));
386 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
389 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
390 if(!fmt_str
) goto fail
;
393 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
394 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
395 pBuffer
->buf_format
== -1)
397 WARN("Could not get OpenAL format from %s\n", fmt_str
);
402 if(!HAS_EXTENSION(prim
->share
, SOFTX_MAP_BUFFER
))
404 pBuffer
->data
= (BYTE
*)(pBuffer
+1);
406 alGenBuffers(1, &pBuffer
->bid
);
411 const ALbitfieldSOFT map_bits
= AL_MAP_READ_BIT_SOFT
| AL_MAP_WRITE_BIT_SOFT
|
412 AL_MAP_PERSISTENT_BIT_SOFT
;
413 alGenBuffers(1, &pBuffer
->bid
);
414 alBufferStorageSOFT(pBuffer
->bid
, pBuffer
->buf_format
, NULL
, pBuffer
->buf_size
,
415 pBuffer
->format
.Format
.nSamplesPerSec
, map_bits
);
416 pBuffer
->data
= alMapBufferSOFT(pBuffer
->bid
, 0, pBuffer
->buf_size
, map_bits
);
419 if(!pBuffer
->data
) goto fail
;
426 DSData_Release(pBuffer
);
430 static void DSData_AddRef(DSData
*data
)
432 InterlockedIncrement(&data
->ref
);
435 /* This function is always called with the device lock held */
436 static void DSData_Release(DSData
*This
)
438 if(InterlockedDecrement(&This
->ref
)) return;
440 TRACE("Deleting %p\n", This
);
443 DSPrimary
*prim
= This
->primary
;
444 if(HAS_EXTENSION(prim
->share
, SOFTX_MAP_BUFFER
))
445 alUnmapBufferSOFT(This
->bid
);
446 alDeleteBuffers(1, &This
->bid
);
449 HeapFree(GetProcessHeap(), 0, This
);
453 HRESULT
DSBuffer_Create(DSBuffer
**ppv
, DSPrimary
*prim
, IDirectSoundBuffer
*orig
)
455 DSBuffer
*This
= NULL
;
459 EnterCriticalSection(&prim
->share
->crst
);
460 for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
462 if(prim
->BufferGroups
[i
].FreeBuffers
)
464 int idx
= CTZ64(prim
->BufferGroups
[i
].FreeBuffers
);
465 This
= prim
->BufferGroups
[i
].Buffers
+ idx
;
466 memset(This
, 0, sizeof(*This
));
467 prim
->BufferGroups
[i
].FreeBuffers
&= ~(U64(1) << idx
);
473 struct DSBufferGroup
*grp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
474 (prim
->NumBufferGroups
+1)*sizeof(prim
->BufferGroups
[0]));
477 for(i
= 0;i
< prim
->NumBufferGroups
;i
++)
478 grp
[i
] = prim
->BufferGroups
[i
];
479 grp
[i
].FreeBuffers
= ~U64(0);
480 grp
[i
].Buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
481 64*sizeof(grp
[0].Buffers
[0]));
484 HeapFree(GetProcessHeap(), 0, grp
);
489 HeapFree(GetProcessHeap(), 0, prim
->BufferGroups
);
490 prim
->BufferGroups
= grp
;
491 prim
->NumBufferGroups
++;
493 This
= prim
->BufferGroups
[i
].Buffers
+ 0;
494 memset(This
, 0, sizeof(*This
));
495 prim
->BufferGroups
[i
].FreeBuffers
&= ~(U64(1) << 0);
499 LeaveCriticalSection(&prim
->share
->crst
);
502 WARN("Out of memory allocating buffers\n");
503 return DSERR_OUTOFMEMORY
;
506 This
->IDirectSoundBuffer8_iface
.lpVtbl
= &DSBuffer_Vtbl
;
507 This
->IDirectSound3DBuffer_iface
.lpVtbl
= &DSBuffer3d_Vtbl
;
508 This
->IDirectSoundNotify_iface
.lpVtbl
= &DSBufferNot_Vtbl
;
509 This
->IKsPropertySet_iface
.lpVtbl
= &DSBufferProp_Vtbl
;
511 This
->share
= prim
->share
;
512 This
->primary
= prim
;
513 This
->ctx
= prim
->ctx
;
515 This
->current
.vol
= 0;
516 This
->current
.pan
= 0;
517 This
->current
.frequency
= 0;
518 This
->current
.ds3d
.dwSize
= sizeof(This
->current
.ds3d
);
519 This
->current
.ds3d
.vPosition
.x
= 0.0f
;
520 This
->current
.ds3d
.vPosition
.y
= 0.0f
;
521 This
->current
.ds3d
.vPosition
.z
= 0.0f
;
522 This
->current
.ds3d
.vVelocity
.x
= 0.0f
;
523 This
->current
.ds3d
.vVelocity
.y
= 0.0f
;
524 This
->current
.ds3d
.vVelocity
.z
= 0.0f
;
525 This
->current
.ds3d
.dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
526 This
->current
.ds3d
.dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
527 This
->current
.ds3d
.vConeOrientation
.x
= 0.0f
;
528 This
->current
.ds3d
.vConeOrientation
.y
= 0.0f
;
529 This
->current
.ds3d
.vConeOrientation
.z
= 1.0f
;
530 This
->current
.ds3d
.lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
531 This
->current
.ds3d
.flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
532 This
->current
.ds3d
.flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
533 This
->current
.ds3d
.dwMode
= DS3DMODE_NORMAL
;
534 This
->current
.eax
.lDirect
= 0;
535 This
->current
.eax
.lDirectHF
= 0;
536 This
->current
.eax
.lRoom
= 0;
537 This
->current
.eax
.lRoomHF
= 0;
538 This
->current
.eax
.lObstruction
= 0;
539 This
->current
.eax
.flObstructionLFRatio
= 0.0f
;
540 This
->current
.eax
.lOcclusion
= 0;
541 This
->current
.eax
.flOcclusionLFRatio
= 0.25f
;
542 This
->current
.eax
.flOcclusionRoomRatio
= 1.5f
;
543 This
->current
.eax
.flOcclusionDirectRatio
= 1.0f
;
544 This
->current
.eax
.lExclusion
= 0;
545 This
->current
.eax
.flExclusionLFRatio
= 1.0f
;
546 This
->current
.eax
.lOutsideVolumeHF
= 0;
547 This
->current
.eax
.flDopplerFactor
= 1.0f
;
548 This
->current
.eax
.flRolloffFactor
= 0.0f
;
549 This
->current
.eax
.flRoomRolloffFactor
= 0.0f
;
550 This
->current
.eax
.flAirAbsorptionFactor
= 0.0f
;
551 This
->current
.eax
.dwFlags
= EAXSOURCEFLAGS_DIRECTHFAUTO
| EAXSOURCEFLAGS_ROOMAUTO
|
552 EAXSOURCEFLAGS_ROOMHFAUTO
;
553 This
->current
.fxslot_targets
[0] = FXSLOT_TARGET_PRIMARY
;
554 for(i
= 1;i
< EAX_MAX_ACTIVE_FXSLOTS
;++i
)
555 This
->current
.fxslot_targets
[i
] = FXSLOT_TARGET_NULL
;
556 for(i
= 0;i
< EAX_MAX_FXSLOTS
;++i
)
558 This
->current
.send
[i
].lSend
= 0;
559 This
->current
.send
[i
].lSendHF
= 0;
560 This
->current
.send
[i
].lOcclusion
= 0;
561 This
->current
.send
[i
].flOcclusionLFRatio
= 0.25f
;
562 This
->current
.send
[i
].flOcclusionRoomRatio
= 1.5f
;
563 This
->current
.send
[i
].flOcclusionDirectRatio
= 1.0f
;
564 This
->current
.send
[i
].lExclusion
= 0;
565 This
->current
.send
[i
].flExclusionLFRatio
= 1.0f
;
567 This
->current
.eax1_reverbmix
= 1.0f
;
571 DSBuffer
*org
= impl_from_IDirectSoundBuffer(orig
);
572 DSData
*data
= org
->buffer
;
576 DSBuffer_Destroy(This
);
577 return DSERR_BUFFERLOST
;
582 /* According to MSDN, volume isn't copied. */
583 if((data
->dsbflags
&DSBCAPS_CTRLPAN
))
584 This
->current
.pan
= org
->current
.pan
;
585 if((data
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
586 This
->current
.frequency
= org
->current
.frequency
;
587 if((data
->dsbflags
&DSBCAPS_CTRL3D
))
588 This
->current
.ds3d
= org
->current
.ds3d
;
591 This
->deferred
.ds3d
= This
->current
.ds3d
;
592 This
->deferred
.eax
= This
->current
.eax
;
593 for(i
= 0;i
< EAX_MAX_ACTIVE_FXSLOTS
;++i
)
594 This
->deferred
.fxslot_targets
[i
] = This
->current
.fxslot_targets
[i
];
595 for(i
= 0;i
< EAX_MAX_FXSLOTS
;++i
)
596 This
->deferred
.send
[i
] = This
->current
.send
[i
];
597 This
->deferred
.eax1_reverbmix
= This
->current
.eax1_reverbmix
;
599 This
->vm_voicepriority
= (DWORD
)-1;
605 void DSBuffer_Destroy(DSBuffer
*This
)
607 DSPrimary
*prim
= This
->primary
;
611 TRACE("Destroying %p\n", This
);
613 EnterCriticalSection(&prim
->share
->crst
);
614 /* Remove from list, if in list */
615 for(i
= 0;i
< prim
->nnotifies
;++i
)
617 if(This
== prim
->notifies
[i
])
619 prim
->notifies
[i
] = prim
->notifies
[--prim
->nnotifies
];
624 setALContext(This
->ctx
);
627 DeviceShare
*share
= This
->share
;
629 alSourceRewind(This
->source
);
630 alSourcei(This
->source
, AL_BUFFER
, 0);
633 if(This
->loc_status
== DSBSTATUS_LOCHARDWARE
)
634 share
->sources
.ids
[share
->sources
.availhw_num
++] = This
->source
;
637 DWORD base
= share
->sources
.maxhw_alloc
;
638 share
->sources
.ids
[base
+ share
->sources
.availsw_num
++] = This
->source
;
642 if(This
->stream_bids
[0])
643 alDeleteBuffers(QBUFFERS
, This
->stream_bids
);
645 alDeleteFilters(1+EAX_MAX_FXSLOTS
, This
->filter
);
648 DSData_Release(This
->buffer
);
652 HeapFree(GetProcessHeap(), 0, This
->notify
);
654 for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
656 DWORD_PTR idx
= This
- prim
->BufferGroups
[i
].Buffers
;
659 prim
->BufferGroups
[i
].FreeBuffers
|= U64(1) << idx
;
664 LeaveCriticalSection(&prim
->share
->crst
);
667 HRESULT
DSBuffer_GetInterface(DSBuffer
*buf
, REFIID riid
, void **ppv
)
670 if(IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
671 *ppv
= &buf
->IDirectSoundBuffer8_iface
;
672 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
674 if(buf
->primary
->parent
->is_8
)
675 *ppv
= &buf
->IDirectSoundBuffer8_iface
;
677 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
679 if((buf
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
680 *ppv
= &buf
->IDirectSound3DBuffer_iface
;
682 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
684 if((buf
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
685 *ppv
= &buf
->IDirectSoundNotify_iface
;
687 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
688 *ppv
= &buf
->IKsPropertySet_iface
;
689 else if(IsEqualIID(riid
, &IID_IUnknown
))
690 *ppv
= &buf
->IDirectSoundBuffer8_iface
;
692 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
696 IUnknown_AddRef((IUnknown
*)*ppv
);
700 return E_NOINTERFACE
;
703 static HRESULT
DSBuffer_SetLoc(DSBuffer
*buf
, DWORD loc_status
)
705 DeviceShare
*share
= buf
->share
;
706 DSData
*data
= buf
->buffer
;
709 if((loc_status
&& buf
->loc_status
== loc_status
) || (!loc_status
&& buf
->loc_status
))
712 /* If we have a source, we're changing location, so return the source we
713 * have to get a new one.
717 alSourceRewind(buf
->source
);
718 alSourcei(buf
->source
, AL_BUFFER
, 0);
721 if(buf
->loc_status
== DSBSTATUS_LOCHARDWARE
)
722 share
->sources
.ids
[share
->sources
.availhw_num
++] = buf
->source
;
725 DWORD base
= share
->sources
.maxhw_alloc
;
726 share
->sources
.ids
[base
+ share
->sources
.availsw_num
++] = buf
->source
;
734 if(share
->sources
.availhw_num
)
735 loc_status
= DSBSTATUS_LOCHARDWARE
;
736 else if(share
->sources
.availsw_num
)
737 loc_status
= DSBSTATUS_LOCSOFTWARE
;
740 if((loc_status
== DSBSTATUS_LOCHARDWARE
&& !share
->sources
.availhw_num
) ||
741 (loc_status
== DSBSTATUS_LOCSOFTWARE
&& !share
->sources
.availsw_num
) ||
744 ERR("Out of %s sources\n",
745 (loc_status
== DSBSTATUS_LOCHARDWARE
) ? "hardware" :
746 (loc_status
== DSBSTATUS_LOCSOFTWARE
) ? "software" : "any"
748 return DSERR_ALLOCATED
;
751 if(loc_status
== DSBSTATUS_LOCHARDWARE
)
752 buf
->source
= share
->sources
.ids
[--(share
->sources
.availhw_num
)];
755 DWORD base
= share
->sources
.maxhw_alloc
;
756 buf
->source
= share
->sources
.ids
[base
+ --(share
->sources
.availsw_num
)];
758 alSourcef(buf
->source
, AL_GAIN
, mB_to_gain((float)buf
->current
.vol
));
759 alSourcef(buf
->source
, AL_PITCH
,
760 buf
->current
.frequency
? (float)buf
->current
.frequency
/data
->format
.Format
.nSamplesPerSec
764 /* TODO: Don't set EAX parameters or connect to effect slots for software
765 * buffers. Need to check if EAX buffer properties are still tracked, or if
766 * they're lost/reset when leaving hardware.
768 * Alternatively, we can just allow it and say software processing supports
769 * EAX too. Depends if apps may get upset over that.
772 if((data
->dsbflags
&DSBCAPS_CTRL3D
))
774 const DSPrimary
*prim
= buf
->primary
;
775 const ALuint source
= buf
->source
;
776 const DS3DBUFFER
*params
= &buf
->current
.ds3d
;
777 const EAXSOURCEPROPERTIES
*eax_params
= &buf
->current
.eax
;
779 alSource3f(source
, AL_POSITION
, params
->vPosition
.x
, params
->vPosition
.y
,
780 -params
->vPosition
.z
);
781 alSource3f(source
, AL_VELOCITY
, params
->vVelocity
.x
, params
->vVelocity
.y
,
782 -params
->vVelocity
.z
);
783 alSourcei(source
, AL_CONE_INNER_ANGLE
, params
->dwInsideConeAngle
);
784 alSourcei(source
, AL_CONE_OUTER_ANGLE
, params
->dwOutsideConeAngle
);
785 alSource3f(source
, AL_DIRECTION
, params
->vConeOrientation
.x
,
786 params
->vConeOrientation
.y
,
787 -params
->vConeOrientation
.z
);
788 alSourcef(source
, AL_CONE_OUTER_GAIN
, mB_to_gain((float)params
->lConeOutsideVolume
));
789 alSourcef(source
, AL_REFERENCE_DISTANCE
, params
->flMinDistance
);
790 alSourcef(source
, AL_MAX_DISTANCE
, params
->flMaxDistance
);
791 if(HAS_EXTENSION(share
, SOFT_SOURCE_SPATIALIZE
))
792 alSourcei(source
, AL_SOURCE_SPATIALIZE_SOFT
,
793 (params
->dwMode
==DS3DMODE_DISABLE
) ? AL_FALSE
: AL_TRUE
795 alSourcei(source
, AL_SOURCE_RELATIVE
,
796 (params
->dwMode
!=DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
799 alSourcef(source
, AL_ROLLOFF_FACTOR
,
800 prim
->current
.ds3d
.flRolloffFactor
+ eax_params
->flRolloffFactor
);
801 alSourcef(source
, AL_DOPPLER_FACTOR
, eax_params
->flDopplerFactor
);
802 if(HAS_EXTENSION(share
, EXT_EFX
))
804 alSourcei(source
, AL_DIRECT_FILTER
, buf
->filter
[0]);
805 for(i
= 0;i
< share
->num_sends
;++i
)
807 DWORD target
= buf
->current
.fxslot_targets
[i
];
808 ALuint filter
=0, slot
=0;
809 if(target
< FXSLOT_TARGET_NULL
)
811 ALint idx
= (target
== FXSLOT_TARGET_PRIMARY
) ?
812 prim
->primary_idx
: (ALint
)target
;
815 slot
= prim
->auxslot
[idx
];
816 filter
= buf
->filter
[1+idx
];
819 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, slot
, i
, filter
);
821 alSourcef(source
, AL_ROOM_ROLLOFF_FACTOR
, eax_params
->flRoomRolloffFactor
);
822 alSourcef(source
, AL_CONE_OUTER_GAINHF
, mB_to_gain((float)eax_params
->lOutsideVolumeHF
));
823 alSourcef(source
, AL_AIR_ABSORPTION_FACTOR
,
824 clampF(prim
->current
.ctx
.flAirAbsorptionHF
/ -5.0f
*
825 eax_params
->flAirAbsorptionFactor
, 0.0f
, 10.0f
)
827 alSourcei(source
, AL_DIRECT_FILTER_GAINHF_AUTO
,
828 (eax_params
->dwFlags
&EAXSOURCEFLAGS_DIRECTHFAUTO
) ? AL_TRUE
: AL_FALSE
);
829 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
830 (eax_params
->dwFlags
&EAXSOURCEFLAGS_ROOMAUTO
) ? AL_TRUE
: AL_FALSE
);
831 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
832 (eax_params
->dwFlags
&EAXSOURCEFLAGS_ROOMHFAUTO
) ? AL_TRUE
: AL_FALSE
);
838 const ALuint source
= buf
->source
;
839 const ALfloat x
= (ALfloat
)(buf
->current
.pan
-DSBPAN_LEFT
)/(DSBPAN_RIGHT
-DSBPAN_LEFT
) -
842 alSource3f(source
, AL_POSITION
, x
, 0.0f
, -sqrtf(1.0f
- x
*x
));
843 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
844 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
845 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
846 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
847 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
848 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
849 alSourcef(source
, AL_DOPPLER_FACTOR
, 0.0f
);
850 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
851 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
852 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
853 if(HAS_EXTENSION(share
, EXT_EFX
))
855 alSourcef(source
, AL_ROOM_ROLLOFF_FACTOR
, 0.0f
);
856 alSourcef(source
, AL_CONE_OUTER_GAINHF
, 1.0f
);
857 alSourcef(source
, AL_AIR_ABSORPTION_FACTOR
, 0.0f
);
858 alSourcei(source
, AL_DIRECT_FILTER_GAINHF_AUTO
, AL_TRUE
);
859 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
, AL_TRUE
);
860 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
, AL_TRUE
);
861 alSourcei(source
, AL_DIRECT_FILTER
, AL_FILTER_NULL
);
862 for(i
= 0;i
< share
->num_sends
;++i
)
863 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, 0, i
, AL_FILTER_NULL
);
865 if(HAS_EXTENSION(share
, SOFT_SOURCE_SPATIALIZE
))
867 /* Set to auto so panning works for mono, and multi-channel works
870 alSourcei(source
, AL_SOURCE_SPATIALIZE_SOFT
, AL_AUTO_SOFT
);
875 buf
->loc_status
= loc_status
;
880 static HRESULT WINAPI
DSBuffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
882 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
883 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
884 return DSBuffer_GetInterface(This
, riid
, ppv
);
887 static ULONG WINAPI
DSBuffer_AddRef(IDirectSoundBuffer8
*iface
)
889 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
892 InterlockedIncrement(&This
->all_ref
);
893 ret
= InterlockedIncrement(&This
->ref
);
894 TRACE("(%p) ref %lu\n", iface
, ret
);
899 static ULONG WINAPI
DSBuffer_Release(IDirectSoundBuffer8
*iface
)
901 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
904 ret
= InterlockedDecrement(&This
->ref
);
905 TRACE("(%p) ref %lu\n", iface
, ret
);
906 if(InterlockedDecrement(&This
->all_ref
) == 0)
907 DSBuffer_Destroy(This
);
912 static HRESULT WINAPI
DSBuffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
914 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
917 TRACE("(%p)->(%p)\n", iface
, caps
);
919 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
921 WARN("Invalid DSBCAPS (%p, %lu)\n", caps
, (caps
? caps
->dwSize
: 0));
922 return DSERR_INVALIDPARAM
;
926 caps
->dwFlags
= data
->dsbflags
;
927 if(!(data
->dsbflags
&DSBCAPS_LOCDEFER
))
929 if(This
->loc_status
== DSBSTATUS_LOCHARDWARE
)
930 caps
->dwFlags
|= DSBCAPS_LOCHARDWARE
;
931 else if(This
->loc_status
== DSBSTATUS_LOCSOFTWARE
)
932 caps
->dwFlags
|= DSBCAPS_LOCSOFTWARE
;
934 caps
->dwBufferBytes
= data
->buf_size
;
935 caps
->dwUnlockTransferRate
= 4096;
936 caps
->dwPlayCpuOverhead
= 0;
941 HRESULT WINAPI
DSBuffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
943 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
944 ALsizei writecursor
, pos
;
947 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
950 if(This
->segsize
!= 0)
952 ALint queued
= QBUFFERS
;
953 ALint status
= AL_INITIAL
;
956 EnterCriticalSection(&This
->share
->crst
);
958 if(LIKELY(This
->source
))
960 setALContext(This
->ctx
);
961 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
962 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
963 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
968 if(status
== AL_STOPPED
)
969 pos
= This
->segsize
*queued
+ This
->queue_base
;
971 pos
= ofs
+ This
->queue_base
;
972 if(pos
>= data
->buf_size
)
975 pos
%= data
->buf_size
;
976 else if(This
->isplaying
)
978 pos
= data
->buf_size
;
979 alSourceStop(This
->source
);
980 alSourcei(This
->source
, AL_BUFFER
, 0);
982 This
->isplaying
= FALSE
;
986 writecursor
= (This
->segsize
*QBUFFERS
+ pos
) % data
->buf_size
;
988 writecursor
= pos
% data
->buf_size
;
990 LeaveCriticalSection(&This
->share
->crst
);
994 const WAVEFORMATEX
*format
= &data
->format
.Format
;
995 ALint status
= AL_INITIAL
;
998 if(LIKELY(This
->source
))
1000 setALContext(This
->ctx
);
1001 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
1002 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
1007 if(status
== AL_PLAYING
)
1010 writecursor
= format
->nSamplesPerSec
/ This
->primary
->refresh
;
1011 writecursor
*= format
->nBlockAlign
;
1015 /* AL_STOPPED means the source naturally reached its end, where
1016 * DirectSound's position should be at the end (OpenAL reports 0
1017 * for stopped sources). The Stop method correlates to pausing,
1018 * which would put the source into an AL_PAUSED state and correctly
1019 * hold its current position. AL_INITIAL means the buffer hasn't
1020 * been played since last changing location.
1024 case AL_STOPPED
: pos
= data
->buf_size
; break;
1025 case AL_PAUSED
: pos
= ofs
; break;
1026 case AL_INITIAL
: pos
= This
->lastpos
; break;
1031 writecursor
= (writecursor
+ pos
) % data
->buf_size
;
1033 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
1035 if(pos
> data
->buf_size
)
1037 ERR("playpos > buf_size\n");
1038 pos
%= data
->buf_size
;
1040 if(writecursor
>= data
->buf_size
)
1042 ERR("writepos >= buf_size\n");
1043 writecursor
%= data
->buf_size
;
1046 if(playpos
) *playpos
= pos
;
1047 if(curpos
) *curpos
= writecursor
;
1052 static HRESULT WINAPI
DSBuffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1054 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1058 TRACE("(%p)->(%p, %lu, %p)\n", iface
, wfx
, allocated
, written
);
1060 if(!wfx
&& !written
)
1062 WARN("Cannot report format or format size\n");
1063 return DSERR_INVALIDPARAM
;
1066 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
1069 if(allocated
< size
)
1070 hr
= DSERR_INVALIDPARAM
;
1072 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
1080 static HRESULT WINAPI
DSBuffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
1082 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1085 TRACE("(%p)->(%p)\n", iface
, vol
);
1089 WARN("Invalid pointer\n");
1090 return DSERR_INVALIDPARAM
;
1093 hr
= DSERR_CONTROLUNAVAIL
;
1094 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1095 WARN("Volume control not set\n");
1098 *vol
= This
->current
.vol
;
1105 static HRESULT WINAPI
DSBuffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
1107 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1110 TRACE("(%p)->(%p)\n", iface
, pan
);
1114 WARN("Invalid pointer\n");
1115 return DSERR_INVALIDPARAM
;
1118 hr
= DSERR_CONTROLUNAVAIL
;
1119 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1120 WARN("Panning control not set\n");
1123 *pan
= This
->current
.pan
;
1130 static HRESULT WINAPI
DSBuffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
1132 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1135 TRACE("(%p)->(%p)\n", iface
, freq
);
1139 WARN("Invalid pointer\n");
1140 return DSERR_INVALIDPARAM
;
1143 hr
= DSERR_CONTROLUNAVAIL
;
1144 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1145 WARN("Frequency control not set\n");
1148 *freq
= This
->current
.frequency
;
1155 HRESULT WINAPI
DSBuffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
1157 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1158 ALint state
, looping
;
1160 TRACE("(%p)->(%p)\n", iface
, status
);
1164 WARN("Invalid pointer\n");
1165 return DSERR_INVALIDPARAM
;
1169 if(This
->segsize
== 0)
1173 if(LIKELY(This
->source
))
1175 setALContext(This
->ctx
);
1176 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1177 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
1184 EnterCriticalSection(&This
->share
->crst
);
1185 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1186 looping
= This
->islooping
;
1187 LeaveCriticalSection(&This
->share
->crst
);
1190 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1191 *status
|= This
->loc_status
;
1192 if(state
== AL_PLAYING
)
1193 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
1195 TRACE("%p status = 0x%08lx\n", This
, *status
);
1199 HRESULT WINAPI
DSBuffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1201 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1206 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
1208 EnterCriticalSection(&This
->share
->crst
);
1209 setALContext(This
->ctx
);
1211 hr
= DSERR_ALREADYINITIALIZED
;
1212 if(This
->init_done
) goto out
;
1214 prim
= This
->primary
;
1217 hr
= DSERR_INVALIDPARAM
;
1220 WARN("Missing DSound buffer description\n");
1223 if(!desc
->lpwfxFormat
)
1225 WARN("Missing buffer format (%p)\n", This
);
1228 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
1230 if(prim
->parent
->is_8
)
1232 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1234 WARN("Can't create multi-channel 3D buffers\n");
1239 static int once
= 0;
1241 ERR("Multi-channel 3D sounds are not spatialized\n");
1244 if((desc
->dwFlags
&DSBCAPS_CTRLPAN
) && desc
->lpwfxFormat
->nChannels
!= 1)
1246 static int once
= 0;
1248 ERR("Panning for multi-channel buffers is not supported\n");
1251 hr
= DSData_Create(&This
->buffer
, desc
, prim
);
1252 if(FAILED(hr
)) goto out
;
1254 data
= This
->buffer
;
1255 if(data
->format
.Format
.wBitsPerSample
== 8)
1256 memset(data
->data
, 0x80, data
->buf_size
);
1258 memset(data
->data
, 0x00, data
->buf_size
);
1261 data
= This
->buffer
;
1262 if(!(data
->dsbflags
&DSBCAPS_STATIC
) && !HAS_EXTENSION(This
->share
, SOFTX_MAP_BUFFER
))
1264 This
->segsize
= (data
->format
.Format
.nAvgBytesPerSec
+prim
->refresh
-1) / prim
->refresh
;
1265 This
->segsize
= clampI(This
->segsize
, data
->format
.Format
.nBlockAlign
, 2048);
1266 This
->segsize
+= data
->format
.Format
.nBlockAlign
- 1;
1267 This
->segsize
-= This
->segsize
%data
->format
.Format
.nBlockAlign
;
1269 alGenBuffers(QBUFFERS
, This
->stream_bids
);
1272 if(!(data
->dsbflags
&DSBCAPS_CTRL3D
))
1274 /* Non-3D sources aren't distance attenuated. */
1275 This
->current
.ds3d
.dwMode
= DS3DMODE_DISABLE
;
1279 if(HAS_EXTENSION(This
->share
, EXT_EFX
))
1283 alGenFilters(1+EAX_MAX_FXSLOTS
, This
->filter
);
1284 alFilteri(This
->filter
[0], AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1285 for(i
= 0;i
< EAX_MAX_FXSLOTS
;++i
)
1286 alFilteri(This
->filter
[1+i
], AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1287 if(UNLIKELY(alGetError() != AL_NO_ERROR
))
1289 alDeleteFilters(1+EAX_MAX_FXSLOTS
, This
->filter
);
1290 This
->filter
[0] = 0;
1291 for(i
= 0;i
< EAX_MAX_FXSLOTS
;++i
)
1292 This
->filter
[1+i
] = 0;
1296 if(!This
->current
.frequency
)
1297 This
->current
.frequency
= data
->format
.Format
.nSamplesPerSec
;
1298 This
->filter_mBLimit
= prim
->filter_mBLimit
;
1301 if(!(data
->dsbflags
&DSBCAPS_LOCDEFER
))
1304 if((data
->dsbflags
&DSBCAPS_LOCHARDWARE
)) loc
= DSBSTATUS_LOCHARDWARE
;
1305 else if((data
->dsbflags
&DSBCAPS_LOCSOFTWARE
)) loc
= DSBSTATUS_LOCSOFTWARE
;
1306 hr
= DSBuffer_SetLoc(This
, loc
);
1309 This
->init_done
= SUCCEEDED(hr
);
1312 LeaveCriticalSection(&This
->share
->crst
);
1317 static HRESULT WINAPI
DSBuffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1319 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1322 TRACE("(%p)->(%lu, %lu, %p, %p, %p, %p, 0x%lx)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1326 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1327 return DSERR_INVALIDPARAM
;
1332 if(ptr2
) *ptr2
= NULL
;
1335 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1336 DSBuffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1337 else if(ofs
>= (DWORD
)This
->buffer
->buf_size
)
1339 WARN("Invalid ofs %lu\n", ofs
);
1340 return DSERR_INVALIDPARAM
;
1342 if((flags
&DSBLOCK_ENTIREBUFFER
))
1343 bytes
= This
->buffer
->buf_size
;
1344 else if(bytes
> (DWORD
)This
->buffer
->buf_size
)
1346 WARN("Invalid size %lu\n", bytes
);
1347 return DSERR_INVALIDPARAM
;
1350 if(InterlockedExchange(&This
->buffer
->locked
, TRUE
) == TRUE
)
1352 WARN("Already locked\n");
1353 return DSERR_INVALIDPARAM
;
1356 *ptr1
= This
->buffer
->data
+ ofs
;
1357 if(bytes
>= (DWORD
)This
->buffer
->buf_size
-ofs
)
1359 *len1
= This
->buffer
->buf_size
- ofs
;
1360 remain
= bytes
- *len1
;
1368 if(ptr2
&& len2
&& remain
)
1370 *ptr2
= This
->buffer
->data
;
1377 static HRESULT WINAPI
DSBuffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1379 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1380 ALint state
= AL_STOPPED
;
1384 TRACE("(%p)->(%lu, %lu, %lu)\n", iface
, res1
, prio
, flags
);
1386 EnterCriticalSection(&This
->share
->crst
);
1387 setALContext(This
->ctx
);
1389 hr
= DSERR_BUFFERLOST
;
1390 if(This
->bufferlost
)
1392 WARN("Buffer %p lost\n", This
);
1396 data
= This
->buffer
;
1397 if((data
->dsbflags
&DSBCAPS_LOCDEFER
))
1401 hr
= DSERR_INVALIDPARAM
;
1402 if((flags
&(DSBPLAY_LOCSOFTWARE
|DSBPLAY_LOCHARDWARE
)) == (DSBPLAY_LOCSOFTWARE
|DSBPLAY_LOCHARDWARE
))
1404 WARN("Both hardware and software specified\n");
1408 if((flags
&DSBPLAY_LOCHARDWARE
)) loc
= DSBSTATUS_LOCHARDWARE
;
1409 else if((flags
&DSBPLAY_LOCSOFTWARE
)) loc
= DSBSTATUS_LOCSOFTWARE
;
1411 if(loc
&& This
->loc_status
&& loc
!= This
->loc_status
)
1413 if(This
->segsize
!= 0)
1420 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1424 if(state
== AL_PLAYING
)
1426 ERR("Attemping to change location on playing buffer\n");
1431 hr
= DSBuffer_SetLoc(This
, loc
);
1432 if(FAILED(hr
)) goto out
;
1436 ERR("Invalid priority set for non-deferred buffer %p, %lu!\n", This
->buffer
, prio
);
1437 hr
= DSERR_INVALIDPARAM
;
1441 if(This
->segsize
!= 0)
1443 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1444 if(This
->isplaying
) state
= AL_PLAYING
;
1448 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1449 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1454 if(state
== AL_PLAYING
)
1457 if(This
->segsize
== 0)
1459 if(state
== AL_INITIAL
)
1461 alSourcei(This
->source
, AL_BUFFER
, data
->bid
);
1462 alSourcei(This
->source
, AL_BYTE_OFFSET
, This
->lastpos
% data
->buf_size
);
1464 alSourcePlay(This
->source
);
1468 alSourceRewind(This
->source
);
1469 alSourcei(This
->source
, AL_BUFFER
, 0);
1470 This
->queue_base
= This
->data_offset
% data
->buf_size
;
1473 if(alGetError() != AL_NO_ERROR
)
1475 ERR("Couldn't start source\n");
1479 This
->isplaying
= TRUE
;
1482 DSBuffer_addnotify(This
);
1486 LeaveCriticalSection(&This
->share
->crst
);
1490 static HRESULT WINAPI
DSBuffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1492 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1495 TRACE("(%p)->(%lu)\n", iface
, pos
);
1497 data
= This
->buffer
;
1498 if(pos
>= (DWORD
)data
->buf_size
)
1499 return DSERR_INVALIDPARAM
;
1500 pos
-= pos
%data
->format
.Format
.nBlockAlign
;
1502 EnterCriticalSection(&This
->share
->crst
);
1504 if(This
->segsize
!= 0)
1508 setALContext(This
->ctx
);
1509 /* Perform a flush, so the next timer update will restart at the
1510 * proper position */
1511 alSourceRewind(This
->source
);
1512 alSourcei(This
->source
, AL_BUFFER
, 0);
1516 This
->queue_base
= This
->data_offset
= pos
;
1521 if(LIKELY(This
->source
))
1523 setALContext(This
->ctx
);
1524 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1529 This
->lastpos
= pos
;
1531 LeaveCriticalSection(&This
->share
->crst
);
1535 static HRESULT WINAPI
DSBuffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1537 /* This call only works on primary buffers */
1538 WARN("(%p)->(%p)\n", iface
, wfx
);
1539 return DSERR_INVALIDCALL
;
1542 static HRESULT WINAPI
DSBuffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1544 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1547 TRACE("(%p)->(%ld)\n", iface
, vol
);
1549 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1551 WARN("Invalid volume (%ld)\n", vol
);
1552 return DSERR_INVALIDPARAM
;
1555 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1556 hr
= DSERR_CONTROLUNAVAIL
;
1559 This
->current
.vol
= vol
;
1560 if(LIKELY(This
->source
))
1562 setALContext(This
->ctx
);
1563 alSourcef(This
->source
, AL_GAIN
, mB_to_gain((float)vol
));
1571 static HRESULT WINAPI
DSBuffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1573 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1576 TRACE("(%p)->(%ld)\n", iface
, pan
);
1578 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1580 WARN("invalid parameter: pan = %ld\n", pan
);
1581 return DSERR_INVALIDPARAM
;
1584 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1585 hr
= DSERR_CONTROLUNAVAIL
;
1588 This
->current
.pan
= pan
;
1589 if(LIKELY(This
->source
&& !(This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
)))
1592 pos
[0] = (ALfloat
)(pan
-DSBPAN_LEFT
)/(ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 0.5f
;
1594 /* NOTE: Strict movement along the X plane can cause the sound to
1595 * jump between left and right sharply. Using a curved path helps
1598 pos
[2] = -sqrtf(1.0f
- pos
[0]*pos
[0]);
1600 setALContext(This
->ctx
);
1601 alSourcefv(This
->source
, AL_POSITION
, pos
);
1610 static HRESULT WINAPI
DSBuffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1612 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1616 TRACE("(%p)->(%lu)\n", iface
, freq
);
1618 if(freq
!= 0 && (freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
))
1620 WARN("invalid parameter: freq = %lu\n", freq
);
1621 return DSERR_INVALIDPARAM
;
1624 data
= This
->buffer
;
1625 if(!(data
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1626 hr
= DSERR_CONTROLUNAVAIL
;
1629 This
->current
.frequency
= freq
? freq
: data
->format
.Format
.nSamplesPerSec
;
1630 if(LIKELY(This
->source
))
1632 setALContext(This
->ctx
);
1633 alSourcef(This
->source
, AL_PITCH
,
1634 This
->current
.frequency
/ (ALfloat
)data
->format
.Format
.nSamplesPerSec
1644 static HRESULT WINAPI
DSBuffer_Stop(IDirectSoundBuffer8
*iface
)
1646 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1648 TRACE("(%p)->()\n", iface
);
1650 EnterCriticalSection(&This
->share
->crst
);
1651 if(LIKELY(This
->source
))
1653 const ALuint source
= This
->source
;
1656 setALContext(This
->ctx
);
1657 alSourcePause(source
);
1658 alGetSourcei(source
, AL_BYTE_OFFSET
, &ofs
);
1659 alGetSourcei(source
, AL_SOURCE_STATE
, &state
);
1662 This
->isplaying
= FALSE
;
1664 DSPrimary_triggernots(This
->primary
);
1665 /* Ensure the notification's last tracked position is updated, as well
1666 * as the queue offsets for streaming sources.
1668 if(This
->segsize
== 0)
1669 This
->lastpos
= (state
== AL_STOPPED
) ? This
->buffer
->buf_size
: ofs
;
1672 DSData
*data
= This
->buffer
;
1675 alGetSourcei(This
->source
, AL_BUFFERS_PROCESSED
, &done
);
1676 This
->queue_base
+= This
->segsize
*done
+ ofs
;
1677 if(This
->queue_base
>= data
->buf_size
)
1680 This
->queue_base
%= data
->buf_size
;
1682 This
->queue_base
= data
->buf_size
;
1684 This
->lastpos
= This
->queue_base
;
1686 alSourceRewind(This
->source
);
1687 alSourcei(This
->source
, AL_BUFFER
, 0);
1691 This
->data_offset
= This
->lastpos
% data
->buf_size
;
1693 This
->islooping
= FALSE
;
1696 LeaveCriticalSection(&This
->share
->crst
);
1701 static HRESULT WINAPI
DSBuffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1703 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1704 DSData
*buf
= This
->buffer
;
1705 DWORD bufsize
= buf
->buf_size
;
1706 DWORD_PTR ofs1
, ofs2
;
1707 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1710 TRACE("(%p)->(%p, %lu, %p, %lu)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1712 if(InterlockedExchange(&buf
->locked
, FALSE
) == FALSE
)
1714 WARN("Not locked\n");
1715 return DSERR_INVALIDPARAM
;
1718 hr
= DSERR_INVALIDPARAM
;
1719 /* Make sure offset is between boundary and boundary + bufsize */
1720 ofs1
= (DWORD_PTR
)ptr1
;
1721 ofs2
= (DWORD_PTR
)ptr2
;
1722 if(ofs1
< boundary
|| (ofs2
&& ofs2
!= boundary
))
1726 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1735 if(HAS_EXTENSION(This
->share
, SOFTX_MAP_BUFFER
))
1737 setALContext(This
->ctx
);
1738 alFlushMappedBufferSOFT(buf
->bid
, 0, buf
->buf_size
);
1742 else if(This
->segsize
== 0)
1744 setALContext(This
->ctx
);
1745 alBufferData(buf
->bid
, buf
->buf_format
, buf
->data
, buf
->buf_size
,
1746 buf
->format
.Format
.nSamplesPerSec
);
1753 WARN("Invalid parameters (%p,%lu) (%p,%lu,%p,%lu)\n", (void*)boundary
, bufsize
,
1754 ptr1
, len1
, ptr2
, len2
);
1758 static HRESULT WINAPI
DSBuffer_Restore(IDirectSoundBuffer8
*iface
)
1760 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1763 TRACE("(%p)->()\n", iface
);
1765 EnterCriticalSection(&This
->share
->crst
);
1766 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1767 (IDirectSoundBuffer
*)&This
->IDirectSoundBuffer8_iface
== This
->primary
->write_emu
)
1769 This
->bufferlost
= 0;
1773 hr
= DSERR_BUFFERLOST
;
1774 LeaveCriticalSection(&This
->share
->crst
);
1779 static HRESULT WINAPI
DSBuffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1781 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1782 ALenum state
= AL_INITIAL
;
1787 TRACE("(%p)->(%lu, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1789 data
= This
->buffer
;
1790 if(!(data
->dsbflags
&DSBCAPS_CTRLFX
))
1792 WARN("FX control not set\n");
1793 return DSERR_CONTROLUNAVAIL
;
1798 WARN("Buffer is locked\n");
1799 return DSERR_INVALIDCALL
;
1802 EnterCriticalSection(&This
->share
->crst
);
1804 setALContext(This
->ctx
);
1805 if(LIKELY(This
->source
))
1807 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1811 if(This
->segsize
!= 0 && state
!= AL_PLAYING
)
1812 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1813 if(state
== AL_PLAYING
)
1815 WARN("Buffer is playing\n");
1816 hr
= DSERR_INVALIDCALL
;
1820 hr
= DSERR_INVALIDPARAM
;
1823 if(desc
|| rescodes
)
1825 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1829 /* No effects; we can handle that */
1834 if(!desc
|| !rescodes
)
1836 WARN("NULL desc and/or result pointer specified.\n");
1840 /* We don't (currently) handle DSound effects */
1841 for(i
= 0;i
< fxcount
;++i
)
1843 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1844 rescodes
[i
] = DSFXR_FAILED
;
1849 LeaveCriticalSection(&This
->share
->crst
);
1854 static HRESULT WINAPI
DSBuffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1856 DSBuffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1859 TRACE("(%p)->(%lu, %lu, %p)\n", This
, flags
, fxcount
, rescodes
);
1861 /* effects aren't supported at the moment.. */
1862 if(fxcount
!= 0 || rescodes
)
1864 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1865 return DSERR_INVALIDPARAM
;
1868 EnterCriticalSection(&This
->share
->crst
);
1869 setALContext(This
->ctx
);
1872 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1876 hr
= DSERR_INVALIDPARAM
;
1877 if((flags
&(DSBPLAY_LOCSOFTWARE
|DSBPLAY_LOCHARDWARE
)) == (DSBPLAY_LOCSOFTWARE
|DSBPLAY_LOCHARDWARE
))
1879 WARN("Both hardware and software specified\n");
1883 if((flags
&DSBPLAY_LOCHARDWARE
)) loc
= DSBSTATUS_LOCHARDWARE
;
1884 else if((flags
&DSBPLAY_LOCSOFTWARE
)) loc
= DSBSTATUS_LOCSOFTWARE
;
1886 if(loc
&& This
->loc_status
&& loc
!= This
->loc_status
)
1888 ALint state
= AL_INITIAL
;
1890 if(This
->segsize
!= 0)
1897 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1901 if(state
== AL_PLAYING
)
1903 ERR("Attemping to change location on playing buffer\n");
1908 hr
= DSBuffer_SetLoc(This
, loc
);
1913 LeaveCriticalSection(&This
->share
->crst
);
1917 static HRESULT WINAPI
DSBuffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1919 FIXME("(%p)->(%s, %lu, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1920 if(ppv
) *ppv
= NULL
;
1924 static IDirectSoundBuffer8Vtbl DSBuffer_Vtbl
= {
1925 DSBuffer_QueryInterface
,
1929 DSBuffer_GetCurrentPosition
,
1933 DSBuffer_GetFrequency
,
1935 DSBuffer_Initialize
,
1938 DSBuffer_SetCurrentPosition
,
1942 DSBuffer_SetFrequency
,
1947 DSBuffer_AcquireResources
,
1948 DSBuffer_GetObjectInPath
1952 void DSBuffer_SetParams(DSBuffer
*This
, const DS3DBUFFER
*params
, LONG flags
)
1954 DSPrimary
*prim
= This
->primary
;
1955 const ALuint source
= This
->source
;
1956 union BufferParamFlags dirty
= { flags
};
1959 /* Copy deferred parameters first. */
1961 This
->current
.ds3d
.vPosition
= params
->vPosition
;
1963 This
->current
.ds3d
.vVelocity
= params
->vVelocity
;
1964 if(dirty
.bit
.cone_angles
)
1966 This
->current
.ds3d
.dwInsideConeAngle
= params
->dwInsideConeAngle
;
1967 This
->current
.ds3d
.dwOutsideConeAngle
= params
->dwOutsideConeAngle
;
1969 if(dirty
.bit
.cone_orient
)
1970 This
->current
.ds3d
.vConeOrientation
= params
->vConeOrientation
;
1971 if(dirty
.bit
.cone_outsidevolume
)
1972 This
->current
.ds3d
.lConeOutsideVolume
= params
->lConeOutsideVolume
;
1973 if(dirty
.bit
.min_distance
)
1974 This
->current
.ds3d
.flMinDistance
= params
->flMinDistance
;
1975 if(dirty
.bit
.max_distance
)
1976 This
->current
.ds3d
.flMaxDistance
= params
->flMaxDistance
;
1978 This
->current
.ds3d
.dwMode
= params
->dwMode
;
1979 /* Always copy EAX params (they're always set deferred first, then applied
1980 * when committing all params).
1982 This
->current
.eax
= This
->deferred
.eax
;
1983 for(i
= 0;i
< EAX_MAX_ACTIVE_FXSLOTS
;++i
)
1984 This
->current
.fxslot_targets
[i
] = This
->deferred
.fxslot_targets
[i
];
1985 for(i
= 0;i
< EAX_MAX_FXSLOTS
;++i
)
1986 This
->current
.send
[i
] = This
->deferred
.send
[i
];
1987 This
->current
.eax1_reverbmix
= This
->deferred
.eax1_reverbmix
;
1989 /* Now apply what's changed to OpenAL. */
1990 if(UNLIKELY(!source
)) return;
1993 alSource3f(source
, AL_POSITION
, params
->vPosition
.x
, params
->vPosition
.y
,
1994 -params
->vPosition
.z
);
1996 alSource3f(source
, AL_VELOCITY
, params
->vVelocity
.x
, params
->vVelocity
.y
,
1997 -params
->vVelocity
.z
);
1998 if(dirty
.bit
.cone_angles
)
2000 alSourcei(source
, AL_CONE_INNER_ANGLE
, params
->dwInsideConeAngle
);
2001 alSourcei(source
, AL_CONE_OUTER_ANGLE
, params
->dwOutsideConeAngle
);
2003 if(dirty
.bit
.cone_orient
)
2004 alSource3f(source
, AL_DIRECTION
, params
->vConeOrientation
.x
,
2005 params
->vConeOrientation
.y
,
2006 -params
->vConeOrientation
.z
);
2007 if(dirty
.bit
.cone_outsidevolume
)
2008 alSourcef(source
, AL_CONE_OUTER_GAIN
, mB_to_gain((float)params
->lConeOutsideVolume
));
2009 if(dirty
.bit
.min_distance
)
2010 alSourcef(source
, AL_REFERENCE_DISTANCE
, params
->flMinDistance
);
2011 if(dirty
.bit
.max_distance
)
2012 alSourcef(source
, AL_MAX_DISTANCE
, params
->flMaxDistance
);
2015 if(HAS_EXTENSION(This
->share
, SOFT_SOURCE_SPATIALIZE
))
2016 alSourcei(source
, AL_SOURCE_SPATIALIZE_SOFT
,
2017 (params
->dwMode
==DS3DMODE_DISABLE
) ? AL_FALSE
: AL_TRUE
2019 alSourcei(source
, AL_SOURCE_RELATIVE
,
2020 (params
->dwMode
!=DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
2024 if(dirty
.bit
.dry_filter
)
2025 alSourcei(source
, AL_DIRECT_FILTER
, This
->filter
[0]);
2026 if(dirty
.bit
.send_filters
)
2028 for(i
= 0;i
< EAX_MAX_ACTIVE_FXSLOTS
;++i
)
2030 DWORD target
= This
->current
.fxslot_targets
[i
];
2031 ALuint filter
=0, slot
=0;
2032 if(target
< FXSLOT_TARGET_NULL
)
2034 ALint idx
= (target
== FXSLOT_TARGET_PRIMARY
) ?
2035 prim
->primary_idx
: (ALint
)target
;
2038 slot
= prim
->auxslot
[idx
];
2039 filter
= This
->filter
[1+idx
];
2042 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, slot
, i
, filter
);
2045 if(dirty
.bit
.doppler
)
2046 alSourcef(source
, AL_DOPPLER_FACTOR
, This
->current
.eax
.flDopplerFactor
);
2047 if(dirty
.bit
.rolloff
)
2048 alSourcef(source
, AL_ROLLOFF_FACTOR
, This
->current
.eax
.flRolloffFactor
+
2049 prim
->current
.ds3d
.flRolloffFactor
);
2050 if(dirty
.bit
.room_rolloff
)
2051 alSourcef(source
, AL_ROOM_ROLLOFF_FACTOR
, This
->current
.eax
.flRoomRolloffFactor
);
2052 if(dirty
.bit
.cone_outsidevolumehf
)
2053 alSourcef(source
, AL_CONE_OUTER_GAINHF
, mB_to_gain((float)This
->current
.eax
.lOutsideVolumeHF
));
2054 if(dirty
.bit
.air_absorb
)
2055 alSourcef(source
, AL_AIR_ABSORPTION_FACTOR
, This
->current
.eax
.flAirAbsorptionFactor
*
2056 prim
->current
.ctx
.flAirAbsorptionHF
/ -5.0f
);
2059 alSourcei(source
, AL_DIRECT_FILTER_GAINHF_AUTO
,
2060 (This
->current
.eax
.dwFlags
&EAXSOURCEFLAGS_DIRECTHFAUTO
) ? AL_TRUE
: AL_FALSE
);
2061 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
2062 (This
->current
.eax
.dwFlags
&EAXSOURCEFLAGS_ROOMAUTO
) ? AL_TRUE
: AL_FALSE
);
2063 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
2064 (This
->current
.eax
.dwFlags
&EAXSOURCEFLAGS_ROOMHFAUTO
) ? AL_TRUE
: AL_FALSE
);
2068 static HRESULT WINAPI
DSBuffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
2070 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2071 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2072 return DSBuffer_GetInterface(This
, riid
, ppv
);
2075 static ULONG WINAPI
DSBuffer3D_AddRef(IDirectSound3DBuffer
*iface
)
2077 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2080 InterlockedIncrement(&This
->all_ref
);
2081 ret
= InterlockedIncrement(&This
->ds3d_ref
);
2082 TRACE("(%p) ref %lu\n", iface
, ret
);
2087 static ULONG WINAPI
DSBuffer3D_Release(IDirectSound3DBuffer
*iface
)
2089 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2092 ret
= InterlockedDecrement(&This
->ds3d_ref
);
2093 TRACE("(%p) ref %lu\n", iface
, ret
);
2094 if(InterlockedDecrement(&This
->all_ref
) == 0)
2095 DSBuffer_Destroy(This
);
2100 static HRESULT WINAPI
DSBuffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
2102 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2104 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
2105 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
2107 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
2108 return DSERR_INVALIDPARAM
;
2111 EnterCriticalSection(&This
->share
->crst
);
2112 *pdwInsideConeAngle
= This
->current
.ds3d
.dwInsideConeAngle
;
2113 *pdwOutsideConeAngle
= This
->current
.ds3d
.dwOutsideConeAngle
;
2114 LeaveCriticalSection(&This
->share
->crst
);
2119 static HRESULT WINAPI
DSBuffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
2121 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2123 TRACE("(%p)->(%p)\n", This
, orient
);
2126 WARN("Invalid pointer\n");
2127 return DSERR_INVALIDPARAM
;
2130 EnterCriticalSection(&This
->share
->crst
);
2131 *orient
= This
->current
.ds3d
.vConeOrientation
;
2132 LeaveCriticalSection(&This
->share
->crst
);
2137 static HRESULT WINAPI
DSBuffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
2139 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2141 TRACE("(%p)->(%p)\n", This
, vol
);
2144 WARN("Invalid pointer\n");
2145 return DSERR_INVALIDPARAM
;
2148 *vol
= This
->current
.ds3d
.lConeOutsideVolume
;
2152 static HRESULT WINAPI
DSBuffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
2154 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2156 TRACE("(%p)->(%p)\n", This
, maxdist
);
2159 WARN("Invalid pointer\n");
2160 return DSERR_INVALIDPARAM
;
2163 *maxdist
= This
->current
.ds3d
.flMaxDistance
;
2167 static HRESULT WINAPI
DSBuffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
2169 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2171 TRACE("(%p)->(%p)\n", This
, mindist
);
2174 WARN("Invalid pointer\n");
2175 return DSERR_INVALIDPARAM
;
2178 *mindist
= This
->current
.ds3d
.flMinDistance
;
2182 static HRESULT WINAPI
DSBuffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
2184 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2186 TRACE("(%p)->(%p)\n", This
, mode
);
2189 WARN("Invalid pointer\n");
2190 return DSERR_INVALIDPARAM
;
2193 *mode
= This
->current
.ds3d
.dwMode
;
2197 static HRESULT WINAPI
DSBuffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
2199 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2201 TRACE("(%p)->(%p)\n", This
, pos
);
2204 WARN("Invalid pointer\n");
2205 return DSERR_INVALIDPARAM
;
2208 EnterCriticalSection(&This
->share
->crst
);
2209 *pos
= This
->current
.ds3d
.vPosition
;
2210 LeaveCriticalSection(&This
->share
->crst
);
2215 static HRESULT WINAPI
DSBuffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
2217 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2219 TRACE("(%p)->(%p)\n", This
, vel
);
2222 WARN("Invalid pointer\n");
2223 return DSERR_INVALIDPARAM
;
2226 EnterCriticalSection(&This
->share
->crst
);
2227 *vel
= This
->current
.ds3d
.vVelocity
;
2228 LeaveCriticalSection(&This
->share
->crst
);
2233 static HRESULT WINAPI
DSBuffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
2235 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2237 TRACE("(%p)->(%p)\n", iface
, ds3dbuffer
);
2239 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2241 WARN("Invalid parameters %p %lu\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2242 return DSERR_INVALIDPARAM
;
2245 EnterCriticalSection(&This
->share
->crst
);
2246 ds3dbuffer
->vPosition
= This
->current
.ds3d
.vPosition
;
2247 ds3dbuffer
->vVelocity
= This
->current
.ds3d
.vVelocity
;
2248 ds3dbuffer
->dwInsideConeAngle
= This
->current
.ds3d
.dwInsideConeAngle
;
2249 ds3dbuffer
->dwOutsideConeAngle
= This
->current
.ds3d
.dwOutsideConeAngle
;
2250 ds3dbuffer
->vConeOrientation
= This
->current
.ds3d
.vConeOrientation
;
2251 ds3dbuffer
->lConeOutsideVolume
= This
->current
.ds3d
.lConeOutsideVolume
;
2252 ds3dbuffer
->flMinDistance
= This
->current
.ds3d
.flMinDistance
;
2253 ds3dbuffer
->flMaxDistance
= This
->current
.ds3d
.flMaxDistance
;
2254 ds3dbuffer
->dwMode
= This
->current
.ds3d
.dwMode
;
2255 LeaveCriticalSection(&This
->share
->crst
);
2260 static HRESULT WINAPI
DSBuffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
2262 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2264 TRACE("(%p)->(%lu, %lu, %lu)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
2265 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
|| dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2267 WARN("Invalid cone angles (%lu, %lu)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
2268 return DSERR_INVALIDPARAM
;
2271 EnterCriticalSection(&This
->share
->crst
);
2272 if(apply
== DS3D_DEFERRED
)
2274 This
->deferred
.ds3d
.dwInsideConeAngle
= dwInsideConeAngle
;
2275 This
->deferred
.ds3d
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2276 This
->dirty
.bit
.cone_angles
= 1;
2280 setALContext(This
->ctx
);
2281 This
->current
.ds3d
.dwInsideConeAngle
= dwInsideConeAngle
;
2282 This
->current
.ds3d
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2283 if(LIKELY(This
->source
))
2285 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2286 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2291 LeaveCriticalSection(&This
->share
->crst
);
2296 static HRESULT WINAPI
DSBuffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2298 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2300 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2302 EnterCriticalSection(&This
->share
->crst
);
2303 if(apply
== DS3D_DEFERRED
)
2305 This
->deferred
.ds3d
.vConeOrientation
.x
= x
;
2306 This
->deferred
.ds3d
.vConeOrientation
.y
= y
;
2307 This
->deferred
.ds3d
.vConeOrientation
.z
= z
;
2308 This
->dirty
.bit
.cone_orient
= 1;
2312 setALContext(This
->ctx
);
2313 This
->current
.ds3d
.vConeOrientation
.x
= x
;
2314 This
->current
.ds3d
.vConeOrientation
.y
= y
;
2315 This
->current
.ds3d
.vConeOrientation
.z
= z
;
2316 if(LIKELY(This
->source
))
2318 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2323 LeaveCriticalSection(&This
->share
->crst
);
2328 static HRESULT WINAPI
DSBuffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2330 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2332 TRACE("(%p)->(%ld, %lu)\n", This
, vol
, apply
);
2333 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2335 WARN("Invalid volume (%ld)\n", vol
);
2336 return DSERR_INVALIDPARAM
;
2339 EnterCriticalSection(&This
->share
->crst
);
2340 if(apply
== DS3D_DEFERRED
)
2342 This
->deferred
.ds3d
.lConeOutsideVolume
= vol
;
2343 This
->dirty
.bit
.cone_outsidevolume
= 1;
2347 setALContext(This
->ctx
);
2348 This
->current
.ds3d
.lConeOutsideVolume
= vol
;
2349 if(LIKELY(This
->source
))
2351 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain((float)vol
));
2356 LeaveCriticalSection(&This
->share
->crst
);
2361 static HRESULT WINAPI
DSBuffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2363 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2365 TRACE("(%p)->(%f, %lu)\n", This
, maxdist
, apply
);
2368 WARN("Invalid max distance (%f)\n", maxdist
);
2369 return DSERR_INVALIDPARAM
;
2372 EnterCriticalSection(&This
->share
->crst
);
2373 if(apply
== DS3D_DEFERRED
)
2375 This
->deferred
.ds3d
.flMaxDistance
= maxdist
;
2376 This
->dirty
.bit
.max_distance
= 1;
2380 setALContext(This
->ctx
);
2381 This
->current
.ds3d
.flMaxDistance
= maxdist
;
2382 if(LIKELY(This
->source
))
2384 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2389 LeaveCriticalSection(&This
->share
->crst
);
2394 static HRESULT WINAPI
DSBuffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2396 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2398 TRACE("(%p)->(%f, %lu)\n", This
, mindist
, apply
);
2401 WARN("Invalid min distance (%f)\n", mindist
);
2402 return DSERR_INVALIDPARAM
;
2405 EnterCriticalSection(&This
->share
->crst
);
2406 if(apply
== DS3D_DEFERRED
)
2408 This
->deferred
.ds3d
.flMinDistance
= mindist
;
2409 This
->dirty
.bit
.min_distance
= 1;
2413 setALContext(This
->ctx
);
2414 This
->current
.ds3d
.flMinDistance
= mindist
;
2415 if(LIKELY(This
->source
))
2417 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2422 LeaveCriticalSection(&This
->share
->crst
);
2427 static HRESULT WINAPI
DSBuffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2429 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2431 TRACE("(%p)->(%lu, %lu)\n", This
, mode
, apply
);
2432 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2433 mode
!= DS3DMODE_DISABLE
)
2435 WARN("Invalid mode (%lu)\n", mode
);
2436 return DSERR_INVALIDPARAM
;
2439 EnterCriticalSection(&This
->share
->crst
);
2440 if(apply
== DS3D_DEFERRED
)
2442 This
->deferred
.ds3d
.dwMode
= mode
;
2443 This
->dirty
.bit
.mode
= 1;
2447 setALContext(This
->ctx
);
2448 This
->current
.ds3d
.dwMode
= mode
;
2449 if(LIKELY(This
->source
))
2451 if(HAS_EXTENSION(This
->share
, SOFT_SOURCE_SPATIALIZE
))
2452 alSourcei(This
->source
, AL_SOURCE_SPATIALIZE_SOFT
,
2453 (mode
==DS3DMODE_DISABLE
) ? AL_FALSE
: AL_TRUE
);
2454 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2455 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2460 LeaveCriticalSection(&This
->share
->crst
);
2465 static HRESULT WINAPI
DSBuffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2467 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2469 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2471 EnterCriticalSection(&This
->share
->crst
);
2472 if(apply
== DS3D_DEFERRED
)
2474 This
->deferred
.ds3d
.vPosition
.x
= x
;
2475 This
->deferred
.ds3d
.vPosition
.y
= y
;
2476 This
->deferred
.ds3d
.vPosition
.z
= z
;
2477 This
->dirty
.bit
.pos
= 1;
2481 setALContext(This
->ctx
);
2482 This
->current
.ds3d
.vPosition
.x
= x
;
2483 This
->current
.ds3d
.vPosition
.y
= y
;
2484 This
->current
.ds3d
.vPosition
.z
= z
;
2485 if(LIKELY(This
->source
))
2487 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2492 LeaveCriticalSection(&This
->share
->crst
);
2497 static HRESULT WINAPI
DSBuffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2499 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2501 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2503 EnterCriticalSection(&This
->share
->crst
);
2504 if(apply
== DS3D_DEFERRED
)
2506 This
->deferred
.ds3d
.vVelocity
.x
= x
;
2507 This
->deferred
.ds3d
.vVelocity
.y
= y
;
2508 This
->deferred
.ds3d
.vVelocity
.z
= z
;
2509 This
->dirty
.bit
.vel
= 1;
2513 setALContext(This
->ctx
);
2514 This
->current
.ds3d
.vVelocity
.x
= x
;
2515 This
->current
.ds3d
.vVelocity
.y
= y
;
2516 This
->current
.ds3d
.vVelocity
.z
= z
;
2517 if(LIKELY(This
->source
))
2519 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2524 LeaveCriticalSection(&This
->share
->crst
);
2529 static HRESULT WINAPI
DSBuffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2531 DSBuffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2532 TRACE("(%p)->(%p, %lu)\n", This
, ds3dbuffer
, apply
);
2534 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2536 WARN("Invalid DS3DBUFFER (%p, %lu)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2537 return DSERR_INVALIDPARAM
;
2540 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2541 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2543 WARN("Invalid cone angles (%lu, %lu)\n",
2544 ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
);
2545 return DSERR_INVALIDPARAM
;
2548 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2549 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2551 WARN("Invalid cone outside volume (%ld)\n", ds3dbuffer
->lConeOutsideVolume
);
2552 return DSERR_INVALIDPARAM
;
2555 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2557 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2558 return DSERR_INVALIDPARAM
;
2561 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2563 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2564 return DSERR_INVALIDPARAM
;
2567 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2568 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2569 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2571 WARN("Invalid mode (%lu)\n", ds3dbuffer
->dwMode
);
2572 return DSERR_INVALIDPARAM
;
2575 if(apply
== DS3D_DEFERRED
)
2577 EnterCriticalSection(&This
->share
->crst
);
2578 This
->deferred
.ds3d
= *ds3dbuffer
;
2579 This
->deferred
.ds3d
.dwSize
= sizeof(This
->deferred
.ds3d
);
2580 This
->dirty
.bit
.pos
= 1;
2581 This
->dirty
.bit
.vel
= 1;
2582 This
->dirty
.bit
.cone_angles
= 1;
2583 This
->dirty
.bit
.cone_orient
= 1;
2584 This
->dirty
.bit
.cone_outsidevolume
= 1;
2585 This
->dirty
.bit
.min_distance
= 1;
2586 This
->dirty
.bit
.max_distance
= 1;
2587 This
->dirty
.bit
.mode
= 1;
2588 LeaveCriticalSection(&This
->share
->crst
);
2592 union BufferParamFlags dirty
= { 0 };
2595 dirty
.bit
.cone_angles
= 1;
2596 dirty
.bit
.cone_orient
= 1;
2597 dirty
.bit
.cone_outsidevolume
= 1;
2598 dirty
.bit
.min_distance
= 1;
2599 dirty
.bit
.max_distance
= 1;
2602 EnterCriticalSection(&This
->share
->crst
);
2603 setALContext(This
->ctx
);
2604 DSBuffer_SetParams(This
, ds3dbuffer
, dirty
.flags
);
2607 LeaveCriticalSection(&This
->share
->crst
);
2613 static IDirectSound3DBufferVtbl DSBuffer3d_Vtbl
=
2615 DSBuffer3D_QueryInterface
,
2618 DSBuffer3D_GetAllParameters
,
2619 DSBuffer3D_GetConeAngles
,
2620 DSBuffer3D_GetConeOrientation
,
2621 DSBuffer3D_GetConeOutsideVolume
,
2622 DSBuffer3D_GetMaxDistance
,
2623 DSBuffer3D_GetMinDistance
,
2625 DSBuffer3D_GetPosition
,
2626 DSBuffer3D_GetVelocity
,
2627 DSBuffer3D_SetAllParameters
,
2628 DSBuffer3D_SetConeAngles
,
2629 DSBuffer3D_SetConeOrientation
,
2630 DSBuffer3D_SetConeOutsideVolume
,
2631 DSBuffer3D_SetMaxDistance
,
2632 DSBuffer3D_SetMinDistance
,
2634 DSBuffer3D_SetPosition
,
2635 DSBuffer3D_SetVelocity
2639 static HRESULT WINAPI
DSBufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2641 DSBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
2642 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2643 return DSBuffer_GetInterface(This
, riid
, ppv
);
2646 static ULONG WINAPI
DSBufferNot_AddRef(IDirectSoundNotify
*iface
)
2648 DSBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
2651 InterlockedIncrement(&This
->all_ref
);
2652 ret
= InterlockedIncrement(&This
->not_ref
);
2653 TRACE("(%p) ref %lu\n", iface
, ret
);
2658 static ULONG WINAPI
DSBufferNot_Release(IDirectSoundNotify
*iface
)
2660 DSBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
2663 ret
= InterlockedDecrement(&This
->not_ref
);
2664 TRACE("(%p) ref %lu\n", iface
, ret
);
2665 if(InterlockedDecrement(&This
->all_ref
) == 0)
2666 DSBuffer_Destroy(This
);
2671 static HRESULT WINAPI
DSBufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2673 DSBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
2674 DSBPOSITIONNOTIFY
*nots
;
2678 TRACE("(%p)->(%lu, %p))\n", iface
, count
, notifications
);
2680 EnterCriticalSection(&This
->share
->crst
);
2681 hr
= DSERR_INVALIDPARAM
;
2682 if(count
&& !notifications
)
2685 hr
= DSBuffer_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2686 if(FAILED(hr
)) goto out
;
2688 hr
= DSERR_INVALIDCALL
;
2689 if((state
&DSBSTATUS_PLAYING
))
2694 HeapFree(GetProcessHeap(), 0, This
->notify
);
2703 hr
= DSERR_INVALIDPARAM
;
2704 for(i
= 0;i
< count
;++i
)
2706 if(notifications
[i
].dwOffset
>= (DWORD
)This
->buffer
->buf_size
&&
2707 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2712 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2714 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2716 HeapFree(GetProcessHeap(), 0, This
->notify
);
2717 This
->notify
= nots
;
2718 This
->nnotify
= count
;
2724 LeaveCriticalSection(&This
->share
->crst
);
2728 static IDirectSoundNotifyVtbl DSBufferNot_Vtbl
=
2730 DSBufferNot_QueryInterface
,
2732 DSBufferNot_Release
,
2733 DSBufferNot_SetNotificationPositions
2737 static const char *debug_bufferprop(const GUID
*guid
)
2739 #define HANDLE_ID(id) if(IsEqualGUID(guid, &(id))) return #id
2740 HANDLE_ID(EAXPROPERTYID_EAX40_Source
);
2741 HANDLE_ID(DSPROPSETID_EAX30_BufferProperties
);
2742 HANDLE_ID(DSPROPSETID_EAX20_BufferProperties
);
2743 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot0
);
2744 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot1
);
2745 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot2
);
2746 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot3
);
2747 HANDLE_ID(DSPROPSETID_EAX30_ListenerProperties
);
2748 HANDLE_ID(DSPROPSETID_EAX20_ListenerProperties
);
2749 HANDLE_ID(EAXPROPERTYID_EAX40_Context
);
2750 HANDLE_ID(DSPROPSETID_EAX10_BufferProperties
);
2751 HANDLE_ID(DSPROPSETID_EAX10_ListenerProperties
);
2752 HANDLE_ID(DSPROPSETID_VoiceManager
);
2753 HANDLE_ID(DSPROPSETID_ZOOMFX_BufferProperties
);
2754 HANDLE_ID(DSPROPSETID_I3DL2_ListenerProperties
);
2755 HANDLE_ID(DSPROPSETID_I3DL2_BufferProperties
);
2757 return debugstr_guid(guid
);
2760 static HRESULT WINAPI
DSBufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2762 DSBuffer
*This
= impl_from_IKsPropertySet(iface
);
2763 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2764 return DSBuffer_GetInterface(This
, riid
, ppv
);
2767 static ULONG WINAPI
DSBufferProp_AddRef(IKsPropertySet
*iface
)
2769 DSBuffer
*This
= impl_from_IKsPropertySet(iface
);
2772 InterlockedIncrement(&This
->all_ref
);
2773 ret
= InterlockedIncrement(&This
->prop_ref
);
2774 TRACE("(%p) ref %lu\n", iface
, ret
);
2779 static ULONG WINAPI
DSBufferProp_Release(IKsPropertySet
*iface
)
2781 DSBuffer
*This
= impl_from_IKsPropertySet(iface
);
2784 ret
= InterlockedDecrement(&This
->prop_ref
);
2785 TRACE("(%p) ref %lu\n", iface
, ret
);
2786 if(InterlockedDecrement(&This
->all_ref
) == 0)
2787 DSBuffer_Destroy(This
);
2792 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2793 handled through secondary buffers. */
2794 static HRESULT WINAPI
DSBufferProp_Get(IKsPropertySet
*iface
,
2795 REFGUID guidPropSet
, ULONG dwPropID
,
2796 LPVOID pInstanceData
, ULONG cbInstanceData
,
2797 LPVOID pPropData
, ULONG cbPropData
,
2800 DSBuffer
*This
= impl_from_IKsPropertySet(iface
);
2801 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2803 TRACE("(%p)->(%s, 0x%lx, %p, %lu, %p, %lu, %p)\n", iface
, debug_bufferprop(guidPropSet
),
2804 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2810 if(cbPropData
> 0 && !pPropData
)
2812 WARN("pPropData is NULL with cbPropData > 0\n");
2816 EnterCriticalSection(&This
->share
->crst
);
2817 if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_Source
))
2818 hr
= EAX4Source_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2819 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_BufferProperties
))
2820 hr
= EAX3Buffer_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2821 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2822 hr
= EAX2Buffer_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2823 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot0
))
2824 hr
= EAX4Slot_Get(This
->primary
, 0, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2825 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot1
))
2826 hr
= EAX4Slot_Get(This
->primary
, 1, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2827 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot2
))
2828 hr
= EAX4Slot_Get(This
->primary
, 2, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2829 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot3
))
2830 hr
= EAX4Slot_Get(This
->primary
, 3, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2831 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_ListenerProperties
))
2832 hr
= EAX3_Get(This
->primary
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2833 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2834 hr
= EAX2_Get(This
->primary
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2835 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_Context
))
2836 hr
= EAX4Context_Get(This
->primary
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2837 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_BufferProperties
))
2838 hr
= EAX1Buffer_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2839 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_ListenerProperties
))
2840 hr
= EAX1_Get(This
->primary
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2841 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_VoiceManager
))
2842 hr
= VoiceMan_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2844 FIXME("Unhandled propset: %s\n", debug_bufferprop(guidPropSet
));
2845 LeaveCriticalSection(&This
->share
->crst
);
2850 static HRESULT WINAPI
DSBufferProp_Set(IKsPropertySet
*iface
,
2851 REFGUID guidPropSet
, ULONG dwPropID
,
2852 LPVOID pInstanceData
, ULONG cbInstanceData
,
2853 LPVOID pPropData
, ULONG cbPropData
)
2855 DSBuffer
*This
= impl_from_IKsPropertySet(iface
);
2856 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2859 TRACE("(%p)->(%s, 0x%lx, %p, %lu, %p, %lu)\n", iface
, debug_bufferprop(guidPropSet
),
2860 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2862 if(cbPropData
> 0 && !pPropData
)
2864 WARN("pPropData is NULL with cbPropData > 0\n");
2868 EnterCriticalSection(&This
->share
->crst
);
2869 if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_Source
))
2871 DWORD propid
= dwPropID
& ~EAXSOURCE_PARAMETER_DEFERRED
;
2872 BOOL immediate
= !(dwPropID
&EAXSOURCE_PARAMETER_DEFERRED
);
2874 setALContext(This
->ctx
);
2875 hr
= EAX4Source_Set(This
, propid
, pPropData
, cbPropData
);
2876 if(hr
== DS_OK
&& immediate
)
2878 DSPrimary
*prim
= This
->primary
;
2879 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2883 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_BufferProperties
))
2885 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX30BUFFER_DEFERRED
;
2886 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX30BUFFER_DEFERRED
);
2888 setALContext(This
->ctx
);
2889 hr
= EAX3Buffer_Set(This
, propid
, pPropData
, cbPropData
);
2890 if(hr
== DS_OK
&& immediate
)
2892 DSPrimary
*prim
= This
->primary
;
2893 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2897 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2899 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20BUFFER_DEFERRED
;
2900 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20BUFFER_DEFERRED
);
2902 setALContext(This
->ctx
);
2903 hr
= EAX2Buffer_Set(This
, propid
, pPropData
, cbPropData
);
2904 if(hr
== DS_OK
&& immediate
)
2906 DSPrimary
*prim
= This
->primary
;
2907 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2911 else if(((idx
=0),IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot0
)) ||
2912 ((idx
=1),IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot1
)) ||
2913 ((idx
=2),IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot2
)) ||
2914 ((idx
=3),IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot3
)))
2916 DSPrimary
*prim
= This
->primary
;
2917 DWORD propid
= dwPropID
& ~EAXFXSLOT_PARAMETER_DEFERRED
;
2918 BOOL immediate
= !(dwPropID
&EAXFXSLOT_PARAMETER_DEFERRED
);
2920 setALContext(prim
->ctx
);
2921 hr
= EAX4Slot_Set(prim
, idx
, propid
, pPropData
, cbPropData
);
2922 if(hr
== DS_OK
&& immediate
)
2923 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2926 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_ListenerProperties
))
2928 DSPrimary
*prim
= This
->primary
;
2929 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX30LISTENER_DEFERRED
;
2930 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX30LISTENER_DEFERRED
);
2932 setALContext(prim
->ctx
);
2933 hr
= EAX3_Set(prim
, propid
, pPropData
, cbPropData
);
2934 if(hr
== DS_OK
&& immediate
)
2935 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2938 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2940 DSPrimary
*prim
= This
->primary
;
2941 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20LISTENER_DEFERRED
;
2942 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20LISTENER_DEFERRED
);
2944 setALContext(prim
->ctx
);
2945 hr
= EAX2_Set(prim
, propid
, pPropData
, cbPropData
);
2946 if(hr
== DS_OK
&& immediate
)
2947 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2950 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_Context
))
2952 DSPrimary
*prim
= This
->primary
;
2953 DWORD propid
= dwPropID
& ~EAXCONTEXT_PARAMETER_DEFERRED
;
2954 BOOL immediate
= !(dwPropID
&EAXCONTEXT_PARAMETER_DEFERRED
);
2956 setALContext(prim
->ctx
);
2957 hr
= EAX4Context_Set(prim
, propid
, pPropData
, cbPropData
);
2958 if(hr
== DS_OK
&& immediate
)
2959 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2962 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_BufferProperties
))
2964 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20BUFFER_DEFERRED
;
2965 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20BUFFER_DEFERRED
);
2967 setALContext(This
->ctx
);
2968 hr
= EAX1Buffer_Set(This
, propid
, pPropData
, cbPropData
);
2969 if(hr
== DS_OK
&& immediate
)
2971 DSPrimary
*prim
= This
->primary
;
2972 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2976 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_ListenerProperties
))
2978 DSPrimary
*prim
= This
->primary
;
2979 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20LISTENER_DEFERRED
;
2980 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20LISTENER_DEFERRED
);
2982 setALContext(prim
->ctx
);
2983 hr
= EAX1_Set(prim
, propid
, pPropData
, cbPropData
);
2984 if(hr
== DS_OK
&& immediate
)
2985 DSPrimary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2988 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_VoiceManager
))
2990 hr
= VoiceMan_Set(This
, dwPropID
, pPropData
, cbPropData
);
2993 FIXME("Unhandled propset: %s\n", debug_bufferprop(guidPropSet
));
2994 LeaveCriticalSection(&This
->share
->crst
);
2999 static HRESULT WINAPI
DSBufferProp_QuerySupport(IKsPropertySet
*iface
,
3000 REFGUID guidPropSet
, ULONG dwPropID
,
3001 ULONG
*pTypeSupport
)
3003 DSBuffer
*This
= impl_from_IKsPropertySet(iface
);
3004 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
3006 TRACE("(%p)->(%s, 0x%lx, %p)\n", iface
, debug_bufferprop(guidPropSet
), dwPropID
,
3013 EnterCriticalSection(&This
->share
->crst
);
3014 if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_Source
))
3015 hr
= EAX4Source_Query(This
, dwPropID
, pTypeSupport
);
3016 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_BufferProperties
))
3017 hr
= EAX3Buffer_Query(This
, dwPropID
, pTypeSupport
);
3018 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
3019 hr
= EAX2Buffer_Query(This
, dwPropID
, pTypeSupport
);
3020 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot0
))
3021 hr
= EAX4Slot_Query(This
->primary
, 0, dwPropID
, pTypeSupport
);
3022 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot1
))
3023 hr
= EAX4Slot_Query(This
->primary
, 1, dwPropID
, pTypeSupport
);
3024 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot2
))
3025 hr
= EAX4Slot_Query(This
->primary
, 2, dwPropID
, pTypeSupport
);
3026 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_FXSlot3
))
3027 hr
= EAX4Slot_Query(This
->primary
, 3, dwPropID
, pTypeSupport
);
3028 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_ListenerProperties
))
3029 hr
= EAX3_Query(This
->primary
, dwPropID
, pTypeSupport
);
3030 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
3031 hr
= EAX2_Query(This
->primary
, dwPropID
, pTypeSupport
);
3032 else if(IsEqualIID(guidPropSet
, &EAXPROPERTYID_EAX40_Context
))
3033 hr
= EAX4Context_Query(This
->primary
, dwPropID
, pTypeSupport
);
3034 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_ListenerProperties
))
3035 hr
= EAX1_Query(This
->primary
, dwPropID
, pTypeSupport
);
3036 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_BufferProperties
))
3037 hr
= EAX1Buffer_Query(This
, dwPropID
, pTypeSupport
);
3038 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_VoiceManager
))
3039 hr
= VoiceMan_Query(This
, dwPropID
, pTypeSupport
);
3041 FIXME("Unhandled propset: %s (propid: %lu)\n", debug_bufferprop(guidPropSet
), dwPropID
);
3042 LeaveCriticalSection(&This
->share
->crst
);
3047 static IKsPropertySetVtbl DSBufferProp_Vtbl
=
3049 DSBufferProp_QueryInterface
,
3050 DSBufferProp_AddRef
,
3051 DSBufferProp_Release
,
3054 DSBufferProp_QuerySupport