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 const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
;
49 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
;
50 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
;
51 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
;
54 static inline DS8Buffer
*impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8
*iface
)
56 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
59 static inline DS8Buffer
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
61 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
64 static inline DS8Buffer
*impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer
*iface
)
66 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSound3DBuffer_iface
);
69 static inline DS8Buffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
71 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundNotify_iface
);
74 static inline DS8Buffer
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
76 return CONTAINING_RECORD(iface
, DS8Buffer
, IKsPropertySet_iface
);
80 /* Should be called with critsect held and context set.. */
81 static void DS8Buffer_addnotify(DS8Buffer
*buf
)
83 DS8Primary
*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 DS8Primary
*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 DS8Primary
*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 DS8Primary
*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 DS8Data_Release(DS8Data
*This
);
278 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*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 if(format
->nAvgBytesPerSec
!= format
->nBlockAlign
*format
->nSamplesPerSec
)
327 WARN("Invalid AvgBytesPerSec %lu (expected %lu = %lu*%u)\n",
328 format
->nAvgBytesPerSec
, format
->nSamplesPerSec
*format
->nBlockAlign
,
329 format
->nSamplesPerSec
, format
->nBlockAlign
);
330 return DSERR_INVALIDPARAM
;
333 if((desc
->dwFlags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
335 WARN("Hardware and software location requested\n");
336 return DSERR_INVALIDPARAM
;
339 buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
340 buf_size
-= buf_size
%format
->nBlockAlign
;
341 if(buf_size
< DSBSIZE_MIN
) return DSERR_BUFFERTOOSMALL
;
342 if(buf_size
> DSBSIZE_MAX
) return DSERR_INVALIDPARAM
;
344 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
345 * will need the EAX-RAM extension. Currently, we just tell the app it
346 * gets what it wanted. */
347 if(!HAS_EXTENSION(prim
->share
, SOFTX_MAP_BUFFER
))
348 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
)+buf_size
);
350 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
351 if(!pBuffer
) return E_OUTOFMEMORY
;
353 pBuffer
->primary
= prim
;
355 pBuffer
->dsbflags
= desc
->dwFlags
;
356 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
357 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
358 pBuffer
->buf_size
= buf_size
;
360 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
361 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
362 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
363 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
364 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
366 const WAVEFORMATEXTENSIBLE
*wfe
;
368 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
369 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
372 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
373 TRACE("Extensible values:\n"
375 " ChannelMask = 0x%lx\n"
377 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
378 debugstr_guid(&wfe
->SubFormat
));
380 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
383 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
384 if(!fmt_str
) goto fail
;
387 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
388 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
389 pBuffer
->buf_format
== -1)
391 WARN("Could not get OpenAL format from %s\n", fmt_str
);
396 if(!HAS_EXTENSION(prim
->share
, SOFTX_MAP_BUFFER
))
398 pBuffer
->data
= (BYTE
*)(pBuffer
+1);
400 alGenBuffers(1, &pBuffer
->bid
);
405 const ALbitfieldSOFT map_bits
= AL_MAP_READ_BIT_SOFT
| AL_MAP_WRITE_BIT_SOFT
|
406 AL_MAP_PERSISTENT_BIT_SOFT
;
407 alGenBuffers(1, &pBuffer
->bid
);
408 alBufferStorageSOFT(pBuffer
->bid
, pBuffer
->buf_format
, NULL
, pBuffer
->buf_size
,
409 pBuffer
->format
.Format
.nSamplesPerSec
, map_bits
);
410 pBuffer
->data
= alMapBufferSOFT(pBuffer
->bid
, 0, pBuffer
->buf_size
, map_bits
);
413 if(!pBuffer
->data
) goto fail
;
420 DS8Data_Release(pBuffer
);
424 static void DS8Data_AddRef(DS8Data
*data
)
426 InterlockedIncrement(&data
->ref
);
429 /* This function is always called with the device lock held */
430 static void DS8Data_Release(DS8Data
*This
)
432 if(InterlockedDecrement(&This
->ref
)) return;
434 TRACE("Deleting %p\n", This
);
437 DS8Primary
*prim
= This
->primary
;
438 if(HAS_EXTENSION(prim
->share
, SOFTX_MAP_BUFFER
))
439 alUnmapBufferSOFT(This
->bid
);
440 alDeleteBuffers(1, &This
->bid
);
443 HeapFree(GetProcessHeap(), 0, This
);
447 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*prim
, IDirectSoundBuffer
*orig
)
449 DS8Buffer
*This
= NULL
;
450 EAX30BUFFERPROPERTIES
*eaxbuffer
;
451 DS3DBUFFER
*ds3dbuffer
;
456 EnterCriticalSection(&prim
->share
->crst
);
457 for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
459 if(prim
->BufferGroups
[i
].FreeBuffers
)
461 int idx
= CTZ64(prim
->BufferGroups
[i
].FreeBuffers
);
462 This
= prim
->BufferGroups
[i
].Buffers
+ idx
;
463 memset(This
, 0, sizeof(*This
));
464 prim
->BufferGroups
[i
].FreeBuffers
&= ~(U64(1) << idx
);
470 struct DSBufferGroup
*grp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
471 (prim
->NumBufferGroups
+1)*sizeof(prim
->BufferGroups
[0]));
474 for(i
= 0;i
< prim
->NumBufferGroups
;i
++)
475 grp
[i
] = prim
->BufferGroups
[i
];
476 grp
[i
].FreeBuffers
= ~U64(0);
477 grp
[i
].Buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
478 64*sizeof(grp
[0].Buffers
[0]));
481 HeapFree(GetProcessHeap(), 0, grp
);
486 HeapFree(GetProcessHeap(), 0, prim
->BufferGroups
);
487 prim
->BufferGroups
= grp
;
488 prim
->NumBufferGroups
++;
490 This
= prim
->BufferGroups
[i
].Buffers
+ 0;
491 memset(This
, 0, sizeof(*This
));
492 prim
->BufferGroups
[i
].FreeBuffers
&= ~(U64(1) << 0);
496 LeaveCriticalSection(&prim
->share
->crst
);
499 WARN("Out of memory allocating buffers\n");
500 return DSERR_OUTOFMEMORY
;
503 This
->IDirectSoundBuffer8_iface
.lpVtbl
= &DS8Buffer_Vtbl
;
504 This
->IDirectSound3DBuffer_iface
.lpVtbl
= &DS8Buffer3d_Vtbl
;
505 This
->IDirectSoundNotify_iface
.lpVtbl
= &DS8BufferNot_Vtbl
;
506 This
->IKsPropertySet_iface
.lpVtbl
= &DS8BufferProp_Vtbl
;
508 This
->share
= prim
->share
;
509 This
->primary
= prim
;
510 This
->ctx
= prim
->ctx
;
511 This
->ref
= This
->all_ref
= 1;
515 DS8Buffer
*org
= impl_from_IDirectSoundBuffer(orig
);
516 hr
= DSERR_BUFFERLOST
;
519 DS8Data_AddRef(org
->buffer
);
520 This
->buffer
= org
->buffer
;
523 This
->rollofffactor
= 0.0f
;
525 ds3dbuffer
= &This
->deferred
.ds3d
;
526 ds3dbuffer
->dwSize
= sizeof(This
->deferred
.ds3d
);
527 ds3dbuffer
->vPosition
.x
= 0.0f
;
528 ds3dbuffer
->vPosition
.y
= 0.0f
;
529 ds3dbuffer
->vPosition
.z
= 0.0f
;
530 ds3dbuffer
->vVelocity
.x
= 0.0f
;
531 ds3dbuffer
->vVelocity
.y
= 0.0f
;
532 ds3dbuffer
->vVelocity
.z
= 0.0f
;
533 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
534 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
535 ds3dbuffer
->vConeOrientation
.x
= 0.0f
;
536 ds3dbuffer
->vConeOrientation
.y
= 0.0f
;
537 ds3dbuffer
->vConeOrientation
.z
= 1.0f
;
538 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
539 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
540 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
541 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
542 eaxbuffer
= &This
->deferred
.eax
;
543 eaxbuffer
->lDirect
= 0;
544 eaxbuffer
->lDirectHF
= 0;
545 eaxbuffer
->lRoom
= 0;
546 eaxbuffer
->lRoomHF
= 0;
547 eaxbuffer
->lObstruction
= 0;
548 eaxbuffer
->flObstructionLFRatio
= 0.0f
;
549 eaxbuffer
->lOcclusion
= 0;
550 eaxbuffer
->flOcclusionLFRatio
= 0.25f
;
551 eaxbuffer
->flOcclusionRoomRatio
= 1.5f
;
552 eaxbuffer
->flOcclusionDirectRatio
= 1.0f
;
553 eaxbuffer
->lExclusion
= 0;
554 eaxbuffer
->flExclusionLFRatio
= 1.0f
;
555 eaxbuffer
->lOutsideVolumeHF
= 0;
556 eaxbuffer
->flDopplerFactor
= 1.0f
;
557 eaxbuffer
->flRolloffFactor
= 0.0f
;
558 eaxbuffer
->flRoomRolloffFactor
= 0.0f
;
559 eaxbuffer
->flAirAbsorptionFactor
= 0.0f
;
560 eaxbuffer
->dwFlags
= EAX30BUFFERFLAGS_DIRECTHFAUTO
| EAX30BUFFERFLAGS_ROOMAUTO
|
561 EAX30BUFFERFLAGS_ROOMHFAUTO
;
562 This
->deferred
.eax1_reverbmix
= 1.0f
;
564 /* Disable until initialized. */
565 This
->ds3dmode
= DS3DMODE_DISABLE
;
571 DS8Buffer_Destroy(This
);
575 void DS8Buffer_Destroy(DS8Buffer
*This
)
577 DS8Primary
*prim
= This
->primary
;
581 TRACE("Destroying %p\n", This
);
583 EnterCriticalSection(&prim
->share
->crst
);
584 /* Remove from list, if in list */
585 for(i
= 0;i
< prim
->nnotifies
;++i
)
587 if(This
== prim
->notifies
[i
])
589 prim
->notifies
[i
] = prim
->notifies
[--prim
->nnotifies
];
594 setALContext(This
->ctx
);
597 alSourceStop(This
->source
);
598 alSourcei(This
->source
, AL_BUFFER
, 0);
601 prim
->share
->sources
.ids
[prim
->share
->sources
.avail_num
++] = This
->source
;
604 if(This
->stream_bids
[0])
605 alDeleteBuffers(QBUFFERS
, This
->stream_bids
);
607 alDeleteFilters(2, This
->filter
);
610 DS8Data_Release(This
->buffer
);
614 HeapFree(GetProcessHeap(), 0, This
->notify
);
616 for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
618 DWORD_PTR idx
= This
- prim
->BufferGroups
[i
].Buffers
;
621 prim
->BufferGroups
[i
].FreeBuffers
|= U64(1) << idx
;
626 LeaveCriticalSection(&prim
->share
->crst
);
630 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
632 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
634 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
637 if(IsEqualIID(riid
, &IID_IUnknown
))
638 *ppv
= &This
->IDirectSoundBuffer8_iface
;
639 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
640 *ppv
= &This
->IDirectSoundBuffer8_iface
;
641 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
643 if(This
->primary
->parent
->is_8
)
644 *ppv
= &This
->IDirectSoundBuffer8_iface
;
646 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
648 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
649 *ppv
= &This
->IDirectSound3DBuffer_iface
;
651 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
653 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
654 *ppv
= &This
->IDirectSoundNotify_iface
;
656 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
657 *ppv
= &This
->IKsPropertySet_iface
;
659 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
663 IUnknown_AddRef((IUnknown
*)*ppv
);
667 return E_NOINTERFACE
;
670 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
672 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
675 InterlockedIncrement(&This
->all_ref
);
676 ret
= InterlockedIncrement(&This
->ref
);
677 TRACE("new refcount %ld\n", ret
);
682 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
684 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
687 ret
= InterlockedDecrement(&This
->ref
);
688 TRACE("new refcount %ld\n", ret
);
689 if(InterlockedDecrement(&This
->all_ref
) == 0)
690 DS8Buffer_Destroy(This
);
695 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
697 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
700 TRACE("(%p)->(%p)\n", iface
, caps
);
702 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
704 WARN("Invalid DSBCAPS (%p, %lu)\n", caps
, (caps
? caps
->dwSize
: 0));
705 return DSERR_INVALIDPARAM
;
709 caps
->dwFlags
= data
->dsbflags
;
710 if((data
->dsbflags
&DSBCAPS_LOCDEFER
))
712 if(This
->loc_status
== DSBSTATUS_LOCHARDWARE
)
713 caps
->dwFlags
|= DSBCAPS_LOCHARDWARE
;
714 else if(This
->loc_status
== DSBSTATUS_LOCSOFTWARE
)
715 caps
->dwFlags
|= DSBCAPS_LOCSOFTWARE
;
717 caps
->dwBufferBytes
= data
->buf_size
;
718 caps
->dwUnlockTransferRate
= 4096;
719 caps
->dwPlayCpuOverhead
= 0;
724 HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
726 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
727 ALsizei writecursor
, pos
;
730 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
733 if(This
->segsize
!= 0)
735 ALint queued
= QBUFFERS
;
739 EnterCriticalSection(&This
->share
->crst
);
741 setALContext(This
->ctx
);
742 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
743 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
744 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
748 if(status
== AL_STOPPED
)
749 pos
= This
->segsize
*queued
+ This
->queue_base
;
751 pos
= ofs
+ This
->queue_base
;
752 if(pos
>= data
->buf_size
)
755 pos
%= data
->buf_size
;
756 else if(This
->isplaying
)
758 pos
= data
->buf_size
;
759 alSourceStop(This
->source
);
760 alSourcei(This
->source
, AL_BUFFER
, 0);
762 This
->isplaying
= FALSE
;
766 writecursor
= (This
->segsize
*QBUFFERS
+ pos
) % data
->buf_size
;
768 writecursor
= pos
% data
->buf_size
;
770 LeaveCriticalSection(&This
->share
->crst
);
774 const WAVEFORMATEX
*format
= &data
->format
.Format
;
778 setALContext(This
->ctx
);
779 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
780 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
784 /* AL_STOPPED means the source naturally reached its end, where
785 * DirectSound's position should be at the end (OpenAL reports a 0
786 * position). The Stop method correlates to pausing, which would put
787 * the source into an AL_PAUSED state and hold its current position.
789 pos
= (status
== AL_STOPPED
) ? data
->buf_size
: ofs
;
790 if(status
== AL_PLAYING
)
792 writecursor
= format
->nSamplesPerSec
/ This
->primary
->refresh
;
793 writecursor
*= format
->nBlockAlign
;
797 writecursor
= (writecursor
+ pos
) % data
->buf_size
;
799 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
801 if(pos
> data
->buf_size
)
803 ERR("playpos > buf_size\n");
804 pos
%= data
->buf_size
;
806 if(writecursor
>= data
->buf_size
)
808 ERR("writepos >= buf_size\n");
809 writecursor
%= data
->buf_size
;
812 if(playpos
) *playpos
= pos
;
813 if(curpos
) *curpos
= writecursor
;
818 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
820 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
824 TRACE("(%p)->(%p, %lu, %p)\n", iface
, wfx
, allocated
, written
);
828 WARN("Cannot report format or format size\n");
829 return DSERR_INVALIDPARAM
;
832 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
836 hr
= DSERR_INVALIDPARAM
;
838 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
846 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
848 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
851 TRACE("(%p)->(%p)\n", iface
, vol
);
855 WARN("Invalid pointer\n");
856 return DSERR_INVALIDPARAM
;
859 hr
= DSERR_CONTROLUNAVAIL
;
860 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
861 WARN("Volume control not set\n");
866 setALContext(This
->ctx
);
867 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
871 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
878 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
880 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
883 TRACE("(%p)->(%p)\n", iface
, pan
);
887 WARN("Invalid pointer\n");
888 return DSERR_INVALIDPARAM
;
891 hr
= DSERR_CONTROLUNAVAIL
;
892 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
893 WARN("Panning control not set\n");
896 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
902 setALContext(This
->ctx
);
903 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
907 *pan
= clampI((LONG
)((pos
[0]+0.5f
)*(DSBPAN_RIGHT
-DSBPAN_LEFT
) + 0.5f
) + DSBPAN_LEFT
,
908 DSBPAN_LEFT
, DSBPAN_RIGHT
);
916 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
918 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
921 TRACE("(%p)->(%p)\n", iface
, freq
);
925 WARN("Invalid pointer\n");
926 return DSERR_INVALIDPARAM
;
929 hr
= DSERR_CONTROLUNAVAIL
;
930 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
931 WARN("Frequency control not set\n");
934 ALfloat pitch
= 1.0f
;
936 setALContext(This
->ctx
);
937 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
941 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
948 HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
950 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
951 ALint state
, looping
;
953 TRACE("(%p)->(%p)\n", iface
, status
);
957 WARN("Invalid pointer\n");
958 return DSERR_INVALIDPARAM
;
962 if(This
->segsize
== 0)
964 setALContext(This
->ctx
);
965 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
966 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
972 EnterCriticalSection(&This
->share
->crst
);
973 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
974 looping
= This
->islooping
;
975 LeaveCriticalSection(&This
->share
->crst
);
978 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
979 *status
|= This
->loc_status
;
980 if(state
== AL_PLAYING
)
981 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
983 TRACE("%p status = 0x%08lx\n", This
, *status
);
987 HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
989 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
994 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
996 EnterCriticalSection(&This
->share
->crst
);
997 setALContext(This
->ctx
);
999 hr
= DSERR_ALREADYINITIALIZED
;
1000 if(This
->init_done
) goto out
;
1002 prim
= This
->primary
;
1005 hr
= DSERR_INVALIDPARAM
;
1008 WARN("Missing DSound buffer description\n");
1011 if(!desc
->lpwfxFormat
)
1013 WARN("Missing buffer format (%p)\n", This
);
1016 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
1018 if(prim
->parent
->is_8
)
1020 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1022 WARN("Can't create multi-channel 3D buffers\n");
1027 static int once
= 0;
1029 ERR("Multi-channel 3D sounds are not spatialized\n");
1032 if((desc
->dwFlags
&DSBCAPS_CTRLPAN
) && desc
->lpwfxFormat
->nChannels
!= 1)
1034 static int once
= 0;
1036 ERR("Panning for multi-channel buffers is not supported\n");
1039 hr
= DS8Data_Create(&This
->buffer
, desc
, prim
);
1040 if(FAILED(hr
)) goto out
;
1042 data
= This
->buffer
;
1043 if(data
->format
.Format
.wBitsPerSample
== 8)
1044 memset(data
->data
, 0x80, data
->buf_size
);
1046 memset(data
->data
, 0x00, data
->buf_size
);
1049 data
= This
->buffer
;
1050 if((data
->dsbflags
&DSBCAPS_LOCHARDWARE
))
1051 This
->loc_status
= DSBSTATUS_LOCHARDWARE
;
1052 else if((data
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
1053 This
->loc_status
= DSBSTATUS_LOCSOFTWARE
;
1055 if(!(data
->dsbflags
&DSBCAPS_STATIC
) && !HAS_EXTENSION(This
->share
, SOFTX_MAP_BUFFER
))
1057 This
->segsize
= (data
->format
.Format
.nAvgBytesPerSec
+prim
->refresh
-1) / prim
->refresh
;
1058 This
->segsize
= clampI(This
->segsize
, data
->format
.Format
.nBlockAlign
, 2048);
1059 This
->segsize
+= data
->format
.Format
.nBlockAlign
- 1;
1060 This
->segsize
-= This
->segsize
%data
->format
.Format
.nBlockAlign
;
1062 alGenBuffers(QBUFFERS
, This
->stream_bids
);
1066 hr
= DSERR_ALLOCATED
;
1067 if(!This
->share
->sources
.avail_num
)
1069 ERR("Out of sources\n");
1073 This
->source
= This
->share
->sources
.ids
[--(This
->share
->sources
.avail_num
)];
1074 alSourceRewind(This
->source
);
1075 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
1076 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
1079 if((data
->dsbflags
&DSBCAPS_CTRL3D
))
1081 union BufferParamFlags dirty
= { 0 };
1083 if(HAS_EXTENSION(This
->share
, EXT_EFX
))
1085 alGenFilters(2, This
->filter
);
1086 alFilteri(This
->filter
[0], AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1087 alFilteri(This
->filter
[1], AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1088 if(UNLIKELY(alGetError() != AL_NO_ERROR
))
1090 alDeleteFilters(2, This
->filter
);
1091 This
->filter
[0] = This
->filter
[1] = 0;
1097 dirty
.bit
.cone_angles
= 1;
1098 dirty
.bit
.cone_orient
= 1;
1099 dirty
.bit
.cone_outsidevolume
= 1;
1100 dirty
.bit
.min_distance
= 1;
1101 dirty
.bit
.max_distance
= 1;
1103 dirty
.bit
.doppler
= 1;
1104 dirty
.bit
.rolloff
= 1;
1105 if(HAS_EXTENSION(This
->share
, EXT_EFX
))
1107 dirty
.bit
.dry_filter
= 1;
1108 dirty
.bit
.wet_filter
= 1;
1109 dirty
.bit
.room_rolloff
= 1;
1110 dirty
.bit
.cone_outsidevolumehf
= 1;
1111 dirty
.bit
.air_absorb
= 1;
1112 dirty
.bit
.flags
= 1;
1114 DS8Buffer_SetParams(This
, &This
->deferred
.ds3d
, &This
->deferred
.eax
, dirty
.flags
);
1119 ALuint source
= This
->source
;
1121 /* Non-3D sources aren't distance attenuated */
1122 This
->ds3dmode
= DS3DMODE_DISABLE
;
1123 alSource3f(source
, AL_POSITION
, 0.0f
, 0.0f
, -1.0f
);
1124 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1125 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1126 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1127 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1128 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1129 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1130 alSourcef(source
, AL_DOPPLER_FACTOR
, 0.0f
);
1131 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1132 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1133 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1134 if(HAS_EXTENSION(This
->share
, EXT_EFX
))
1136 alSourcef(source
, AL_ROOM_ROLLOFF_FACTOR
, 0.0f
);
1137 alSourcef(source
, AL_CONE_OUTER_GAINHF
, 1.0f
);
1138 alSourcef(source
, AL_AIR_ABSORPTION_FACTOR
, 0.0f
);
1139 alSourcei(source
, AL_DIRECT_FILTER_GAINHF_AUTO
, AL_TRUE
);
1140 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
, AL_TRUE
);
1141 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
, AL_TRUE
);
1142 alSourcei(source
, AL_DIRECT_FILTER
, AL_FILTER_NULL
);
1143 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, 0, 0, AL_FILTER_NULL
);
1145 if(HAS_EXTENSION(This
->share
, SOFT_SOURCE_SPATIALIZE
))
1147 /* Set to auto so panning works for mono, and multi-channel works
1150 alSourcei(source
, AL_SOURCE_SPATIALIZE_SOFT
, AL_AUTO_SOFT
);
1157 This
->init_done
= SUCCEEDED(hr
);
1160 LeaveCriticalSection(&This
->share
->crst
);
1165 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1167 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1170 TRACE("(%p)->(%lu, %lu, %p, %p, %p, %p, 0x%lx)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1174 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1175 return DSERR_INVALIDPARAM
;
1180 if(ptr2
) *ptr2
= NULL
;
1183 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1184 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1185 else if(ofs
>= (DWORD
)This
->buffer
->buf_size
)
1187 WARN("Invalid ofs %lu\n", ofs
);
1188 return DSERR_INVALIDPARAM
;
1190 if((flags
&DSBLOCK_ENTIREBUFFER
))
1191 bytes
= This
->buffer
->buf_size
;
1192 else if(bytes
> (DWORD
)This
->buffer
->buf_size
)
1194 WARN("Invalid size %lu\n", bytes
);
1195 return DSERR_INVALIDPARAM
;
1198 if(InterlockedExchange(&This
->buffer
->locked
, TRUE
) == TRUE
)
1200 WARN("Already locked\n");
1201 return DSERR_INVALIDPARAM
;
1204 *ptr1
= This
->buffer
->data
+ ofs
;
1205 if(bytes
>= (DWORD
)This
->buffer
->buf_size
-ofs
)
1207 *len1
= This
->buffer
->buf_size
- ofs
;
1208 remain
= bytes
- *len1
;
1216 if(ptr2
&& len2
&& remain
)
1218 *ptr2
= This
->buffer
->data
;
1225 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1227 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1228 ALint state
= AL_STOPPED
;
1232 TRACE("(%p)->(%lu, %lu, %lu)\n", iface
, res1
, prio
, flags
);
1234 EnterCriticalSection(&This
->share
->crst
);
1235 setALContext(This
->ctx
);
1237 hr
= DSERR_BUFFERLOST
;
1238 if(This
->bufferlost
)
1240 WARN("Buffer %p lost\n", This
);
1244 data
= This
->buffer
;
1245 if((data
->dsbflags
&DSBCAPS_LOCDEFER
))
1247 if((flags
&DSBPLAY_LOCSOFTWARE
))
1248 This
->loc_status
= DSBSTATUS_LOCSOFTWARE
;
1250 This
->loc_status
= DSBSTATUS_LOCHARDWARE
;
1254 ERR("Invalid priority set for non-deferred buffer %p, %lu!\n", This
->buffer
, prio
);
1255 hr
= DSERR_INVALIDPARAM
;
1259 if(This
->segsize
!= 0)
1261 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1262 if(This
->isplaying
) state
= AL_PLAYING
;
1266 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1267 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1272 if(state
== AL_PLAYING
)
1275 if(This
->segsize
== 0)
1277 if(state
!= AL_PAUSED
)
1278 alSourcei(This
->source
, AL_BUFFER
, data
->bid
);
1279 alSourcePlay(This
->source
);
1283 alSourceRewind(This
->source
);
1284 alSourcei(This
->source
, AL_BUFFER
, 0);
1285 This
->queue_base
= This
->data_offset
% data
->buf_size
;
1288 if(alGetError() != AL_NO_ERROR
)
1290 ERR("Couldn't start source\n");
1291 alSourcei(This
->source
, AL_BUFFER
, 0);
1296 This
->isplaying
= TRUE
;
1297 This
->playflags
= flags
;
1300 DS8Buffer_addnotify(This
);
1304 LeaveCriticalSection(&This
->share
->crst
);
1308 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1310 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1313 TRACE("(%p)->(%lu)\n", iface
, pos
);
1315 data
= This
->buffer
;
1316 if(pos
>= (DWORD
)data
->buf_size
)
1317 return DSERR_INVALIDPARAM
;
1318 pos
-= pos
%data
->format
.Format
.nBlockAlign
;
1320 EnterCriticalSection(&This
->share
->crst
);
1322 if(This
->segsize
!= 0)
1326 setALContext(This
->ctx
);
1327 /* Perform a flush, so the next timer update will restart at the
1328 * proper position */
1329 alSourceRewind(This
->source
);
1330 alSourcei(This
->source
, AL_BUFFER
, 0);
1334 This
->queue_base
= This
->data_offset
= pos
;
1339 setALContext(This
->ctx
);
1340 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1344 This
->lastpos
= pos
;
1346 LeaveCriticalSection(&This
->share
->crst
);
1350 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1352 /* This call only works on primary buffers */
1353 WARN("(%p)->(%p)\n", iface
, wfx
);
1354 return DSERR_INVALIDCALL
;
1357 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1359 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1362 TRACE("(%p)->(%ld)\n", iface
, vol
);
1364 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1366 WARN("Invalid volume (%ld)\n", vol
);
1367 return DSERR_INVALIDPARAM
;
1370 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1371 hr
= DSERR_CONTROLUNAVAIL
;
1374 ALfloat fvol
= mB_to_gain(vol
);
1375 setALContext(This
->ctx
);
1376 alSourcef(This
->source
, AL_GAIN
, fvol
);
1383 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1385 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1388 TRACE("(%p)->(%ld)\n", iface
, pan
);
1390 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1392 WARN("invalid parameter: pan = %ld\n", pan
);
1393 return DSERR_INVALIDPARAM
;
1396 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1397 hr
= DSERR_CONTROLUNAVAIL
;
1400 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1403 pos
[0] = (ALfloat
)(pan
-DSBPAN_LEFT
)/(ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 0.5f
;
1405 /* NOTE: Strict movement along the X plane can cause the sound to
1406 * jump between left and right sharply. Using a curved path helps
1409 pos
[2] = -sqrtf(1.0f
- pos
[0]*pos
[0]);
1411 setALContext(This
->ctx
);
1412 alSourcefv(This
->source
, AL_POSITION
, pos
);
1421 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1423 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1426 TRACE("(%p)->(%lu)\n", iface
, freq
);
1428 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1430 WARN("invalid parameter: freq = %lu\n", freq
);
1431 return DSERR_INVALIDPARAM
;
1434 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1435 hr
= DSERR_CONTROLUNAVAIL
;
1438 ALfloat pitch
= 1.0f
;
1439 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1440 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1442 setALContext(This
->ctx
);
1443 alSourcef(This
->source
, AL_PITCH
, pitch
);
1451 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1453 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1455 TRACE("(%p)->()\n", iface
);
1457 EnterCriticalSection(&This
->share
->crst
);
1458 setALContext(This
->ctx
);
1460 alSourcePause(This
->source
);
1463 This
->isplaying
= FALSE
;
1464 DS8Primary_triggernots(This
->primary
);
1467 LeaveCriticalSection(&This
->share
->crst
);
1472 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1474 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1475 DS8Data
*buf
= This
->buffer
;
1476 DWORD bufsize
= buf
->buf_size
;
1477 DWORD_PTR ofs1
, ofs2
;
1478 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1481 TRACE("(%p)->(%p, %lu, %p, %lu)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1483 if(InterlockedExchange(&buf
->locked
, FALSE
) == FALSE
)
1485 WARN("Not locked\n");
1486 return DSERR_INVALIDPARAM
;
1489 hr
= DSERR_INVALIDPARAM
;
1490 /* Make sure offset is between boundary and boundary + bufsize */
1491 ofs1
= (DWORD_PTR
)ptr1
;
1492 ofs2
= (DWORD_PTR
)ptr2
;
1493 if(ofs1
< boundary
|| (ofs2
&& ofs2
!= boundary
))
1497 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1506 if(HAS_EXTENSION(This
->share
, SOFTX_MAP_BUFFER
))
1508 setALContext(This
->ctx
);
1509 alFlushMappedBufferSOFT(buf
->bid
, 0, buf
->buf_size
);
1513 else if(This
->segsize
== 0)
1515 setALContext(This
->ctx
);
1516 alBufferData(buf
->bid
, buf
->buf_format
, buf
->data
, buf
->buf_size
,
1517 buf
->format
.Format
.nSamplesPerSec
);
1524 WARN("Invalid parameters (0x%lx,%lu) (%p,%lu,%p,%lu)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1528 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1530 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1533 TRACE("(%p)->()\n", iface
);
1535 EnterCriticalSection(&This
->share
->crst
);
1536 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1537 iface
== This
->primary
->write_emu
)
1539 This
->bufferlost
= 0;
1543 hr
= DSERR_BUFFERLOST
;
1544 LeaveCriticalSection(&This
->share
->crst
);
1549 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1551 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1552 ALenum state
= AL_INITIAL
;
1557 TRACE("(%p)->(%lu, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1559 data
= This
->buffer
;
1560 if(!(data
->dsbflags
&DSBCAPS_CTRLFX
))
1562 WARN("FX control not set\n");
1563 return DSERR_CONTROLUNAVAIL
;
1568 WARN("Buffer is locked\n");
1569 return DSERR_INVALIDCALL
;
1572 EnterCriticalSection(&This
->share
->crst
);
1573 setALContext(This
->ctx
);
1575 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1577 if(This
->segsize
!= 0 && state
!= AL_PLAYING
)
1578 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1579 if(state
== AL_PLAYING
)
1581 WARN("Buffer is playing\n");
1582 hr
= DSERR_INVALIDCALL
;
1586 hr
= DSERR_INVALIDPARAM
;
1589 if(desc
|| rescodes
)
1591 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1595 /* No effects; we can handle that */
1600 if(!desc
|| !rescodes
)
1602 WARN("NULL desc and/or result pointer specified.\n");
1606 /* We don't (currently) handle DSound effects */
1607 for(i
= 0;i
< fxcount
;++i
)
1609 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1610 rescodes
[i
] = DSFXR_FAILED
;
1616 LeaveCriticalSection(&This
->share
->crst
);
1621 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1623 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1625 TRACE("(%p)->(%lu, %lu, %p)\n", This
, flags
, fxcount
, rescodes
);
1627 /* effects aren't supported at the moment.. */
1628 if(fxcount
!= 0 || rescodes
)
1630 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1631 return DSERR_INVALIDPARAM
;
1634 EnterCriticalSection(&This
->share
->crst
);
1635 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1637 if((flags
&DSBPLAY_LOCSOFTWARE
))
1638 This
->loc_status
= DSBSTATUS_LOCSOFTWARE
;
1640 This
->loc_status
= DSBSTATUS_LOCHARDWARE
;
1642 LeaveCriticalSection(&This
->share
->crst
);
1647 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1649 FIXME("(%p)->(%s, %lu, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1653 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
= {
1654 DS8Buffer_QueryInterface
,
1658 DS8Buffer_GetCurrentPosition
,
1659 DS8Buffer_GetFormat
,
1660 DS8Buffer_GetVolume
,
1662 DS8Buffer_GetFrequency
,
1663 DS8Buffer_GetStatus
,
1664 DS8Buffer_Initialize
,
1667 DS8Buffer_SetCurrentPosition
,
1668 DS8Buffer_SetFormat
,
1669 DS8Buffer_SetVolume
,
1671 DS8Buffer_SetFrequency
,
1676 DS8Buffer_AcquireResources
,
1677 DS8Buffer_GetObjectInPath
1681 void DS8Buffer_SetParams(DS8Buffer
*This
, const DS3DBUFFER
*params
, const EAX30BUFFERPROPERTIES
*eax_params
, LONG flags
)
1683 DS8Primary
*prim
= This
->primary
;
1684 const ALuint source
= This
->source
;
1685 union BufferParamFlags dirty
= { flags
};
1688 alSource3f(source
, AL_POSITION
, params
->vPosition
.x
, params
->vPosition
.y
,
1689 -params
->vPosition
.z
);
1691 alSource3f(source
, AL_VELOCITY
, params
->vVelocity
.x
, params
->vVelocity
.y
,
1692 -params
->vVelocity
.z
);
1693 if(dirty
.bit
.cone_angles
)
1695 alSourcei(source
, AL_CONE_INNER_ANGLE
, params
->dwInsideConeAngle
);
1696 alSourcei(source
, AL_CONE_OUTER_ANGLE
, params
->dwOutsideConeAngle
);
1698 if(dirty
.bit
.cone_orient
)
1699 alSource3f(source
, AL_DIRECTION
, params
->vConeOrientation
.x
,
1700 params
->vConeOrientation
.y
,
1701 -params
->vConeOrientation
.z
);
1702 if(dirty
.bit
.cone_outsidevolume
)
1703 alSourcef(source
, AL_CONE_OUTER_GAIN
, mB_to_gain(params
->lConeOutsideVolume
));
1704 if(dirty
.bit
.min_distance
)
1705 alSourcef(source
, AL_REFERENCE_DISTANCE
, params
->flMinDistance
);
1706 if(dirty
.bit
.max_distance
)
1707 alSourcef(source
, AL_MAX_DISTANCE
, params
->flMaxDistance
);
1710 This
->ds3dmode
= params
->dwMode
;
1711 if(HAS_EXTENSION(This
->share
, SOFT_SOURCE_SPATIALIZE
))
1712 alSourcei(source
, AL_SOURCE_SPATIALIZE_SOFT
,
1713 (params
->dwMode
==DS3DMODE_DISABLE
) ? AL_FALSE
: AL_TRUE
);
1714 alSourcei(source
, AL_SOURCE_RELATIVE
, (params
->dwMode
!=DS3DMODE_NORMAL
) ?
1715 AL_TRUE
: AL_FALSE
);
1716 alSourcef(source
, AL_ROLLOFF_FACTOR
, (params
->dwMode
==DS3DMODE_DISABLE
) ?
1717 0.0f
: prim
->rollofffactor
);
1720 if(dirty
.bit
.dry_filter
)
1721 alSourcei(source
, AL_DIRECT_FILTER
, This
->filter
[0]);
1722 if(dirty
.bit
.wet_filter
)
1723 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, prim
->auxslot
, 0, This
->filter
[1]);
1724 if(dirty
.bit
.doppler
)
1725 alSourcef(source
, AL_DOPPLER_FACTOR
, eax_params
->flDopplerFactor
);
1726 if(dirty
.bit
.rolloff
)
1728 This
->rollofffactor
= eax_params
->flRolloffFactor
;
1729 alSourcef(source
, AL_ROLLOFF_FACTOR
, eax_params
->flRolloffFactor
+ prim
->rollofffactor
);
1731 if(dirty
.bit
.room_rolloff
)
1732 alSourcef(source
, AL_ROOM_ROLLOFF_FACTOR
, eax_params
->flRoomRolloffFactor
);
1733 if(dirty
.bit
.cone_outsidevolumehf
)
1734 alSourcef(source
, AL_CONE_OUTER_GAINHF
, mB_to_gain(eax_params
->lOutsideVolumeHF
));
1735 if(dirty
.bit
.air_absorb
)
1736 alSourcef(source
, AL_AIR_ABSORPTION_FACTOR
, eax_params
->flAirAbsorptionFactor
);
1739 alSourcei(source
, AL_DIRECT_FILTER_GAINHF_AUTO
,
1740 (eax_params
->dwFlags
&EAX30BUFFERFLAGS_DIRECTHFAUTO
) ? AL_TRUE
: AL_FALSE
);
1741 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
1742 (eax_params
->dwFlags
&EAX30BUFFERFLAGS_ROOMAUTO
) ? AL_TRUE
: AL_FALSE
);
1743 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
1744 (eax_params
->dwFlags
&EAX30BUFFERFLAGS_ROOMHFAUTO
) ? AL_TRUE
: AL_FALSE
);
1748 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
1750 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1751 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1754 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
1756 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1759 InterlockedIncrement(&This
->all_ref
);
1760 ret
= InterlockedIncrement(&This
->ds3d_ref
);
1761 TRACE("new refcount %ld\n", ret
);
1766 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
1768 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1771 ret
= InterlockedDecrement(&This
->ds3d_ref
);
1772 TRACE("new refcount %ld\n", ret
);
1773 if(InterlockedDecrement(&This
->all_ref
) == 0)
1774 DS8Buffer_Destroy(This
);
1779 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
1781 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1782 ALint inangle
, outangle
;
1784 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
1785 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
1787 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
1788 return DSERR_INVALIDPARAM
;
1791 EnterCriticalSection(&This
->share
->crst
);
1792 setALContext(This
->ctx
);
1794 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
1795 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
1799 LeaveCriticalSection(&This
->share
->crst
);
1801 *pdwInsideConeAngle
= inangle
;
1802 *pdwOutsideConeAngle
= outangle
;
1806 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
1808 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1811 TRACE("(%p)->(%p)\n", This
, orient
);
1814 WARN("Invalid pointer\n");
1815 return DSERR_INVALIDPARAM
;
1818 setALContext(This
->ctx
);
1819 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
1825 orient
->z
= -dir
[2];
1829 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
1831 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1834 TRACE("(%p)->(%p)\n", This
, vol
);
1837 WARN("Invalid pointer\n");
1838 return DSERR_INVALIDPARAM
;
1841 setALContext(This
->ctx
);
1842 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
1846 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
1850 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
1852 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1855 TRACE("(%p)->(%p)\n", This
, maxdist
);
1858 WARN("Invalid pointer\n");
1859 return DSERR_INVALIDPARAM
;
1862 setALContext(This
->ctx
);
1863 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
1871 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
1873 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1876 TRACE("(%p)->(%p)\n", This
, mindist
);
1879 WARN("Invalid pointer\n");
1880 return DSERR_INVALIDPARAM
;
1883 setALContext(This
->ctx
);
1884 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
1892 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
1894 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1896 TRACE("(%p)->(%p)\n", This
, mode
);
1899 WARN("Invalid pointer\n");
1900 return DSERR_INVALIDPARAM
;
1903 EnterCriticalSection(&This
->share
->crst
);
1904 *mode
= This
->ds3dmode
;
1905 LeaveCriticalSection(&This
->share
->crst
);
1910 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
1912 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1915 TRACE("(%p)->(%p)\n", This
, pos
);
1918 WARN("Invalid pointer\n");
1919 return DSERR_INVALIDPARAM
;
1922 setALContext(This
->ctx
);
1923 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
1933 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
1935 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1938 TRACE("(%p)->(%p)\n", This
, vel
);
1941 WARN("Invalid pointer\n");
1942 return DSERR_INVALIDPARAM
;
1945 setALContext(This
->ctx
);
1946 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
1956 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
1958 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1960 TRACE("(%p)->(%p)\n", iface
, ds3dbuffer
);
1962 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
1964 WARN("Invalid parameters %p %lu\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
1965 return DSERR_INVALIDPARAM
;
1968 EnterCriticalSection(&This
->share
->crst
);
1969 setALContext(This
->ctx
);
1971 DS8Buffer3D_GetPosition(iface
, &ds3dbuffer
->vPosition
);
1972 DS8Buffer3D_GetVelocity(iface
, &ds3dbuffer
->vVelocity
);
1973 DS8Buffer3D_GetConeAngles(iface
, &ds3dbuffer
->dwInsideConeAngle
, &ds3dbuffer
->dwOutsideConeAngle
);
1974 DS8Buffer3D_GetConeOrientation(iface
, &ds3dbuffer
->vConeOrientation
);
1975 DS8Buffer3D_GetConeOutsideVolume(iface
, &ds3dbuffer
->lConeOutsideVolume
);
1976 DS8Buffer3D_GetMinDistance(iface
, &ds3dbuffer
->flMinDistance
);
1977 DS8Buffer3D_GetMaxDistance(iface
, &ds3dbuffer
->flMaxDistance
);
1978 DS8Buffer3D_GetMode(iface
, &ds3dbuffer
->dwMode
);
1981 LeaveCriticalSection(&This
->share
->crst
);
1986 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
1988 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1990 TRACE("(%p)->(%lu, %lu, %lu)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
1991 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
1992 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
1994 WARN("Invalid cone angles (%lu, %lu)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
1995 return DSERR_INVALIDPARAM
;
1998 EnterCriticalSection(&This
->share
->crst
);
1999 if(apply
== DS3D_DEFERRED
)
2001 This
->deferred
.ds3d
.dwInsideConeAngle
= dwInsideConeAngle
;
2002 This
->deferred
.ds3d
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2003 This
->dirty
.bit
.cone_angles
= 1;
2007 setALContext(This
->ctx
);
2008 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2009 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2013 LeaveCriticalSection(&This
->share
->crst
);
2018 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2020 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2022 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2024 if(apply
== DS3D_DEFERRED
)
2026 EnterCriticalSection(&This
->share
->crst
);
2027 This
->deferred
.ds3d
.vConeOrientation
.x
= x
;
2028 This
->deferred
.ds3d
.vConeOrientation
.y
= y
;
2029 This
->deferred
.ds3d
.vConeOrientation
.z
= z
;
2030 This
->dirty
.bit
.cone_orient
= 1;
2031 LeaveCriticalSection(&This
->share
->crst
);
2035 setALContext(This
->ctx
);
2036 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2044 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2046 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2048 TRACE("(%p)->(%ld, %lu)\n", This
, vol
, apply
);
2049 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2051 WARN("Invalid volume (%ld)\n", vol
);
2052 return DSERR_INVALIDPARAM
;
2055 if(apply
== DS3D_DEFERRED
)
2057 EnterCriticalSection(&This
->share
->crst
);
2058 This
->deferred
.ds3d
.lConeOutsideVolume
= vol
;
2059 This
->dirty
.bit
.cone_outsidevolume
= 1;
2060 LeaveCriticalSection(&This
->share
->crst
);
2064 setALContext(This
->ctx
);
2065 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2073 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2075 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2077 TRACE("(%p)->(%f, %lu)\n", This
, maxdist
, apply
);
2080 WARN("Invalid max distance (%f)\n", maxdist
);
2081 return DSERR_INVALIDPARAM
;
2084 if(apply
== DS3D_DEFERRED
)
2086 EnterCriticalSection(&This
->share
->crst
);
2087 This
->deferred
.ds3d
.flMaxDistance
= maxdist
;
2088 This
->dirty
.bit
.max_distance
= 1;
2089 LeaveCriticalSection(&This
->share
->crst
);
2093 setALContext(This
->ctx
);
2094 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2102 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2104 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2106 TRACE("(%p)->(%f, %lu)\n", This
, mindist
, apply
);
2109 WARN("Invalid min distance (%f)\n", mindist
);
2110 return DSERR_INVALIDPARAM
;
2113 if(apply
== DS3D_DEFERRED
)
2115 EnterCriticalSection(&This
->share
->crst
);
2116 This
->deferred
.ds3d
.flMinDistance
= mindist
;
2117 This
->dirty
.bit
.min_distance
= 1;
2118 LeaveCriticalSection(&This
->share
->crst
);
2122 setALContext(This
->ctx
);
2123 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2131 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2133 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2135 TRACE("(%p)->(%lu, %lu)\n", This
, mode
, apply
);
2136 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2137 mode
!= DS3DMODE_DISABLE
)
2139 WARN("Invalid mode (%lu)\n", mode
);
2140 return DSERR_INVALIDPARAM
;
2143 EnterCriticalSection(&This
->share
->crst
);
2144 if(apply
== DS3D_DEFERRED
)
2146 This
->deferred
.ds3d
.dwMode
= mode
;
2147 This
->dirty
.bit
.mode
= 1;
2151 DS8Primary
*prim
= This
->primary
;
2153 setALContext(This
->ctx
);
2154 This
->ds3dmode
= mode
;
2155 if(HAS_EXTENSION(This
->share
, SOFT_SOURCE_SPATIALIZE
))
2156 alSourcei(This
->source
, AL_SOURCE_SPATIALIZE_SOFT
,
2157 (mode
==DS3DMODE_DISABLE
) ? AL_FALSE
: AL_TRUE
);
2158 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2159 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2160 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2161 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: prim
->rollofffactor
);
2165 LeaveCriticalSection(&This
->share
->crst
);
2170 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2172 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2174 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2176 if(apply
== DS3D_DEFERRED
)
2178 EnterCriticalSection(&This
->share
->crst
);
2179 This
->deferred
.ds3d
.vPosition
.x
= x
;
2180 This
->deferred
.ds3d
.vPosition
.y
= y
;
2181 This
->deferred
.ds3d
.vPosition
.z
= z
;
2182 This
->dirty
.bit
.pos
= 1;
2183 LeaveCriticalSection(&This
->share
->crst
);
2187 setALContext(This
->ctx
);
2188 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2196 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2198 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2200 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2202 if(apply
== DS3D_DEFERRED
)
2204 EnterCriticalSection(&This
->share
->crst
);
2205 This
->deferred
.ds3d
.vVelocity
.x
= x
;
2206 This
->deferred
.ds3d
.vVelocity
.y
= y
;
2207 This
->deferred
.ds3d
.vVelocity
.z
= z
;
2208 This
->dirty
.bit
.vel
= 1;
2209 LeaveCriticalSection(&This
->share
->crst
);
2213 setALContext(This
->ctx
);
2214 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2222 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2224 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2225 TRACE("(%p)->(%p, %lu)\n", This
, ds3dbuffer
, apply
);
2227 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2229 WARN("Invalid DS3DBUFFER (%p, %lu)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2230 return DSERR_INVALIDPARAM
;
2233 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2234 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2236 WARN("Invalid cone angles (%lu, %lu)\n",
2237 ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
);
2238 return DSERR_INVALIDPARAM
;
2241 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2242 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2244 WARN("Invalid cone outside volume (%ld)\n", ds3dbuffer
->lConeOutsideVolume
);
2245 return DSERR_INVALIDPARAM
;
2248 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2250 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2251 return DSERR_INVALIDPARAM
;
2254 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2256 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2257 return DSERR_INVALIDPARAM
;
2260 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2261 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2262 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2264 WARN("Invalid mode (%lu)\n", ds3dbuffer
->dwMode
);
2265 return DSERR_INVALIDPARAM
;
2268 if(apply
== DS3D_DEFERRED
)
2270 EnterCriticalSection(&This
->share
->crst
);
2271 This
->deferred
.ds3d
= *ds3dbuffer
;
2272 This
->deferred
.ds3d
.dwSize
= sizeof(This
->deferred
.ds3d
);
2273 This
->dirty
.bit
.pos
= 1;
2274 This
->dirty
.bit
.vel
= 1;
2275 This
->dirty
.bit
.cone_angles
= 1;
2276 This
->dirty
.bit
.cone_orient
= 1;
2277 This
->dirty
.bit
.cone_outsidevolume
= 1;
2278 This
->dirty
.bit
.min_distance
= 1;
2279 This
->dirty
.bit
.max_distance
= 1;
2280 This
->dirty
.bit
.mode
= 1;
2281 LeaveCriticalSection(&This
->share
->crst
);
2285 union BufferParamFlags dirty
= { 0 };
2288 dirty
.bit
.cone_angles
= 1;
2289 dirty
.bit
.cone_orient
= 1;
2290 dirty
.bit
.cone_outsidevolume
= 1;
2291 dirty
.bit
.min_distance
= 1;
2292 dirty
.bit
.max_distance
= 1;
2295 EnterCriticalSection(&This
->share
->crst
);
2296 setALContext(This
->ctx
);
2297 DS8Buffer_SetParams(This
, ds3dbuffer
, NULL
, dirty
.flags
);
2300 LeaveCriticalSection(&This
->share
->crst
);
2306 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2308 DS8Buffer3D_QueryInterface
,
2310 DS8Buffer3D_Release
,
2311 DS8Buffer3D_GetAllParameters
,
2312 DS8Buffer3D_GetConeAngles
,
2313 DS8Buffer3D_GetConeOrientation
,
2314 DS8Buffer3D_GetConeOutsideVolume
,
2315 DS8Buffer3D_GetMaxDistance
,
2316 DS8Buffer3D_GetMinDistance
,
2317 DS8Buffer3D_GetMode
,
2318 DS8Buffer3D_GetPosition
,
2319 DS8Buffer3D_GetVelocity
,
2320 DS8Buffer3D_SetAllParameters
,
2321 DS8Buffer3D_SetConeAngles
,
2322 DS8Buffer3D_SetConeOrientation
,
2323 DS8Buffer3D_SetConeOutsideVolume
,
2324 DS8Buffer3D_SetMaxDistance
,
2325 DS8Buffer3D_SetMinDistance
,
2326 DS8Buffer3D_SetMode
,
2327 DS8Buffer3D_SetPosition
,
2328 DS8Buffer3D_SetVelocity
2332 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2334 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2335 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2338 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2340 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2343 InterlockedIncrement(&This
->all_ref
);
2344 ret
= InterlockedIncrement(&This
->not_ref
);
2345 TRACE("new refcount %ld\n", ret
);
2350 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2352 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2355 ret
= InterlockedDecrement(&This
->not_ref
);
2356 TRACE("new refcount %ld\n", ret
);
2357 if(InterlockedDecrement(&This
->all_ref
) == 0)
2358 DS8Buffer_Destroy(This
);
2363 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2365 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2366 DSBPOSITIONNOTIFY
*nots
;
2370 TRACE("(%p)->(%lu, %p))\n", iface
, count
, notifications
);
2372 EnterCriticalSection(&This
->share
->crst
);
2373 hr
= DSERR_INVALIDPARAM
;
2374 if(count
&& !notifications
)
2377 hr
= DS8Buffer_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2378 if(FAILED(hr
)) goto out
;
2380 hr
= DSERR_INVALIDCALL
;
2381 if((state
&DSBSTATUS_PLAYING
))
2386 HeapFree(GetProcessHeap(), 0, This
->notify
);
2395 hr
= DSERR_INVALIDPARAM
;
2396 for(i
= 0;i
< count
;++i
)
2398 if(notifications
[i
].dwOffset
>= (DWORD
)This
->buffer
->buf_size
&&
2399 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2404 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2406 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2408 HeapFree(GetProcessHeap(), 0, This
->notify
);
2409 This
->notify
= nots
;
2410 This
->nnotify
= count
;
2416 LeaveCriticalSection(&This
->share
->crst
);
2420 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2422 DS8BufferNot_QueryInterface
,
2423 DS8BufferNot_AddRef
,
2424 DS8BufferNot_Release
,
2425 DS8BufferNot_SetNotificationPositions
2429 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2431 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2432 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2435 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2437 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2440 InterlockedIncrement(&This
->all_ref
);
2441 ret
= InterlockedIncrement(&This
->prop_ref
);
2442 TRACE("new refcount %ld\n", ret
);
2447 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2449 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2452 ret
= InterlockedDecrement(&This
->prop_ref
);
2453 TRACE("new refcount %ld\n", ret
);
2454 if(InterlockedDecrement(&This
->all_ref
) == 0)
2455 DS8Buffer_Destroy(This
);
2460 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2461 handled through secondary buffers. */
2462 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2463 REFGUID guidPropSet
, ULONG dwPropID
,
2464 LPVOID pInstanceData
, ULONG cbInstanceData
,
2465 LPVOID pPropData
, ULONG cbPropData
,
2468 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2469 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2471 TRACE("(%p)->(%s, %lu, %p, %lu, %p, %lu, %p)\n", iface
, debugstr_guid(guidPropSet
),
2472 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2478 if(cbPropData
> 0 && !pPropData
)
2480 WARN("pPropData is NULL with cbPropData > 0\n");
2484 EnterCriticalSection(&This
->share
->crst
);
2485 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_BufferProperties
))
2486 hr
= EAX3Buffer_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2487 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2488 hr
= EAX2Buffer_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2489 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_ListenerProperties
))
2490 hr
= EAX3_Get(This
->primary
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2491 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2492 hr
= EAX2_Get(This
->primary
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2493 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_BufferProperties
))
2494 hr
= EAX1Buffer_Get(This
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2495 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_ListenerProperties
))
2496 hr
= EAX1_Get(This
->primary
, dwPropID
, pPropData
, cbPropData
, pcbReturned
);
2498 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2499 LeaveCriticalSection(&This
->share
->crst
);
2504 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2505 REFGUID guidPropSet
, ULONG dwPropID
,
2506 LPVOID pInstanceData
, ULONG cbInstanceData
,
2507 LPVOID pPropData
, ULONG cbPropData
)
2509 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2510 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2512 TRACE("(%p)->(%s, %lu, %p, %lu, %p, %lu)\n", iface
, debugstr_guid(guidPropSet
),
2513 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2515 if(cbPropData
> 0 && !pPropData
)
2517 WARN("pPropData is NULL with cbPropData > 0\n");
2521 EnterCriticalSection(&This
->share
->crst
);
2522 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_BufferProperties
))
2524 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX30BUFFER_DEFERRED
;
2525 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX30BUFFER_DEFERRED
);
2527 setALContext(This
->ctx
);
2528 hr
= EAX3Buffer_Set(This
, propid
, pPropData
, cbPropData
);
2529 if(hr
== DS_OK
&& immediate
)
2531 DS8Primary
*prim
= This
->primary
;
2532 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2536 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2538 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20BUFFER_DEFERRED
;
2539 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20BUFFER_DEFERRED
);
2541 setALContext(This
->ctx
);
2542 hr
= EAX2Buffer_Set(This
, propid
, pPropData
, cbPropData
);
2543 if(hr
== DS_OK
&& immediate
)
2545 DS8Primary
*prim
= This
->primary
;
2546 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2550 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_ListenerProperties
))
2552 DS8Primary
*prim
= This
->primary
;
2553 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX30LISTENER_DEFERRED
;
2554 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX30LISTENER_DEFERRED
);
2556 setALContext(prim
->ctx
);
2557 hr
= EAX3_Set(prim
, propid
, pPropData
, cbPropData
);
2558 if(hr
== DS_OK
&& immediate
)
2559 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2562 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2564 DS8Primary
*prim
= This
->primary
;
2565 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20LISTENER_DEFERRED
;
2566 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20LISTENER_DEFERRED
);
2568 setALContext(prim
->ctx
);
2569 hr
= EAX2_Set(prim
, propid
, pPropData
, cbPropData
);
2570 if(hr
== DS_OK
&& immediate
)
2571 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2574 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_BufferProperties
))
2576 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20BUFFER_DEFERRED
;
2577 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20BUFFER_DEFERRED
);
2579 setALContext(This
->ctx
);
2580 hr
= EAX1Buffer_Set(This
, propid
, pPropData
, cbPropData
);
2581 if(hr
== DS_OK
&& immediate
)
2583 DS8Primary
*prim
= This
->primary
;
2584 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2588 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_ListenerProperties
))
2590 DS8Primary
*prim
= This
->primary
;
2591 DWORD propid
= dwPropID
& ~DSPROPERTY_EAX20LISTENER_DEFERRED
;
2592 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAX20LISTENER_DEFERRED
);
2594 setALContext(prim
->ctx
);
2595 hr
= EAX1_Set(prim
, propid
, pPropData
, cbPropData
);
2596 if(hr
== DS_OK
&& immediate
)
2597 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2601 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2602 LeaveCriticalSection(&This
->share
->crst
);
2607 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
2608 REFGUID guidPropSet
, ULONG dwPropID
,
2609 ULONG
*pTypeSupport
)
2611 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2612 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2614 TRACE("(%p)->(%s, %lu, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2620 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_BufferProperties
))
2622 EnterCriticalSection(&This
->share
->crst
);
2624 if(This
->filter
[0] == 0)
2625 hr
= E_PROP_ID_UNSUPPORTED
;
2626 else switch(dwPropID
)
2628 case DSPROPERTY_EAX30BUFFER_NONE
:
2629 case DSPROPERTY_EAX30BUFFER_ALLPARAMETERS
:
2630 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONPARAMETERS
:
2631 case DSPROPERTY_EAX30BUFFER_OCCLUSIONPARAMETERS
:
2632 case DSPROPERTY_EAX30BUFFER_EXCLUSIONPARAMETERS
:
2633 case DSPROPERTY_EAX30BUFFER_DIRECT
:
2634 case DSPROPERTY_EAX30BUFFER_DIRECTHF
:
2635 case DSPROPERTY_EAX30BUFFER_ROOM
:
2636 case DSPROPERTY_EAX30BUFFER_ROOMHF
:
2637 case DSPROPERTY_EAX30BUFFER_OBSTRUCTION
:
2638 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONLFRATIO
:
2639 case DSPROPERTY_EAX30BUFFER_OCCLUSION
:
2640 case DSPROPERTY_EAX30BUFFER_OCCLUSIONLFRATIO
:
2641 case DSPROPERTY_EAX30BUFFER_OCCLUSIONROOMRATIO
:
2642 case DSPROPERTY_EAX30BUFFER_OCCLUSIONDIRECTRATIO
:
2643 case DSPROPERTY_EAX30BUFFER_EXCLUSION
:
2644 case DSPROPERTY_EAX30BUFFER_EXCLUSIONLFRATIO
:
2645 case DSPROPERTY_EAX30BUFFER_OUTSIDEVOLUMEHF
:
2646 case DSPROPERTY_EAX30BUFFER_DOPPLERFACTOR
:
2647 case DSPROPERTY_EAX30BUFFER_ROLLOFFFACTOR
:
2648 case DSPROPERTY_EAX30BUFFER_ROOMROLLOFFFACTOR
:
2649 case DSPROPERTY_EAX30BUFFER_AIRABSORPTIONFACTOR
:
2650 case DSPROPERTY_EAX30BUFFER_FLAGS
:
2651 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
2655 hr
= E_PROP_ID_UNSUPPORTED
;
2656 FIXME("Unhandled EAX3 buffer propid: 0x%08lx\n", dwPropID
);
2660 LeaveCriticalSection(&This
->share
->crst
);
2662 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2664 EnterCriticalSection(&This
->share
->crst
);
2666 if(This
->filter
[0] == 0)
2667 hr
= E_PROP_ID_UNSUPPORTED
;
2668 else switch(dwPropID
)
2670 case DSPROPERTY_EAX20BUFFER_NONE
:
2671 case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS
:
2672 case DSPROPERTY_EAX20BUFFER_DIRECT
:
2673 case DSPROPERTY_EAX20BUFFER_DIRECTHF
:
2674 case DSPROPERTY_EAX20BUFFER_ROOM
:
2675 case DSPROPERTY_EAX20BUFFER_ROOMHF
:
2676 case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR
:
2677 case DSPROPERTY_EAX20BUFFER_OBSTRUCTION
:
2678 case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO
:
2679 case DSPROPERTY_EAX20BUFFER_OCCLUSION
:
2680 case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO
:
2681 case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO
:
2682 case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF
:
2683 case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR
:
2684 case DSPROPERTY_EAX20BUFFER_FLAGS
:
2685 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
2689 hr
= E_PROP_ID_UNSUPPORTED
;
2690 FIXME("Unhandled EAX2 buffer propid: 0x%08lx\n", dwPropID
);
2694 LeaveCriticalSection(&This
->share
->crst
);
2696 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX30_ListenerProperties
))
2698 DS8Primary
*prim
= This
->primary
;
2700 EnterCriticalSection(&This
->share
->crst
);
2702 if(prim
->effect
== 0)
2703 hr
= E_PROP_ID_UNSUPPORTED
;
2704 else switch(dwPropID
)
2706 case DSPROPERTY_EAX30LISTENER_NONE
:
2707 case DSPROPERTY_EAX30LISTENER_ALLPARAMETERS
:
2708 case DSPROPERTY_EAX30LISTENER_ENVIRONMENT
:
2709 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTSIZE
:
2710 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTDIFFUSION
:
2711 case DSPROPERTY_EAX30LISTENER_ROOM
:
2712 case DSPROPERTY_EAX30LISTENER_ROOMHF
:
2713 case DSPROPERTY_EAX30LISTENER_ROOMLF
:
2714 case DSPROPERTY_EAX30LISTENER_DECAYTIME
:
2715 case DSPROPERTY_EAX30LISTENER_DECAYHFRATIO
:
2716 case DSPROPERTY_EAX30LISTENER_DECAYLFRATIO
:
2717 case DSPROPERTY_EAX30LISTENER_REFLECTIONS
:
2718 case DSPROPERTY_EAX30LISTENER_REFLECTIONSDELAY
:
2719 case DSPROPERTY_EAX30LISTENER_REFLECTIONSPAN
:
2720 case DSPROPERTY_EAX30LISTENER_REVERB
:
2721 case DSPROPERTY_EAX30LISTENER_REVERBDELAY
:
2722 case DSPROPERTY_EAX30LISTENER_REVERBPAN
:
2723 case DSPROPERTY_EAX30LISTENER_ECHOTIME
:
2724 case DSPROPERTY_EAX30LISTENER_ECHODEPTH
:
2725 case DSPROPERTY_EAX30LISTENER_MODULATIONTIME
:
2726 case DSPROPERTY_EAX30LISTENER_MODULATIONDEPTH
:
2727 case DSPROPERTY_EAX30LISTENER_AIRABSORPTIONHF
:
2728 case DSPROPERTY_EAX30LISTENER_HFREFERENCE
:
2729 case DSPROPERTY_EAX30LISTENER_LFREFERENCE
:
2730 case DSPROPERTY_EAX30LISTENER_ROOMROLLOFFFACTOR
:
2731 case DSPROPERTY_EAX30LISTENER_FLAGS
:
2732 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
2736 hr
= E_PROP_ID_UNSUPPORTED
;
2737 FIXME("Unhandled EAX3 listener propid: 0x%08lx\n", dwPropID
);
2741 LeaveCriticalSection(&This
->share
->crst
);
2743 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2745 DS8Primary
*prim
= This
->primary
;
2747 EnterCriticalSection(&This
->share
->crst
);
2749 if(prim
->effect
== 0)
2750 hr
= E_PROP_ID_UNSUPPORTED
;
2751 else switch(dwPropID
)
2753 case DSPROPERTY_EAX20LISTENER_NONE
:
2754 case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS
:
2755 case DSPROPERTY_EAX20LISTENER_ROOM
:
2756 case DSPROPERTY_EAX20LISTENER_ROOMHF
:
2757 case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR
:
2758 case DSPROPERTY_EAX20LISTENER_DECAYTIME
:
2759 case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO
:
2760 case DSPROPERTY_EAX20LISTENER_REFLECTIONS
:
2761 case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY
:
2762 case DSPROPERTY_EAX20LISTENER_REVERB
:
2763 case DSPROPERTY_EAX20LISTENER_REVERBDELAY
:
2764 case DSPROPERTY_EAX20LISTENER_ENVIRONMENT
:
2765 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE
:
2766 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION
:
2767 case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF
:
2768 case DSPROPERTY_EAX20LISTENER_FLAGS
:
2769 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
2773 hr
= E_PROP_ID_UNSUPPORTED
;
2774 FIXME("Unhandled EAX2 listener propid: 0x%08lx\n", dwPropID
);
2778 LeaveCriticalSection(&This
->share
->crst
);
2780 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_ListenerProperties
))
2782 DS8Primary
*prim
= This
->primary
;
2784 EnterCriticalSection(&This
->share
->crst
);
2786 if(prim
->effect
== 0)
2787 hr
= E_PROP_ID_UNSUPPORTED
;
2788 else switch(dwPropID
)
2790 case DSPROPERTY_EAX10LISTENER_ALL
:
2791 case DSPROPERTY_EAX10LISTENER_ENVIRONMENT
:
2792 case DSPROPERTY_EAX10LISTENER_VOLUME
:
2793 case DSPROPERTY_EAX10LISTENER_DECAYTIME
:
2794 case DSPROPERTY_EAX10LISTENER_DAMPING
:
2795 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
2799 hr
= E_PROP_ID_UNSUPPORTED
;
2800 FIXME("Unhandled EAX1 listener propid: 0x%08lx\n", dwPropID
);
2804 LeaveCriticalSection(&This
->share
->crst
);
2806 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX10_BufferProperties
))
2808 EnterCriticalSection(&This
->share
->crst
);
2810 if(This
->filter
[0] == 0)
2811 hr
= E_PROP_ID_UNSUPPORTED
;
2812 else switch(dwPropID
)
2814 case DSPROPERTY_EAX10BUFFER_ALL
:
2815 case DSPROPERTY_EAX10BUFFER_REVERBMIX
:
2816 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
2820 hr
= E_PROP_ID_UNSUPPORTED
;
2821 FIXME("Unhandled EAX1 buffer propid: 0x%08lx\n", dwPropID
);
2825 LeaveCriticalSection(&This
->share
->crst
);
2828 FIXME("Unhandled propset: %s (propid: %lu)\n", debugstr_guid(guidPropSet
), dwPropID
);
2833 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
2835 DS8BufferProp_QueryInterface
,
2836 DS8BufferProp_AddRef
,
2837 DS8BufferProp_Release
,
2840 DS8BufferProp_QuerySupport