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
33 #include "dsound_private.h"
35 DEFINE_GUID(CLSID_DirectSoundPrivate
,0x11ab3ec0,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
37 DEFINE_GUID(DSPROPSETID_DirectSoundDevice
,0x84624f82,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
39 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM
, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
40 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
42 #ifndef E_PROP_ID_UNSUPPORTED
43 #define E_PROP_ID_UNSUPPORTED ((HRESULT)0x80070490)
47 #define DS_INCOMPLETE ((HRESULT)0x08780020)
50 #ifndef WAVE_FORMAT_IEEE_FLOAT
51 #define WAVE_FORMAT_IEEE_FLOAT 3
54 /* TODO: when bufferlost is set, return from all calls except initialize with
57 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
;
58 static const IDirectSoundBufferVtbl DSBuffer_Vtbl
;
59 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
;
60 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
;
61 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
;
64 static inline DS8Buffer
*impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8
*iface
)
66 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
69 static inline DS8Buffer
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
71 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer_iface
);
74 static inline DS8Buffer
*impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer
*iface
)
76 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSound3DBuffer_iface
);
79 static inline DS8Buffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
81 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundNotify_iface
);
84 static inline DS8Buffer
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
86 return CONTAINING_RECORD(iface
, DS8Buffer
, IKsPropertySet_iface
);
90 /* Should be called with critsect held and context set.. */
91 static void DS8Buffer_addnotify(DS8Buffer
*buf
)
93 DS8Primary
*prim
= buf
->primary
;
97 list
= prim
->notifies
;
98 for(i
= 0; i
< prim
->nnotifies
; ++i
)
102 ERR("Buffer %p already in notification list\n", buf
);
106 if(prim
->nnotifies
== prim
->sizenotifies
)
108 list
= HeapReAlloc(GetProcessHeap(), 0, list
, (prim
->nnotifies
+ 1) * sizeof(*list
));
110 prim
->sizenotifies
++;
112 list
[prim
->nnotifies
++] = buf
;
113 prim
->notifies
= list
;
117 static const char *get_fmtstr_PCM(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
119 out
->Format
= *format
;
120 out
->Format
.cbSize
= 0;
122 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
123 !prim
->SupportedExt
[EXT_MCFORMATS
])
125 WARN("Multi-channel not available\n");
129 if(format
->wBitsPerSample
== 8)
131 switch(format
->nChannels
)
133 case 1: return "AL_FORMAT_MONO8";
134 case 2: return "AL_FORMAT_STEREO8";
135 case 4: return "AL_FORMAT_QUAD8";
136 case 6: return "AL_FORMAT_51CHN8";
137 case 7: return "AL_FORMAT_61CHN8";
138 case 8: return "AL_FORMAT_71CHN8";
141 else if(format
->wBitsPerSample
== 16)
143 switch(format
->nChannels
)
145 case 1: return "AL_FORMAT_MONO16";
146 case 2: return "AL_FORMAT_STEREO16";
147 case 4: return "AL_FORMAT_QUAD16";
148 case 6: return "AL_FORMAT_51CHN16";
149 case 7: return "AL_FORMAT_61CHN16";
150 case 8: return "AL_FORMAT_71CHN16";
154 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
155 format
->wBitsPerSample
, format
->nChannels
);
159 static const char *get_fmtstr_FLOAT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
161 out
->Format
= *format
;
162 out
->Format
.cbSize
= 0;
164 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
165 !prim
->SupportedExt
[EXT_MCFORMATS
])
167 WARN("Multi-channel not available\n");
171 if(format
->wBitsPerSample
== 32 && prim
->SupportedExt
[EXT_FLOAT32
])
173 switch(format
->nChannels
)
175 case 1: return "AL_FORMAT_MONO_FLOAT32";
176 case 2: return "AL_FORMAT_STEREO_FLOAT32";
177 case 4: return "AL_FORMAT_QUAD32";
178 case 6: return "AL_FORMAT_51CHN32";
179 case 7: return "AL_FORMAT_61CHN32";
180 case 8: return "AL_FORMAT_71CHN32";
184 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
185 format
->wBitsPerSample
, format
->nChannels
);
189 /* Speaker configs */
190 #define MONO SPEAKER_FRONT_CENTER
191 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
192 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
193 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
194 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
195 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
196 #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)
198 static const char *get_fmtstr_EXT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
200 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
201 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
203 if(!out
->Samples
.wValidBitsPerSample
)
204 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
205 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
207 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
211 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
212 !prim
->SupportedExt
[EXT_MCFORMATS
])
214 WARN("Multi-channel not available\n");
218 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
220 if(out
->Samples
.wValidBitsPerSample
== 8)
222 switch(out
->dwChannelMask
)
224 case MONO
: return "AL_FORMAT_MONO8";
225 case STEREO
: return "AL_FORMAT_STEREO8";
226 case REAR
: return "AL_FORMAT_REAR8";
227 case QUAD
: return "AL_FORMAT_QUAD8";
228 case X5DOT1
: return "AL_FORMAT_51CHN8";
229 case X6DOT1
: return "AL_FORMAT_61CHN8";
230 case X7DOT1
: return "AL_FORMAT_71CHN8";
233 else if(out
->Samples
.wValidBitsPerSample
== 16)
235 switch(out
->dwChannelMask
)
237 case MONO
: return "AL_FORMAT_MONO16";
238 case STEREO
: return "AL_FORMAT_STEREO16";
239 case REAR
: return "AL_FORMAT_REAR16";
240 case QUAD
: return "AL_FORMAT_QUAD16";
241 case X5DOT1
: return "AL_FORMAT_51CHN16";
242 case X6DOT1
: return "AL_FORMAT_61CHN16";
243 case X7DOT1
: return "AL_FORMAT_71CHN16";
247 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#lx)\n",
248 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
251 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
252 prim
->SupportedExt
[EXT_FLOAT32
])
254 if(out
->Samples
.wValidBitsPerSample
== 32)
256 switch(out
->dwChannelMask
)
258 case MONO
: return "AL_FORMAT_MONO_FLOAT32";
259 case STEREO
: return "AL_FORMAT_STEREO_FLOAT32";
260 case REAR
: return "AL_FORMAT_REAR32";
261 case QUAD
: return "AL_FORMAT_QUAD32";
262 case X5DOT1
: return "AL_FORMAT_51CHN32";
263 case X6DOT1
: return "AL_FORMAT_61CHN32";
264 case X7DOT1
: return "AL_FORMAT_71CHN32";
269 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
273 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#lx)\n",
274 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
277 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
278 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
282 static void DS8Data_Release(DS8Data
*This
);
283 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*prim
)
285 HRESULT hr
= DSERR_INVALIDPARAM
;
286 const WAVEFORMATEX
*format
;
287 const char *fmt_str
= NULL
;
290 format
= desc
->lpwfxFormat
;
291 TRACE("Requested buffer format:\n"
292 " FormatTag = 0x%04x\n"
294 " SamplesPerSec = %lu\n"
295 " AvgBytesPerSec = %lu\n"
297 " BitsPerSample = %d\n",
298 format
->wFormatTag
, format
->nChannels
,
299 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
300 format
->nBlockAlign
, format
->wBitsPerSample
);
302 if(format
->nSamplesPerSec
<= 0)
304 WARN("Invalid SamplesPerSec specified\n");
305 return DSERR_INVALIDPARAM
;
307 if(format
->nBlockAlign
<= 0)
309 WARN("Invalid BlockAlign specified\n");
310 return DSERR_INVALIDPARAM
;
313 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
314 * will need the EAX-RAM extension. Currently, we just tell the app it
315 * gets what it wanted. */
316 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
317 if(!pBuffer
) return E_OUTOFMEMORY
;
319 pBuffer
->primary
= prim
;
321 pBuffer
->dsbflags
= desc
->dwFlags
;
322 if((pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
324 WARN("Hardware and software location requested\n");
327 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
328 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
330 pBuffer
->buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
331 pBuffer
->buf_size
-= pBuffer
->buf_size
%format
->nBlockAlign
;
333 hr
= DSERR_BUFFERTOOSMALL
;
334 if(pBuffer
->buf_size
< DSBSIZE_MIN
)
337 hr
= DSERR_INVALIDPARAM
;
338 if(pBuffer
->buf_size
> DSBSIZE_MAX
)
341 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
342 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
343 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
344 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
345 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
347 const WAVEFORMATEXTENSIBLE
*wfe
;
349 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
350 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
353 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
354 TRACE("Extensible values:\n"
356 " ChannelMask = 0x%lx\n"
358 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
359 debugstr_guid(&wfe
->SubFormat
));
361 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
364 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
365 if(!fmt_str
) goto fail
;
367 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
368 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
369 pBuffer
->buf_format
== -1)
371 WARN("Could not get OpenAL format from %s\n", fmt_str
);
375 hr
= DSERR_INVALIDPARAM
;
376 if(format
->nBlockAlign
!= format
->nChannels
*format
->wBitsPerSample
/8)
378 WARN("Incorrect BlockAlign specified\n");
381 if(format
->nAvgBytesPerSec
!= format
->nBlockAlign
*format
->nSamplesPerSec
)
383 WARN("Incorrect AvgBytesPerSec specified\n");
388 if(!prim
->SupportedExt
[SOFTX_MAP_BUFFER
])
390 pBuffer
->data
= HeapAlloc(GetProcessHeap(), 0, pBuffer
->buf_size
);
391 if(!pBuffer
->data
) goto fail
;
393 alGenBuffers(1, &pBuffer
->bid
);
398 const ALbitfieldSOFT map_bits
= AL_MAP_READ_BIT_SOFT
| AL_MAP_WRITE_BIT_SOFT
|
399 AL_MAP_PERSISTENT_BIT_SOFT
;
400 alGenBuffers(1, &pBuffer
->bid
);
401 prim
->ExtAL
->BufferStorageSOFT(pBuffer
->bid
, pBuffer
->buf_format
, NULL
, pBuffer
->buf_size
,
402 pBuffer
->format
.Format
.nSamplesPerSec
, map_bits
);
403 pBuffer
->data
= prim
->ExtAL
->MapBufferSOFT(pBuffer
->bid
, 0, pBuffer
->buf_size
, map_bits
);
406 if(!pBuffer
->data
) goto fail
;
413 DS8Data_Release(pBuffer
);
417 static void DS8Data_AddRef(DS8Data
*data
)
419 InterlockedIncrement(&data
->ref
);
422 /* This function is always called with the device lock held */
423 static void DS8Data_Release(DS8Data
*This
)
425 if(InterlockedDecrement(&This
->ref
)) return;
427 TRACE("Deleting %p\n", This
);
430 DS8Primary
*prim
= This
->primary
;
431 if(prim
->SupportedExt
[SOFTX_MAP_BUFFER
])
433 prim
->ExtAL
->UnmapBufferSOFT(This
->bid
);
436 alDeleteBuffers(1, &This
->bid
);
439 HeapFree(GetProcessHeap(), 0, This
->data
);
440 HeapFree(GetProcessHeap(), 0, This
);
444 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*prim
, IDirectSoundBuffer
*orig
)
446 DS8Buffer
*This
= NULL
;
451 EnterCriticalSection(prim
->crst
);
452 for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
454 if(prim
->BufferGroups
[i
].FreeBuffers
)
456 int idx
= CTZ64(prim
->BufferGroups
[i
].FreeBuffers
);
457 This
= prim
->BufferGroups
[i
].Buffers
+ idx
;
458 memset(This
, 0, sizeof(*This
));
459 prim
->BufferGroups
[i
].FreeBuffers
&= ~(U64(1) << idx
);
463 LeaveCriticalSection(prim
->crst
);
466 WARN("Allocating extra DS8Buffer\n");
467 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
468 if(!This
) return DSERR_OUTOFMEMORY
;
471 This
->IDirectSoundBuffer8_iface
.lpVtbl
= &DS8Buffer_Vtbl
;
472 This
->IDirectSoundBuffer_iface
.lpVtbl
= &DSBuffer_Vtbl
;
473 This
->IDirectSound3DBuffer_iface
.lpVtbl
= &DS8Buffer3d_Vtbl
;
474 This
->IDirectSoundNotify_iface
.lpVtbl
= &DS8BufferNot_Vtbl
;
475 This
->IKsPropertySet_iface
.lpVtbl
= &DS8BufferProp_Vtbl
;
477 This
->primary
= prim
;
478 This
->ctx
= prim
->ctx
;
479 This
->ExtAL
= prim
->ExtAL
;
480 This
->crst
= prim
->crst
;
481 This
->ref
= This
->all_ref
= 1;
485 DS8Buffer
*org
= impl_from_IDirectSoundBuffer(orig
);
486 hr
= DSERR_BUFFERLOST
;
489 DS8Data_AddRef(org
->buffer
);
490 This
->buffer
= org
->buffer
;
493 /* Disable until initialized.. */
494 This
->ds3dmode
= DS3DMODE_DISABLE
;
500 DS8Buffer_Destroy(This
);
504 void DS8Buffer_Destroy(DS8Buffer
*This
)
506 DS8Primary
*prim
= This
->primary
;
509 TRACE("Destroying %p\n", This
);
511 EnterCriticalSection(prim
->crst
);
512 /* Remove from list, if in list */
513 for(i
= 0;i
< prim
->nnotifies
;++i
)
515 if(This
== prim
->notifies
[i
])
517 prim
->notifies
[i
] = prim
->notifies
[--prim
->nnotifies
];
522 setALContext(This
->ctx
);
525 alSourceStop(This
->source
);
526 alSourcei(This
->source
, AL_BUFFER
, 0);
529 prim
->sources
[prim
->parent
->share
->nsources
++] = This
->source
;
532 if(This
->stream_bids
[0])
533 alDeleteBuffers(QBUFFERS
, This
->stream_bids
);
536 DS8Data_Release(This
->buffer
);
540 HeapFree(GetProcessHeap(), 0, This
->notify
);
542 for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
544 DWORD_PTR idx
= This
- prim
->BufferGroups
[i
].Buffers
;
547 prim
->BufferGroups
[i
].FreeBuffers
|= U64(1) << idx
;
552 LeaveCriticalSection(prim
->crst
);
554 HeapFree(GetProcessHeap(), 0, This
);
558 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
560 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
562 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
565 if(IsEqualIID(riid
, &IID_IUnknown
))
566 *ppv
= &This
->IDirectSoundBuffer8_iface
;
567 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
568 *ppv
= &This
->IDirectSoundBuffer_iface
;
569 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
571 if(This
->primary
->parent
->is_8
)
572 *ppv
= &This
->IDirectSoundBuffer8_iface
;
574 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
576 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
577 *ppv
= &This
->IDirectSound3DBuffer_iface
;
579 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
581 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
582 *ppv
= &This
->IDirectSoundNotify_iface
;
584 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
585 *ppv
= &This
->IKsPropertySet_iface
;
587 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
591 IUnknown_AddRef((IUnknown
*)*ppv
);
595 return E_NOINTERFACE
;
598 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
600 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
603 InterlockedIncrement(&This
->all_ref
);
604 ret
= InterlockedIncrement(&This
->ref
);
605 TRACE("new refcount %ld\n", ret
);
610 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
612 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
615 ret
= InterlockedDecrement(&This
->ref
);
616 TRACE("new refcount %ld\n", ret
);
617 if(InterlockedDecrement(&This
->all_ref
) == 0)
618 DS8Buffer_Destroy(This
);
623 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
625 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
627 TRACE("(%p)->(%p)\n", iface
, caps
);
629 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
631 WARN("Invalid DSBCAPS (%p, %lu)\n", caps
, (caps
? caps
->dwSize
: 0));
632 return DSERR_INVALIDPARAM
;
635 caps
->dwFlags
= This
->buffer
->dsbflags
;
636 caps
->dwBufferBytes
= This
->buffer
->buf_size
;
637 caps
->dwUnlockTransferRate
= 4096;
638 caps
->dwPlayCpuOverhead
= 0;
642 HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
644 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
645 ALsizei writecursor
, pos
;
648 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
651 if(This
->segsize
!= 0)
653 ALint queued
= QBUFFERS
;
657 EnterCriticalSection(This
->crst
);
659 setALContext(This
->ctx
);
660 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
661 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
662 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
666 if(status
== AL_STOPPED
)
667 pos
= This
->segsize
*queued
+ This
->queue_base
;
669 pos
= ofs
+ This
->queue_base
;
670 if(pos
>= data
->buf_size
)
673 pos
%= data
->buf_size
;
674 else if(This
->isplaying
)
676 pos
= data
->buf_size
;
677 alSourceStop(This
->source
);
678 alSourcei(This
->source
, AL_BUFFER
, 0);
680 This
->isplaying
= FALSE
;
684 writecursor
= (This
->segsize
*QBUFFERS
+ pos
) % data
->buf_size
;
686 writecursor
= pos
% data
->buf_size
;
688 LeaveCriticalSection(This
->crst
);
692 const WAVEFORMATEX
*format
= &data
->format
.Format
;
696 setALContext(This
->ctx
);
697 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
698 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
702 /* AL_STOPPED means the source naturally reached its end, where
703 * DirectSound's position should be at the end (OpenAL reports a 0
704 * position). The Stop method correlates to pausing, which would put
705 * the source into an AL_PAUSED state and hold its current position.
707 pos
= (status
== AL_STOPPED
) ? data
->buf_size
: ofs
;
708 if(status
== AL_PLAYING
)
710 writecursor
= format
->nSamplesPerSec
/ This
->primary
->refresh
;
711 writecursor
*= format
->nBlockAlign
;
715 writecursor
= (writecursor
+ pos
) % data
->buf_size
;
717 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
719 if(pos
> data
->buf_size
)
721 ERR("playpos > buf_size\n");
722 pos
%= data
->buf_size
;
724 if(writecursor
>= data
->buf_size
)
726 ERR("writepos >= buf_size\n");
727 writecursor
%= data
->buf_size
;
730 if(playpos
) *playpos
= pos
;
731 if(curpos
) *curpos
= writecursor
;
736 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
738 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
742 TRACE("(%p)->(%p, %lu, %p)\n", iface
, wfx
, allocated
, written
);
746 WARN("Cannot report format or format size\n");
747 return DSERR_INVALIDPARAM
;
750 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
754 hr
= DSERR_INVALIDPARAM
;
756 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
764 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
766 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
769 TRACE("(%p)->(%p)\n", iface
, vol
);
773 WARN("Invalid pointer\n");
774 return DSERR_INVALIDPARAM
;
777 hr
= DSERR_CONTROLUNAVAIL
;
778 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
779 WARN("Volume control not set\n");
784 setALContext(This
->ctx
);
785 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
789 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
796 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
798 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
801 TRACE("(%p)->(%p)\n", iface
, pan
);
805 WARN("Invalid pointer\n");
806 return DSERR_INVALIDPARAM
;
809 hr
= DSERR_CONTROLUNAVAIL
;
810 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
811 WARN("Panning control not set\n");
814 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
820 setALContext(This
->ctx
);
821 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
825 *pan
= clampI((LONG
)((pos
[0]+0.5f
)*(DSBPAN_RIGHT
-DSBPAN_LEFT
) + 0.5f
) + DSBPAN_LEFT
,
826 DSBPAN_LEFT
, DSBPAN_RIGHT
);
834 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
836 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
839 TRACE("(%p)->(%p)\n", iface
, freq
);
843 WARN("Invalid pointer\n");
844 return DSERR_INVALIDPARAM
;
847 hr
= DSERR_CONTROLUNAVAIL
;
848 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
849 WARN("Frequency control not set\n");
852 ALfloat pitch
= 1.0f
;
854 setALContext(This
->ctx
);
855 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
859 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
866 HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
868 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
869 ALint state
, looping
;
871 TRACE("(%p)->(%p)\n", iface
, status
);
875 WARN("Invalid pointer\n");
876 return DSERR_INVALIDPARAM
;
880 if(This
->segsize
== 0)
882 setALContext(This
->ctx
);
883 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
884 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
890 EnterCriticalSection(This
->crst
);
892 setALContext(This
->ctx
);
893 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
897 if(state
!= AL_PLAYING
)
898 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
899 looping
= This
->islooping
;
901 LeaveCriticalSection(This
->crst
);
904 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
906 if((This
->buffer
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
907 *status
|= DSBSTATUS_LOCSOFTWARE
;
908 else if((This
->buffer
->dsbflags
&DSBCAPS_LOCHARDWARE
))
909 *status
|= DSBSTATUS_LOCHARDWARE
;
911 if(state
== AL_PLAYING
)
912 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
914 TRACE("%p status = 0x%08lx\n", This
, *status
);
918 static HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
920 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
921 DS3DBUFFER
*ds3dbuffer
;
926 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
928 EnterCriticalSection(This
->crst
);
929 setALContext(This
->ctx
);
931 hr
= DSERR_ALREADYINITIALIZED
;
932 if(This
->source
) goto out
;
936 hr
= DSERR_INVALIDPARAM
;
939 WARN("Missing DSound buffer description\n");
942 if(!desc
->lpwfxFormat
)
944 WARN("Missing buffer format (%p)\n", This
);
947 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
949 if(This
->primary
->parent
->is_8
)
951 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
953 WARN("Can't create multi-channel 3D buffers\n");
956 ERR("Multi-channel 3D sounds are not spatialized\n");
959 hr
= DS8Data_Create(&This
->buffer
, desc
, This
->primary
);
960 if(FAILED(hr
)) goto out
;
963 if(data
->format
.Format
.wBitsPerSample
== 8)
964 memset(data
->data
, 0x80, data
->buf_size
);
966 memset(data
->data
, 0x00, data
->buf_size
);
969 prim
= This
->primary
;
971 if(!(data
->dsbflags
&DSBCAPS_STATIC
) && !prim
->SupportedExt
[SOFTX_MAP_BUFFER
])
973 This
->segsize
= (data
->format
.Format
.nAvgBytesPerSec
+prim
->refresh
-1) / prim
->refresh
;
974 This
->segsize
= clampI(This
->segsize
, data
->format
.Format
.nBlockAlign
, 2048);
975 This
->segsize
+= data
->format
.Format
.nBlockAlign
- 1;
976 This
->segsize
-= This
->segsize
%data
->format
.Format
.nBlockAlign
;
978 alGenBuffers(QBUFFERS
, This
->stream_bids
);
982 hr
= DSERR_ALLOCATED
;
983 if(!prim
->parent
->share
->nsources
)
986 This
->source
= prim
->sources
[--(prim
->parent
->share
->nsources
)];
987 alSourceRewind(This
->source
);
988 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
989 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
992 ds3dbuffer
= &This
->params
;
993 ds3dbuffer
->dwSize
= sizeof(This
->params
);
994 ds3dbuffer
->vPosition
.x
= 0.0f
;
995 ds3dbuffer
->vPosition
.y
= 0.0f
;
996 ds3dbuffer
->vPosition
.z
= 0.0f
;
997 ds3dbuffer
->vVelocity
.x
= 0.0f
;
998 ds3dbuffer
->vVelocity
.y
= 0.0f
;
999 ds3dbuffer
->vVelocity
.z
= 0.0f
;
1000 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1001 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1002 ds3dbuffer
->vConeOrientation
.x
= 0.0f
;
1003 ds3dbuffer
->vConeOrientation
.y
= 0.0f
;
1004 ds3dbuffer
->vConeOrientation
.z
= 1.0f
;
1005 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
1006 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
1007 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
1008 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
1010 if((data
->dsbflags
&DSBCAPS_CTRL3D
))
1012 union BufferParamFlags dirty
= { 0 };
1014 if(prim
->auxslot
!= 0)
1015 alSource3i(This
->source
, AL_AUXILIARY_SEND_FILTER
, prim
->auxslot
, 0, AL_FILTER_NULL
);
1019 dirty
.bit
.cone_angles
= 1;
1020 dirty
.bit
.cone_orient
= 1;
1021 dirty
.bit
.cone_outsidevolume
= 1;
1022 dirty
.bit
.min_distance
= 1;
1023 dirty
.bit
.max_distance
= 1;
1025 DS8Buffer_SetParams(This
, ds3dbuffer
, dirty
.flags
);
1030 ALuint source
= This
->source
;
1032 if(prim
->auxslot
!= 0)
1034 /* Simple hack to make reverb affect non-3D sounds too */
1035 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, prim
->auxslot
, 0, AL_FILTER_NULL
);
1036 /*alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);*/
1039 /* Non-3D sources aren't distance attenuated */
1040 This
->ds3dmode
= DS3DMODE_DISABLE
;
1041 alSource3f(source
, AL_POSITION
, 0.0f
, 0.0f
, -1.0f
);
1042 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1043 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1044 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1045 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1046 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1047 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1048 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1049 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1050 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1057 LeaveCriticalSection(This
->crst
);
1062 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1064 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1067 TRACE("(%p)->(%lu, %lu, %p, %p, %p, %p, 0x%lx)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1071 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1072 return DSERR_INVALIDPARAM
;
1077 if(ptr2
) *ptr2
= NULL
;
1080 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1081 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1082 else if(ofs
>= (DWORD
)This
->buffer
->buf_size
)
1084 WARN("Invalid ofs %lu\n", ofs
);
1085 return DSERR_INVALIDPARAM
;
1087 if((flags
&DSBLOCK_ENTIREBUFFER
))
1088 bytes
= This
->buffer
->buf_size
;
1089 else if(bytes
> (DWORD
)This
->buffer
->buf_size
)
1091 WARN("Invalid size %lu\n", bytes
);
1092 return DSERR_INVALIDPARAM
;
1095 if(InterlockedExchange(&This
->buffer
->locked
, TRUE
) == TRUE
)
1097 WARN("Already locked\n");
1098 return DSERR_INVALIDPARAM
;
1101 *ptr1
= This
->buffer
->data
+ ofs
;
1102 if(bytes
>= (DWORD
)This
->buffer
->buf_size
-ofs
)
1104 *len1
= This
->buffer
->buf_size
- ofs
;
1105 remain
= bytes
- *len1
;
1113 if(ptr2
&& len2
&& remain
)
1115 *ptr2
= This
->buffer
->data
;
1122 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1124 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1125 ALint state
= AL_STOPPED
;
1129 TRACE("(%p)->(%lu, %lu, %lu)\n", iface
, res1
, prio
, flags
);
1131 EnterCriticalSection(This
->crst
);
1132 setALContext(This
->ctx
);
1134 hr
= DSERR_BUFFERLOST
;
1135 if(This
->bufferlost
)
1137 WARN("Buffer %p lost\n", This
);
1141 data
= This
->buffer
;
1142 if((data
->dsbflags
&DSBCAPS_LOCDEFER
))
1144 if(!(data
->dsbflags
&(DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCSOFTWARE
)))
1146 if(flags
& DSBPLAY_LOCSOFTWARE
)
1147 data
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1149 data
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1154 ERR("Invalid priority set for non-deferred buffer %p, %lu!\n", This
->buffer
, prio
);
1155 hr
= DSERR_INVALIDPARAM
;
1159 if(This
->segsize
!= 0)
1161 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1162 if(This
->isplaying
) state
= AL_PLAYING
;
1166 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1167 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1172 if(state
== AL_PLAYING
)
1175 if(This
->segsize
== 0)
1177 if(state
!= AL_PAUSED
)
1178 alSourcei(This
->source
, AL_BUFFER
, data
->bid
);
1179 alSourcePlay(This
->source
);
1183 alSourceRewind(This
->source
);
1184 alSourcei(This
->source
, AL_BUFFER
, 0);
1185 This
->queue_base
= This
->data_offset
% data
->buf_size
;
1188 if(alGetError() != AL_NO_ERROR
)
1190 ERR("Couldn't start source\n");
1191 alSourcei(This
->source
, AL_BUFFER
, 0);
1196 This
->isplaying
= TRUE
;
1197 This
->playflags
= flags
;
1200 DS8Buffer_addnotify(This
);
1204 LeaveCriticalSection(This
->crst
);
1208 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1210 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1213 TRACE("(%p)->(%lu)\n", iface
, pos
);
1215 data
= This
->buffer
;
1216 if(pos
>= (DWORD
)data
->buf_size
)
1217 return DSERR_INVALIDPARAM
;
1218 pos
-= pos
%data
->format
.Format
.nBlockAlign
;
1220 EnterCriticalSection(This
->crst
);
1222 if(This
->segsize
!= 0)
1226 setALContext(This
->ctx
);
1227 /* Perform a flush, so the next timer update will restart at the
1228 * proper position */
1229 alSourceRewind(This
->source
);
1230 alSourcei(This
->source
, AL_BUFFER
, 0);
1234 This
->queue_base
= This
->data_offset
= pos
;
1239 setALContext(This
->ctx
);
1240 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1243 This
->lastpos
= pos
;
1245 LeaveCriticalSection(This
->crst
);
1249 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1251 /* This call only works on primary buffers */
1252 WARN("(%p)->(%p)\n", iface
, wfx
);
1253 return DSERR_INVALIDCALL
;
1256 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1258 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1261 TRACE("(%p)->(%ld)\n", iface
, vol
);
1263 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1265 WARN("Invalid volume (%ld)\n", vol
);
1266 return DSERR_INVALIDPARAM
;
1269 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1270 hr
= DSERR_CONTROLUNAVAIL
;
1273 ALfloat fvol
= mB_to_gain(vol
);
1274 setALContext(This
->ctx
);
1275 alSourcef(This
->source
, AL_GAIN
, fvol
);
1282 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1284 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1287 TRACE("(%p)->(%ld)\n", iface
, pan
);
1289 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1291 WARN("invalid parameter: pan = %ld\n", pan
);
1292 return DSERR_INVALIDPARAM
;
1295 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1296 hr
= DSERR_CONTROLUNAVAIL
;
1299 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1302 pos
[0] = (ALfloat
)(pan
-DSBPAN_LEFT
)/(ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 0.5f
;
1304 /* NOTE: Strict movement along the X plane can cause the sound to
1305 * jump between left and right sharply. Using a curved path helps
1308 pos
[2] = -sqrtf(1.0f
- pos
[0]*pos
[0]);
1310 setALContext(This
->ctx
);
1311 alSourcefv(This
->source
, AL_POSITION
, pos
);
1315 if(pan
!= 0 && This
->buffer
->format
.Format
.nChannels
> 1)
1316 FIXME("Panning for multi-channel buffers is not supported\n");
1323 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1325 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1328 TRACE("(%p)->(%lu)\n", iface
, freq
);
1330 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1332 WARN("invalid parameter: freq = %lu\n", freq
);
1333 return DSERR_INVALIDPARAM
;
1336 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1337 hr
= DSERR_CONTROLUNAVAIL
;
1340 ALfloat pitch
= 1.0f
;
1341 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1342 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1344 setALContext(This
->ctx
);
1345 alSourcef(This
->source
, AL_PITCH
, pitch
);
1353 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1355 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1357 TRACE("(%p)->()\n", iface
);
1359 EnterCriticalSection(This
->crst
);
1360 setALContext(This
->ctx
);
1362 alSourcePause(This
->source
);
1365 This
->isplaying
= FALSE
;
1368 LeaveCriticalSection(This
->crst
);
1373 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1375 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1376 DS8Data
*buf
= This
->buffer
;
1377 DWORD bufsize
= buf
->buf_size
;
1378 DWORD_PTR ofs1
, ofs2
;
1379 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1382 TRACE("(%p)->(%p, %lu, %p, %lu)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1384 if(InterlockedExchange(&This
->buffer
->locked
, FALSE
) == FALSE
)
1386 WARN("Not locked\n");
1387 return DSERR_INVALIDPARAM
;
1390 hr
= DSERR_INVALIDPARAM
;
1391 /* Make sure offset is between boundary and boundary + bufsize */
1392 ofs1
= (DWORD_PTR
)ptr1
;
1393 ofs2
= (DWORD_PTR
)ptr2
;
1394 if(ofs1
< boundary
|| (ofs2
&& ofs2
!= boundary
))
1398 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1407 if(This
->primary
->SupportedExt
[SOFTX_MAP_BUFFER
])
1409 setALContext(This
->ctx
);
1410 This
->ExtAL
->FlushMappedBufferSOFT(buf
->bid
, 0, buf
->buf_size
);
1414 else if(This
->segsize
== 0)
1416 setALContext(This
->ctx
);
1417 alBufferData(buf
->bid
, buf
->buf_format
, buf
->data
, buf
->buf_size
,
1418 buf
->format
.Format
.nSamplesPerSec
);
1425 WARN("Invalid parameters (0x%lx,%lu) (%p,%lu,%p,%lu)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1429 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1431 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1434 TRACE("(%p)->()\n", iface
);
1436 EnterCriticalSection(This
->crst
);
1437 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1438 iface
== This
->primary
->write_emu
)
1440 This
->bufferlost
= 0;
1444 hr
= DSERR_BUFFERLOST
;
1445 LeaveCriticalSection(This
->crst
);
1450 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1452 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1453 ALenum state
= AL_INITIAL
;
1458 TRACE("(%p)->(%lu, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1460 data
= This
->buffer
;
1461 if(!(data
->dsbflags
&DSBCAPS_CTRLFX
))
1463 WARN("FX control not set\n");
1464 return DSERR_CONTROLUNAVAIL
;
1469 WARN("Buffer is locked\n");
1470 return DSERR_INVALIDCALL
;
1473 EnterCriticalSection(This
->crst
);
1474 setALContext(This
->ctx
);
1476 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1478 if(This
->segsize
!= 0 && state
!= AL_PLAYING
)
1479 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1480 if(state
== AL_PLAYING
)
1482 WARN("Buffer is playing\n");
1483 hr
= DSERR_INVALIDCALL
;
1487 hr
= DSERR_INVALIDPARAM
;
1490 if(desc
|| rescodes
)
1492 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1496 /* No effects; we can handle that */
1501 if(!desc
|| !rescodes
)
1503 WARN("NULL desc and/or result pointer specified.\n");
1507 /* We don't (currently) handle DSound effects */
1508 for(i
= 0;i
< fxcount
;++i
)
1510 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1511 rescodes
[i
] = DSFXR_FAILED
;
1517 LeaveCriticalSection(This
->crst
);
1522 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1524 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1526 TRACE("(%p)->(%lu, %lu, %p)\n", This
, flags
, fxcount
, rescodes
);
1528 /* effects aren't supported at the moment.. */
1529 if(fxcount
!= 0 || rescodes
)
1531 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1532 return DSERR_INVALIDPARAM
;
1535 EnterCriticalSection(This
->crst
);
1536 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1538 This
->buffer
->dsbflags
&= ~(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
);
1539 if((flags
&DSBPLAY_LOCSOFTWARE
))
1540 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1542 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1544 LeaveCriticalSection(This
->crst
);
1549 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1551 FIXME("(%p)->(%s, %lu, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1555 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
= {
1556 DS8Buffer_QueryInterface
,
1560 DS8Buffer_GetCurrentPosition
,
1561 DS8Buffer_GetFormat
,
1562 DS8Buffer_GetVolume
,
1564 DS8Buffer_GetFrequency
,
1565 DS8Buffer_GetStatus
,
1566 DS8Buffer_Initialize
,
1569 DS8Buffer_SetCurrentPosition
,
1570 DS8Buffer_SetFormat
,
1571 DS8Buffer_SetVolume
,
1573 DS8Buffer_SetFrequency
,
1578 DS8Buffer_AcquireResources
,
1579 DS8Buffer_GetObjectInPath
1583 static HRESULT WINAPI
DSBuffer_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, void **ppv
)
1585 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1586 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1589 static ULONG WINAPI
DSBuffer_AddRef(IDirectSoundBuffer
*iface
)
1591 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1592 return DS8Buffer_AddRef(&This
->IDirectSoundBuffer8_iface
);
1595 static ULONG WINAPI
DSBuffer_Release(IDirectSoundBuffer
*iface
)
1597 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1598 return DS8Buffer_Release(&This
->IDirectSoundBuffer8_iface
);
1601 static HRESULT WINAPI
DSBuffer_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
1603 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1604 return DS8Buffer_GetCaps(&This
->IDirectSoundBuffer8_iface
, caps
);
1607 static HRESULT WINAPI
DSBuffer_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
1609 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1610 return DS8Buffer_GetCurrentPosition(&This
->IDirectSoundBuffer8_iface
, playpos
, curpos
);
1613 static HRESULT WINAPI
DSBuffer_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1615 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1616 return DS8Buffer_GetFormat(&This
->IDirectSoundBuffer8_iface
, wfx
, allocated
, written
);
1619 static HRESULT WINAPI
DSBuffer_GetVolume(IDirectSoundBuffer
*iface
, LONG
*vol
)
1621 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1622 return DS8Buffer_GetVolume(&This
->IDirectSoundBuffer8_iface
, vol
);
1625 static HRESULT WINAPI
DSBuffer_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
1627 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1628 return DS8Buffer_GetPan(&This
->IDirectSoundBuffer8_iface
, pan
);
1631 static HRESULT WINAPI
DSBuffer_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
1633 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1634 return DS8Buffer_GetFrequency(&This
->IDirectSoundBuffer8_iface
, freq
);
1637 static HRESULT WINAPI
DSBuffer_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
1639 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1640 return DS8Buffer_GetStatus(&This
->IDirectSoundBuffer8_iface
, status
);
1643 static HRESULT WINAPI
DSBuffer_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1645 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1646 return DS8Buffer_Initialize(&This
->IDirectSoundBuffer8_iface
, ds
, desc
);
1649 static HRESULT WINAPI
DSBuffer_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1651 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1652 return DS8Buffer_Lock(&This
->IDirectSoundBuffer8_iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1655 static HRESULT WINAPI
DSBuffer_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1657 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1658 return DS8Buffer_Play(&This
->IDirectSoundBuffer8_iface
, res1
, prio
, flags
);
1661 static HRESULT WINAPI
DSBuffer_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
1663 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1664 return DS8Buffer_SetCurrentPosition(&This
->IDirectSoundBuffer8_iface
, pos
);
1667 static HRESULT WINAPI
DSBuffer_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
1669 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1670 return DS8Buffer_SetFormat(&This
->IDirectSoundBuffer8_iface
, wfx
);
1673 static HRESULT WINAPI
DSBuffer_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
1675 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1676 return DS8Buffer_SetVolume(&This
->IDirectSoundBuffer8_iface
, vol
);
1679 static HRESULT WINAPI
DSBuffer_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
1681 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1682 return DS8Buffer_SetPan(&This
->IDirectSoundBuffer8_iface
, pan
);
1685 static HRESULT WINAPI
DSBuffer_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
1687 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1688 return DS8Buffer_SetFrequency(&This
->IDirectSoundBuffer8_iface
, freq
);
1691 static HRESULT WINAPI
DSBuffer_Stop(IDirectSoundBuffer
*iface
)
1693 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1694 return DS8Buffer_Stop(&This
->IDirectSoundBuffer8_iface
);
1697 static HRESULT WINAPI
DSBuffer_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1699 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1700 return DS8Buffer_Unlock(&This
->IDirectSoundBuffer8_iface
, ptr1
, len1
, ptr2
, len2
);
1703 static HRESULT WINAPI
DSBuffer_Restore(IDirectSoundBuffer
*iface
)
1705 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1706 return DS8Buffer_Restore(&This
->IDirectSoundBuffer8_iface
);
1709 static const IDirectSoundBufferVtbl DSBuffer_Vtbl
= {
1710 DSBuffer_QueryInterface
,
1714 DSBuffer_GetCurrentPosition
,
1718 DSBuffer_GetFrequency
,
1720 DSBuffer_Initialize
,
1723 DSBuffer_SetCurrentPosition
,
1727 DSBuffer_SetFrequency
,
1734 void DS8Buffer_SetParams(DS8Buffer
*This
, const DS3DBUFFER
*params
, LONG flags
)
1736 const ALuint source
= This
->source
;
1737 union BufferParamFlags dirty
= { flags
};
1740 alSource3f(source
, AL_POSITION
, params
->vPosition
.x
, params
->vPosition
.y
,
1741 -params
->vPosition
.z
);
1743 alSource3f(source
, AL_VELOCITY
, params
->vVelocity
.x
, params
->vVelocity
.y
,
1744 -params
->vVelocity
.z
);
1745 if(dirty
.bit
.cone_angles
)
1747 alSourcei(source
, AL_CONE_INNER_ANGLE
, params
->dwInsideConeAngle
);
1748 alSourcei(source
, AL_CONE_OUTER_ANGLE
, params
->dwOutsideConeAngle
);
1750 if(dirty
.bit
.cone_orient
)
1751 alSource3f(source
, AL_DIRECTION
, params
->vConeOrientation
.x
,
1752 params
->vConeOrientation
.y
,
1753 -params
->vConeOrientation
.z
);
1754 if(dirty
.bit
.cone_outsidevolume
)
1755 alSourcef(source
, AL_CONE_OUTER_GAIN
, mB_to_gain(params
->lConeOutsideVolume
));
1756 if(dirty
.bit
.min_distance
)
1757 alSourcef(source
, AL_REFERENCE_DISTANCE
, params
->flMinDistance
);
1758 if(dirty
.bit
.max_distance
)
1759 alSourcef(source
, AL_MAX_DISTANCE
, params
->flMaxDistance
);
1762 This
->ds3dmode
= params
->dwMode
;
1763 alSourcei(source
, AL_SOURCE_RELATIVE
, (params
->dwMode
!=DS3DMODE_NORMAL
) ?
1764 AL_TRUE
: AL_FALSE
);
1765 alSourcef(source
, AL_ROLLOFF_FACTOR
, (params
->dwMode
==DS3DMODE_DISABLE
) ?
1766 0.0f
: This
->primary
->rollofffactor
);
1770 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
1772 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1773 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1776 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
1778 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1781 InterlockedIncrement(&This
->all_ref
);
1782 ret
= InterlockedIncrement(&This
->ds3d_ref
);
1783 TRACE("new refcount %ld\n", ret
);
1788 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
1790 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1793 ret
= InterlockedDecrement(&This
->ds3d_ref
);
1794 TRACE("new refcount %ld\n", ret
);
1795 if(InterlockedDecrement(&This
->all_ref
) == 0)
1796 DS8Buffer_Destroy(This
);
1801 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
1803 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1804 ALint inangle
, outangle
;
1806 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
1807 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
1809 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
1810 return DSERR_INVALIDPARAM
;
1813 EnterCriticalSection(This
->crst
);
1814 setALContext(This
->ctx
);
1816 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
1817 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
1821 LeaveCriticalSection(This
->crst
);
1823 *pdwInsideConeAngle
= inangle
;
1824 *pdwOutsideConeAngle
= outangle
;
1828 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
1830 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1833 TRACE("(%p)->(%p)\n", This
, orient
);
1836 WARN("Invalid pointer\n");
1837 return DSERR_INVALIDPARAM
;
1840 setALContext(This
->ctx
);
1841 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
1847 orient
->z
= -dir
[2];
1851 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
1853 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1856 TRACE("(%p)->(%p)\n", This
, vol
);
1859 WARN("Invalid pointer\n");
1860 return DSERR_INVALIDPARAM
;
1863 setALContext(This
->ctx
);
1864 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
1868 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
1872 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
1874 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1877 TRACE("(%p)->(%p)\n", This
, maxdist
);
1880 WARN("Invalid pointer\n");
1881 return DSERR_INVALIDPARAM
;
1884 setALContext(This
->ctx
);
1885 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
1893 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
1895 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1898 TRACE("(%p)->(%p)\n", This
, mindist
);
1901 WARN("Invalid pointer\n");
1902 return DSERR_INVALIDPARAM
;
1905 setALContext(This
->ctx
);
1906 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
1914 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
1916 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1918 TRACE("(%p)->(%p)\n", This
, mode
);
1921 WARN("Invalid pointer\n");
1922 return DSERR_INVALIDPARAM
;
1925 EnterCriticalSection(This
->crst
);
1926 *mode
= This
->ds3dmode
;
1927 LeaveCriticalSection(This
->crst
);
1932 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
1934 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1937 TRACE("(%p)->(%p)\n", This
, pos
);
1940 WARN("Invalid pointer\n");
1941 return DSERR_INVALIDPARAM
;
1944 setALContext(This
->ctx
);
1945 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
1955 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
1957 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1960 TRACE("(%p)->(%p)\n", This
, vel
);
1963 WARN("Invalid pointer\n");
1964 return DSERR_INVALIDPARAM
;
1967 setALContext(This
->ctx
);
1968 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
1978 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
1980 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1982 TRACE("(%p)->(%p)\n", iface
, ds3dbuffer
);
1984 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
1986 WARN("Invalid parameters %p %lu\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
1987 return DSERR_INVALIDPARAM
;
1990 EnterCriticalSection(This
->crst
);
1991 setALContext(This
->ctx
);
1993 DS8Buffer3D_GetPosition(iface
, &ds3dbuffer
->vPosition
);
1994 DS8Buffer3D_GetVelocity(iface
, &ds3dbuffer
->vVelocity
);
1995 DS8Buffer3D_GetConeAngles(iface
, &ds3dbuffer
->dwInsideConeAngle
, &ds3dbuffer
->dwOutsideConeAngle
);
1996 DS8Buffer3D_GetConeOrientation(iface
, &ds3dbuffer
->vConeOrientation
);
1997 DS8Buffer3D_GetConeOutsideVolume(iface
, &ds3dbuffer
->lConeOutsideVolume
);
1998 DS8Buffer3D_GetMinDistance(iface
, &ds3dbuffer
->flMinDistance
);
1999 DS8Buffer3D_GetMaxDistance(iface
, &ds3dbuffer
->flMaxDistance
);
2000 DS8Buffer3D_GetMode(iface
, &ds3dbuffer
->dwMode
);
2003 LeaveCriticalSection(This
->crst
);
2008 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
2010 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2012 TRACE("(%p)->(%lu, %lu, %lu)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
2013 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2014 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2016 WARN("Invalid cone angles (%lu, %lu)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
2017 return DSERR_INVALIDPARAM
;
2020 EnterCriticalSection(This
->crst
);
2021 if(apply
== DS3D_DEFERRED
)
2023 This
->params
.dwInsideConeAngle
= dwInsideConeAngle
;
2024 This
->params
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2025 This
->dirty
.bit
.cone_angles
= 1;
2029 setALContext(This
->ctx
);
2030 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2031 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2035 LeaveCriticalSection(This
->crst
);
2040 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2042 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2044 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2046 if(apply
== DS3D_DEFERRED
)
2048 EnterCriticalSection(This
->crst
);
2049 This
->params
.vConeOrientation
.x
= x
;
2050 This
->params
.vConeOrientation
.y
= y
;
2051 This
->params
.vConeOrientation
.z
= z
;
2052 This
->dirty
.bit
.cone_orient
= 1;
2053 LeaveCriticalSection(This
->crst
);
2057 setALContext(This
->ctx
);
2058 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2066 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2068 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2070 TRACE("(%p)->(%ld, %lu)\n", This
, vol
, apply
);
2071 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2073 WARN("Invalid volume (%ld)\n", vol
);
2074 return DSERR_INVALIDPARAM
;
2077 if(apply
== DS3D_DEFERRED
)
2079 EnterCriticalSection(This
->crst
);
2080 This
->params
.lConeOutsideVolume
= vol
;
2081 This
->dirty
.bit
.cone_outsidevolume
= 1;
2082 LeaveCriticalSection(This
->crst
);
2086 setALContext(This
->ctx
);
2087 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2095 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2097 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2099 TRACE("(%p)->(%f, %lu)\n", This
, maxdist
, apply
);
2102 WARN("Invalid max distance (%f)\n", maxdist
);
2103 return DSERR_INVALIDPARAM
;
2106 if(apply
== DS3D_DEFERRED
)
2108 EnterCriticalSection(This
->crst
);
2109 This
->params
.flMaxDistance
= maxdist
;
2110 This
->dirty
.bit
.max_distance
= 1;
2111 LeaveCriticalSection(This
->crst
);
2115 setALContext(This
->ctx
);
2116 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2124 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2126 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2128 TRACE("(%p)->(%f, %lu)\n", This
, mindist
, apply
);
2131 WARN("Invalid min distance (%f)\n", mindist
);
2132 return DSERR_INVALIDPARAM
;
2135 if(apply
== DS3D_DEFERRED
)
2137 EnterCriticalSection(This
->crst
);
2138 This
->params
.flMinDistance
= mindist
;
2139 This
->dirty
.bit
.min_distance
= 1;
2140 LeaveCriticalSection(This
->crst
);
2144 setALContext(This
->ctx
);
2145 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2153 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2155 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2157 TRACE("(%p)->(%lu, %lu)\n", This
, mode
, apply
);
2158 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2159 mode
!= DS3DMODE_DISABLE
)
2161 WARN("Invalid mode (%lu)\n", mode
);
2162 return DSERR_INVALIDPARAM
;
2165 EnterCriticalSection(This
->crst
);
2166 if(apply
== DS3D_DEFERRED
)
2168 This
->params
.dwMode
= mode
;
2169 This
->dirty
.bit
.mode
= 1;
2173 setALContext(This
->ctx
);
2174 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2175 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2176 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2177 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: This
->primary
->rollofffactor
);
2178 This
->ds3dmode
= mode
;
2182 LeaveCriticalSection(This
->crst
);
2187 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2189 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2191 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2193 if(apply
== DS3D_DEFERRED
)
2195 EnterCriticalSection(This
->crst
);
2196 This
->params
.vPosition
.x
= x
;
2197 This
->params
.vPosition
.y
= y
;
2198 This
->params
.vPosition
.z
= z
;
2199 This
->dirty
.bit
.pos
= 1;
2200 LeaveCriticalSection(This
->crst
);
2204 setALContext(This
->ctx
);
2205 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2213 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2215 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2217 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2219 if(apply
== DS3D_DEFERRED
)
2221 EnterCriticalSection(This
->crst
);
2222 This
->params
.vVelocity
.x
= x
;
2223 This
->params
.vVelocity
.y
= y
;
2224 This
->params
.vVelocity
.z
= z
;
2225 This
->dirty
.bit
.vel
= 1;
2226 LeaveCriticalSection(This
->crst
);
2230 setALContext(This
->ctx
);
2231 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2239 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2241 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2242 TRACE("(%p)->(%p, %lu)\n", This
, ds3dbuffer
, apply
);
2244 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2246 WARN("Invalid DS3DBUFFER (%p, %lu)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2247 return DSERR_INVALIDPARAM
;
2250 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2251 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2253 WARN("Invalid cone angles (%lu, %lu)\n",
2254 ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
);
2255 return DSERR_INVALIDPARAM
;
2258 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2259 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2261 WARN("Invalid cone outside volume (%ld)\n", ds3dbuffer
->lConeOutsideVolume
);
2262 return DSERR_INVALIDPARAM
;
2265 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2267 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2268 return DSERR_INVALIDPARAM
;
2271 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2273 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2274 return DSERR_INVALIDPARAM
;
2277 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2278 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2279 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2281 WARN("Invalid mode (%lu)\n", ds3dbuffer
->dwMode
);
2282 return DSERR_INVALIDPARAM
;
2285 if(apply
== DS3D_DEFERRED
)
2287 EnterCriticalSection(This
->crst
);
2288 This
->params
= *ds3dbuffer
;
2289 This
->params
.dwSize
= sizeof(This
->params
);
2290 This
->dirty
.bit
.pos
= 1;
2291 This
->dirty
.bit
.vel
= 1;
2292 This
->dirty
.bit
.cone_angles
= 1;
2293 This
->dirty
.bit
.cone_orient
= 1;
2294 This
->dirty
.bit
.cone_outsidevolume
= 1;
2295 This
->dirty
.bit
.min_distance
= 1;
2296 This
->dirty
.bit
.max_distance
= 1;
2297 This
->dirty
.bit
.mode
= 1;
2298 LeaveCriticalSection(This
->crst
);
2302 union BufferParamFlags dirty
= { 0 };
2305 dirty
.bit
.cone_angles
= 1;
2306 dirty
.bit
.cone_orient
= 1;
2307 dirty
.bit
.cone_outsidevolume
= 1;
2308 dirty
.bit
.min_distance
= 1;
2309 dirty
.bit
.max_distance
= 1;
2312 EnterCriticalSection(This
->crst
);
2313 setALContext(This
->ctx
);
2314 DS8Buffer_SetParams(This
, ds3dbuffer
, dirty
.flags
);
2317 LeaveCriticalSection(This
->crst
);
2323 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2325 DS8Buffer3D_QueryInterface
,
2327 DS8Buffer3D_Release
,
2328 DS8Buffer3D_GetAllParameters
,
2329 DS8Buffer3D_GetConeAngles
,
2330 DS8Buffer3D_GetConeOrientation
,
2331 DS8Buffer3D_GetConeOutsideVolume
,
2332 DS8Buffer3D_GetMaxDistance
,
2333 DS8Buffer3D_GetMinDistance
,
2334 DS8Buffer3D_GetMode
,
2335 DS8Buffer3D_GetPosition
,
2336 DS8Buffer3D_GetVelocity
,
2337 DS8Buffer3D_SetAllParameters
,
2338 DS8Buffer3D_SetConeAngles
,
2339 DS8Buffer3D_SetConeOrientation
,
2340 DS8Buffer3D_SetConeOutsideVolume
,
2341 DS8Buffer3D_SetMaxDistance
,
2342 DS8Buffer3D_SetMinDistance
,
2343 DS8Buffer3D_SetMode
,
2344 DS8Buffer3D_SetPosition
,
2345 DS8Buffer3D_SetVelocity
2349 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2351 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2352 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2355 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2357 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2360 InterlockedIncrement(&This
->all_ref
);
2361 ret
= InterlockedIncrement(&This
->not_ref
);
2362 TRACE("new refcount %ld\n", ret
);
2367 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2369 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2372 ret
= InterlockedDecrement(&This
->not_ref
);
2373 TRACE("new refcount %ld\n", ret
);
2374 if(InterlockedDecrement(&This
->all_ref
) == 0)
2375 DS8Buffer_Destroy(This
);
2380 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2382 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2383 DSBPOSITIONNOTIFY
*nots
;
2387 TRACE("(%p)->(%lu, %p))\n", iface
, count
, notifications
);
2389 EnterCriticalSection(This
->crst
);
2390 hr
= DSERR_INVALIDPARAM
;
2391 if(count
&& !notifications
)
2394 hr
= DS8Buffer_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2395 if(FAILED(hr
)) goto out
;
2397 hr
= DSERR_INVALIDCALL
;
2398 if((state
&DSBSTATUS_PLAYING
))
2403 HeapFree(GetProcessHeap(), 0, This
->notify
);
2412 hr
= DSERR_INVALIDPARAM
;
2413 for(i
= 0;i
< count
;++i
)
2415 if(notifications
[i
].dwOffset
>= (DWORD
)This
->buffer
->buf_size
&&
2416 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2421 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2423 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2425 HeapFree(GetProcessHeap(), 0, This
->notify
);
2426 This
->notify
= nots
;
2427 This
->nnotify
= count
;
2433 LeaveCriticalSection(This
->crst
);
2437 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2439 DS8BufferNot_QueryInterface
,
2440 DS8BufferNot_AddRef
,
2441 DS8BufferNot_Release
,
2442 DS8BufferNot_SetNotificationPositions
2446 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2448 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2449 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2452 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2454 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2457 InterlockedIncrement(&This
->all_ref
);
2458 ret
= InterlockedIncrement(&This
->prop_ref
);
2459 TRACE("new refcount %ld\n", ret
);
2464 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2466 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2469 ret
= InterlockedDecrement(&This
->prop_ref
);
2470 TRACE("new refcount %ld\n", ret
);
2471 if(InterlockedDecrement(&This
->all_ref
) == 0)
2472 DS8Buffer_Destroy(This
);
2477 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2478 handled through secondary buffers. */
2479 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2480 REFGUID guidPropSet
, ULONG dwPropID
,
2481 LPVOID pInstanceData
, ULONG cbInstanceData
,
2482 LPVOID pPropData
, ULONG cbPropData
,
2485 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2486 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2488 TRACE("(%p)->(%s, %lu, %p, %lu, %p, %lu, %p)\n", iface
, debugstr_guid(guidPropSet
),
2489 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2496 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2501 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2503 DS8Primary
*prim
= This
->primary
;
2505 EnterCriticalSection(This
->crst
);
2507 hr
= DSERR_INVALIDPARAM
;
2508 if(prim
->effect
== 0)
2509 hr
= E_PROP_ID_UNSUPPORTED
;
2510 else switch(dwPropID
)
2512 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
2513 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
2517 EAXLISTENERPROPERTIES
*props
;
2518 } data
= { pPropData
};
2520 *data
.props
= prim
->eax_prop
;
2521 *pcbReturned
= sizeof(EAXLISTENERPROPERTIES
);
2526 case DSPROPERTY_EAXLISTENER_ROOM
:
2527 if(cbPropData
>= sizeof(LONG
))
2532 } data
= { pPropData
};
2534 *data
.l
= prim
->eax_prop
.lRoom
;
2535 *pcbReturned
= sizeof(LONG
);
2539 case DSPROPERTY_EAXLISTENER_ROOMHF
:
2540 if(cbPropData
>= sizeof(LONG
))
2545 } data
= { pPropData
};
2547 *data
.l
= prim
->eax_prop
.lRoomHF
;
2548 *pcbReturned
= sizeof(LONG
);
2553 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
2554 if(cbPropData
>= sizeof(FLOAT
))
2559 } data
= { pPropData
};
2561 *data
.fl
= prim
->eax_prop
.flRoomRolloffFactor
;
2562 *pcbReturned
= sizeof(FLOAT
);
2567 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
2568 if(cbPropData
>= sizeof(DWORD
))
2573 } data
= { pPropData
};
2575 *data
.dw
= prim
->eax_prop
.dwEnvironment
;
2576 *pcbReturned
= sizeof(DWORD
);
2581 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
2582 if(cbPropData
>= sizeof(FLOAT
))
2587 } data
= { pPropData
};
2589 *data
.fl
= prim
->eax_prop
.flEnvironmentSize
;
2590 *pcbReturned
= sizeof(FLOAT
);
2594 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
2595 if(cbPropData
>= sizeof(FLOAT
))
2600 } data
= { pPropData
};
2602 *data
.fl
= prim
->eax_prop
.flEnvironmentDiffusion
;
2603 *pcbReturned
= sizeof(FLOAT
);
2608 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
2609 if(cbPropData
>= sizeof(FLOAT
))
2614 } data
= { pPropData
};
2616 *data
.fl
= prim
->eax_prop
.flAirAbsorptionHF
;
2617 *pcbReturned
= sizeof(FLOAT
);
2622 case DSPROPERTY_EAXLISTENER_FLAGS
:
2623 if(cbPropData
>= sizeof(DWORD
))
2628 } data
= { pPropData
};
2630 *data
.dw
= prim
->eax_prop
.dwFlags
;
2631 *pcbReturned
= sizeof(DWORD
);
2637 hr
= E_PROP_ID_UNSUPPORTED
;
2638 FIXME("Unhandled propid: 0x%08lx\n", dwPropID
);
2642 LeaveCriticalSection(This
->crst
);
2645 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2650 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2651 REFGUID guidPropSet
, ULONG dwPropID
,
2652 LPVOID pInstanceData
, ULONG cbInstanceData
,
2653 LPVOID pPropData
, ULONG cbPropData
)
2655 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2656 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2658 TRACE("(%p)->(%s, %lu, %p, %lu, %p, %lu)\n", iface
, debugstr_guid(guidPropSet
),
2659 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2662 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2667 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2669 DS8Primary
*prim
= This
->primary
;
2670 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
2671 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
2673 EnterCriticalSection(prim
->crst
);
2674 setALContext(prim
->ctx
);
2676 hr
= DSERR_INVALIDPARAM
;
2677 if(prim
->effect
== 0)
2678 hr
= E_PROP_ID_UNSUPPORTED
;
2681 case DSPROPERTY_EAXLISTENER_NONE
: /* not setting any property, just applying */
2685 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
2687 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
2691 const EAXLISTENERPROPERTIES
*props
;
2692 } data
= { pPropData
};
2694 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
2695 prim
->eax_prop
= *data
.props
;
2696 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_DENSITY
,
2697 clampF(powf(data
.props
->flEnvironmentSize
, 3.0f
) / 16.0f
,
2700 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_DIFFUSION
,
2701 data
.props
->flEnvironmentDiffusion
);
2703 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_GAIN
,
2704 mB_to_gain(data
.props
->lRoom
));
2705 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_GAINHF
,
2706 mB_to_gain(data
.props
->lRoomHF
));
2708 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
2709 data
.props
->flRoomRolloffFactor
);
2711 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_DECAY_TIME
,
2712 data
.props
->flDecayTime
);
2713 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_DECAY_HFRATIO
,
2714 data
.props
->flDecayHFRatio
);
2716 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_REFLECTIONS_GAIN
,
2717 mB_to_gain(data
.props
->lReflections
));
2718 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_REFLECTIONS_DELAY
,
2719 data
.props
->flReflectionsDelay
);
2721 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_LATE_REVERB_GAIN
,
2722 mB_to_gain(data
.props
->lReverb
));
2723 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_LATE_REVERB_DELAY
,
2724 data
.props
->flReverbDelay
);
2726 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
2727 mBF_to_gain(data
.props
->flAirAbsorptionHF
));
2729 prim
->ExtAL
->Effecti(prim
->effect
, AL_REVERB_DECAY_HFLIMIT
,
2730 (data
.props
->dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
2731 AL_TRUE
: AL_FALSE
);
2735 prim
->dirty
.bit
.effect
= 1;
2740 case DSPROPERTY_EAXLISTENER_ROOM
:
2741 if(cbPropData
>= sizeof(LONG
))
2746 } data
= { pPropData
};
2748 prim
->eax_prop
.lRoom
= *data
.l
;
2749 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_GAIN
,
2750 mB_to_gain(prim
->eax_prop
.lRoom
));
2753 prim
->dirty
.bit
.effect
= 1;
2757 case DSPROPERTY_EAXLISTENER_ROOMHF
:
2758 if(cbPropData
>= sizeof(LONG
))
2763 } data
= { pPropData
};
2765 prim
->eax_prop
.lRoomHF
= *data
.l
;
2766 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_GAINHF
,
2767 mB_to_gain(prim
->eax_prop
.lRoomHF
));
2770 prim
->dirty
.bit
.effect
= 1;
2775 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
2776 if(cbPropData
>= sizeof(FLOAT
))
2781 } data
= { pPropData
};
2783 prim
->eax_prop
.flRoomRolloffFactor
= *data
.fl
;
2784 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
2785 prim
->eax_prop
.flRoomRolloffFactor
);
2788 prim
->dirty
.bit
.effect
= 1;
2793 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
2794 if(cbPropData
>= sizeof(DWORD
))
2799 } data
= { pPropData
};
2801 if(*data
.dw
<= EAX_MAX_ENVIRONMENT
)
2803 /* Get the environment index's default and pass it down to
2805 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
2806 pPropData
= (void*)&EnvironmentDefaults
[*data
.dw
];
2807 cbPropData
= sizeof(EnvironmentDefaults
[*data
.dw
]);
2813 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
2814 if(cbPropData
>= sizeof(FLOAT
))
2819 } data
= { pPropData
};
2821 if(*data
.fl
>= 1.0f
&& *data
.fl
<= 100.0f
)
2823 float scale
= (*data
.fl
)/prim
->eax_prop
.flEnvironmentSize
;
2825 prim
->eax_prop
.flEnvironmentSize
= *data
.fl
;
2827 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYTIMESCALE
))
2829 prim
->eax_prop
.flDecayTime
*= scale
;
2830 prim
->eax_prop
.flDecayTime
= clampF(prim
->eax_prop
.flDecayTime
, 0.1f
, 20.0f
);
2832 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSSCALE
))
2834 prim
->eax_prop
.lReflections
-= gain_to_mB(scale
);
2835 prim
->eax_prop
.lReflections
= clampI(prim
->eax_prop
.lReflections
, -10000, 1000);
2837 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE
))
2839 prim
->eax_prop
.flReflectionsDelay
*= scale
;
2840 prim
->eax_prop
.flReflectionsDelay
= clampF(prim
->eax_prop
.flReflectionsDelay
, 0.0f
, 0.3f
);
2842 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBSCALE
))
2844 prim
->eax_prop
.lReverb
-= gain_to_mB(scale
);
2845 prim
->eax_prop
.lReverb
= clampI(prim
->eax_prop
.lReverb
, -10000, 2000);
2847 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBDELAYSCALE
))
2849 prim
->eax_prop
.flReverbDelay
*= scale
;
2850 prim
->eax_prop
.flReverbDelay
= clampF(prim
->eax_prop
.flReverbDelay
, 0.0f
, 0.1f
);
2853 /* Pass the updated environment properties down to ALLPARAMETERS */
2854 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
2855 pPropData
= (void*)&prim
->eax_prop
;
2856 cbPropData
= sizeof(prim
->eax_prop
);
2861 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
2862 if(cbPropData
>= sizeof(FLOAT
))
2867 } data
= { pPropData
};
2869 prim
->eax_prop
.flEnvironmentDiffusion
= *data
.fl
;
2870 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_DIFFUSION
,
2871 prim
->eax_prop
.flEnvironmentDiffusion
);
2874 prim
->dirty
.bit
.effect
= 1;
2879 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
2880 if(cbPropData
>= sizeof(FLOAT
))
2885 } data
= { pPropData
};
2887 prim
->eax_prop
.flAirAbsorptionHF
= *data
.fl
;
2888 prim
->ExtAL
->Effectf(prim
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
2889 mBF_to_gain(prim
->eax_prop
.flAirAbsorptionHF
));
2892 prim
->dirty
.bit
.effect
= 1;
2897 case DSPROPERTY_EAXLISTENER_FLAGS
:
2898 if(cbPropData
>= sizeof(DWORD
))
2903 } data
= { pPropData
};
2905 prim
->eax_prop
.dwFlags
= *data
.dw
;
2906 prim
->ExtAL
->Effecti(prim
->effect
, AL_REVERB_DECAY_HFLIMIT
,
2907 (prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
2908 AL_TRUE
: AL_FALSE
);
2911 prim
->dirty
.bit
.effect
= 1;
2917 hr
= E_PROP_ID_UNSUPPORTED
;
2918 FIXME("Unhandled propid: 0x%08lx\n", propid
);
2922 if(hr
== DS_OK
&& immediate
)
2923 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
2926 LeaveCriticalSection(prim
->crst
);
2929 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2934 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
2935 REFGUID guidPropSet
, ULONG dwPropID
,
2936 ULONG
*pTypeSupport
)
2938 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2939 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2941 TRACE("(%p)->(%s, %lu, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2948 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2953 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2955 DS8Primary
*prim
= This
->primary
;
2957 EnterCriticalSection(This
->crst
);
2959 if(prim
->effect
== 0)
2960 hr
= E_PROP_ID_UNSUPPORTED
;
2961 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
||
2962 dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
||
2963 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
||
2964 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
||
2965 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
||
2966 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
||
2967 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
||
2968 dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
||
2969 dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
2971 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
|KSPROPERTY_SUPPORT_SET
;
2975 FIXME("Unhandled propid: 0x%08lx\n", dwPropID
);
2977 LeaveCriticalSection(This
->crst
);
2980 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2985 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
2987 DS8BufferProp_QueryInterface
,
2988 DS8BufferProp_AddRef
,
2989 DS8BufferProp_Release
,
2992 DS8BufferProp_QuerySupport