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()); }
77 static void trigger_notifies(DS8Buffer
*buf
, DWORD lastpos
, DWORD curpos
)
80 for(i
= 0; i
< buf
->nnotify
; ++i
)
82 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
83 HANDLE event
= not->hEventNotify
;
84 DWORD ofs
= not->dwOffset
;
86 if(ofs
== (DWORD
)DSBPN_OFFSETSTOP
)
92 if(ofs
< curpos
|| ofs
>= lastpos
)
98 if(ofs
>= lastpos
&& ofs
< curpos
)
103 static DWORD CALLBACK
ThreadProc(void *dwUser
)
105 DS8Primary
*prim
= (DS8Primary
*)dwUser
;
109 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
);
111 while(GetMessageA(&msg
, NULL
, 0, 0))
113 if(msg
.message
!= WM_USER
)
116 EnterCriticalSection(&prim
->crst
);
117 setALContext(prim
->ctx
);
119 /* OpenAL doesn't support our lovely buffer extensions
120 * so just make sure enough buffers are queued
122 if(!prim
->ExtAL
.BufferSamplesSOFT
&& !prim
->ExtAL
.BufferSubData
&&
123 !prim
->ExtAL
.BufferDataStatic
)
125 for(i
= 0;i
< prim
->nbuffers
;++i
)
127 DS8Buffer
*buf
= prim
->buffers
[i
];
128 ALint done
= 0, queued
= QBUFFERS
, state
= AL_PLAYING
;
131 if(buf
->buffer
->numsegs
== 1 || !buf
->isplaying
)
134 alGetSourcei(buf
->source
, AL_SOURCE_STATE
, &state
);
135 alGetSourcei(buf
->source
, AL_BUFFERS_QUEUED
, &queued
);
136 alGetSourcei(buf
->source
, AL_BUFFERS_PROCESSED
, &done
);
140 alSourceUnqueueBuffers(buf
->source
, 1, &which
);
141 while(queued
< QBUFFERS
)
143 which
= buf
->buffer
->buffers
[buf
->curidx
];
144 ofs
= buf
->curidx
*buf
->buffer
->segsize
;
145 if(buf
->curidx
< buf
->buffer
->numsegs
-1)
146 alBufferData(which
, buf
->buffer
->buf_format
,
147 buf
->buffer
->data
+ ofs
, buf
->buffer
->segsize
,
148 buf
->buffer
->format
.Format
.nSamplesPerSec
);
150 alBufferData(which
, buf
->buffer
->buf_format
,
151 buf
->buffer
->data
+ ofs
, buf
->buffer
->lastsegsize
,
152 buf
->buffer
->format
.Format
.nSamplesPerSec
);
154 alSourceQueueBuffers(buf
->source
, 1, &which
);
155 buf
->curidx
= (buf
->curidx
+1)%buf
->buffer
->numsegs
;
158 if(!buf
->curidx
&& !buf
->islooping
)
160 buf
->isplaying
= FALSE
;
164 if(state
!= AL_PLAYING
)
168 IDirectSoundBuffer8_Stop(&buf
->IDirectSoundBuffer8_iface
);
171 alSourcePlay(buf
->source
);
177 for(i
= 0;i
< prim
->nnotifies
;)
179 DS8Buffer
*buf
= prim
->notifies
[i
];
180 IDirectSoundBuffer8
*dsb
= &buf
->IDirectSoundBuffer8_iface
;
181 DWORD status
, curpos
;
184 hr
= IDirectSoundBuffer8_GetStatus(dsb
, &status
);
187 if(!(status
&DSBSTATUS_PLAYING
))
189 /* Stop will remove this buffer from list,
190 * and put another at the current position
193 IDirectSoundBuffer8_Stop(dsb
);
196 hr
= IDirectSoundBuffer8_GetCurrentPosition(dsb
, &curpos
, NULL
);
197 if(SUCCEEDED(hr
) && buf
->lastpos
!= curpos
)
199 trigger_notifies(buf
, buf
->lastpos
, curpos
);
200 buf
->lastpos
= curpos
;
206 LeaveCriticalSection(&prim
->crst
);
212 HRESULT
DS8Primary_Create(DS8Primary
**ppv
, DS8Impl
*parent
)
214 HRESULT hr
= DSERR_OUTOFMEMORY
;
215 DS8Primary
*This
= NULL
;
216 DS3DLISTENER
*listener
;
222 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
225 This
->IDirectSoundBuffer_iface
.lpVtbl
= (IDirectSoundBufferVtbl
*)&DS8Primary_Vtbl
;
226 This
->IDirectSound3DListener_iface
.lpVtbl
= (IDirectSound3DListenerVtbl
*)&DS8Primary3D_Vtbl
;
227 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8PrimaryProp_Vtbl
;
229 InitializeCriticalSection(&This
->crst
);
230 This
->crst
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DS8Primary.crst");
232 /* Allocate enough for a WAVEFORMATEXTENSIBLE */
233 wfx
= &This
->format
.Format
;
236 This
->ctx
= alcCreateContext(parent
->device
, NULL
);
239 ALCenum err
= alcGetError(parent
->device
);
240 ERR("Could not create context (0x%x)!\n", err
);
244 setALContext(This
->ctx
);
245 if(alIsExtensionPresent("AL_EXT_FLOAT32"))
247 TRACE("Found AL_EXT_FLOAT32\n");
248 This
->SupportedExt
[EXT_FLOAT32
] = AL_TRUE
;
250 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
252 TRACE("Found AL_EXT_MCFORMATS\n");
253 This
->SupportedExt
[EXT_MCFORMATS
] = AL_TRUE
;
255 if(alIsExtensionPresent("AL_EXT_STATIC_BUFFER"))
257 TRACE("Found AL_EXT_STATIC_BUFFER\n");
258 This
->ExtAL
.BufferDataStatic
= alGetProcAddress("alBufferDataStatic");
259 This
->SupportedExt
[EXT_STATIC_BUFFER
] = AL_TRUE
;
261 if(alIsExtensionPresent("AL_SOFTX_buffer_samples"))
263 TRACE("Found AL_SOFTX_buffer_samples\n");
264 This
->ExtAL
.BufferSamplesSOFT
= alGetProcAddress("alBufferSamplesSOFT");
265 This
->ExtAL
.BufferSubSamplesSOFT
= alGetProcAddress("alBufferSubSamplesSOFT");
266 This
->ExtAL
.GetBufferSamplesSOFT
= alGetProcAddress("alGetBufferSamplesSOFT");
267 This
->ExtAL
.IsBufferFormatSupportedSOFT
= alGetProcAddress("alIsBufferFormatSupportedSOFT");
268 This
->SupportedExt
[SOFT_BUFFER_SAMPLES
] = AL_TRUE
;
270 if(alIsExtensionPresent("AL_SOFT_buffer_sub_data"))
272 TRACE("Found AL_SOFT_buffer_sub_data\n");
273 This
->ExtAL
.BufferSubData
= alGetProcAddress("alBufferSubDataSOFT");
274 This
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] = AL_TRUE
;
276 if(alIsExtensionPresent("AL_SOFTX_deferred_updates"))
278 TRACE("Found AL_SOFTX_deferred_updates\n");
279 This
->ExtAL
.DeferUpdates
= alGetProcAddress("alDeferUpdatesSOFT");
280 This
->ExtAL
.ProcessUpdates
= alGetProcAddress("alProcessUpdatesSOFT");
281 This
->SupportedExt
[SOFT_DEFERRED_UPDATES
] = AL_TRUE
;
285 This
->ExtAL
.DeferUpdates
= wrap_DeferUpdates
;
286 This
->ExtAL
.ProcessUpdates
= wrap_ProcessUpdates
;
289 if(alcIsExtensionPresent(parent
->device
, "ALC_EXT_EFX"))
291 #define LOAD_FUNC(x) (This->ExtAL.x = alGetProcAddress("al"#x))
292 LOAD_FUNC(GenEffects
);
293 LOAD_FUNC(DeleteEffects
);
297 LOAD_FUNC(GenAuxiliaryEffectSlots
);
298 LOAD_FUNC(DeleteAuxiliaryEffectSlots
);
299 LOAD_FUNC(AuxiliaryEffectSloti
);
301 This
->SupportedExt
[EXT_EFX
] = AL_TRUE
;
303 This
->ExtAL
.GenEffects(1, &This
->effect
);
304 This
->ExtAL
.Effecti(This
->effect
, AL_EFFECT_TYPE
, AL_EFFECT_REVERB
);
306 This
->ExtAL
.GenAuxiliaryEffectSlots(1, &This
->auxslot
);
308 This
->eax_prop
= EnvironmentDefaults
[EAX_ENVIRONMENT_GENERIC
];
310 wfx
->wFormatTag
= WAVE_FORMAT_PCM
;
312 wfx
->wBitsPerSample
= 8;
313 wfx
->nSamplesPerSec
= 22050;
314 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
315 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
318 This
->stopped
= TRUE
;
319 This
->parent
= parent
;
320 /* Apparently primary buffer size is always 32k,
321 * tested on windows with 192k 24 bits sound @ 6 channels
322 * where it will run out in 60 ms and it isn't pointer aligned
324 This
->buf_size
= 32768;
326 if(!This
->ExtAL
.BufferSubData
&& !This
->ExtAL
.BufferSamplesSOFT
&&
327 !This
->ExtAL
.BufferDataStatic
)
329 ERR("Missing alBufferSubDataSOFT, alBufferSamplesSOFT , and alBufferDataStatic on device '%s', sound playback quality may be degraded\n",
330 alcGetString(parent
->device
, ALC_DEVICE_SPECIFIER
));
331 ERR("Please consider using OpenAL-Soft\n");
334 /* Make sure DS3DListener defaults are applied to OpenAL */
335 listener
= &This
->listen
;
336 listener
->dwSize
= sizeof(*listener
);
337 listener
->vPosition
.x
= 0.0;
338 listener
->vPosition
.y
= 0.0;
339 listener
->vPosition
.z
= 0.0;
340 listener
->vVelocity
.x
= 0.0;
341 listener
->vVelocity
.y
= 0.0;
342 listener
->vVelocity
.z
= 0.0;
343 listener
->vOrientFront
.x
= 0.0;
344 listener
->vOrientFront
.y
= 0.0;
345 listener
->vOrientFront
.z
= 1.0;
346 listener
->vOrientTop
.x
= 0.0;
347 listener
->vOrientTop
.y
= 1.0;
348 listener
->vOrientTop
.z
= 0.0;
349 listener
->flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
350 listener
->flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
351 listener
->flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
352 hr
= IDirectSound3DListener_SetAllParameters(&This
->IDirectSound3DListener_iface
, listener
, DS3D_IMMEDIATE
);
354 ERR("Could not set 3d parameters: %08x\n", hr
);
356 for(nsources
= 0;nsources
< sizeof(srcs
)/sizeof(*srcs
);nsources
++)
358 alGenSources(1, &srcs
[nsources
]);
359 if(alGetError() != AL_NO_ERROR
)
362 alDeleteSources(nsources
, srcs
);
367 This
->max_sources
= nsources
;
368 This
->sizenotifies
= This
->sizebuffers
= This
->sizesources
= nsources
+1;
370 hr
= DSERR_OUTOFMEMORY
;
371 This
->sources
= HeapAlloc(GetProcessHeap(), 0, nsources
*sizeof(*This
->sources
));
372 This
->buffers
= HeapAlloc(GetProcessHeap(), 0, nsources
*sizeof(*This
->buffers
));
373 This
->notifies
= HeapAlloc(GetProcessHeap(), 0, nsources
*sizeof(*This
->notifies
));
374 if(!This
->sources
|| !This
->buffers
|| !This
->notifies
)
377 This
->thread_hdl
= CreateThread(NULL
, 0, ThreadProc
, This
, 0, &This
->thread_id
);
378 if(This
->thread_hdl
== NULL
)
385 DS8Primary_Destroy(This
);
389 void DS8Primary_Destroy(DS8Primary
*This
)
391 TRACE("Destroying primary %p\n", This
);
395 timeKillEvent(This
->timer_id
);
396 timeEndPeriod(This
->timer_res
);
397 TRACE("Killed timer\n");
401 PostThreadMessageA(This
->thread_id
, WM_QUIT
, 0, 0);
402 WaitForSingleObject(This
->thread_hdl
, 1000);
403 CloseHandle(This
->thread_hdl
);
408 /* Calling setALContext is not appropriate here,
409 * since we *have* to unset the context before destroying it
413 EnterCriticalSection(&openal_crst
);
414 old_ctx
= get_context();
415 if(old_ctx
!= This
->ctx
)
416 set_context(This
->ctx
);
420 while(This
->nbuffers
--)
421 DS8Buffer_Destroy(This
->buffers
[This
->nbuffers
]);
424 alDeleteSources(This
->nsources
, This
->sources
);
427 This
->ExtAL
.DeleteEffects(1, &This
->effect
);
429 This
->ExtAL
.DeleteAuxiliaryEffectSlots(1, &This
->auxslot
);
431 HeapFree(GetProcessHeap(), 0, This
->sources
);
432 HeapFree(GetProcessHeap(), 0, This
->notifies
);
433 HeapFree(GetProcessHeap(), 0, This
->buffers
);
435 set_context(old_ctx
);
436 alcDestroyContext(This
->ctx
);
437 LeaveCriticalSection(&openal_crst
);
440 This
->crst
.DebugInfo
->Spare
[0] = 0;
441 DeleteCriticalSection(&This
->crst
);
443 HeapFree(GetProcessHeap(), 0, This
);
446 static inline DS8Primary
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
448 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSoundBuffer_iface
);
451 static HRESULT WINAPI
DS8Primary_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, LPVOID
*ppv
)
453 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
455 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
458 if(IsEqualIID(riid
, &IID_IUnknown
) ||
459 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
460 *ppv
= &This
->IDirectSoundBuffer_iface
;
461 else if(IsEqualIID(riid
, &IID_IDirectSound3DListener
))
463 if((This
->flags
&DSBCAPS_CTRL3D
))
464 *ppv
= &This
->IDirectSound3DListener_iface
;
467 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
471 IUnknown_AddRef((IUnknown
*)*ppv
);
475 return E_NOINTERFACE
;
478 static ULONG WINAPI
DS8Primary_AddRef(IDirectSoundBuffer
*iface
)
480 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
483 ret
= InterlockedIncrement(&This
->ref
);
490 static ULONG WINAPI
DS8Primary_Release(IDirectSoundBuffer
*iface
)
492 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
495 ret
= InterlockedDecrement(&This
->ref
);
500 static HRESULT WINAPI
DS8Primary_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
502 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
504 TRACE("(%p)->(%p)\n", iface
, caps
);
506 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
508 WARN("Invalid DSBCAPS (%p, %u)\n", caps
, caps
? caps
->dwSize
: 0);
509 return DSERR_INVALIDPARAM
;
512 EnterCriticalSection(&This
->crst
);
513 caps
->dwFlags
= This
->flags
;
514 caps
->dwBufferBytes
= This
->buf_size
;
515 caps
->dwUnlockTransferRate
= 0;
516 caps
->dwPlayCpuOverhead
= 0;
517 LeaveCriticalSection(&This
->crst
);
522 static HRESULT WINAPI
DS8Primary_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
524 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
525 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
527 EnterCriticalSection(&This
->crst
);
529 hr
= IDirectSoundBuffer8_GetCurrentPosition(This
->write_emu
, playpos
, curpos
);
530 LeaveCriticalSection(&This
->crst
);
535 static HRESULT WINAPI
DS8Primary_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
537 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
543 WARN("Cannot report format or format size\n");
544 return DSERR_INVALIDPARAM
;
547 EnterCriticalSection(&This
->crst
);
548 size
= sizeof(This
->format
.Format
) + This
->format
.Format
.cbSize
;
554 hr
= DSERR_INVALIDPARAM
;
556 memcpy(wfx
, &This
->format
.Format
, size
);
558 LeaveCriticalSection(&This
->crst
);
563 static HRESULT WINAPI
DS8Primary_GetVolume(IDirectSoundBuffer
*iface
, LONG
*volume
)
565 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
568 TRACE("(%p)->(%p)\n", iface
, volume
);
571 return DSERR_INVALIDPARAM
;
573 EnterCriticalSection(&This
->crst
);
574 if(!(This
->flags
& DSBCAPS_CTRLVOLUME
))
575 hr
= DSERR_CONTROLUNAVAIL
;
581 setALContext(This
->ctx
);
582 alGetListenerf(AL_GAIN
, &gain
);
586 vol
= gain_to_mB(gain
);
587 vol
= max(vol
, DSBVOLUME_MIN
);
588 *volume
= min(vol
, DSBVOLUME_MAX
);
590 LeaveCriticalSection(&This
->crst
);
595 static HRESULT WINAPI
DS8Primary_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
597 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
600 WARN("(%p)->(%p): semi-stub\n", iface
, pan
);
603 return DSERR_INVALIDPARAM
;
605 EnterCriticalSection(&This
->crst
);
607 hr
= IDirectSoundBuffer8_GetPan(This
->write_emu
, pan
);
608 else if(!(This
->flags
& DSBCAPS_CTRLPAN
))
609 hr
= DSERR_CONTROLUNAVAIL
;
612 LeaveCriticalSection(&This
->crst
);
617 static HRESULT WINAPI
DS8Primary_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
619 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
622 WARN("(%p)->(%p): semi-stub\n", iface
, freq
);
625 return DSERR_INVALIDPARAM
;
627 EnterCriticalSection(&This
->crst
);
628 if(!(This
->flags
& DSBCAPS_CTRLFREQUENCY
))
629 hr
= DSERR_CONTROLUNAVAIL
;
631 *freq
= This
->format
.Format
.nSamplesPerSec
;
632 LeaveCriticalSection(&This
->crst
);
637 static HRESULT WINAPI
DS8Primary_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
639 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
641 TRACE("(%p)->(%p)\n", iface
, status
);
644 return DSERR_INVALIDPARAM
;
646 EnterCriticalSection(&This
->crst
);
648 *status
= DSBSTATUS_PLAYING
|DSBSTATUS_LOOPING
;
649 if((This
->flags
&DSBCAPS_LOCDEFER
))
650 *status
|= DSBSTATUS_LOCHARDWARE
;
657 for(i
= 0;i
< This
->nbuffers
;++i
)
659 hr
= IDirectSoundBuffer_GetStatus((IDirectSoundBuffer
*)This
->buffers
[i
], &state
);
660 if(SUCCEEDED(hr
) && (state
&DSBSTATUS_PLAYING
))
663 if(i
== This
->nbuffers
)
665 /* Primary stopped and no buffers playing.. */
670 LeaveCriticalSection(&This
->crst
);
675 static HRESULT WINAPI
DS8Primary_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
677 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
680 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
682 if(!desc
|| desc
->lpwfxFormat
|| desc
->dwBufferBytes
)
684 WARN("Bad DSBDESC for primary buffer\n");
685 return DSERR_INVALIDPARAM
;
687 if((desc
->dwFlags
&DSBCAPS_CTRLFX
) ||
688 (desc
->dwFlags
&DSBCAPS_CTRLPOSITIONNOTIFY
) ||
689 (desc
->dwFlags
&DSBCAPS_LOCSOFTWARE
))
691 WARN("Bad dwFlags %08x\n", desc
->dwFlags
);
692 return DSERR_INVALIDPARAM
;
695 EnterCriticalSection(&This
->crst
);
696 /* Should be 0 if not initialized */
699 hr
= DSERR_ALREADYINITIALIZED
;
703 if(This
->parent
->prio_level
== DSSCL_WRITEPRIMARY
)
705 DSBUFFERDESC emudesc
;
710 ERR("There shouldn't be a write_emu!\n");
711 IDirectSoundBuffer8_Release(This
->write_emu
);
712 This
->write_emu
= NULL
;
715 memset(&emudesc
, 0, sizeof(emudesc
));
716 emudesc
.dwSize
= sizeof(emudesc
);
717 emudesc
.dwFlags
= DSBCAPS_LOCHARDWARE
| (desc
->dwFlags
&DSBCAPS_CTRLPAN
);
718 /* Dont play last incomplete sample */
719 emudesc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
%This
->format
.Format
.nBlockAlign
);
720 emudesc
.lpwfxFormat
= &This
->format
.Format
;
722 hr
= DS8Buffer_Create(&emu
, This
, NULL
);
725 This
->write_emu
= &emu
->IDirectSoundBuffer8_iface
;
726 hr
= IDirectSoundBuffer8_Initialize(This
->write_emu
, ds
, &emudesc
);
729 IDirectSoundBuffer8_Release(This
->write_emu
);
730 This
->write_emu
= NULL
;
736 This
->flags
= desc
->dwFlags
| DSBCAPS_LOCHARDWARE
;
738 LeaveCriticalSection(&This
->crst
);
742 static HRESULT WINAPI
DS8Primary_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
744 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
745 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
747 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, %u)\n", iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
749 EnterCriticalSection(&This
->crst
);
751 hr
= IDirectSoundBuffer8_Lock(This
->write_emu
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
752 LeaveCriticalSection(&This
->crst
);
757 static HRESULT WINAPI
DS8Primary_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD res2
, DWORD flags
)
759 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
762 TRACE("(%p)->(%u, %u, %u)\n", iface
, res1
, res2
, flags
);
764 if(!(flags
& DSBPLAY_LOOPING
))
766 WARN("Flags (%08x) not set to DSBPLAY_LOOPING\n", flags
);
767 return DSERR_INVALIDPARAM
;
770 EnterCriticalSection(&This
->crst
);
773 hr
= IDirectSoundBuffer8_Play(This
->write_emu
, res1
, res2
, flags
);
775 This
->stopped
= FALSE
;
776 LeaveCriticalSection(&This
->crst
);
781 static HRESULT WINAPI
DS8Primary_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
783 WARN("(%p)->(%u)\n", iface
, pos
);
784 return DSERR_INVALIDCALL
;
787 /* Just assume the format is crap, and clean up the damage */
788 static void copy_waveformat(WAVEFORMATEX
*wfx
, const WAVEFORMATEX
*from
)
790 if(from
->wFormatTag
== WAVE_FORMAT_PCM
)
793 if(from
->wBitsPerSample
== 8 ||
794 from
->wBitsPerSample
== 16 ||
795 from
->wBitsPerSample
== 24 ||
796 from
->wBitsPerSample
== 32)
797 wfx
->wBitsPerSample
= from
->wBitsPerSample
;
799 else if(from
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
801 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)wfx
;
802 const WAVEFORMATEXTENSIBLE
*fromx
= (const WAVEFORMATEXTENSIBLE
*)from
;
803 DWORD size
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
805 /* Fail silently.. */
806 if(from
->cbSize
< size
)
808 if(!fromx
->Samples
.wValidBitsPerSample
&&
809 !fromx
->Format
.wBitsPerSample
)
812 if(!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
813 !IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
815 ERR("Unhandled extensible format: %s\n", debugstr_guid(&wfe
->SubFormat
));
819 wfe
->Format
.wBitsPerSample
= from
->wBitsPerSample
;
820 wfe
->Samples
.wValidBitsPerSample
= fromx
->Samples
.wValidBitsPerSample
;
821 if(!wfe
->Samples
.wValidBitsPerSample
)
822 wfe
->Samples
.wValidBitsPerSample
= wfe
->Format
.wBitsPerSample
;
823 wfe
->Format
.cbSize
= size
;
824 wfe
->dwChannelMask
= fromx
->dwChannelMask
;
825 wfe
->SubFormat
= fromx
->SubFormat
;
829 ERR("Unhandled format tag %04x\n", from
->wFormatTag
);
834 wfx
->nChannels
= from
->nChannels
;
835 wfx
->wFormatTag
= from
->wFormatTag
;
836 if(from
->nSamplesPerSec
>= DSBFREQUENCY_MIN
&&
837 from
->nSamplesPerSec
<= DSBFREQUENCY_MAX
)
838 wfx
->nSamplesPerSec
= from
->nSamplesPerSec
;
839 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
840 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
843 static HRESULT WINAPI
DS8Primary_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
845 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
849 TRACE("(%p)->(%p)\n", iface
, wfx
);
853 WARN("Missing format\n");
854 return DSERR_INVALIDPARAM
;
857 EnterCriticalSection(&This
->crst
);
859 if(This
->parent
->prio_level
< DSSCL_PRIORITY
)
861 hr
= DSERR_PRIOLEVELNEEDED
;
865 TRACE("Requested primary format:\n"
866 " FormatTag = %04x\n"
868 " SamplesPerSec = %u\n"
869 " AvgBytesPerSec = %u\n"
871 " BitsPerSample = %u\n",
872 wfx
->wFormatTag
, wfx
->nChannels
,
873 wfx
->nSamplesPerSec
, wfx
->nAvgBytesPerSec
,
874 wfx
->nBlockAlign
, wfx
->wBitsPerSample
);
876 copy_waveformat(&This
->format
.Format
, wfx
);
878 freq
= This
->format
.Format
.nSamplesPerSec
;
879 alcGetIntegerv(This
->parent
->device
, ALC_FREQUENCY
, 1, &freq
);
880 getALCError(This
->parent
->device
);
882 This
->format
.Format
.nSamplesPerSec
= freq
;
883 This
->format
.Format
.nAvgBytesPerSec
= This
->format
.Format
.nBlockAlign
*
884 This
->format
.Format
.nSamplesPerSec
;
891 memset(&desc
, 0, sizeof(desc
));
892 desc
.dwSize
= sizeof(desc
);
893 desc
.dwFlags
= DSBCAPS_LOCHARDWARE
|DSBCAPS_CTRLPAN
;
894 desc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
% This
->format
.Format
.nBlockAlign
);
895 desc
.lpwfxFormat
= &This
->format
.Format
;
897 hr
= DS8Buffer_Create(&buf
, This
, NULL
);
901 hr
= IDirectSoundBuffer8_Initialize(&buf
->IDirectSoundBuffer8_iface
, (IDirectSound
*)&This
->parent
->IDirectSound8_iface
, &desc
);
903 DS8Buffer_Destroy(buf
);
906 IDirectSoundBuffer8_Release(This
->write_emu
);
907 This
->write_emu
= &buf
->IDirectSoundBuffer8_iface
;
912 LeaveCriticalSection(&This
->crst
);
916 static HRESULT WINAPI
DS8Primary_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
918 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
921 TRACE("(%p)->(%d)\n", iface
, vol
);
923 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
925 WARN("Invalid volume (%d)\n", vol
);
926 return DSERR_INVALIDPARAM
;
929 EnterCriticalSection(&This
->crst
);
930 if(!(This
->flags
&DSBCAPS_CTRLVOLUME
))
931 hr
= DSERR_CONTROLUNAVAIL
;
934 setALContext(This
->ctx
);
935 alListenerf(AL_GAIN
, mB_to_gain(vol
));
938 LeaveCriticalSection(&This
->crst
);
943 static HRESULT WINAPI
DS8Primary_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
945 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
948 TRACE("(%p)->(%d)\n", iface
, pan
);
950 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
952 WARN("invalid parameter: pan = %d\n", pan
);
953 return DSERR_INVALIDPARAM
;
956 EnterCriticalSection(&This
->crst
);
957 if(!(This
->flags
&DSBCAPS_CTRLPAN
))
959 WARN("control unavailable\n");
960 hr
= DSERR_CONTROLUNAVAIL
;
962 else if(This
->write_emu
)
963 hr
= IDirectSoundBuffer8_SetPan(This
->write_emu
, pan
);
966 FIXME("Not supported\n");
969 LeaveCriticalSection(&This
->crst
);
974 static HRESULT WINAPI
DS8Primary_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
976 WARN("(%p)->(%u)\n", iface
, freq
);
977 return DSERR_CONTROLUNAVAIL
;
980 static HRESULT WINAPI
DS8Primary_Stop(IDirectSoundBuffer
*iface
)
982 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
985 TRACE("(%p)->()\n", iface
);
987 EnterCriticalSection(&This
->crst
);
989 hr
= IDirectSoundBuffer8_Stop(This
->write_emu
);
991 This
->stopped
= TRUE
;
992 LeaveCriticalSection(&This
->crst
);
997 static HRESULT WINAPI
DS8Primary_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
999 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
1000 HRESULT hr
= DSERR_INVALIDCALL
;
1002 TRACE("(%p)->(%p, %u, %p, %u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1004 EnterCriticalSection(&This
->crst
);
1006 hr
= IDirectSoundBuffer8_Unlock(This
->write_emu
, ptr1
, len1
, ptr2
, len2
);
1007 LeaveCriticalSection(&This
->crst
);
1012 static HRESULT WINAPI
DS8Primary_Restore(IDirectSoundBuffer
*iface
)
1014 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
1017 TRACE("(%p)->()\n", iface
);
1019 EnterCriticalSection(&This
->crst
);
1021 hr
= IDirectSoundBuffer8_Restore(This
->write_emu
);
1022 LeaveCriticalSection(&This
->crst
);
1027 static const IDirectSoundBufferVtbl DS8Primary_Vtbl
=
1029 DS8Primary_QueryInterface
,
1033 DS8Primary_GetCurrentPosition
,
1034 DS8Primary_GetFormat
,
1035 DS8Primary_GetVolume
,
1037 DS8Primary_GetFrequency
,
1038 DS8Primary_GetStatus
,
1039 DS8Primary_Initialize
,
1042 DS8Primary_SetCurrentPosition
,
1043 DS8Primary_SetFormat
,
1044 DS8Primary_SetVolume
,
1046 DS8Primary_SetFrequency
,
1052 static inline DS8Primary
*impl_from_IDirectSound3DListener(IDirectSound3DListener
*iface
)
1054 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSound3DListener_iface
);
1057 static HRESULT WINAPI
DS8Primary3D_QueryInterface(IDirectSound3DListener
*iface
, REFIID riid
, void **ppv
)
1059 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1060 return IDirectSoundBuffer_QueryInterface((IDirectSoundBuffer
*)This
, riid
, ppv
);
1063 static ULONG WINAPI
DS8Primary3D_AddRef(IDirectSound3DListener
*iface
)
1065 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1068 ret
= InterlockedIncrement(&This
->ds3d_ref
);
1069 TRACE("new refcount %d\n", ret
);
1075 /* Considering the primary buffer doesn't get destroyed
1076 * it doesn't make sense to destroy ds3d here
1078 static ULONG WINAPI
DS8Primary3D_Release(IDirectSound3DListener
*iface
)
1080 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1083 ret
= InterlockedDecrement(&This
->ds3d_ref
);
1084 TRACE("new refcount %d\n", ret
);
1090 static HRESULT WINAPI
DS8Primary3D_GetAllParameters(IDirectSound3DListener
*iface
, DS3DLISTENER
*listener
)
1092 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1095 TRACE("(%p)->(%p)\n", iface
, listener
);
1097 if(!listener
|| listener
->dwSize
< sizeof(*listener
))
1099 WARN("Invalid DS3DLISTENER %p %u\n", listener
, listener
? listener
->dwSize
: 0);
1100 return DSERR_INVALIDPARAM
;
1103 EnterCriticalSection(&This
->crst
);
1104 setALContext(This
->ctx
);
1105 IDirectSound3DListener_GetPosition(iface
, &listener
->vPosition
);
1106 IDirectSound3DListener_GetVelocity(iface
, &listener
->vVelocity
);
1107 IDirectSound3DListener_GetOrientation(iface
, &listener
->vOrientFront
, &listener
->vOrientTop
);
1108 IDirectSound3DListener_GetDistanceFactor(iface
, &listener
->flDistanceFactor
);
1109 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flRolloffFactor
);
1110 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flDopplerFactor
);
1112 LeaveCriticalSection(&This
->crst
);
1118 static HRESULT WINAPI
DS8Primary3D_GetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE
*distancefactor
)
1120 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1122 TRACE("(%p)->(%p)\n", iface
, distancefactor
);
1126 WARN("Invalid parameter %p\n", distancefactor
);
1127 return DSERR_INVALIDPARAM
;
1130 EnterCriticalSection(&This
->crst
);
1131 setALContext(This
->ctx
);
1133 *distancefactor
= 343.3f
/alGetFloat(AL_SPEED_OF_SOUND
);
1137 LeaveCriticalSection(&This
->crst
);
1142 static HRESULT WINAPI
DS8Primary3D_GetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE
*dopplerfactor
)
1144 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1146 TRACE("(%p)->(%p)\n", iface
, dopplerfactor
);
1150 WARN("Invalid parameter %p\n", dopplerfactor
);
1151 return DSERR_INVALIDPARAM
;
1154 EnterCriticalSection(&This
->crst
);
1155 setALContext(This
->ctx
);
1157 *dopplerfactor
= alGetFloat(AL_DOPPLER_FACTOR
);
1161 LeaveCriticalSection(&This
->crst
);
1166 static HRESULT WINAPI
DS8Primary3D_GetOrientation(IDirectSound3DListener
*iface
, D3DVECTOR
*front
, D3DVECTOR
*top
)
1168 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1171 TRACE("(%p)->(%p, %p)\n", iface
, front
, top
);
1175 WARN("Invalid parameter %p %p\n", front
, top
);
1176 return DSERR_INVALIDPARAM
;
1179 EnterCriticalSection(&This
->crst
);
1180 setALContext(This
->ctx
);
1182 alGetListenerfv(AL_ORIENTATION
, orient
);
1185 front
->x
= orient
[0];
1186 front
->y
= orient
[1];
1187 front
->z
= -orient
[2];
1190 top
->z
= -orient
[5];
1193 LeaveCriticalSection(&This
->crst
);
1198 static HRESULT WINAPI
DS8Primary3D_GetPosition(IDirectSound3DListener
*iface
, D3DVECTOR
*pos
)
1200 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1203 TRACE("(%p)->(%p)\n", iface
, pos
);
1207 WARN("Invalid parameter %p\n", pos
);
1208 return DSERR_INVALIDPARAM
;
1211 EnterCriticalSection(&This
->crst
);
1212 setALContext(This
->ctx
);
1214 alGetListenerfv(AL_POSITION
, alpos
);
1222 LeaveCriticalSection(&This
->crst
);
1227 static HRESULT WINAPI
DS8Primary3D_GetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE
*rollofffactor
)
1229 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1231 TRACE("(%p)->(%p)\n", iface
, rollofffactor
);
1235 WARN("Invalid parameter %p\n", rollofffactor
);
1236 return DSERR_INVALIDPARAM
;
1239 EnterCriticalSection(&This
->crst
);
1240 *rollofffactor
= This
->rollofffactor
;
1241 LeaveCriticalSection(&This
->crst
);
1246 static HRESULT WINAPI
DS8Primary3D_GetVelocity(IDirectSound3DListener
*iface
, D3DVECTOR
*velocity
)
1248 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1251 TRACE("(%p)->(%p)\n", iface
, velocity
);
1255 WARN("Invalid parameter %p\n", velocity
);
1256 return DSERR_INVALIDPARAM
;
1259 EnterCriticalSection(&This
->crst
);
1260 setALContext(This
->ctx
);
1262 alGetListenerfv(AL_VELOCITY
, vel
);
1265 velocity
->x
= vel
[0];
1266 velocity
->y
= vel
[1];
1267 velocity
->z
= -vel
[2];
1270 LeaveCriticalSection(&This
->crst
);
1275 static HRESULT WINAPI
DS8Primary3D_SetAllParameters(IDirectSound3DListener
*iface
, const DS3DLISTENER
*listen
, DWORD apply
)
1277 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1279 TRACE("(%p)->(%p, %u)\n", iface
, listen
, apply
);
1281 if(!listen
|| listen
->dwSize
< sizeof(*listen
))
1283 WARN("Invalid parameter %p %u\n", listen
, listen
? listen
->dwSize
: 0);
1284 return DSERR_INVALIDPARAM
;
1287 if(listen
->flDistanceFactor
> DS3D_MAXDISTANCEFACTOR
||
1288 listen
->flDistanceFactor
< DS3D_MINDISTANCEFACTOR
)
1290 WARN("Invalid distance factor (%f)\n", listen
->flDistanceFactor
);
1291 return DSERR_INVALIDPARAM
;
1294 if(listen
->flDopplerFactor
> DS3D_MAXDOPPLERFACTOR
||
1295 listen
->flDopplerFactor
< DS3D_MINDOPPLERFACTOR
)
1297 WARN("Invalid doppler factor (%f)\n", listen
->flDopplerFactor
);
1298 return DSERR_INVALIDPARAM
;
1301 if(listen
->flRolloffFactor
< DS3D_MINROLLOFFFACTOR
||
1302 listen
->flRolloffFactor
> DS3D_MAXROLLOFFFACTOR
)
1304 WARN("Invalid rolloff factor (%f)\n", listen
->flRolloffFactor
);
1305 return DSERR_INVALIDPARAM
;
1308 EnterCriticalSection(&This
->crst
);
1309 setALContext(This
->ctx
);
1310 IDirectSound3DListener_SetPosition(iface
, listen
->vPosition
.x
, listen
->vPosition
.y
, listen
->vPosition
.z
, apply
);
1311 IDirectSound3DListener_SetVelocity(iface
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, listen
->vVelocity
.z
, apply
);
1312 IDirectSound3DListener_SetOrientation(iface
, listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, listen
->vOrientFront
.z
,
1313 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, listen
->vOrientTop
.z
, apply
);
1314 IDirectSound3DListener_SetDistanceFactor(iface
, listen
->flDistanceFactor
, apply
);
1315 IDirectSound3DListener_SetRolloffFactor(iface
, listen
->flRolloffFactor
, apply
);
1316 IDirectSound3DListener_SetDopplerFactor(iface
, listen
->flDopplerFactor
, apply
);
1318 LeaveCriticalSection(&This
->crst
);
1323 static HRESULT WINAPI
DS8Primary3D_SetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1325 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1327 TRACE("(%p)->(%f, %u)\n", iface
, factor
, apply
);
1329 if(factor
< DS3D_MINDISTANCEFACTOR
||
1330 factor
> DS3D_MAXDISTANCEFACTOR
)
1332 WARN("Invalid parameter %f\n", factor
);
1333 return DSERR_INVALIDPARAM
;
1336 EnterCriticalSection(&This
->crst
);
1337 if(apply
== DS3D_DEFERRED
)
1339 This
->listen
.flDistanceFactor
= factor
;
1340 This
->dirty
.bit
.distancefactor
= 1;
1344 setALContext(This
->ctx
);
1345 alSpeedOfSound(343.3f
/factor
);
1346 if(This
->SupportedExt
[EXT_EFX
])
1347 alListenerf(AL_METERS_PER_UNIT
, factor
);
1351 LeaveCriticalSection(&This
->crst
);
1356 static HRESULT WINAPI
DS8Primary3D_SetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1358 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1360 TRACE("(%p)->(%f, %u)\n", iface
, factor
, apply
);
1362 if(factor
< DS3D_MINDOPPLERFACTOR
||
1363 factor
> DS3D_MAXDOPPLERFACTOR
)
1365 WARN("Invalid parameter %f\n", factor
);
1366 return DSERR_INVALIDPARAM
;
1369 EnterCriticalSection(&This
->crst
);
1370 if(apply
== DS3D_DEFERRED
)
1372 This
->listen
.flDopplerFactor
= factor
;
1373 This
->dirty
.bit
.dopplerfactor
= 1;
1377 setALContext(This
->ctx
);
1378 alDopplerFactor(factor
);
1382 LeaveCriticalSection(&This
->crst
);
1387 static HRESULT WINAPI
DS8Primary3D_SetOrientation(IDirectSound3DListener
*iface
, D3DVALUE xFront
, D3DVALUE yFront
, D3DVALUE zFront
, D3DVALUE xTop
, D3DVALUE yTop
, D3DVALUE zTop
, DWORD apply
)
1389 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1391 TRACE("(%p)->(%f, %f, %f, %f, %f, %f, %u)\n", iface
, xFront
, yFront
, zFront
, xTop
, yTop
, zTop
, apply
);
1393 EnterCriticalSection(&This
->crst
);
1394 if(apply
== DS3D_DEFERRED
)
1396 This
->listen
.vOrientFront
.x
= xFront
;
1397 This
->listen
.vOrientFront
.y
= yFront
;
1398 This
->listen
.vOrientFront
.z
= zFront
;
1399 This
->listen
.vOrientTop
.x
= xTop
;
1400 This
->listen
.vOrientTop
.y
= yTop
;
1401 This
->listen
.vOrientTop
.z
= zTop
;
1402 This
->dirty
.bit
.orientation
= 1;
1406 ALfloat orient
[6] = {
1407 xFront
, yFront
, -zFront
,
1410 setALContext(This
->ctx
);
1411 alListenerfv(AL_ORIENTATION
, orient
);
1415 LeaveCriticalSection(&This
->crst
);
1420 static HRESULT WINAPI
DS8Primary3D_SetPosition(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1422 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1424 TRACE("(%p)->(%f, %f, %f, %u)\n", iface
, x
, y
, z
, apply
);
1426 EnterCriticalSection(&This
->crst
);
1427 if(apply
== DS3D_DEFERRED
)
1429 This
->listen
.vPosition
.x
= x
;
1430 This
->listen
.vPosition
.y
= y
;
1431 This
->listen
.vPosition
.z
= z
;
1432 This
->dirty
.bit
.pos
= 1;
1436 setALContext(This
->ctx
);
1437 alListener3f(AL_POSITION
, x
, y
, -z
);
1441 LeaveCriticalSection(&This
->crst
);
1446 static HRESULT WINAPI
DS8Primary3D_SetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1448 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1450 TRACE("(%p)->(%f, %u)\n", iface
, factor
, apply
);
1452 if(factor
< DS3D_MINROLLOFFFACTOR
||
1453 factor
> DS3D_MAXROLLOFFFACTOR
)
1455 WARN("Invalid parameter %f\n", factor
);
1456 return DSERR_INVALIDPARAM
;
1459 EnterCriticalSection(&This
->crst
);
1460 if(apply
== DS3D_DEFERRED
)
1462 This
->listen
.flRolloffFactor
= factor
;
1463 This
->dirty
.bit
.rollofffactor
= 1;
1469 setALContext(This
->ctx
);
1470 for(i
= 0;i
< This
->nbuffers
;++i
)
1472 if(This
->buffers
[i
]->ds3dmode
!= DS3DMODE_DISABLE
)
1473 alSourcef(This
->buffers
[i
]->source
, AL_ROLLOFF_FACTOR
, factor
);
1478 This
->rollofffactor
= factor
;
1480 LeaveCriticalSection(&This
->crst
);
1485 static HRESULT WINAPI
DS8Primary3D_SetVelocity(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1487 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1489 TRACE("(%p)->(%f, %f, %f, %u)\n", iface
, x
, y
, z
, apply
);
1491 EnterCriticalSection(&This
->crst
);
1492 if(apply
== DS3D_DEFERRED
)
1494 This
->listen
.vVelocity
.x
= x
;
1495 This
->listen
.vVelocity
.y
= y
;
1496 This
->listen
.vVelocity
.z
= z
;
1497 This
->dirty
.bit
.vel
= 1;
1501 setALContext(This
->ctx
);
1502 alListener3f(AL_VELOCITY
, x
, y
, -z
);
1506 LeaveCriticalSection(&This
->crst
);
1511 static HRESULT WINAPI
DS8Primary3D_CommitDeferredSettings(IDirectSound3DListener
*iface
)
1513 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1514 const DS3DLISTENER
*listen
= &This
->listen
;
1517 EnterCriticalSection(&This
->crst
);
1518 setALContext(This
->ctx
);
1519 This
->ExtAL
.DeferUpdates();
1521 if(This
->dirty
.bit
.pos
)
1522 alListener3f(AL_POSITION
, listen
->vPosition
.x
, listen
->vPosition
.y
, -listen
->vPosition
.z
);
1523 if(This
->dirty
.bit
.vel
)
1524 alListener3f(AL_VELOCITY
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, -listen
->vVelocity
.z
);
1525 if(This
->dirty
.bit
.orientation
)
1527 ALfloat orient
[6] = {
1528 listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, -listen
->vOrientFront
.z
,
1529 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, -listen
->vOrientTop
.z
1531 alListenerfv(AL_ORIENTATION
, orient
);
1533 if(This
->dirty
.bit
.distancefactor
)
1535 alSpeedOfSound(343.3f
/listen
->flDistanceFactor
);
1536 if(This
->SupportedExt
[EXT_EFX
])
1537 alListenerf(AL_METERS_PER_UNIT
, listen
->flDistanceFactor
);
1540 if(This
->dirty
.bit
.rollofffactor
)
1542 ALfloat rolloff
= This
->rollofffactor
;
1543 for(i
= 0;i
< This
->nbuffers
;++i
)
1545 DS8Buffer
*buf
= This
->buffers
[i
];
1546 if(buf
->ds3dmode
!= DS3DMODE_DISABLE
)
1547 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
, rolloff
);
1551 if(This
->dirty
.bit
.dopplerfactor
)
1552 alDopplerFactor(listen
->flDopplerFactor
);
1554 if(This
->dirty
.bit
.effect
)
1555 This
->ExtAL
.AuxiliaryEffectSloti(This
->auxslot
, AL_EFFECTSLOT_EFFECT
, This
->effect
);
1557 /* getALError is here for debugging */
1560 TRACE("Dirty flags was: 0x%02x\n", This
->dirty
.flags
);
1561 This
->dirty
.flags
= 0;
1563 for(i
= 0;i
< This
->nbuffers
;++i
)
1565 DS8Buffer
*buf
= This
->buffers
[i
];
1567 if(!buf
->dirty
.flags
)
1570 if(buf
->dirty
.bit
.pos
)
1571 alSource3f(buf
->source
, AL_POSITION
,
1572 buf
->ds3dbuffer
.vPosition
.x
,
1573 buf
->ds3dbuffer
.vPosition
.y
,
1574 -buf
->ds3dbuffer
.vPosition
.z
);
1575 if(buf
->dirty
.bit
.vel
)
1576 alSource3f(buf
->source
, AL_VELOCITY
,
1577 buf
->ds3dbuffer
.vVelocity
.x
,
1578 buf
->ds3dbuffer
.vVelocity
.y
,
1579 -buf
->ds3dbuffer
.vVelocity
.z
);
1580 if(buf
->dirty
.bit
.cone_angles
)
1582 alSourcei(buf
->source
, AL_CONE_INNER_ANGLE
,
1583 buf
->ds3dbuffer
.dwInsideConeAngle
);
1584 alSourcei(buf
->source
, AL_CONE_OUTER_ANGLE
,
1585 buf
->ds3dbuffer
.dwOutsideConeAngle
);
1587 if(buf
->dirty
.bit
.cone_orient
)
1588 alSource3f(buf
->source
, AL_DIRECTION
,
1589 buf
->ds3dbuffer
.vConeOrientation
.x
,
1590 buf
->ds3dbuffer
.vConeOrientation
.y
,
1591 -buf
->ds3dbuffer
.vConeOrientation
.z
);
1592 if(buf
->dirty
.bit
.cone_outsidevolume
)
1593 alSourcef(buf
->source
, AL_CONE_OUTER_GAIN
,
1594 mB_to_gain(buf
->ds3dbuffer
.lConeOutsideVolume
));
1595 if(buf
->dirty
.bit
.min_distance
)
1596 alSourcef(buf
->source
, AL_REFERENCE_DISTANCE
, buf
->ds3dbuffer
.flMinDistance
);
1597 if(buf
->dirty
.bit
.max_distance
)
1598 alSourcef(buf
->source
, AL_MAX_DISTANCE
, buf
->ds3dbuffer
.flMaxDistance
);
1599 if(buf
->dirty
.bit
.mode
)
1601 buf
->ds3dmode
= buf
->ds3dbuffer
.dwMode
;
1602 alSourcei(buf
->source
, AL_SOURCE_RELATIVE
,
1603 (buf
->ds3dmode
!=DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
1604 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
,
1605 (buf
->ds3dmode
==DS3DMODE_DISABLE
) ? 0.0f
: This
->rollofffactor
);
1607 buf
->dirty
.flags
= 0;
1611 This
->ExtAL
.ProcessUpdates();
1613 LeaveCriticalSection(&This
->crst
);
1618 static const IDirectSound3DListenerVtbl DS8Primary3D_Vtbl
=
1620 DS8Primary3D_QueryInterface
,
1621 DS8Primary3D_AddRef
,
1622 DS8Primary3D_Release
,
1623 DS8Primary3D_GetAllParameters
,
1624 DS8Primary3D_GetDistanceFactor
,
1625 DS8Primary3D_GetDopplerFactor
,
1626 DS8Primary3D_GetOrientation
,
1627 DS8Primary3D_GetPosition
,
1628 DS8Primary3D_GetRolloffFactor
,
1629 DS8Primary3D_GetVelocity
,
1630 DS8Primary3D_SetAllParameters
,
1631 DS8Primary3D_SetDistanceFactor
,
1632 DS8Primary3D_SetDopplerFactor
,
1633 DS8Primary3D_SetOrientation
,
1634 DS8Primary3D_SetPosition
,
1635 DS8Primary3D_SetRolloffFactor
,
1636 DS8Primary3D_SetVelocity
,
1637 DS8Primary3D_CommitDeferredSettings
1640 /* NOTE: Although the app handles listener properties through secondary buffers,
1641 * we pass the requests to the primary buffer though a propertyset interface.
1642 * These methods are not exposed to the app. */
1643 static inline DS8Primary
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
1645 return CONTAINING_RECORD(iface
, DS8Primary
, IKsPropertySet_iface
);
1648 static HRESULT WINAPI
DS8PrimaryProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
1650 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1651 return IDirectSoundBuffer_QueryInterface((IDirectSoundBuffer
*)This
, riid
, ppv
);
1654 static ULONG WINAPI
DS8PrimaryProp_AddRef(IKsPropertySet
*iface
)
1656 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1659 ret
= InterlockedIncrement(&This
->prop_ref
);
1660 TRACE("new refcount %d\n", ret
);
1665 static ULONG WINAPI
DS8PrimaryProp_Release(IKsPropertySet
*iface
)
1667 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1670 ret
= InterlockedDecrement(&This
->prop_ref
);
1671 TRACE("new refcount %d\n", ret
);
1676 static HRESULT WINAPI
DS8PrimaryProp_Get(IKsPropertySet
*iface
,
1677 REFGUID guidPropSet
, ULONG dwPropID
,
1678 LPVOID pInstanceData
, ULONG cbInstanceData
,
1679 LPVOID pPropData
, ULONG cbPropData
,
1682 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1683 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1685 TRACE("(%p)->(%s, %u, %p, %u, %p, %u, %p)\n", iface
, debugstr_guid(guidPropSet
),
1686 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
1688 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1690 EnterCriticalSection(&This
->crst
);
1692 if(This
->effect
== 0)
1693 res
= E_PROP_ID_UNSUPPORTED
;
1694 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
)
1696 res
= DSERR_INVALIDPARAM
;
1697 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1701 EAXLISTENERPROPERTIES
*props
;
1702 } data
= { pPropData
};
1704 *data
.props
= This
->eax_prop
;
1705 *pcbReturned
= sizeof(EAXLISTENERPROPERTIES
);
1709 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
)
1711 res
= DSERR_INVALIDPARAM
;
1712 if(cbPropData
>= sizeof(LONG
))
1717 } data
= { pPropData
};
1719 *data
.l
= This
->eax_prop
.lRoom
;
1720 *pcbReturned
= sizeof(LONG
);
1724 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
)
1726 res
= DSERR_INVALIDPARAM
;
1727 if(cbPropData
>= sizeof(LONG
))
1732 } data
= { pPropData
};
1734 *data
.l
= This
->eax_prop
.lRoomHF
;
1735 *pcbReturned
= sizeof(LONG
);
1739 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
)
1741 res
= DSERR_INVALIDPARAM
;
1742 if(cbPropData
>= sizeof(FLOAT
))
1747 } data
= { pPropData
};
1749 *data
.fl
= This
->eax_prop
.flRoomRolloffFactor
;
1750 *pcbReturned
= sizeof(FLOAT
);
1754 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
)
1756 res
= DSERR_INVALIDPARAM
;
1757 if(cbPropData
>= sizeof(DWORD
))
1762 } data
= { pPropData
};
1764 *data
.dw
= This
->eax_prop
.dwEnvironment
;
1765 *pcbReturned
= sizeof(DWORD
);
1769 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
)
1771 res
= DSERR_INVALIDPARAM
;
1772 if(cbPropData
>= sizeof(FLOAT
))
1777 } data
= { pPropData
};
1779 *data
.fl
= This
->eax_prop
.flEnvironmentSize
;
1780 *pcbReturned
= sizeof(FLOAT
);
1784 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
)
1786 res
= DSERR_INVALIDPARAM
;
1787 if(cbPropData
>= sizeof(FLOAT
))
1792 } data
= { pPropData
};
1794 *data
.fl
= This
->eax_prop
.flEnvironmentDiffusion
;
1795 *pcbReturned
= sizeof(FLOAT
);
1799 else if(dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
)
1801 res
= DSERR_INVALIDPARAM
;
1802 if(cbPropData
>= sizeof(FLOAT
))
1807 } data
= { pPropData
};
1809 *data
.fl
= This
->eax_prop
.flAirAbsorptionHF
;
1810 *pcbReturned
= sizeof(FLOAT
);
1814 else if(dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
1816 res
= DSERR_INVALIDPARAM
;
1817 if(cbPropData
>= sizeof(DWORD
))
1822 } data
= { pPropData
};
1824 *data
.dw
= This
->eax_prop
.dwFlags
;
1825 *pcbReturned
= sizeof(DWORD
);
1830 FIXME("Unhandled propid: 0x%08x\n", dwPropID
);
1832 LeaveCriticalSection(&This
->crst
);
1835 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
1840 static HRESULT WINAPI
DS8PrimaryProp_Set(IKsPropertySet
*iface
,
1841 REFGUID guidPropSet
, ULONG dwPropID
,
1842 LPVOID pInstanceData
, ULONG cbInstanceData
,
1843 LPVOID pPropData
, ULONG cbPropData
)
1845 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1846 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1848 TRACE("(%p)->(%s, %u, %p, %u, %p, %u)\n", iface
, debugstr_guid(guidPropSet
),
1849 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
1851 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1853 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
1854 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
1856 EnterCriticalSection(&This
->crst
);
1857 setALContext(This
->ctx
);
1859 if(This
->effect
== 0)
1860 res
= E_PROP_ID_UNSUPPORTED
;
1861 else if(propid
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
)
1864 res
= DSERR_INVALIDPARAM
;
1865 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1869 const EAXLISTENERPROPERTIES
*props
;
1870 } data
= { pPropData
};
1872 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
1873 This
->eax_prop
= *data
.props
;
1874 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DENSITY
,
1875 (data
.props
->flEnvironmentSize
< 2.0f
) ?
1876 (data
.props
->flEnvironmentSize
- 1.0f
) : 1.0f
);
1877 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1878 data
.props
->flEnvironmentDiffusion
);
1880 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAIN
,
1881 mB_to_gain(data
.props
->lRoom
));
1882 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAINHF
,
1883 mB_to_gain(data
.props
->lRoomHF
));
1885 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1886 data
.props
->flRoomRolloffFactor
);
1888 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DECAY_TIME
,
1889 data
.props
->flDecayTime
);
1890 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DECAY_HFRATIO
,
1891 data
.props
->flDecayHFRatio
);
1893 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_REFLECTIONS_GAIN
,
1894 mB_to_gain(data
.props
->lReflections
));
1895 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_REFLECTIONS_DELAY
,
1896 data
.props
->flReflectionsDelay
);
1898 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_LATE_REVERB_GAIN
,
1899 mB_to_gain(data
.props
->lReverb
));
1900 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_LATE_REVERB_DELAY
,
1901 data
.props
->flReverbDelay
);
1903 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1904 mB_to_gain(data
.props
->flAirAbsorptionHF
));
1906 This
->ExtAL
.Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
1907 (data
.props
->dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
1908 AL_TRUE
: AL_FALSE
);
1912 This
->dirty
.bit
.effect
= 1;
1916 else if(propid
== DSPROPERTY_EAXLISTENER_ROOM
)
1918 res
= DSERR_INVALIDPARAM
;
1919 if(cbPropData
>= sizeof(LONG
))
1924 } data
= { pPropData
};
1926 This
->eax_prop
.lRoom
= *data
.l
;
1927 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAIN
,
1928 mB_to_gain(This
->eax_prop
.lRoom
));
1931 This
->dirty
.bit
.effect
= 1;
1935 else if(propid
== DSPROPERTY_EAXLISTENER_ROOMHF
)
1937 res
= DSERR_INVALIDPARAM
;
1938 if(cbPropData
>= sizeof(LONG
))
1943 } data
= { pPropData
};
1945 This
->eax_prop
.lRoomHF
= *data
.l
;
1946 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_GAINHF
,
1947 mB_to_gain(This
->eax_prop
.lRoomHF
));
1950 This
->dirty
.bit
.effect
= 1;
1954 else if(propid
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
)
1956 res
= DSERR_INVALIDPARAM
;
1957 if(cbPropData
>= sizeof(FLOAT
))
1962 } data
= { pPropData
};
1964 This
->eax_prop
.flRoomRolloffFactor
= *data
.fl
;
1965 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1966 This
->eax_prop
.flRoomRolloffFactor
);
1969 This
->dirty
.bit
.effect
= 1;
1973 else if(propid
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
)
1975 res
= DSERR_INVALIDPARAM
;
1976 if(cbPropData
>= sizeof(DWORD
))
1981 } data
= { pPropData
};
1983 if(*data
.dw
< EAX_ENVIRONMENT_COUNT
)
1985 /* Get the environment index's default and pass it down to
1987 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1988 pPropData
= (void*)&EnvironmentDefaults
[*data
.dw
];
1989 cbPropData
= sizeof(EnvironmentDefaults
[*data
.dw
]);
1994 else if(propid
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
)
1996 res
= DSERR_INVALIDPARAM
;
1997 if(cbPropData
>= sizeof(FLOAT
))
2002 } data
= { pPropData
};
2004 if(*data
.fl
>= 1.0f
&& *data
.fl
<= 100.0f
)
2006 double scale
= (*data
.fl
)/This
->eax_prop
.flEnvironmentSize
;
2008 This
->eax_prop
.flEnvironmentSize
= *data
.fl
;
2010 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYTIMESCALE
))
2012 This
->eax_prop
.flDecayTime
*= scale
;
2013 This
->eax_prop
.flDecayTime
= clampF(This
->eax_prop
.flDecayTime
, 0.1f
, 20.0f
);
2015 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSSCALE
))
2017 This
->eax_prop
.lReflections
+= gain_to_mB(1.0/scale
);
2018 This
->eax_prop
.lReflections
= clampI(This
->eax_prop
.lReflections
, -10000, 1000);
2020 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE
))
2022 This
->eax_prop
.flReflectionsDelay
*= scale
;
2023 This
->eax_prop
.flReflectionsDelay
= clampF(This
->eax_prop
.flReflectionsDelay
, 0.0f
, 0.3f
);
2025 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBSCALE
))
2027 This
->eax_prop
.lReverb
+= gain_to_mB(1.0/scale
);
2028 This
->eax_prop
.lReverb
= clampI(This
->eax_prop
.lReverb
, -10000, 2000);
2030 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBDELAYSCALE
))
2032 This
->eax_prop
.flReverbDelay
*= scale
;
2033 This
->eax_prop
.flReverbDelay
= clampF(This
->eax_prop
.flReverbDelay
, 0.0f
, 0.1f
);
2036 /* Pass the updated environment properties down to ALLPARAMETERS */
2037 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
2038 pPropData
= (void*)&This
->eax_prop
;
2039 cbPropData
= sizeof(This
->eax_prop
);
2044 else if(propid
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
)
2046 res
= DSERR_INVALIDPARAM
;
2047 if(cbPropData
>= sizeof(FLOAT
))
2052 } data
= { pPropData
};
2054 This
->eax_prop
.flEnvironmentDiffusion
= *data
.fl
;
2055 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
2056 This
->eax_prop
.flEnvironmentDiffusion
);
2059 This
->dirty
.bit
.effect
= 1;
2063 else if(propid
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
)
2065 res
= DSERR_INVALIDPARAM
;
2066 if(cbPropData
>= sizeof(FLOAT
))
2071 } data
= { pPropData
};
2073 This
->eax_prop
.flAirAbsorptionHF
= *data
.fl
;
2074 This
->ExtAL
.Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
2075 mB_to_gain(This
->eax_prop
.flAirAbsorptionHF
));
2078 This
->dirty
.bit
.effect
= 1;
2082 else if(propid
== DSPROPERTY_EAXLISTENER_FLAGS
)
2084 res
= DSERR_INVALIDPARAM
;
2085 if(cbPropData
>= sizeof(DWORD
))
2090 } data
= { pPropData
};
2092 This
->eax_prop
.dwFlags
= *data
.dw
;
2093 This
->ExtAL
.Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
2094 (This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
2095 AL_TRUE
: AL_FALSE
);
2098 This
->dirty
.bit
.effect
= 1;
2102 else if(propid
!= 0)
2103 FIXME("Unhandled propid: 0x%08x\n", propid
);
2105 if(res
== DS_OK
&& immediate
)
2106 IDirectSound3DListener_CommitDeferredSettings(&This
->IDirectSound3DListener_iface
);
2109 LeaveCriticalSection(&This
->crst
);
2112 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2117 static HRESULT WINAPI
DS8PrimaryProp_QuerySupport(IKsPropertySet
*iface
,
2118 REFGUID guidPropSet
, ULONG dwPropID
,
2119 PULONG pTypeSupport
)
2121 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
2122 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
2124 TRACE("(%p)->(%s, %u, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2126 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2128 EnterCriticalSection(&This
->crst
);
2130 if(This
->effect
== 0)
2131 res
= E_PROP_ID_UNSUPPORTED
;
2132 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
||
2133 dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
||
2134 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
||
2135 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
||
2136 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
||
2137 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
||
2138 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
||
2139 dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
||
2140 dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
2142 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
|KSPROPERTY_SUPPORT_SET
;
2146 FIXME("Unhandled propid: 0x%08x\n", dwPropID
);
2148 LeaveCriticalSection(&This
->crst
);
2151 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2156 static const IKsPropertySetVtbl DS8PrimaryProp_Vtbl
=
2158 DS8PrimaryProp_QueryInterface
,
2159 DS8PrimaryProp_AddRef
,
2160 DS8PrimaryProp_Release
,
2163 DS8PrimaryProp_QuerySupport