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
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
39 #include "wine/debug.h"
42 #include "dsound_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
56 #include "dsound_private.h"
58 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM
, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
59 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
61 #ifndef E_PROP_ID_UNSUPPORTED
62 #define E_PROP_ID_UNSUPPORTED ((HRESULT)0x80070490)
67 static const IDirectSoundBufferVtbl DS8Primary_Vtbl
;
68 static const IDirectSound3DListenerVtbl DS8Primary3D_Vtbl
;
69 static const IKsPropertySetVtbl DS8PrimaryProp_Vtbl
;
71 static void AL_APIENTRY
wrap_DeferUpdates(void)
72 { alcSuspendContext(alcGetCurrentContext()); }
73 static void AL_APIENTRY
wrap_ProcessUpdates(void)
74 { alcProcessContext(alcGetCurrentContext()); }
76 HRESULT
DS8Primary_Create(DS8Primary
**ppv
, DS8Impl
*parent
)
78 HRESULT hr
= DSERR_OUTOFMEMORY
;
79 DS8Primary
*This
= NULL
;
80 DS3DLISTENER
*listener
;
86 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
89 This
->IDirectSoundBuffer_iface
.lpVtbl
= (IDirectSoundBufferVtbl
*)&DS8Primary_Vtbl
;
90 This
->IDirectSound3DListener_iface
.lpVtbl
= (IDirectSound3DListenerVtbl
*)&DS8Primary3D_Vtbl
;
91 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8PrimaryProp_Vtbl
;
93 InitializeCriticalSection(&This
->crst
);
94 This
->crst
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DS8Primary.crst");
96 /* Allocate enough for a WAVEFORMATEXTENSIBLE */
97 wfx
= &This
->format
.Format
;
100 This
->ctx
= alcCreateContext(parent
->device
, NULL
);
103 ALCenum err
= alcGetError(parent
->device
);
104 ERR("Could not create context (0x%x)!\n", err
);
108 setALContext(This
->ctx
);
109 if(alIsExtensionPresent("AL_EXT_FLOAT32"))
111 TRACE("Found AL_EXT_FLOAT32\n");
112 This
->SupportedExt
[EXT_FLOAT32
] = AL_TRUE
;
114 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
116 TRACE("Found AL_EXT_MCFORMATS\n");
117 This
->SupportedExt
[EXT_MCFORMATS
] = AL_TRUE
;
119 if(alIsExtensionPresent("AL_EXT_STATIC_BUFFER"))
121 TRACE("Found AL_EXT_STATIC_BUFFER\n");
122 This
->ExtAL
.BufferDataStatic
= alGetProcAddress("alBufferDataStatic");
123 This
->SupportedExt
[EXT_STATIC_BUFFER
] = AL_TRUE
;
125 if(alIsExtensionPresent("AL_SOFTX_buffer_samples"))
127 TRACE("Found AL_SOFTX_buffer_samples\n");
128 This
->ExtAL
.BufferSamplesSOFT
= alGetProcAddress("alBufferSamplesSOFT");
129 This
->ExtAL
.BufferSubSamplesSOFT
= alGetProcAddress("alBufferSubSamplesSOFT");
130 This
->ExtAL
.GetBufferSamplesSOFT
= alGetProcAddress("alGetBufferSamplesSOFT");
131 This
->ExtAL
.IsBufferFormatSupportedSOFT
= alGetProcAddress("alIsBufferFormatSupportedSOFT");
132 This
->SupportedExt
[SOFT_BUFFER_SAMPLES
] = AL_TRUE
;
134 if(alIsExtensionPresent("AL_SOFT_buffer_sub_data"))
136 TRACE("Found AL_SOFT_buffer_sub_data\n");
137 This
->ExtAL
.BufferSubData
= alGetProcAddress("alBufferSubDataSOFT");
138 This
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] = AL_TRUE
;
140 if(alIsExtensionPresent("AL_SOFTX_deferred_updates"))
142 TRACE("Found AL_SOFTX_deferred_updates\n");
143 This
->ExtAL
.DeferUpdates
= alGetProcAddress("alDeferUpdatesSOFT");
144 This
->ExtAL
.ProcessUpdates
= alGetProcAddress("alProcessUpdatesSOFT");
145 This
->SupportedExt
[SOFT_DEFERRED_UPDATES
] = AL_TRUE
;
149 This
->ExtAL
.DeferUpdates
= wrap_DeferUpdates
;
150 This
->ExtAL
.ProcessUpdates
= wrap_ProcessUpdates
;
153 if(alcIsExtensionPresent(parent
->device
, "ALC_EXT_EFX"))
155 #define LOAD_FUNC(x) (This->ExtAL.x = alGetProcAddress("al"#x))
156 LOAD_FUNC(GenEffects
);
157 LOAD_FUNC(DeleteEffects
);
161 LOAD_FUNC(GenAuxiliaryEffectSlots
);
162 LOAD_FUNC(DeleteAuxiliaryEffectSlots
);
163 LOAD_FUNC(AuxiliaryEffectSloti
);
165 This
->SupportedExt
[EXT_EFX
] = AL_TRUE
;
167 This
->ExtAL
.GenEffects(1, &This
->effect
);
168 This
->ExtAL
.Effecti(This
->effect
, AL_EFFECT_TYPE
, AL_EFFECT_REVERB
);
170 This
->ExtAL
.GenAuxiliaryEffectSlots(1, &This
->auxslot
);
172 This
->eax_prop
= EnvironmentDefaults
[EAX_ENVIRONMENT_GENERIC
];
174 wfx
->wFormatTag
= WAVE_FORMAT_PCM
;
176 wfx
->wBitsPerSample
= 8;
177 wfx
->nSamplesPerSec
= 22050;
178 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
179 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
182 This
->stopped
= TRUE
;
183 This
->parent
= parent
;
184 /* Apparently primary buffer size is always 32k,
185 * tested on windows with 192k 24 bits sound @ 6 channels
186 * where it will run out in 60 ms and it isn't pointer aligned
188 This
->buf_size
= 32768;
190 if(!This
->ExtAL
.BufferSubData
&& !This
->ExtAL
.BufferSamplesSOFT
&&
191 !This
->ExtAL
.BufferDataStatic
)
193 ERR("Missing alBufferSubDataSOFT, alBufferSamplesSOFT , and alBufferDataStatic on device '%s', sound playback quality may be degraded\n",
194 alcGetString(parent
->device
, ALC_DEVICE_SPECIFIER
));
195 ERR("Please consider using OpenAL-Soft\n");
198 /* Make sure DS3DListener defaults are applied to OpenAL */
199 listener
= &This
->listen
;
200 listener
->dwSize
= sizeof(*listener
);
201 listener
->vPosition
.x
= 0.0;
202 listener
->vPosition
.y
= 0.0;
203 listener
->vPosition
.z
= 0.0;
204 listener
->vVelocity
.x
= 0.0;
205 listener
->vVelocity
.y
= 0.0;
206 listener
->vVelocity
.z
= 0.0;
207 listener
->vOrientFront
.x
= 0.0;
208 listener
->vOrientFront
.y
= 0.0;
209 listener
->vOrientFront
.z
= 1.0;
210 listener
->vOrientTop
.x
= 0.0;
211 listener
->vOrientTop
.y
= 1.0;
212 listener
->vOrientTop
.z
= 0.0;
213 listener
->flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
214 listener
->flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
215 listener
->flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
216 hr
= IDirectSound3DListener_SetAllParameters(&This
->IDirectSound3DListener_iface
, listener
, DS3D_IMMEDIATE
);
218 ERR("Could not set 3d parameters: %08x\n", hr
);
220 for(nsources
= 0;nsources
< sizeof(srcs
)/sizeof(*srcs
);nsources
++)
222 alGenSources(1, &srcs
[nsources
]);
223 if(alGetError() != AL_NO_ERROR
)
226 alDeleteSources(nsources
, srcs
);
231 This
->max_sources
= nsources
;
232 This
->sizenotifies
= This
->sizebuffers
= This
->sizesources
= nsources
+1;
234 hr
= DSERR_OUTOFMEMORY
;
235 This
->sources
= HeapAlloc(GetProcessHeap(), 0, nsources
*sizeof(*This
->sources
));
236 This
->buffers
= HeapAlloc(GetProcessHeap(), 0, nsources
*sizeof(*This
->buffers
));
237 This
->notifies
= HeapAlloc(GetProcessHeap(), 0, nsources
*sizeof(*This
->notifies
));
238 if(!This
->sources
|| !This
->buffers
|| !This
->notifies
)
245 DS8Primary_Destroy(This
);
249 void DS8Primary_Destroy(DS8Primary
*This
)
251 TRACE("Destroying primary %p\n", This
);
255 timeKillEvent(This
->timer_id
);
256 timeEndPeriod(This
->timer_res
);
257 TRACE("Killed timer\n");
262 /* Calling setALContext is not appropriate here,
263 * since we *have* to unset the context before destroying it
267 EnterCriticalSection(&openal_crst
);
268 old_ctx
= get_context();
269 if(old_ctx
!= This
->ctx
)
270 set_context(This
->ctx
);
274 while(This
->nbuffers
--)
275 DS8Buffer_Destroy(This
->buffers
[This
->nbuffers
]);
278 alDeleteSources(This
->nsources
, This
->sources
);
281 This
->ExtAL
.DeleteEffects(1, &This
->effect
);
283 This
->ExtAL
.DeleteAuxiliaryEffectSlots(1, &This
->auxslot
);
285 HeapFree(GetProcessHeap(), 0, This
->sources
);
286 HeapFree(GetProcessHeap(), 0, This
->notifies
);
287 HeapFree(GetProcessHeap(), 0, This
->buffers
);
289 set_context(old_ctx
);
290 alcDestroyContext(This
->ctx
);
291 LeaveCriticalSection(&openal_crst
);
294 This
->crst
.DebugInfo
->Spare
[0] = 0;
295 DeleteCriticalSection(&This
->crst
);
297 HeapFree(GetProcessHeap(), 0, This
);
300 static inline DS8Primary
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
302 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSoundBuffer_iface
);
305 static HRESULT WINAPI
DS8Primary_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, LPVOID
*ppv
)
307 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
309 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
312 if(IsEqualIID(riid
, &IID_IUnknown
) ||
313 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
314 *ppv
= &This
->IDirectSoundBuffer_iface
;
315 else if(IsEqualIID(riid
, &IID_IDirectSound3DListener
))
317 if((This
->flags
&DSBCAPS_CTRL3D
))
318 *ppv
= &This
->IDirectSound3DListener_iface
;
321 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
325 IUnknown_AddRef((IUnknown
*)*ppv
);
329 return E_NOINTERFACE
;
332 static ULONG WINAPI
DS8Primary_AddRef(IDirectSoundBuffer
*iface
)
334 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
337 ret
= InterlockedIncrement(&This
->ref
);
344 static ULONG WINAPI
DS8Primary_Release(IDirectSoundBuffer
*iface
)
346 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
349 ret
= InterlockedDecrement(&This
->ref
);
354 static HRESULT WINAPI
DS8Primary_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
356 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
358 TRACE("(%p)->(%p)\n", iface
, caps
);
360 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
362 WARN("Invalid DSBCAPS (%p, %u)\n", caps
, caps
? caps
->dwSize
: 0);
363 return DSERR_INVALIDPARAM
;
366 EnterCriticalSection(&This
->crst
);
367 caps
->dwFlags
= This
->flags
;
368 caps
->dwBufferBytes
= This
->buf_size
;
369 caps
->dwUnlockTransferRate
= 0;
370 caps
->dwPlayCpuOverhead
= 0;
371 LeaveCriticalSection(&This
->crst
);
376 static HRESULT WINAPI
DS8Primary_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
378 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
379 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
381 EnterCriticalSection(&This
->crst
);
383 hr
= IDirectSoundBuffer8_GetCurrentPosition(This
->write_emu
, playpos
, curpos
);
384 LeaveCriticalSection(&This
->crst
);
389 static HRESULT WINAPI
DS8Primary_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
391 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
397 WARN("Cannot report format or format size\n");
398 return DSERR_INVALIDPARAM
;
401 EnterCriticalSection(&This
->crst
);
402 size
= sizeof(This
->format
.Format
) + This
->format
.Format
.cbSize
;
408 hr
= DSERR_INVALIDPARAM
;
410 memcpy(wfx
, &This
->format
.Format
, size
);
412 LeaveCriticalSection(&This
->crst
);
417 static HRESULT WINAPI
DS8Primary_GetVolume(IDirectSoundBuffer
*iface
, LONG
*volume
)
419 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
422 TRACE("(%p)->(%p)\n", iface
, volume
);
425 return DSERR_INVALIDPARAM
;
427 EnterCriticalSection(&This
->crst
);
428 if(!(This
->flags
& DSBCAPS_CTRLVOLUME
))
429 hr
= DSERR_CONTROLUNAVAIL
;
435 setALContext(This
->ctx
);
436 alGetListenerf(AL_GAIN
, &gain
);
440 vol
= gain_to_mB(gain
);
441 vol
= max(vol
, DSBVOLUME_MIN
);
442 *volume
= min(vol
, DSBVOLUME_MAX
);
444 LeaveCriticalSection(&This
->crst
);
449 static HRESULT WINAPI
DS8Primary_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
451 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
454 WARN("(%p)->(%p): semi-stub\n", iface
, pan
);
457 return DSERR_INVALIDPARAM
;
459 EnterCriticalSection(&This
->crst
);
461 hr
= IDirectSoundBuffer8_GetPan(This
->write_emu
, pan
);
462 else if(!(This
->flags
& DSBCAPS_CTRLPAN
))
463 hr
= DSERR_CONTROLUNAVAIL
;
466 LeaveCriticalSection(&This
->crst
);
471 static HRESULT WINAPI
DS8Primary_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
473 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
476 WARN("(%p)->(%p): semi-stub\n", iface
, freq
);
479 return DSERR_INVALIDPARAM
;
481 EnterCriticalSection(&This
->crst
);
482 if(!(This
->flags
& DSBCAPS_CTRLFREQUENCY
))
483 hr
= DSERR_CONTROLUNAVAIL
;
485 *freq
= This
->format
.Format
.nSamplesPerSec
;
486 LeaveCriticalSection(&This
->crst
);
491 static HRESULT WINAPI
DS8Primary_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
493 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
495 TRACE("(%p)->(%p)\n", iface
, status
);
498 return DSERR_INVALIDPARAM
;
500 EnterCriticalSection(&This
->crst
);
502 *status
= DSBSTATUS_PLAYING
|DSBSTATUS_LOOPING
;
503 if((This
->flags
&DSBCAPS_LOCDEFER
))
504 *status
|= DSBSTATUS_LOCHARDWARE
;
511 for(i
= 0;i
< This
->nbuffers
;++i
)
513 hr
= IDirectSoundBuffer_GetStatus((IDirectSoundBuffer
*)This
->buffers
[i
], &state
);
514 if(SUCCEEDED(hr
) && (state
&DSBSTATUS_PLAYING
))
517 if(i
== This
->nbuffers
)
519 /* Primary stopped and no buffers playing.. */
524 LeaveCriticalSection(&This
->crst
);
529 static HRESULT WINAPI
DS8Primary_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
531 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
534 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
536 if(!desc
|| desc
->lpwfxFormat
|| desc
->dwBufferBytes
)
538 WARN("Bad DSBDESC for primary buffer\n");
539 return DSERR_INVALIDPARAM
;
541 if((desc
->dwFlags
&DSBCAPS_CTRLFX
) ||
542 (desc
->dwFlags
&DSBCAPS_CTRLPOSITIONNOTIFY
) ||
543 (desc
->dwFlags
&DSBCAPS_LOCSOFTWARE
))
545 WARN("Bad dwFlags %08x\n", desc
->dwFlags
);
546 return DSERR_INVALIDPARAM
;
549 EnterCriticalSection(&This
->crst
);
550 /* Should be 0 if not initialized */
553 hr
= DSERR_ALREADYINITIALIZED
;
557 if(This
->parent
->prio_level
== DSSCL_WRITEPRIMARY
)
559 DSBUFFERDESC emudesc
;
564 ERR("There shouldn't be a write_emu!\n");
565 IDirectSoundBuffer8_Release(This
->write_emu
);
566 This
->write_emu
= NULL
;
569 memset(&emudesc
, 0, sizeof(emudesc
));
570 emudesc
.dwSize
= sizeof(emudesc
);
571 emudesc
.dwFlags
= DSBCAPS_LOCHARDWARE
| (desc
->dwFlags
&DSBCAPS_CTRLPAN
);
572 /* Dont play last incomplete sample */
573 emudesc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
%This
->format
.Format
.nBlockAlign
);
574 emudesc
.lpwfxFormat
= &This
->format
.Format
;
576 hr
= DS8Buffer_Create(&emu
, This
, NULL
);
579 This
->write_emu
= &emu
->IDirectSoundBuffer8_iface
;
580 hr
= IDirectSoundBuffer8_Initialize(This
->write_emu
, ds
, &emudesc
);
583 IDirectSoundBuffer8_Release(This
->write_emu
);
584 This
->write_emu
= NULL
;
590 This
->flags
= desc
->dwFlags
| DSBCAPS_LOCHARDWARE
;
592 LeaveCriticalSection(&This
->crst
);
596 static HRESULT WINAPI
DS8Primary_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
598 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
599 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
601 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, %u)\n", iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
603 EnterCriticalSection(&This
->crst
);
605 hr
= IDirectSoundBuffer8_Lock(This
->write_emu
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
606 LeaveCriticalSection(&This
->crst
);
611 static HRESULT WINAPI
DS8Primary_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD res2
, DWORD flags
)
613 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
616 TRACE("(%p)->(%u, %u, %u)\n", iface
, res1
, res2
, flags
);
618 if(!(flags
& DSBPLAY_LOOPING
))
620 WARN("Flags (%08x) not set to DSBPLAY_LOOPING\n", flags
);
621 return DSERR_INVALIDPARAM
;
624 EnterCriticalSection(&This
->crst
);
627 hr
= IDirectSoundBuffer8_Play(This
->write_emu
, res1
, res2
, flags
);
629 This
->stopped
= FALSE
;
630 LeaveCriticalSection(&This
->crst
);
635 static HRESULT WINAPI
DS8Primary_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
637 WARN("(%p)->(%u)\n", iface
, pos
);
638 return DSERR_INVALIDCALL
;
641 /* Just assume the format is crap, and clean up the damage */
642 static void copy_waveformat(WAVEFORMATEX
*wfx
, const WAVEFORMATEX
*from
)
644 if(from
->wFormatTag
== WAVE_FORMAT_PCM
)
647 if(from
->wBitsPerSample
== 8 ||
648 from
->wBitsPerSample
== 16 ||
649 from
->wBitsPerSample
== 24 ||
650 from
->wBitsPerSample
== 32)
651 wfx
->wBitsPerSample
= from
->wBitsPerSample
;
653 else if(from
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
655 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)wfx
;
656 const WAVEFORMATEXTENSIBLE
*fromx
= (const WAVEFORMATEXTENSIBLE
*)from
;
657 DWORD size
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
659 /* Fail silently.. */
660 if(from
->cbSize
< size
)
662 if(!fromx
->Samples
.wValidBitsPerSample
&&
663 !fromx
->Format
.wBitsPerSample
)
666 if(!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
667 !IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
669 ERR("Unhandled extensible format: %s\n", debugstr_guid(&wfe
->SubFormat
));
673 wfe
->Format
.wBitsPerSample
= from
->wBitsPerSample
;
674 wfe
->Samples
.wValidBitsPerSample
= fromx
->Samples
.wValidBitsPerSample
;
675 if(!wfe
->Samples
.wValidBitsPerSample
)
676 wfe
->Samples
.wValidBitsPerSample
= wfe
->Format
.wBitsPerSample
;
677 wfe
->Format
.cbSize
= size
;
678 wfe
->dwChannelMask
= fromx
->dwChannelMask
;
679 wfe
->SubFormat
= fromx
->SubFormat
;
683 ERR("Unhandled format tag %04x\n", from
->wFormatTag
);
688 wfx
->nChannels
= from
->nChannels
;
689 wfx
->wFormatTag
= from
->wFormatTag
;
690 if(from
->nSamplesPerSec
>= DSBFREQUENCY_MIN
&&
691 from
->nSamplesPerSec
<= DSBFREQUENCY_MAX
)
692 wfx
->nSamplesPerSec
= from
->nSamplesPerSec
;
693 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
694 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
697 static HRESULT WINAPI
DS8Primary_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
699 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
703 TRACE("(%p)->(%p)\n", iface
, wfx
);
707 WARN("Missing format\n");
708 return DSERR_INVALIDPARAM
;
711 EnterCriticalSection(&This
->crst
);
713 if(This
->parent
->prio_level
< DSSCL_PRIORITY
)
715 hr
= DSERR_PRIOLEVELNEEDED
;
719 TRACE("Requested primary format:\n"
720 " FormatTag = %04x\n"
722 " SamplesPerSec = %u\n"
723 " AvgBytesPerSec = %u\n"
725 " BitsPerSample = %u\n",
726 wfx
->wFormatTag
, wfx
->nChannels
,
727 wfx
->nSamplesPerSec
, wfx
->nAvgBytesPerSec
,
728 wfx
->nBlockAlign
, wfx
->wBitsPerSample
);
730 copy_waveformat(&This
->format
.Format
, wfx
);
732 freq
= This
->format
.Format
.nSamplesPerSec
;
733 alcGetIntegerv(This
->parent
->device
, ALC_FREQUENCY
, 1, &freq
);
734 getALCError(This
->parent
->device
);
736 This
->format
.Format
.nSamplesPerSec
= freq
;
737 This
->format
.Format
.nAvgBytesPerSec
= This
->format
.Format
.nBlockAlign
*
738 This
->format
.Format
.nSamplesPerSec
;
745 memset(&desc
, 0, sizeof(desc
));
746 desc
.dwSize
= sizeof(desc
);
747 desc
.dwFlags
= DSBCAPS_LOCHARDWARE
|DSBCAPS_CTRLPAN
;
748 desc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
% This
->format
.Format
.nBlockAlign
);
749 desc
.lpwfxFormat
= &This
->format
.Format
;
751 hr
= DS8Buffer_Create(&buf
, This
, NULL
);
755 hr
= IDirectSoundBuffer8_Initialize(&buf
->IDirectSoundBuffer8_iface
, (IDirectSound
*)&This
->parent
->IDirectSound8_iface
, &desc
);
757 DS8Buffer_Destroy(buf
);
760 IDirectSoundBuffer8_Release(This
->write_emu
);
761 This
->write_emu
= &buf
->IDirectSoundBuffer8_iface
;
766 LeaveCriticalSection(&This
->crst
);
770 static HRESULT WINAPI
DS8Primary_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
772 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
775 TRACE("(%p)->(%d)\n", iface
, vol
);
777 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
779 WARN("Invalid volume (%d)\n", vol
);
780 return DSERR_INVALIDPARAM
;
783 EnterCriticalSection(&This
->crst
);
784 if(!(This
->flags
&DSBCAPS_CTRLVOLUME
))
785 hr
= DSERR_CONTROLUNAVAIL
;
788 setALContext(This
->ctx
);
789 alListenerf(AL_GAIN
, mB_to_gain(vol
));
792 LeaveCriticalSection(&This
->crst
);
797 static HRESULT WINAPI
DS8Primary_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
799 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
802 TRACE("(%p)->(%d)\n", iface
, pan
);
804 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
806 WARN("invalid parameter: pan = %d\n", pan
);
807 return DSERR_INVALIDPARAM
;
810 EnterCriticalSection(&This
->crst
);
811 if(!(This
->flags
&DSBCAPS_CTRLPAN
))
813 WARN("control unavailable\n");
814 hr
= DSERR_CONTROLUNAVAIL
;
816 else if(This
->write_emu
)
817 hr
= IDirectSoundBuffer8_SetPan(This
->write_emu
, pan
);
820 FIXME("Not supported\n");
823 LeaveCriticalSection(&This
->crst
);
828 static HRESULT WINAPI
DS8Primary_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
830 WARN("(%p)->(%u)\n", iface
, freq
);
831 return DSERR_CONTROLUNAVAIL
;
834 static HRESULT WINAPI
DS8Primary_Stop(IDirectSoundBuffer
*iface
)
836 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
839 TRACE("(%p)->()\n", iface
);
841 EnterCriticalSection(&This
->crst
);
843 hr
= IDirectSoundBuffer8_Stop(This
->write_emu
);
845 This
->stopped
= TRUE
;
846 LeaveCriticalSection(&This
->crst
);
851 static HRESULT WINAPI
DS8Primary_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
853 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
854 HRESULT hr
= DSERR_INVALIDCALL
;
856 TRACE("(%p)->(%p, %u, %p, %u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
858 EnterCriticalSection(&This
->crst
);
860 hr
= IDirectSoundBuffer8_Unlock(This
->write_emu
, ptr1
, len1
, ptr2
, len2
);
861 LeaveCriticalSection(&This
->crst
);
866 static HRESULT WINAPI
DS8Primary_Restore(IDirectSoundBuffer
*iface
)
868 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
871 TRACE("(%p)->()\n", iface
);
873 EnterCriticalSection(&This
->crst
);
875 hr
= IDirectSoundBuffer8_Restore(This
->write_emu
);
876 LeaveCriticalSection(&This
->crst
);
881 static const IDirectSoundBufferVtbl DS8Primary_Vtbl
=
883 DS8Primary_QueryInterface
,
887 DS8Primary_GetCurrentPosition
,
888 DS8Primary_GetFormat
,
889 DS8Primary_GetVolume
,
891 DS8Primary_GetFrequency
,
892 DS8Primary_GetStatus
,
893 DS8Primary_Initialize
,
896 DS8Primary_SetCurrentPosition
,
897 DS8Primary_SetFormat
,
898 DS8Primary_SetVolume
,
900 DS8Primary_SetFrequency
,
906 static inline DS8Primary
*impl_from_IDirectSound3DListener(IDirectSound3DListener
*iface
)
908 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSound3DListener_iface
);
911 static HRESULT WINAPI
DS8Primary3D_QueryInterface(IDirectSound3DListener
*iface
, REFIID riid
, void **ppv
)
913 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
914 return IDirectSoundBuffer_QueryInterface((IDirectSoundBuffer
*)This
, riid
, ppv
);
917 static ULONG WINAPI
DS8Primary3D_AddRef(IDirectSound3DListener
*iface
)
919 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
922 ret
= InterlockedIncrement(&This
->ds3d_ref
);
923 TRACE("new refcount %d\n", ret
);
929 /* Considering the primary buffer doesn't get destroyed
930 * it doesn't make sense to destroy ds3d here
932 static ULONG WINAPI
DS8Primary3D_Release(IDirectSound3DListener
*iface
)
934 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
937 ret
= InterlockedDecrement(&This
->ds3d_ref
);
938 TRACE("new refcount %d\n", ret
);
944 static HRESULT WINAPI
DS8Primary3D_GetAllParameters(IDirectSound3DListener
*iface
, DS3DLISTENER
*listener
)
946 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
949 TRACE("(%p)->(%p)\n", iface
, listener
);
951 if(!listener
|| listener
->dwSize
< sizeof(*listener
))
953 WARN("Invalid DS3DLISTENER %p %u\n", listener
, listener
? listener
->dwSize
: 0);
954 return DSERR_INVALIDPARAM
;
957 EnterCriticalSection(&This
->crst
);
958 setALContext(This
->ctx
);
959 IDirectSound3DListener_GetPosition(iface
, &listener
->vPosition
);
960 IDirectSound3DListener_GetVelocity(iface
, &listener
->vVelocity
);
961 IDirectSound3DListener_GetOrientation(iface
, &listener
->vOrientFront
, &listener
->vOrientTop
);
962 IDirectSound3DListener_GetDistanceFactor(iface
, &listener
->flDistanceFactor
);
963 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flRolloffFactor
);
964 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flDopplerFactor
);
966 LeaveCriticalSection(&This
->crst
);
972 static HRESULT WINAPI
DS8Primary3D_GetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE
*distancefactor
)
974 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
976 TRACE("(%p)->(%p)\n", iface
, distancefactor
);
980 WARN("Invalid parameter %p\n", distancefactor
);
981 return DSERR_INVALIDPARAM
;
984 EnterCriticalSection(&This
->crst
);
985 setALContext(This
->ctx
);
987 *distancefactor
= 343.3f
/alGetFloat(AL_SPEED_OF_SOUND
);
991 LeaveCriticalSection(&This
->crst
);
996 static HRESULT WINAPI
DS8Primary3D_GetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE
*dopplerfactor
)
998 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1000 TRACE("(%p)->(%p)\n", iface
, dopplerfactor
);
1004 WARN("Invalid parameter %p\n", dopplerfactor
);
1005 return DSERR_INVALIDPARAM
;
1008 EnterCriticalSection(&This
->crst
);
1009 setALContext(This
->ctx
);
1011 *dopplerfactor
= alGetFloat(AL_DOPPLER_FACTOR
);
1015 LeaveCriticalSection(&This
->crst
);
1020 static HRESULT WINAPI
DS8Primary3D_GetOrientation(IDirectSound3DListener
*iface
, D3DVECTOR
*front
, D3DVECTOR
*top
)
1022 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1025 TRACE("(%p)->(%p, %p)\n", iface
, front
, top
);
1029 WARN("Invalid parameter %p %p\n", front
, top
);
1030 return DSERR_INVALIDPARAM
;
1033 EnterCriticalSection(&This
->crst
);
1034 setALContext(This
->ctx
);
1036 alGetListenerfv(AL_ORIENTATION
, orient
);
1039 front
->x
= orient
[0];
1040 front
->y
= orient
[1];
1041 front
->z
= -orient
[2];
1044 top
->z
= -orient
[5];
1047 LeaveCriticalSection(&This
->crst
);
1052 static HRESULT WINAPI
DS8Primary3D_GetPosition(IDirectSound3DListener
*iface
, D3DVECTOR
*pos
)
1054 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1057 TRACE("(%p)->(%p)\n", iface
, pos
);
1061 WARN("Invalid parameter %p\n", pos
);
1062 return DSERR_INVALIDPARAM
;
1065 EnterCriticalSection(&This
->crst
);
1066 setALContext(This
->ctx
);
1068 alGetListenerfv(AL_POSITION
, alpos
);
1076 LeaveCriticalSection(&This
->crst
);
1081 static HRESULT WINAPI
DS8Primary3D_GetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE
*rollofffactor
)
1083 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1085 TRACE("(%p)->(%p)\n", iface
, rollofffactor
);
1089 WARN("Invalid parameter %p\n", rollofffactor
);
1090 return DSERR_INVALIDPARAM
;
1093 EnterCriticalSection(&This
->crst
);
1094 *rollofffactor
= This
->rollofffactor
;
1095 LeaveCriticalSection(&This
->crst
);
1100 static HRESULT WINAPI
DS8Primary3D_GetVelocity(IDirectSound3DListener
*iface
, D3DVECTOR
*velocity
)
1102 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1105 TRACE("(%p)->(%p)\n", iface
, velocity
);
1109 WARN("Invalid parameter %p\n", velocity
);
1110 return DSERR_INVALIDPARAM
;
1113 EnterCriticalSection(&This
->crst
);
1114 setALContext(This
->ctx
);
1116 alGetListenerfv(AL_VELOCITY
, vel
);
1119 velocity
->x
= vel
[0];
1120 velocity
->y
= vel
[1];
1121 velocity
->z
= -vel
[2];
1124 LeaveCriticalSection(&This
->crst
);
1129 static HRESULT WINAPI
DS8Primary3D_SetAllParameters(IDirectSound3DListener
*iface
, const DS3DLISTENER
*listen
, DWORD apply
)
1131 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1133 TRACE("(%p)->(%p, %u)\n", iface
, listen
, apply
);
1135 if(!listen
|| listen
->dwSize
< sizeof(*listen
))
1137 WARN("Invalid parameter %p %u\n", listen
, listen
? listen
->dwSize
: 0);
1138 return DSERR_INVALIDPARAM
;
1141 if(listen
->flDistanceFactor
> DS3D_MAXDISTANCEFACTOR
||
1142 listen
->flDistanceFactor
< DS3D_MINDISTANCEFACTOR
)
1144 WARN("Invalid distance factor (%f)\n", listen
->flDistanceFactor
);
1145 return DSERR_INVALIDPARAM
;
1148 if(listen
->flDopplerFactor
> DS3D_MAXDOPPLERFACTOR
||
1149 listen
->flDopplerFactor
< DS3D_MINDOPPLERFACTOR
)
1151 WARN("Invalid doppler factor (%f)\n", listen
->flDopplerFactor
);
1152 return DSERR_INVALIDPARAM
;
1155 if(listen
->flRolloffFactor
< DS3D_MINROLLOFFFACTOR
||
1156 listen
->flRolloffFactor
> DS3D_MAXROLLOFFFACTOR
)
1158 WARN("Invalid rolloff factor (%f)\n", listen
->flRolloffFactor
);
1159 return DSERR_INVALIDPARAM
;
1162 EnterCriticalSection(&This
->crst
);
1163 setALContext(This
->ctx
);
1164 IDirectSound3DListener_SetPosition(iface
, listen
->vPosition
.x
, listen
->vPosition
.y
, listen
->vPosition
.z
, apply
);
1165 IDirectSound3DListener_SetVelocity(iface
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, listen
->vVelocity
.z
, apply
);
1166 IDirectSound3DListener_SetOrientation(iface
, listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, listen
->vOrientFront
.z
,
1167 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, listen
->vOrientTop
.z
, apply
);
1168 IDirectSound3DListener_SetDistanceFactor(iface
, listen
->flDistanceFactor
, apply
);
1169 IDirectSound3DListener_SetRolloffFactor(iface
, listen
->flRolloffFactor
, apply
);
1170 IDirectSound3DListener_SetDopplerFactor(iface
, listen
->flDopplerFactor
, apply
);
1172 LeaveCriticalSection(&This
->crst
);
1177 static HRESULT WINAPI
DS8Primary3D_SetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1179 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1181 TRACE("(%p)->(%f, %u)\n", iface
, factor
, apply
);
1183 if(factor
< DS3D_MINDISTANCEFACTOR
||
1184 factor
> DS3D_MAXDISTANCEFACTOR
)
1186 WARN("Invalid parameter %f\n", factor
);
1187 return DSERR_INVALIDPARAM
;
1190 EnterCriticalSection(&This
->crst
);
1191 if(apply
== DS3D_DEFERRED
)
1193 This
->listen
.flDistanceFactor
= factor
;
1194 This
->dirty
.bit
.distancefactor
= 1;
1198 setALContext(This
->ctx
);
1199 alSpeedOfSound(343.3f
/factor
);
1200 if(This
->SupportedExt
[EXT_EFX
])
1201 alListenerf(AL_METERS_PER_UNIT
, factor
);
1205 LeaveCriticalSection(&This
->crst
);
1210 static HRESULT WINAPI
DS8Primary3D_SetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1212 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1214 TRACE("(%p)->(%f, %u)\n", iface
, factor
, apply
);
1216 if(factor
< DS3D_MINDOPPLERFACTOR
||
1217 factor
> DS3D_MAXDOPPLERFACTOR
)
1219 WARN("Invalid parameter %f\n", factor
);
1220 return DSERR_INVALIDPARAM
;
1223 EnterCriticalSection(&This
->crst
);
1224 if(apply
== DS3D_DEFERRED
)
1226 This
->listen
.flDopplerFactor
= factor
;
1227 This
->dirty
.bit
.dopplerfactor
= 1;
1231 setALContext(This
->ctx
);
1232 alDopplerFactor(factor
);
1236 LeaveCriticalSection(&This
->crst
);
1241 static HRESULT WINAPI
DS8Primary3D_SetOrientation(IDirectSound3DListener
*iface
, D3DVALUE xFront
, D3DVALUE yFront
, D3DVALUE zFront
, D3DVALUE xTop
, D3DVALUE yTop
, D3DVALUE zTop
, DWORD apply
)
1243 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1245 TRACE("(%p)->(%f, %f, %f, %f, %f, %f, %u)\n", iface
, xFront
, yFront
, zFront
, xTop
, yTop
, zTop
, apply
);
1247 EnterCriticalSection(&This
->crst
);
1248 if(apply
== DS3D_DEFERRED
)
1250 This
->listen
.vOrientFront
.x
= xFront
;
1251 This
->listen
.vOrientFront
.y
= yFront
;
1252 This
->listen
.vOrientFront
.z
= zFront
;
1253 This
->listen
.vOrientTop
.x
= xTop
;
1254 This
->listen
.vOrientTop
.y
= yTop
;
1255 This
->listen
.vOrientTop
.z
= zTop
;
1256 This
->dirty
.bit
.orientation
= 1;
1260 ALfloat orient
[6] = {
1261 xFront
, yFront
, -zFront
,
1264 setALContext(This
->ctx
);
1265 alListenerfv(AL_ORIENTATION
, orient
);
1269 LeaveCriticalSection(&This
->crst
);
1274 static HRESULT WINAPI
DS8Primary3D_SetPosition(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1276 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1278 TRACE("(%p)->(%f, %f, %f, %u)\n", iface
, x
, y
, z
, apply
);
1280 EnterCriticalSection(&This
->crst
);
1281 if(apply
== DS3D_DEFERRED
)
1283 This
->listen
.vPosition
.x
= x
;
1284 This
->listen
.vPosition
.y
= y
;
1285 This
->listen
.vPosition
.z
= z
;
1286 This
->dirty
.bit
.pos
= 1;
1290 setALContext(This
->ctx
);
1291 alListener3f(AL_POSITION
, x
, y
, -z
);
1295 LeaveCriticalSection(&This
->crst
);
1300 static HRESULT WINAPI
DS8Primary3D_SetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1302 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1304 TRACE("(%p)->(%f, %u)\n", iface
, factor
, apply
);
1306 if(factor
< DS3D_MINROLLOFFFACTOR
||
1307 factor
> DS3D_MAXROLLOFFFACTOR
)
1309 WARN("Invalid parameter %f\n", factor
);
1310 return DSERR_INVALIDPARAM
;
1313 EnterCriticalSection(&This
->crst
);
1314 if(apply
== DS3D_DEFERRED
)
1316 This
->listen
.flRolloffFactor
= factor
;
1317 This
->dirty
.bit
.rollofffactor
= 1;
1323 setALContext(This
->ctx
);
1324 for(i
= 0;i
< This
->nbuffers
;++i
)
1326 if(This
->buffers
[i
]->ds3dmode
!= DS3DMODE_DISABLE
)
1327 alSourcef(This
->buffers
[i
]->source
, AL_ROLLOFF_FACTOR
, factor
);
1332 This
->rollofffactor
= factor
;
1334 LeaveCriticalSection(&This
->crst
);
1339 static HRESULT WINAPI
DS8Primary3D_SetVelocity(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1341 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1343 TRACE("(%p)->(%f, %f, %f, %u)\n", iface
, x
, y
, z
, apply
);
1345 EnterCriticalSection(&This
->crst
);
1346 if(apply
== DS3D_DEFERRED
)
1348 This
->listen
.vVelocity
.x
= x
;
1349 This
->listen
.vVelocity
.y
= y
;
1350 This
->listen
.vVelocity
.z
= z
;
1351 This
->dirty
.bit
.vel
= 1;
1355 setALContext(This
->ctx
);
1356 alListener3f(AL_VELOCITY
, x
, y
, -z
);
1360 LeaveCriticalSection(&This
->crst
);
1365 static HRESULT WINAPI
DS8Primary3D_CommitDeferredSettings(IDirectSound3DListener
*iface
)
1367 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1368 const DS3DLISTENER
*listen
= &This
->listen
;
1371 EnterCriticalSection(&This
->crst
);
1372 setALContext(This
->ctx
);
1373 This
->ExtAL
.DeferUpdates();
1375 if(This
->dirty
.bit
.pos
)
1376 alListener3f(AL_POSITION
, listen
->vPosition
.x
, listen
->vPosition
.y
, -listen
->vPosition
.z
);
1377 if(This
->dirty
.bit
.vel
)
1378 alListener3f(AL_VELOCITY
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, -listen
->vVelocity
.z
);
1379 if(This
->dirty
.bit
.orientation
)
1381 ALfloat orient
[6] = {
1382 listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, -listen
->vOrientFront
.z
,
1383 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, -listen
->vOrientTop
.z
1385 alListenerfv(AL_ORIENTATION
, orient
);
1387 if(This
->dirty
.bit
.distancefactor
)
1389 alSpeedOfSound(343.3f
/listen
->flDistanceFactor
);
1390 if(This
->SupportedExt
[EXT_EFX
])
1391 alListenerf(AL_METERS_PER_UNIT
, listen
->flDistanceFactor
);
1394 if(This
->dirty
.bit
.rollofffactor
)
1396 ALfloat rolloff
= This
->rollofffactor
;
1397 for(i
= 0;i
< This
->nbuffers
;++i
)
1399 DS8Buffer
*buf
= This
->buffers
[i
];
1400 if(buf
->ds3dmode
!= DS3DMODE_DISABLE
)
1401 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
, rolloff
);
1405 if(This
->dirty
.bit
.dopplerfactor
)
1406 alDopplerFactor(listen
->flDopplerFactor
);
1408 if(This
->dirty
.bit
.effect
)
1409 This
->ExtAL
.AuxiliaryEffectSloti(This
->auxslot
, AL_EFFECTSLOT_EFFECT
, This
->effect
);
1411 /* getALError is here for debugging */
1414 TRACE("Dirty flags was: 0x%02x\n", This
->dirty
.flags
);
1415 This
->dirty
.flags
= 0;
1417 for(i
= 0;i
< This
->nbuffers
;++i
)
1419 DS8Buffer
*buf
= This
->buffers
[i
];
1421 if(!buf
->dirty
.flags
)
1424 if(buf
->dirty
.bit
.pos
)
1425 alSource3f(buf
->source
, AL_POSITION
,
1426 buf
->ds3dbuffer
.vPosition
.x
,
1427 buf
->ds3dbuffer
.vPosition
.y
,
1428 -buf
->ds3dbuffer
.vPosition
.z
);
1429 if(buf
->dirty
.bit
.vel
)
1430 alSource3f(buf
->source
, AL_VELOCITY
,
1431 buf
->ds3dbuffer
.vVelocity
.x
,
1432 buf
->ds3dbuffer
.vVelocity
.y
,
1433 -buf
->ds3dbuffer
.vVelocity
.z
);
1434 if(buf
->dirty
.bit
.cone_angles
)
1436 alSourcei(buf
->source
, AL_CONE_INNER_ANGLE
,
1437 buf
->ds3dbuffer
.dwInsideConeAngle
);
1438 alSourcei(buf
->source
, AL_CONE_OUTER_ANGLE
,
1439 buf
->ds3dbuffer
.dwOutsideConeAngle
);
1441 if(buf
->dirty
.bit
.cone_orient
)
1442 alSource3f(buf
->source
, AL_DIRECTION
,
1443 buf
->ds3dbuffer
.vConeOrientation
.x
,
1444 buf
->ds3dbuffer
.vConeOrientation
.y
,
1445 -buf
->ds3dbuffer
.vConeOrientation
.z
);
1446 if(buf
->dirty
.bit
.cone_outsidevolume
)
1447 alSourcef(buf
->source
, AL_CONE_OUTER_GAIN
,
1448 mB_to_gain(buf
->ds3dbuffer
.lConeOutsideVolume
));
1449 if(buf
->dirty
.bit
.min_distance
)
1450 alSourcef(buf
->source
, AL_REFERENCE_DISTANCE
, buf
->ds3dbuffer
.flMinDistance
);
1451 if(buf
->dirty
.bit
.max_distance
)
1452 alSourcef(buf
->source
, AL_MAX_DISTANCE
, buf
->ds3dbuffer
.flMaxDistance
);
1453 if(buf
->dirty
.bit
.mode
)
1455 buf
->ds3dmode
= buf
->ds3dbuffer
.dwMode
;
1456 alSourcei(buf
->source
, AL_SOURCE_RELATIVE
,
1457 (buf
->ds3dmode
!=DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
1458 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
,
1459 (buf
->ds3dmode
==DS3DMODE_DISABLE
) ? 0.0f
: This
->rollofffactor
);
1461 buf
->dirty
.flags
= 0;
1465 This
->ExtAL
.ProcessUpdates();
1467 LeaveCriticalSection(&This
->crst
);
1472 static const IDirectSound3DListenerVtbl DS8Primary3D_Vtbl
=
1474 DS8Primary3D_QueryInterface
,
1475 DS8Primary3D_AddRef
,
1476 DS8Primary3D_Release
,
1477 DS8Primary3D_GetAllParameters
,
1478 DS8Primary3D_GetDistanceFactor
,
1479 DS8Primary3D_GetDopplerFactor
,
1480 DS8Primary3D_GetOrientation
,
1481 DS8Primary3D_GetPosition
,
1482 DS8Primary3D_GetRolloffFactor
,
1483 DS8Primary3D_GetVelocity
,
1484 DS8Primary3D_SetAllParameters
,
1485 DS8Primary3D_SetDistanceFactor
,
1486 DS8Primary3D_SetDopplerFactor
,
1487 DS8Primary3D_SetOrientation
,
1488 DS8Primary3D_SetPosition
,
1489 DS8Primary3D_SetRolloffFactor
,
1490 DS8Primary3D_SetVelocity
,
1491 DS8Primary3D_CommitDeferredSettings
1494 /* NOTE: Although the app handles listener properties through secondary buffers,
1495 * we pass the requests to the primary buffer though a propertyset interface.
1496 * These methods are not exposed to the app. */
1497 static inline DS8Primary
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
1499 return CONTAINING_RECORD(iface
, DS8Primary
, IKsPropertySet_iface
);
1502 static HRESULT WINAPI
DS8PrimaryProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
1504 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1505 return IDirectSoundBuffer_QueryInterface((IDirectSoundBuffer
*)This
, riid
, ppv
);
1508 static ULONG WINAPI
DS8PrimaryProp_AddRef(IKsPropertySet
*iface
)
1510 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1513 ret
= InterlockedIncrement(&This
->prop_ref
);
1514 TRACE("new refcount %d\n", ret
);
1519 static ULONG WINAPI
DS8PrimaryProp_Release(IKsPropertySet
*iface
)
1521 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1524 ret
= InterlockedDecrement(&This
->prop_ref
);
1525 TRACE("new refcount %d\n", ret
);
1530 static HRESULT WINAPI
DS8PrimaryProp_Get(IKsPropertySet
*iface
,
1531 REFGUID guidPropSet
, ULONG dwPropID
,
1532 LPVOID pInstanceData
, ULONG cbInstanceData
,
1533 LPVOID pPropData
, ULONG cbPropData
,
1536 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1537 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1539 TRACE("(%p)->(%s, %u, %p, %u, %p, %u, %p)\n", iface
, debugstr_guid(guidPropSet
),
1540 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
1542 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1544 EnterCriticalSection(&This
->crst
);
1546 if(This
->effect
== 0)
1547 res
= E_PROP_ID_UNSUPPORTED
;
1548 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
)
1550 res
= DSERR_INVALIDPARAM
;
1551 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1555 EAXLISTENERPROPERTIES
*props
;
1556 } data
= { pPropData
};
1558 *data
.props
= This
->eax_prop
;
1559 *pcbReturned
= sizeof(EAXLISTENERPROPERTIES
);
1563 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
)
1565 res
= DSERR_INVALIDPARAM
;
1566 if(cbPropData
>= sizeof(LONG
))
1571 } data
= { pPropData
};
1573 *data
.l
= This
->eax_prop
.lRoom
;
1574 *pcbReturned
= sizeof(LONG
);
1578 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
)
1580 res
= DSERR_INVALIDPARAM
;
1581 if(cbPropData
>= sizeof(LONG
))
1586 } data
= { pPropData
};
1588 *data
.l
= This
->eax_prop
.lRoomHF
;
1589 *pcbReturned
= sizeof(LONG
);
1593 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
)
1595 res
= DSERR_INVALIDPARAM
;
1596 if(cbPropData
>= sizeof(FLOAT
))
1601 } data
= { pPropData
};
1603 *data
.fl
= This
->eax_prop
.flRoomRolloffFactor
;
1604 *pcbReturned
= sizeof(FLOAT
);
1608 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
)
1610 res
= DSERR_INVALIDPARAM
;
1611 if(cbPropData
>= sizeof(DWORD
))
1616 } data
= { pPropData
};
1618 *data
.dw
= This
->eax_prop
.dwEnvironment
;
1619 *pcbReturned
= sizeof(DWORD
);
1623 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
)
1625 res
= DSERR_INVALIDPARAM
;
1626 if(cbPropData
>= sizeof(FLOAT
))
1631 } data
= { pPropData
};
1633 *data
.fl
= This
->eax_prop
.flEnvironmentSize
;
1634 *pcbReturned
= sizeof(FLOAT
);
1638 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
)
1640 res
= DSERR_INVALIDPARAM
;
1641 if(cbPropData
>= sizeof(FLOAT
))
1646 } data
= { pPropData
};
1648 *data
.fl
= This
->eax_prop
.flEnvironmentDiffusion
;
1649 *pcbReturned
= sizeof(FLOAT
);
1653 else if(dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
)
1655 res
= DSERR_INVALIDPARAM
;
1656 if(cbPropData
>= sizeof(FLOAT
))
1661 } data
= { pPropData
};
1663 *data
.fl
= This
->eax_prop
.flAirAbsorptionHF
;
1664 *pcbReturned
= sizeof(FLOAT
);
1668 else if(dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
1670 res
= DSERR_INVALIDPARAM
;
1671 if(cbPropData
>= sizeof(DWORD
))
1676 } data
= { pPropData
};
1678 *data
.dw
= This
->eax_prop
.dwFlags
;
1679 *pcbReturned
= sizeof(DWORD
);
1684 FIXME("Unhandled propid: 0x%08x\n", dwPropID
);
1686 LeaveCriticalSection(&This
->crst
);
1689 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
1694 static HRESULT WINAPI
DS8PrimaryProp_Set(IKsPropertySet
*iface
,
1695 REFGUID guidPropSet
, ULONG dwPropID
,
1696 LPVOID pInstanceData
, ULONG cbInstanceData
,
1697 LPVOID pPropData
, ULONG cbPropData
)
1699 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1700 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1702 TRACE("(%p)->(%s, %u, %p, %u, %p, %u)\n", iface
, debugstr_guid(guidPropSet
),
1703 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
1705 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1707 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
1708 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
1710 EnterCriticalSection(&This
->crst
);
1711 setALContext(This
->ctx
);
1713 if(This
->effect
== 0)
1714 res
= E_PROP_ID_UNSUPPORTED
;
1715 else if(propid
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
)
1718 res
= DSERR_INVALIDPARAM
;
1719 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1723 const EAXLISTENERPROPERTIES
*props
;
1724 } data
= { pPropData
};
1726 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
1727 This
->eax_prop
= *data
.props
;
1728 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DENSITY
,
1729 (data
.props
->flEnvironmentSize
< 2.0f
) ?
1730 (data
.props
->flEnvironmentSize
- 1.0f
) : 1.0f
);
1731 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1732 data
.props
->flEnvironmentDiffusion
);
1734 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAIN
,
1735 mB_to_gain(data
.props
->lRoom
));
1736 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAINHF
,
1737 mB_to_gain(data
.props
->lRoomHF
));
1739 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1740 data
.props
->flRoomRolloffFactor
);
1742 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DECAY_TIME
,
1743 data
.props
->flDecayTime
);
1744 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DECAY_HFRATIO
,
1745 data
.props
->flDecayHFRatio
);
1747 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_REFLECTIONS_GAIN
,
1748 mB_to_gain(data
.props
->lReflections
));
1749 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_REFLECTIONS_DELAY
,
1750 data
.props
->flReflectionsDelay
);
1752 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_LATE_REVERB_GAIN
,
1753 mB_to_gain(data
.props
->lReverb
));
1754 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_LATE_REVERB_DELAY
,
1755 data
.props
->flReverbDelay
);
1757 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1758 mB_to_gain(data
.props
->flAirAbsorptionHF
));
1760 This
->ExtAL
.Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
1761 (data
.props
->dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
1762 AL_TRUE
: AL_FALSE
);
1766 This
->dirty
.bit
.effect
= 1;
1770 else if(propid
== DSPROPERTY_EAXLISTENER_ROOM
)
1772 res
= DSERR_INVALIDPARAM
;
1773 if(cbPropData
>= sizeof(LONG
))
1778 } data
= { pPropData
};
1780 This
->eax_prop
.lRoom
= *data
.l
;
1781 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAIN
,
1782 mB_to_gain(This
->eax_prop
.lRoom
));
1785 This
->dirty
.bit
.effect
= 1;
1789 else if(propid
== DSPROPERTY_EAXLISTENER_ROOMHF
)
1791 res
= DSERR_INVALIDPARAM
;
1792 if(cbPropData
>= sizeof(LONG
))
1797 } data
= { pPropData
};
1799 This
->eax_prop
.lRoomHF
= *data
.l
;
1800 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAINHF
,
1801 mB_to_gain(This
->eax_prop
.lRoomHF
));
1804 This
->dirty
.bit
.effect
= 1;
1808 else if(propid
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
)
1810 res
= DSERR_INVALIDPARAM
;
1811 if(cbPropData
>= sizeof(FLOAT
))
1816 } data
= { pPropData
};
1818 This
->eax_prop
.flRoomRolloffFactor
= *data
.fl
;
1819 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1820 This
->eax_prop
.flRoomRolloffFactor
);
1823 This
->dirty
.bit
.effect
= 1;
1827 else if(propid
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
)
1829 res
= DSERR_INVALIDPARAM
;
1830 if(cbPropData
>= sizeof(DWORD
))
1835 } data
= { pPropData
};
1837 if(*data
.dw
< EAX_ENVIRONMENT_COUNT
)
1839 /* Get the environment index's default and pass it down to
1841 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1842 pPropData
= (void*)&EnvironmentDefaults
[*data
.dw
];
1843 cbPropData
= sizeof(EnvironmentDefaults
[*data
.dw
]);
1848 else if(propid
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
)
1850 res
= DSERR_INVALIDPARAM
;
1851 if(cbPropData
>= sizeof(FLOAT
))
1856 } data
= { pPropData
};
1858 if(*data
.fl
>= 1.0f
&& *data
.fl
<= 100.0f
)
1860 double scale
= (*data
.fl
)/This
->eax_prop
.flEnvironmentSize
;
1862 This
->eax_prop
.flEnvironmentSize
= *data
.fl
;
1864 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYTIMESCALE
))
1866 This
->eax_prop
.flDecayTime
*= scale
;
1867 This
->eax_prop
.flDecayTime
= clampF(This
->eax_prop
.flDecayTime
, 0.1f
, 20.0f
);
1869 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSSCALE
))
1871 This
->eax_prop
.lReflections
+= gain_to_mB(1.0/scale
);
1872 This
->eax_prop
.lReflections
= clampI(This
->eax_prop
.lReflections
, -10000, 1000);
1874 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE
))
1876 This
->eax_prop
.flReflectionsDelay
*= scale
;
1877 This
->eax_prop
.flReflectionsDelay
= clampF(This
->eax_prop
.flReflectionsDelay
, 0.0f
, 0.3f
);
1879 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBSCALE
))
1881 This
->eax_prop
.lReverb
+= gain_to_mB(1.0/scale
);
1882 This
->eax_prop
.lReverb
= clampI(This
->eax_prop
.lReverb
, -10000, 2000);
1884 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBDELAYSCALE
))
1886 This
->eax_prop
.flReverbDelay
*= scale
;
1887 This
->eax_prop
.flReverbDelay
= clampF(This
->eax_prop
.flReverbDelay
, 0.0f
, 0.1f
);
1890 /* Pass the updated environment properties down to ALLPARAMETERS */
1891 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1892 pPropData
= (void*)&This
->eax_prop
;
1893 cbPropData
= sizeof(This
->eax_prop
);
1898 else if(propid
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
)
1900 res
= DSERR_INVALIDPARAM
;
1901 if(cbPropData
>= sizeof(FLOAT
))
1906 } data
= { pPropData
};
1908 This
->eax_prop
.flEnvironmentDiffusion
= *data
.fl
;
1909 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1910 This
->eax_prop
.flEnvironmentDiffusion
);
1913 This
->dirty
.bit
.effect
= 1;
1917 else if(propid
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
)
1919 res
= DSERR_INVALIDPARAM
;
1920 if(cbPropData
>= sizeof(FLOAT
))
1925 } data
= { pPropData
};
1927 This
->eax_prop
.flAirAbsorptionHF
= *data
.fl
;
1928 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1929 mB_to_gain(This
->eax_prop
.flAirAbsorptionHF
));
1932 This
->dirty
.bit
.effect
= 1;
1936 else if(propid
== DSPROPERTY_EAXLISTENER_FLAGS
)
1938 res
= DSERR_INVALIDPARAM
;
1939 if(cbPropData
>= sizeof(DWORD
))
1944 } data
= { pPropData
};
1946 This
->eax_prop
.dwFlags
= *data
.dw
;
1947 This
->ExtAL
.Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
1948 (This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
1949 AL_TRUE
: AL_FALSE
);
1952 This
->dirty
.bit
.effect
= 1;
1956 else if(propid
!= 0)
1957 FIXME("Unhandled propid: 0x%08x\n", propid
);
1959 if(res
== DS_OK
&& immediate
)
1960 IDirectSound3DListener_CommitDeferredSettings(&This
->IDirectSound3DListener_iface
);
1963 LeaveCriticalSection(&This
->crst
);
1966 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
1971 static HRESULT WINAPI
DS8PrimaryProp_QuerySupport(IKsPropertySet
*iface
,
1972 REFGUID guidPropSet
, ULONG dwPropID
,
1973 PULONG pTypeSupport
)
1975 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1976 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1978 TRACE("(%p)->(%s, %u, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
1980 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1982 EnterCriticalSection(&This
->crst
);
1984 if(This
->effect
== 0)
1985 res
= E_PROP_ID_UNSUPPORTED
;
1986 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
||
1987 dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
||
1988 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
||
1989 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
||
1990 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
||
1991 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
||
1992 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
||
1993 dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
||
1994 dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
1996 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
|KSPROPERTY_SUPPORT_SET
;
2000 FIXME("Unhandled propid: 0x%08x\n", dwPropID
);
2002 LeaveCriticalSection(&This
->crst
);
2005 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2010 static const IKsPropertySetVtbl DS8PrimaryProp_Vtbl
=
2012 DS8PrimaryProp_QueryInterface
,
2013 DS8PrimaryProp_AddRef
,
2014 DS8PrimaryProp_Release
,
2017 DS8PrimaryProp_QuerySupport