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
;
72 static inline DS8Primary
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
74 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSoundBuffer_iface
);
77 static inline DS8Primary
*impl_from_IDirectSound3DListener(IDirectSound3DListener
*iface
)
79 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSound3DListener_iface
);
82 static inline DS8Primary
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
84 return CONTAINING_RECORD(iface
, DS8Primary
, IKsPropertySet_iface
);
88 static void AL_APIENTRY
wrap_DeferUpdates(void)
89 { alcSuspendContext(alcGetCurrentContext()); }
90 static void AL_APIENTRY
wrap_ProcessUpdates(void)
91 { alcProcessContext(alcGetCurrentContext()); }
94 static void trigger_elapsed_notifies(DS8Buffer
*buf
, DWORD lastpos
, DWORD curpos
)
97 for(i
= 0; i
< buf
->nnotify
; ++i
)
99 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
100 HANDLE event
= not->hEventNotify
;
101 DWORD ofs
= not->dwOffset
;
103 if(ofs
== (DWORD
)DSBPN_OFFSETSTOP
)
106 /* Wraparound case */
109 if(ofs
< curpos
|| ofs
>= lastpos
)
115 if(ofs
>= lastpos
&& ofs
< curpos
)
120 static void trigger_stop_notifies(DS8Buffer
*buf
)
123 for(i
= 0; i
< buf
->nnotify
; ++i
)
125 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
126 if(not->dwOffset
== (DWORD
)DSBPN_OFFSETSTOP
)
127 SetEvent(not->hEventNotify
);
131 static DWORD CALLBACK
DS8Primary_thread(void *dwUser
)
133 DS8Primary
*prim
= (DS8Primary
*)dwUser
;
134 DWORD i
, active_notifies
;
137 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
);
139 TRACE("Primary buffer (%p) message loop start\n", prim
);
140 while(GetMessageA(&msg
, NULL
, 0, 0))
142 if(msg
.message
!= WM_USER
)
145 EnterCriticalSection(prim
->crst
);
146 setALContext(prim
->ctx
);
148 for(i
= 0;i
< prim
->nnotifies
;)
150 DS8Buffer
*buf
= prim
->notifies
[i
];
151 IDirectSoundBuffer8
*dsb
= &buf
->IDirectSoundBuffer8_iface
;
152 DWORD status
=0, curpos
=buf
->lastpos
;
154 IDirectSoundBuffer8_GetStatus(dsb
, &status
);
155 IDirectSoundBuffer8_GetCurrentPosition(dsb
, &curpos
, NULL
);
156 if(buf
->lastpos
!= curpos
)
158 trigger_elapsed_notifies(buf
, buf
->lastpos
, curpos
);
159 buf
->lastpos
= curpos
;
161 if(!(status
&DSBSTATUS_PLAYING
))
163 /* Remove this buffer from list and put another at the
164 * current position; don't increment i
166 trigger_stop_notifies(buf
);
167 prim
->notifies
[i
] = prim
->notifies
[--prim
->nnotifies
];
174 /* OpenAL doesn't support our lovely buffer extensions
175 * so just make sure enough buffers are queued
177 if(!prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
] &&
178 !prim
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] &&
179 !prim
->SupportedExt
[EXT_STATIC_BUFFER
])
181 for(i
= 0;i
< prim
->nbuffers
;++i
)
183 DS8Buffer
*buf
= prim
->buffers
[i
];
184 ALint done
= 0, queued
= QBUFFERS
, state
= AL_PLAYING
;
187 if(buf
->buffer
->numsegs
== 1 || !buf
->isplaying
)
190 alGetSourcei(buf
->source
, AL_SOURCE_STATE
, &state
);
191 alGetSourcei(buf
->source
, AL_BUFFERS_QUEUED
, &queued
);
192 alGetSourcei(buf
->source
, AL_BUFFERS_PROCESSED
, &done
);
196 alSourceUnqueueBuffers(buf
->source
, 1, &which
);
197 while(queued
< QBUFFERS
)
199 which
= buf
->buffer
->buffers
[buf
->curidx
];
200 ofs
= buf
->curidx
*buf
->buffer
->segsize
;
201 if(buf
->curidx
< buf
->buffer
->numsegs
-1)
202 alBufferData(which
, buf
->buffer
->buf_format
,
203 buf
->buffer
->data
+ ofs
, buf
->buffer
->segsize
,
204 buf
->buffer
->format
.Format
.nSamplesPerSec
);
206 alBufferData(which
, buf
->buffer
->buf_format
,
207 buf
->buffer
->data
+ ofs
, buf
->buffer
->lastsegsize
,
208 buf
->buffer
->format
.Format
.nSamplesPerSec
);
210 alSourceQueueBuffers(buf
->source
, 1, &which
);
211 buf
->curidx
= (buf
->curidx
+1)%buf
->buffer
->numsegs
;
214 if(!buf
->curidx
&& !buf
->islooping
)
216 buf
->isplaying
= FALSE
;
220 if(state
!= AL_PLAYING
)
224 IDirectSoundBuffer8_Stop(&buf
->IDirectSoundBuffer8_iface
);
227 alSourcePlay(buf
->source
);
232 else if(active_notifies
== 0 && prim
->timer_id
)
234 TRACE("No more notifies, killing timer\n");
235 timeKillEvent(prim
->timer_id
);
237 timeEndPeriod(prim
->timer_res
);
241 LeaveCriticalSection(prim
->crst
);
243 TRACE("Primary buffer (%p) message loop quit\n", prim
);
247 timeKillEvent(prim
->timer_id
);
249 timeEndPeriod(prim
->timer_res
);
250 TRACE("Killed timer\n");
256 static void CALLBACK
DS8Primary_timer(UINT timerID
, UINT msg
, DWORD_PTR dwUser
,
257 DWORD_PTR dw1
, DWORD_PTR dw2
)
263 PostThreadMessageA(dwUser
, WM_USER
, 0, 0);
266 void DS8Primary_starttimer(DS8Primary
*prim
)
268 DWORD triggertime
, res
= DS_TIME_RES
;
269 ALint refresh
= FAKE_REFRESH_COUNT
;
275 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
277 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
278 checkALCError(prim
->parent
->device
);
280 triggertime
= 1000 / refresh
/ 2;
281 if(triggertime
< time
.wPeriodMin
)
282 triggertime
= time
.wPeriodMin
;
283 TRACE("Calling timer every %"LONGFMT
"u ms for %i refreshes per second\n", triggertime
, refresh
);
285 if (res
< time
.wPeriodMin
)
286 res
= time
.wPeriodMin
;
287 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
288 WARN("Could not set minimum resolution, don't expect sound\n");
290 prim
->timer_res
= res
;
291 prim
->timer_id
= timeSetEvent(triggertime
, res
, DS8Primary_timer
, prim
->thread_id
, TIME_PERIODIC
|TIME_KILL_SYNCHRONOUS
);
296 HRESULT
DS8Primary_PreInit(DS8Primary
*This
, DS8Impl
*parent
)
298 DS3DLISTENER
*listener
;
302 This
->IDirectSoundBuffer_iface
.lpVtbl
= (IDirectSoundBufferVtbl
*)&DS8Primary_Vtbl
;
303 This
->IDirectSound3DListener_iface
.lpVtbl
= (IDirectSound3DListenerVtbl
*)&DS8Primary3D_Vtbl
;
304 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8PrimaryProp_Vtbl
;
306 This
->parent
= parent
;
307 This
->crst
= &parent
->share
->crst
;
308 This
->ctx
= parent
->share
->ctx
;
309 This
->SupportedExt
= parent
->share
->SupportedExt
;
310 This
->ExtAL
= &parent
->share
->ExtAL
;
311 This
->sources
= parent
->share
->sources
;
312 This
->auxslot
= parent
->share
->auxslot
;
314 /* Allocate enough for a WAVEFORMATEXTENSIBLE */
315 wfx
= &This
->format
.Format
;
317 wfx
->wFormatTag
= WAVE_FORMAT_PCM
;
319 wfx
->wBitsPerSample
= 8;
320 wfx
->nSamplesPerSec
= 22050;
321 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
322 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
325 This
->stopped
= TRUE
;
327 /* Apparently primary buffer size is always 32k,
328 * tested on windows with 192k 24 bits sound @ 6 channels
329 * where it will run out in 60 ms and it isn't pointer aligned
331 This
->buf_size
= 32768;
333 if(This
->SupportedExt
[SOFT_DEFERRED_UPDATES
])
335 This
->DeferUpdates
= This
->ExtAL
->DeferUpdatesSOFT
;
336 This
->ProcessUpdates
= This
->ExtAL
->ProcessUpdatesSOFT
;
340 This
->DeferUpdates
= wrap_DeferUpdates
;
341 This
->ProcessUpdates
= wrap_ProcessUpdates
;
344 This
->eax_prop
= EnvironmentDefaults
[EAX_ENVIRONMENT_GENERIC
];
345 if(This
->SupportedExt
[EXT_EFX
] && This
->auxslot
!= 0)
347 ALint revid
= alGetEnumValue("AL_EFFECT_REVERB");
348 if(revid
!= 0 && revid
!= -1)
350 This
->ExtAL
->GenEffects(1, &This
->effect
);
351 This
->ExtAL
->Effecti(This
->effect
, AL_EFFECT_TYPE
, AL_EFFECT_REVERB
);
356 /* Make sure DS3DListener defaults are applied to OpenAL */
357 listener
= &This
->listen
;
358 listener
->dwSize
= sizeof(*listener
);
359 listener
->vPosition
.x
= 0.0;
360 listener
->vPosition
.y
= 0.0;
361 listener
->vPosition
.z
= 0.0;
362 listener
->vVelocity
.x
= 0.0;
363 listener
->vVelocity
.y
= 0.0;
364 listener
->vVelocity
.z
= 0.0;
365 listener
->vOrientFront
.x
= 0.0;
366 listener
->vOrientFront
.y
= 0.0;
367 listener
->vOrientFront
.z
= 1.0;
368 listener
->vOrientTop
.x
= 0.0;
369 listener
->vOrientTop
.y
= 1.0;
370 listener
->vOrientTop
.z
= 0.0;
371 listener
->flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
372 listener
->flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
373 listener
->flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
374 hr
= IDirectSound3DListener_SetAllParameters(&This
->IDirectSound3DListener_iface
, listener
, DS3D_IMMEDIATE
);
376 ERR("Could not set 3d parameters: %08"LONGFMT
"x\n", hr
);
378 This
->sizenotifies
= This
->sizebuffers
= parent
->share
->max_sources
;
380 hr
= DSERR_OUTOFMEMORY
;
381 This
->buffers
= HeapAlloc(GetProcessHeap(), 0, This
->sizebuffers
*sizeof(*This
->buffers
));
382 This
->notifies
= HeapAlloc(GetProcessHeap(), 0, This
->sizenotifies
*sizeof(*This
->notifies
));
383 if(!This
->buffers
|| !This
->notifies
)
386 This
->thread_hdl
= CreateThread(NULL
, 0, DS8Primary_thread
, This
, 0, &This
->thread_id
);
387 if(This
->thread_hdl
== NULL
)
393 DS8Primary_Clear(This
);
397 void DS8Primary_Clear(DS8Primary
*This
)
399 TRACE("Clearing primary %p\n", This
);
406 PostThreadMessageA(This
->thread_id
, WM_QUIT
, 0, 0);
407 if(WaitForSingleObject(This
->thread_hdl
, 1000) != WAIT_OBJECT_0
)
409 /* HACK: Apparently, if the device is initialized (thus the primary
410 * buffer has PreInit called) then immediately deleted (the primary
411 * buffer has Clear called), the WM_QUIT message gets sent before
412 * the thread has a chance to run which apparently prevents it from
413 * receiving the message.
414 * If the wait attempt fails, try sending the message again. */
415 PostThreadMessageA(This
->thread_id
, WM_QUIT
, 0, 0);
416 if(WaitForSingleObject(This
->thread_hdl
, 1000) != WAIT_OBJECT_0
)
417 ERR("Thread wait timed out\n");
419 CloseHandle(This
->thread_hdl
);
422 setALContext(This
->ctx
);
424 This
->ExtAL
->DeleteEffects(1, &This
->effect
);
426 while(This
->nbuffers
--)
427 DS8Buffer_Destroy(This
->buffers
[This
->nbuffers
]);
429 HeapFree(GetProcessHeap(), 0, This
->notifies
);
430 HeapFree(GetProcessHeap(), 0, This
->buffers
);
431 memset(This
, 0, sizeof(*This
));
434 static HRESULT WINAPI
DS8Primary_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, LPVOID
*ppv
)
436 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
438 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
441 if(IsEqualIID(riid
, &IID_IUnknown
) ||
442 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
443 *ppv
= &This
->IDirectSoundBuffer_iface
;
444 else if(IsEqualIID(riid
, &IID_IDirectSound3DListener
))
446 if((This
->flags
&DSBCAPS_CTRL3D
))
447 *ppv
= &This
->IDirectSound3DListener_iface
;
450 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
454 IUnknown_AddRef((IUnknown
*)*ppv
);
458 return E_NOINTERFACE
;
461 static ULONG WINAPI
DS8Primary_AddRef(IDirectSoundBuffer
*iface
)
463 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
466 ret
= InterlockedIncrement(&This
->ref
);
467 if(ret
== 1) This
->flags
= 0;
472 static ULONG WINAPI
DS8Primary_Release(IDirectSoundBuffer
*iface
)
474 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
477 ret
= InterlockedDecrement(&This
->ref
);
482 static HRESULT WINAPI
DS8Primary_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
484 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
486 TRACE("(%p)->(%p)\n", iface
, caps
);
488 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
490 WARN("Invalid DSBCAPS (%p, %"LONGFMT
"u)\n", caps
, caps
? caps
->dwSize
: 0);
491 return DSERR_INVALIDPARAM
;
494 EnterCriticalSection(This
->crst
);
495 caps
->dwFlags
= This
->flags
;
496 caps
->dwBufferBytes
= This
->buf_size
;
497 caps
->dwUnlockTransferRate
= 0;
498 caps
->dwPlayCpuOverhead
= 0;
499 LeaveCriticalSection(This
->crst
);
504 static HRESULT WINAPI
DS8Primary_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
506 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
507 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
509 EnterCriticalSection(This
->crst
);
511 hr
= IDirectSoundBuffer8_GetCurrentPosition(This
->write_emu
, playpos
, curpos
);
512 LeaveCriticalSection(This
->crst
);
517 static HRESULT WINAPI
DS8Primary_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
519 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
525 WARN("Cannot report format or format size\n");
526 return DSERR_INVALIDPARAM
;
529 EnterCriticalSection(This
->crst
);
530 size
= sizeof(This
->format
.Format
) + This
->format
.Format
.cbSize
;
536 hr
= DSERR_INVALIDPARAM
;
538 memcpy(wfx
, &This
->format
.Format
, size
);
540 LeaveCriticalSection(This
->crst
);
545 static HRESULT WINAPI
DS8Primary_GetVolume(IDirectSoundBuffer
*iface
, LONG
*volume
)
547 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
550 TRACE("(%p)->(%p)\n", iface
, volume
);
553 return DSERR_INVALIDPARAM
;
555 EnterCriticalSection(This
->crst
);
556 if(!(This
->flags
& DSBCAPS_CTRLVOLUME
))
557 hr
= DSERR_CONTROLUNAVAIL
;
562 setALContext(This
->ctx
);
563 alGetListenerf(AL_GAIN
, &gain
);
567 *volume
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
569 LeaveCriticalSection(This
->crst
);
574 static HRESULT WINAPI
DS8Primary_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
576 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
579 WARN("(%p)->(%p): semi-stub\n", iface
, pan
);
582 return DSERR_INVALIDPARAM
;
584 EnterCriticalSection(This
->crst
);
586 hr
= IDirectSoundBuffer8_GetPan(This
->write_emu
, pan
);
587 else if(!(This
->flags
& DSBCAPS_CTRLPAN
))
588 hr
= DSERR_CONTROLUNAVAIL
;
591 LeaveCriticalSection(This
->crst
);
596 static HRESULT WINAPI
DS8Primary_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
598 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
601 WARN("(%p)->(%p): semi-stub\n", iface
, freq
);
604 return DSERR_INVALIDPARAM
;
606 EnterCriticalSection(This
->crst
);
607 if(!(This
->flags
& DSBCAPS_CTRLFREQUENCY
))
608 hr
= DSERR_CONTROLUNAVAIL
;
610 *freq
= This
->format
.Format
.nSamplesPerSec
;
611 LeaveCriticalSection(This
->crst
);
616 static HRESULT WINAPI
DS8Primary_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
618 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
620 TRACE("(%p)->(%p)\n", iface
, status
);
623 return DSERR_INVALIDPARAM
;
625 EnterCriticalSection(This
->crst
);
627 *status
= DSBSTATUS_PLAYING
|DSBSTATUS_LOOPING
;
628 if((This
->flags
&DSBCAPS_LOCDEFER
))
629 *status
|= DSBSTATUS_LOCHARDWARE
;
636 for(i
= 0;i
< This
->nbuffers
;++i
)
638 hr
= IDirectSoundBuffer8_GetStatus(&This
->buffers
[i
]->IDirectSoundBuffer8_iface
, &state
);
639 if(SUCCEEDED(hr
) && (state
&DSBSTATUS_PLAYING
))
642 if(i
== This
->nbuffers
)
644 /* Primary stopped and no buffers playing.. */
649 LeaveCriticalSection(This
->crst
);
654 static HRESULT WINAPI
DS8Primary_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
656 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
659 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
661 if(!desc
|| desc
->lpwfxFormat
|| desc
->dwBufferBytes
)
663 WARN("Bad DSBDESC for primary buffer\n");
664 return DSERR_INVALIDPARAM
;
666 if((desc
->dwFlags
&DSBCAPS_CTRLFX
) ||
667 (desc
->dwFlags
&DSBCAPS_CTRLPOSITIONNOTIFY
) ||
668 (desc
->dwFlags
&DSBCAPS_LOCSOFTWARE
))
670 WARN("Bad dwFlags %08"LONGFMT
"x\n", desc
->dwFlags
);
671 return DSERR_INVALIDPARAM
;
674 EnterCriticalSection(This
->crst
);
675 /* Should be 0 if not initialized */
678 hr
= DSERR_ALREADYINITIALIZED
;
682 if(This
->parent
->prio_level
== DSSCL_WRITEPRIMARY
)
684 DSBUFFERDESC emudesc
;
689 ERR("There shouldn't be a write_emu!\n");
690 IDirectSoundBuffer8_Release(This
->write_emu
);
691 This
->write_emu
= NULL
;
694 memset(&emudesc
, 0, sizeof(emudesc
));
695 emudesc
.dwSize
= sizeof(emudesc
);
696 emudesc
.dwFlags
= DSBCAPS_LOCHARDWARE
| (desc
->dwFlags
&DSBCAPS_CTRLPAN
);
697 /* Dont play last incomplete sample */
698 emudesc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
%This
->format
.Format
.nBlockAlign
);
699 emudesc
.lpwfxFormat
= &This
->format
.Format
;
701 hr
= DS8Buffer_Create(&emu
, This
, NULL
);
704 This
->write_emu
= &emu
->IDirectSoundBuffer8_iface
;
705 hr
= IDirectSoundBuffer8_Initialize(This
->write_emu
, ds
, &emudesc
);
708 IDirectSoundBuffer8_Release(This
->write_emu
);
709 This
->write_emu
= NULL
;
715 This
->flags
= desc
->dwFlags
| DSBCAPS_LOCHARDWARE
;
717 LeaveCriticalSection(This
->crst
);
721 static HRESULT WINAPI
DS8Primary_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
723 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
724 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
726 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %p, %p, %p, %p, %"LONGFMT
"u)\n", iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
728 EnterCriticalSection(This
->crst
);
730 hr
= IDirectSoundBuffer8_Lock(This
->write_emu
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
731 LeaveCriticalSection(This
->crst
);
736 static HRESULT WINAPI
DS8Primary_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD res2
, DWORD flags
)
738 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
741 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %"LONGFMT
"u)\n", iface
, res1
, res2
, flags
);
743 if(!(flags
& DSBPLAY_LOOPING
))
745 WARN("Flags (%08"LONGFMT
"x) not set to DSBPLAY_LOOPING\n", flags
);
746 return DSERR_INVALIDPARAM
;
749 EnterCriticalSection(This
->crst
);
752 hr
= IDirectSoundBuffer8_Play(This
->write_emu
, res1
, res2
, flags
);
754 This
->stopped
= FALSE
;
755 LeaveCriticalSection(This
->crst
);
760 static HRESULT WINAPI
DS8Primary_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
762 WARN("(%p)->(%"LONGFMT
"u)\n", iface
, pos
);
763 return DSERR_INVALIDCALL
;
766 /* Just assume the format is crap, and clean up the damage */
767 static void copy_waveformat(WAVEFORMATEX
*wfx
, const WAVEFORMATEX
*from
)
769 if(from
->wFormatTag
== WAVE_FORMAT_PCM
)
772 if(from
->wBitsPerSample
== 8 ||
773 from
->wBitsPerSample
== 16 ||
774 from
->wBitsPerSample
== 24 ||
775 from
->wBitsPerSample
== 32)
776 wfx
->wBitsPerSample
= from
->wBitsPerSample
;
778 else if(from
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
780 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)wfx
;
781 const WAVEFORMATEXTENSIBLE
*fromx
= (const WAVEFORMATEXTENSIBLE
*)from
;
782 DWORD size
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
784 /* Fail silently.. */
785 if(from
->cbSize
< size
)
787 if(!fromx
->Samples
.wValidBitsPerSample
&&
788 !fromx
->Format
.wBitsPerSample
)
791 if(!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
792 !IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
794 ERR("Unhandled extensible format: %s\n", debugstr_guid(&wfe
->SubFormat
));
798 wfe
->Format
.wBitsPerSample
= from
->wBitsPerSample
;
799 wfe
->Samples
.wValidBitsPerSample
= fromx
->Samples
.wValidBitsPerSample
;
800 if(!wfe
->Samples
.wValidBitsPerSample
)
801 wfe
->Samples
.wValidBitsPerSample
= wfe
->Format
.wBitsPerSample
;
802 wfe
->Format
.cbSize
= size
;
803 wfe
->dwChannelMask
= fromx
->dwChannelMask
;
804 wfe
->SubFormat
= fromx
->SubFormat
;
808 ERR("Unhandled format tag %04x\n", from
->wFormatTag
);
813 wfx
->nChannels
= from
->nChannels
;
814 wfx
->wFormatTag
= from
->wFormatTag
;
815 if(from
->nSamplesPerSec
>= DSBFREQUENCY_MIN
&&
816 from
->nSamplesPerSec
<= DSBFREQUENCY_MAX
)
817 wfx
->nSamplesPerSec
= from
->nSamplesPerSec
;
818 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
819 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
822 static HRESULT WINAPI
DS8Primary_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
824 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
828 TRACE("(%p)->(%p)\n", iface
, wfx
);
832 WARN("Missing format\n");
833 return DSERR_INVALIDPARAM
;
836 EnterCriticalSection(This
->crst
);
838 if(This
->parent
->prio_level
< DSSCL_PRIORITY
)
840 hr
= DSERR_PRIOLEVELNEEDED
;
844 TRACE("Requested primary format:\n"
845 " FormatTag = %04x\n"
847 " SamplesPerSec = %"LONGFMT
"u\n"
848 " AvgBytesPerSec = %"LONGFMT
"u\n"
850 " BitsPerSample = %u\n",
851 wfx
->wFormatTag
, wfx
->nChannels
,
852 wfx
->nSamplesPerSec
, wfx
->nAvgBytesPerSec
,
853 wfx
->nBlockAlign
, wfx
->wBitsPerSample
);
855 copy_waveformat(&This
->format
.Format
, wfx
);
857 freq
= This
->format
.Format
.nSamplesPerSec
;
858 alcGetIntegerv(This
->parent
->device
, ALC_FREQUENCY
, 1, &freq
);
859 checkALCError(This
->parent
->device
);
861 This
->format
.Format
.nSamplesPerSec
= freq
;
862 This
->format
.Format
.nAvgBytesPerSec
= This
->format
.Format
.nBlockAlign
*
863 This
->format
.Format
.nSamplesPerSec
;
870 memset(&desc
, 0, sizeof(desc
));
871 desc
.dwSize
= sizeof(desc
);
872 desc
.dwFlags
= DSBCAPS_LOCHARDWARE
|DSBCAPS_CTRLPAN
;
873 desc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
% This
->format
.Format
.nBlockAlign
);
874 desc
.lpwfxFormat
= &This
->format
.Format
;
876 hr
= DS8Buffer_Create(&buf
, This
, NULL
);
880 hr
= IDirectSoundBuffer8_Initialize(&buf
->IDirectSoundBuffer8_iface
, &This
->parent
->IDirectSound_iface
, &desc
);
882 DS8Buffer_Destroy(buf
);
885 IDirectSoundBuffer8_Release(This
->write_emu
);
886 This
->write_emu
= &buf
->IDirectSoundBuffer8_iface
;
891 LeaveCriticalSection(This
->crst
);
895 static HRESULT WINAPI
DS8Primary_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
897 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
900 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, vol
);
902 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
904 WARN("Invalid volume (%"LONGFMT
"d)\n", vol
);
905 return DSERR_INVALIDPARAM
;
908 EnterCriticalSection(This
->crst
);
909 if(!(This
->flags
&DSBCAPS_CTRLVOLUME
))
910 hr
= DSERR_CONTROLUNAVAIL
;
913 setALContext(This
->ctx
);
914 alListenerf(AL_GAIN
, mB_to_gain(vol
));
917 LeaveCriticalSection(This
->crst
);
922 static HRESULT WINAPI
DS8Primary_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
924 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
927 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, pan
);
929 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
931 WARN("invalid parameter: pan = %"LONGFMT
"d\n", pan
);
932 return DSERR_INVALIDPARAM
;
935 EnterCriticalSection(This
->crst
);
936 if(!(This
->flags
&DSBCAPS_CTRLPAN
))
938 WARN("control unavailable\n");
939 hr
= DSERR_CONTROLUNAVAIL
;
941 else if(This
->write_emu
)
942 hr
= IDirectSoundBuffer8_SetPan(This
->write_emu
, pan
);
945 FIXME("Not supported\n");
948 LeaveCriticalSection(This
->crst
);
953 static HRESULT WINAPI
DS8Primary_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
955 WARN("(%p)->(%"LONGFMT
"u)\n", iface
, freq
);
956 return DSERR_CONTROLUNAVAIL
;
959 static HRESULT WINAPI
DS8Primary_Stop(IDirectSoundBuffer
*iface
)
961 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
964 TRACE("(%p)->()\n", iface
);
966 EnterCriticalSection(This
->crst
);
968 hr
= IDirectSoundBuffer8_Stop(This
->write_emu
);
970 This
->stopped
= TRUE
;
971 LeaveCriticalSection(This
->crst
);
976 static HRESULT WINAPI
DS8Primary_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
978 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
979 HRESULT hr
= DSERR_INVALIDCALL
;
981 TRACE("(%p)->(%p, %"LONGFMT
"u, %p, %"LONGFMT
"u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
983 EnterCriticalSection(This
->crst
);
985 hr
= IDirectSoundBuffer8_Unlock(This
->write_emu
, ptr1
, len1
, ptr2
, len2
);
986 LeaveCriticalSection(This
->crst
);
991 static HRESULT WINAPI
DS8Primary_Restore(IDirectSoundBuffer
*iface
)
993 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
996 TRACE("(%p)->()\n", iface
);
998 EnterCriticalSection(This
->crst
);
1000 hr
= IDirectSoundBuffer8_Restore(This
->write_emu
);
1001 LeaveCriticalSection(This
->crst
);
1006 static const IDirectSoundBufferVtbl DS8Primary_Vtbl
=
1008 DS8Primary_QueryInterface
,
1012 DS8Primary_GetCurrentPosition
,
1013 DS8Primary_GetFormat
,
1014 DS8Primary_GetVolume
,
1016 DS8Primary_GetFrequency
,
1017 DS8Primary_GetStatus
,
1018 DS8Primary_Initialize
,
1021 DS8Primary_SetCurrentPosition
,
1022 DS8Primary_SetFormat
,
1023 DS8Primary_SetVolume
,
1025 DS8Primary_SetFrequency
,
1032 static HRESULT WINAPI
DS8Primary3D_QueryInterface(IDirectSound3DListener
*iface
, REFIID riid
, void **ppv
)
1034 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1035 return DS8Primary_QueryInterface(&This
->IDirectSoundBuffer_iface
, riid
, ppv
);
1038 static ULONG WINAPI
DS8Primary3D_AddRef(IDirectSound3DListener
*iface
)
1040 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1043 ret
= InterlockedIncrement(&This
->ds3d_ref
);
1044 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1049 static ULONG WINAPI
DS8Primary3D_Release(IDirectSound3DListener
*iface
)
1051 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1054 ret
= InterlockedDecrement(&This
->ds3d_ref
);
1055 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1061 static HRESULT WINAPI
DS8Primary3D_GetAllParameters(IDirectSound3DListener
*iface
, DS3DLISTENER
*listener
)
1063 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1065 TRACE("(%p)->(%p)\n", iface
, listener
);
1067 if(!listener
|| listener
->dwSize
< sizeof(*listener
))
1069 WARN("Invalid DS3DLISTENER %p %"LONGFMT
"u\n", listener
, listener
? listener
->dwSize
: 0);
1070 return DSERR_INVALIDPARAM
;
1073 EnterCriticalSection(This
->crst
);
1074 setALContext(This
->ctx
);
1075 IDirectSound3DListener_GetPosition(iface
, &listener
->vPosition
);
1076 IDirectSound3DListener_GetVelocity(iface
, &listener
->vVelocity
);
1077 IDirectSound3DListener_GetOrientation(iface
, &listener
->vOrientFront
, &listener
->vOrientTop
);
1078 IDirectSound3DListener_GetDistanceFactor(iface
, &listener
->flDistanceFactor
);
1079 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flRolloffFactor
);
1080 IDirectSound3DListener_GetDopplerFactor(iface
, &listener
->flDopplerFactor
);
1082 LeaveCriticalSection(This
->crst
);
1087 static HRESULT WINAPI
DS8Primary3D_GetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE
*distancefactor
)
1089 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1091 TRACE("(%p)->(%p)\n", iface
, distancefactor
);
1095 WARN("Invalid parameter %p\n", distancefactor
);
1096 return DSERR_INVALIDPARAM
;
1099 setALContext(This
->ctx
);
1100 *distancefactor
= 343.3f
/alGetFloat(AL_SPEED_OF_SOUND
);
1107 static HRESULT WINAPI
DS8Primary3D_GetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE
*dopplerfactor
)
1109 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1111 TRACE("(%p)->(%p)\n", iface
, dopplerfactor
);
1115 WARN("Invalid parameter %p\n", dopplerfactor
);
1116 return DSERR_INVALIDPARAM
;
1119 setALContext(This
->ctx
);
1120 *dopplerfactor
= alGetFloat(AL_DOPPLER_FACTOR
);
1127 static HRESULT WINAPI
DS8Primary3D_GetOrientation(IDirectSound3DListener
*iface
, D3DVECTOR
*front
, D3DVECTOR
*top
)
1129 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1132 TRACE("(%p)->(%p, %p)\n", iface
, front
, top
);
1136 WARN("Invalid parameter %p %p\n", front
, top
);
1137 return DSERR_INVALIDPARAM
;
1140 setALContext(This
->ctx
);
1141 alGetListenerfv(AL_ORIENTATION
, orient
);
1145 front
->x
= orient
[0];
1146 front
->y
= orient
[1];
1147 front
->z
= -orient
[2];
1150 top
->z
= -orient
[5];
1154 static HRESULT WINAPI
DS8Primary3D_GetPosition(IDirectSound3DListener
*iface
, D3DVECTOR
*pos
)
1156 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1159 TRACE("(%p)->(%p)\n", iface
, pos
);
1163 WARN("Invalid parameter %p\n", pos
);
1164 return DSERR_INVALIDPARAM
;
1167 setALContext(This
->ctx
);
1168 alGetListenerfv(AL_POSITION
, alpos
);
1178 static HRESULT WINAPI
DS8Primary3D_GetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE
*rollofffactor
)
1180 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1182 TRACE("(%p)->(%p)\n", iface
, rollofffactor
);
1186 WARN("Invalid parameter %p\n", rollofffactor
);
1187 return DSERR_INVALIDPARAM
;
1190 EnterCriticalSection(This
->crst
);
1191 *rollofffactor
= This
->rollofffactor
;
1192 LeaveCriticalSection(This
->crst
);
1197 static HRESULT WINAPI
DS8Primary3D_GetVelocity(IDirectSound3DListener
*iface
, D3DVECTOR
*velocity
)
1199 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1202 TRACE("(%p)->(%p)\n", iface
, velocity
);
1206 WARN("Invalid parameter %p\n", velocity
);
1207 return DSERR_INVALIDPARAM
;
1210 setALContext(This
->ctx
);
1211 alGetListenerfv(AL_VELOCITY
, vel
);
1215 velocity
->x
= vel
[0];
1216 velocity
->y
= vel
[1];
1217 velocity
->z
= -vel
[2];
1221 static HRESULT WINAPI
DS8Primary3D_SetAllParameters(IDirectSound3DListener
*iface
, const DS3DLISTENER
*listen
, DWORD apply
)
1223 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1225 TRACE("(%p)->(%p, %"LONGFMT
"u)\n", iface
, listen
, apply
);
1227 if(!listen
|| listen
->dwSize
< sizeof(*listen
))
1229 WARN("Invalid parameter %p %"LONGFMT
"u\n", listen
, listen
? listen
->dwSize
: 0);
1230 return DSERR_INVALIDPARAM
;
1233 if(listen
->flDistanceFactor
> DS3D_MAXDISTANCEFACTOR
||
1234 listen
->flDistanceFactor
< DS3D_MINDISTANCEFACTOR
)
1236 WARN("Invalid distance factor (%f)\n", listen
->flDistanceFactor
);
1237 return DSERR_INVALIDPARAM
;
1240 if(listen
->flDopplerFactor
> DS3D_MAXDOPPLERFACTOR
||
1241 listen
->flDopplerFactor
< DS3D_MINDOPPLERFACTOR
)
1243 WARN("Invalid doppler factor (%f)\n", listen
->flDopplerFactor
);
1244 return DSERR_INVALIDPARAM
;
1247 if(listen
->flRolloffFactor
< DS3D_MINROLLOFFFACTOR
||
1248 listen
->flRolloffFactor
> DS3D_MAXROLLOFFFACTOR
)
1250 WARN("Invalid rolloff factor (%f)\n", listen
->flRolloffFactor
);
1251 return DSERR_INVALIDPARAM
;
1254 EnterCriticalSection(This
->crst
);
1255 setALContext(This
->ctx
);
1256 IDirectSound3DListener_SetPosition(iface
, listen
->vPosition
.x
, listen
->vPosition
.y
, listen
->vPosition
.z
, apply
);
1257 IDirectSound3DListener_SetVelocity(iface
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, listen
->vVelocity
.z
, apply
);
1258 IDirectSound3DListener_SetOrientation(iface
, listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, listen
->vOrientFront
.z
,
1259 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, listen
->vOrientTop
.z
, apply
);
1260 IDirectSound3DListener_SetDistanceFactor(iface
, listen
->flDistanceFactor
, apply
);
1261 IDirectSound3DListener_SetRolloffFactor(iface
, listen
->flRolloffFactor
, apply
);
1262 IDirectSound3DListener_SetDopplerFactor(iface
, listen
->flDopplerFactor
, apply
);
1264 LeaveCriticalSection(This
->crst
);
1269 static HRESULT WINAPI
DS8Primary3D_SetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1271 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1273 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1275 if(factor
< DS3D_MINDISTANCEFACTOR
||
1276 factor
> DS3D_MAXDISTANCEFACTOR
)
1278 WARN("Invalid parameter %f\n", factor
);
1279 return DSERR_INVALIDPARAM
;
1282 if(apply
== DS3D_DEFERRED
)
1284 EnterCriticalSection(This
->crst
);
1285 This
->listen
.flDistanceFactor
= factor
;
1286 This
->dirty
.bit
.distancefactor
= 1;
1287 LeaveCriticalSection(This
->crst
);
1291 setALContext(This
->ctx
);
1292 alSpeedOfSound(343.3f
/factor
);
1293 if(This
->SupportedExt
[EXT_EFX
])
1294 alListenerf(AL_METERS_PER_UNIT
, factor
);
1302 static HRESULT WINAPI
DS8Primary3D_SetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1304 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1306 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1308 if(factor
< DS3D_MINDOPPLERFACTOR
||
1309 factor
> DS3D_MAXDOPPLERFACTOR
)
1311 WARN("Invalid parameter %f\n", factor
);
1312 return DSERR_INVALIDPARAM
;
1315 if(apply
== DS3D_DEFERRED
)
1317 EnterCriticalSection(This
->crst
);
1318 This
->listen
.flDopplerFactor
= factor
;
1319 This
->dirty
.bit
.dopplerfactor
= 1;
1320 LeaveCriticalSection(This
->crst
);
1324 setALContext(This
->ctx
);
1325 alDopplerFactor(factor
);
1333 static HRESULT WINAPI
DS8Primary3D_SetOrientation(IDirectSound3DListener
*iface
, D3DVALUE xFront
, D3DVALUE yFront
, D3DVALUE zFront
, D3DVALUE xTop
, D3DVALUE yTop
, D3DVALUE zTop
, DWORD apply
)
1335 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1337 TRACE("(%p)->(%f, %f, %f, %f, %f, %f, %"LONGFMT
"u)\n", iface
, xFront
, yFront
, zFront
, xTop
, yTop
, zTop
, apply
);
1339 if(apply
== DS3D_DEFERRED
)
1341 EnterCriticalSection(This
->crst
);
1342 This
->listen
.vOrientFront
.x
= xFront
;
1343 This
->listen
.vOrientFront
.y
= yFront
;
1344 This
->listen
.vOrientFront
.z
= zFront
;
1345 This
->listen
.vOrientTop
.x
= xTop
;
1346 This
->listen
.vOrientTop
.y
= yTop
;
1347 This
->listen
.vOrientTop
.z
= zTop
;
1348 This
->dirty
.bit
.orientation
= 1;
1349 LeaveCriticalSection(This
->crst
);
1353 ALfloat orient
[6] = {
1354 xFront
, yFront
, -zFront
,
1357 setALContext(This
->ctx
);
1358 alListenerfv(AL_ORIENTATION
, orient
);
1366 static HRESULT WINAPI
DS8Primary3D_SetPosition(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1368 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1370 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", iface
, x
, y
, z
, apply
);
1372 if(apply
== DS3D_DEFERRED
)
1374 EnterCriticalSection(This
->crst
);
1375 This
->listen
.vPosition
.x
= x
;
1376 This
->listen
.vPosition
.y
= y
;
1377 This
->listen
.vPosition
.z
= z
;
1378 This
->dirty
.bit
.pos
= 1;
1379 LeaveCriticalSection(This
->crst
);
1383 setALContext(This
->ctx
);
1384 alListener3f(AL_POSITION
, x
, y
, -z
);
1392 static HRESULT WINAPI
DS8Primary3D_SetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1394 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1396 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1398 if(factor
< DS3D_MINROLLOFFFACTOR
||
1399 factor
> DS3D_MAXROLLOFFFACTOR
)
1401 WARN("Invalid parameter %f\n", factor
);
1402 return DSERR_INVALIDPARAM
;
1405 EnterCriticalSection(This
->crst
);
1406 if(apply
== DS3D_DEFERRED
)
1408 This
->listen
.flRolloffFactor
= factor
;
1409 This
->dirty
.bit
.rollofffactor
= 1;
1415 setALContext(This
->ctx
);
1416 for(i
= 0;i
< This
->nbuffers
;++i
)
1418 if(This
->buffers
[i
]->ds3dmode
!= DS3DMODE_DISABLE
)
1419 alSourcef(This
->buffers
[i
]->source
, AL_ROLLOFF_FACTOR
, factor
);
1424 This
->rollofffactor
= factor
;
1426 LeaveCriticalSection(This
->crst
);
1431 static HRESULT WINAPI
DS8Primary3D_SetVelocity(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1433 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1435 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", iface
, x
, y
, z
, apply
);
1437 if(apply
== DS3D_DEFERRED
)
1439 EnterCriticalSection(This
->crst
);
1440 This
->listen
.vVelocity
.x
= x
;
1441 This
->listen
.vVelocity
.y
= y
;
1442 This
->listen
.vVelocity
.z
= z
;
1443 This
->dirty
.bit
.vel
= 1;
1444 LeaveCriticalSection(This
->crst
);
1448 setALContext(This
->ctx
);
1449 alListener3f(AL_VELOCITY
, x
, y
, -z
);
1457 static HRESULT WINAPI
DS8Primary3D_CommitDeferredSettings(IDirectSound3DListener
*iface
)
1459 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1460 const DS3DLISTENER
*listen
= &This
->listen
;
1463 EnterCriticalSection(This
->crst
);
1464 setALContext(This
->ctx
);
1465 This
->DeferUpdates();
1467 if(This
->dirty
.bit
.pos
)
1468 alListener3f(AL_POSITION
, listen
->vPosition
.x
, listen
->vPosition
.y
, -listen
->vPosition
.z
);
1469 if(This
->dirty
.bit
.vel
)
1470 alListener3f(AL_VELOCITY
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, -listen
->vVelocity
.z
);
1471 if(This
->dirty
.bit
.orientation
)
1473 ALfloat orient
[6] = {
1474 listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, -listen
->vOrientFront
.z
,
1475 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, -listen
->vOrientTop
.z
1477 alListenerfv(AL_ORIENTATION
, orient
);
1479 if(This
->dirty
.bit
.distancefactor
)
1481 alSpeedOfSound(343.3f
/listen
->flDistanceFactor
);
1482 if(This
->SupportedExt
[EXT_EFX
])
1483 alListenerf(AL_METERS_PER_UNIT
, listen
->flDistanceFactor
);
1486 if(This
->dirty
.bit
.rollofffactor
)
1488 ALfloat rolloff
= This
->rollofffactor
;
1489 for(i
= 0;i
< This
->nbuffers
;++i
)
1491 DS8Buffer
*buf
= This
->buffers
[i
];
1492 if(buf
->ds3dmode
!= DS3DMODE_DISABLE
)
1493 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
, rolloff
);
1497 if(This
->dirty
.bit
.dopplerfactor
)
1498 alDopplerFactor(listen
->flDopplerFactor
);
1500 if(This
->dirty
.bit
.effect
)
1501 This
->ExtAL
->AuxiliaryEffectSloti(This
->auxslot
, AL_EFFECTSLOT_EFFECT
, This
->effect
);
1503 /* checkALError is here for debugging */
1506 TRACE("Dirty flags was: 0x%02x\n", This
->dirty
.flags
);
1507 This
->dirty
.flags
= 0;
1509 for(i
= 0;i
< This
->nbuffers
;++i
)
1511 DS8Buffer
*buf
= This
->buffers
[i
];
1513 if(!buf
->dirty
.flags
)
1516 if(buf
->dirty
.bit
.pos
)
1517 alSource3f(buf
->source
, AL_POSITION
,
1518 buf
->ds3dbuffer
.vPosition
.x
,
1519 buf
->ds3dbuffer
.vPosition
.y
,
1520 -buf
->ds3dbuffer
.vPosition
.z
);
1521 if(buf
->dirty
.bit
.vel
)
1522 alSource3f(buf
->source
, AL_VELOCITY
,
1523 buf
->ds3dbuffer
.vVelocity
.x
,
1524 buf
->ds3dbuffer
.vVelocity
.y
,
1525 -buf
->ds3dbuffer
.vVelocity
.z
);
1526 if(buf
->dirty
.bit
.cone_angles
)
1528 alSourcei(buf
->source
, AL_CONE_INNER_ANGLE
,
1529 buf
->ds3dbuffer
.dwInsideConeAngle
);
1530 alSourcei(buf
->source
, AL_CONE_OUTER_ANGLE
,
1531 buf
->ds3dbuffer
.dwOutsideConeAngle
);
1533 if(buf
->dirty
.bit
.cone_orient
)
1534 alSource3f(buf
->source
, AL_DIRECTION
,
1535 buf
->ds3dbuffer
.vConeOrientation
.x
,
1536 buf
->ds3dbuffer
.vConeOrientation
.y
,
1537 -buf
->ds3dbuffer
.vConeOrientation
.z
);
1538 if(buf
->dirty
.bit
.cone_outsidevolume
)
1539 alSourcef(buf
->source
, AL_CONE_OUTER_GAIN
,
1540 mB_to_gain(buf
->ds3dbuffer
.lConeOutsideVolume
));
1541 if(buf
->dirty
.bit
.min_distance
)
1542 alSourcef(buf
->source
, AL_REFERENCE_DISTANCE
, buf
->ds3dbuffer
.flMinDistance
);
1543 if(buf
->dirty
.bit
.max_distance
)
1544 alSourcef(buf
->source
, AL_MAX_DISTANCE
, buf
->ds3dbuffer
.flMaxDistance
);
1545 if(buf
->dirty
.bit
.mode
)
1547 buf
->ds3dmode
= buf
->ds3dbuffer
.dwMode
;
1548 alSourcei(buf
->source
, AL_SOURCE_RELATIVE
,
1549 (buf
->ds3dmode
!=DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
1550 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
,
1551 (buf
->ds3dmode
==DS3DMODE_DISABLE
) ? 0.0f
: This
->rollofffactor
);
1553 buf
->dirty
.flags
= 0;
1557 This
->ProcessUpdates();
1559 LeaveCriticalSection(This
->crst
);
1564 static const IDirectSound3DListenerVtbl DS8Primary3D_Vtbl
=
1566 DS8Primary3D_QueryInterface
,
1567 DS8Primary3D_AddRef
,
1568 DS8Primary3D_Release
,
1569 DS8Primary3D_GetAllParameters
,
1570 DS8Primary3D_GetDistanceFactor
,
1571 DS8Primary3D_GetDopplerFactor
,
1572 DS8Primary3D_GetOrientation
,
1573 DS8Primary3D_GetPosition
,
1574 DS8Primary3D_GetRolloffFactor
,
1575 DS8Primary3D_GetVelocity
,
1576 DS8Primary3D_SetAllParameters
,
1577 DS8Primary3D_SetDistanceFactor
,
1578 DS8Primary3D_SetDopplerFactor
,
1579 DS8Primary3D_SetOrientation
,
1580 DS8Primary3D_SetPosition
,
1581 DS8Primary3D_SetRolloffFactor
,
1582 DS8Primary3D_SetVelocity
,
1583 DS8Primary3D_CommitDeferredSettings
1586 /* NOTE: Although the app handles listener properties through secondary buffers,
1587 * we pass the requests to the primary buffer though a propertyset interface.
1588 * These methods are not exposed to the app. */
1589 static HRESULT WINAPI
DS8PrimaryProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
1591 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1592 return DS8Primary_QueryInterface(&This
->IDirectSoundBuffer_iface
, riid
, ppv
);
1595 static ULONG WINAPI
DS8PrimaryProp_AddRef(IKsPropertySet
*iface
)
1597 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1600 ret
= InterlockedIncrement(&This
->prop_ref
);
1601 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1606 static ULONG WINAPI
DS8PrimaryProp_Release(IKsPropertySet
*iface
)
1608 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1611 ret
= InterlockedDecrement(&This
->prop_ref
);
1612 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1617 static HRESULT WINAPI
DS8PrimaryProp_Get(IKsPropertySet
*iface
,
1618 REFGUID guidPropSet
, ULONG dwPropID
,
1619 LPVOID pInstanceData
, ULONG cbInstanceData
,
1620 LPVOID pPropData
, ULONG cbPropData
,
1623 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1624 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1625 (void)pInstanceData
;
1626 (void)cbInstanceData
;
1628 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1630 EnterCriticalSection(This
->crst
);
1632 if(This
->effect
== 0)
1633 res
= E_PROP_ID_UNSUPPORTED
;
1634 else switch(dwPropID
)
1636 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
1637 res
= DSERR_INVALIDPARAM
;
1638 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1642 EAXLISTENERPROPERTIES
*props
;
1643 } data
= { pPropData
};
1645 *data
.props
= This
->eax_prop
;
1646 *pcbReturned
= sizeof(EAXLISTENERPROPERTIES
);
1651 case DSPROPERTY_EAXLISTENER_ROOM
:
1652 res
= DSERR_INVALIDPARAM
;
1653 if(cbPropData
>= sizeof(LONG
))
1658 } data
= { pPropData
};
1660 *data
.l
= This
->eax_prop
.lRoom
;
1661 *pcbReturned
= sizeof(LONG
);
1665 case DSPROPERTY_EAXLISTENER_ROOMHF
:
1666 res
= DSERR_INVALIDPARAM
;
1667 if(cbPropData
>= sizeof(LONG
))
1672 } data
= { pPropData
};
1674 *data
.l
= This
->eax_prop
.lRoomHF
;
1675 *pcbReturned
= sizeof(LONG
);
1680 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
1681 res
= DSERR_INVALIDPARAM
;
1682 if(cbPropData
>= sizeof(FLOAT
))
1687 } data
= { pPropData
};
1689 *data
.fl
= This
->eax_prop
.flRoomRolloffFactor
;
1690 *pcbReturned
= sizeof(FLOAT
);
1695 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
1696 res
= DSERR_INVALIDPARAM
;
1697 if(cbPropData
>= sizeof(DWORD
))
1702 } data
= { pPropData
};
1704 *data
.dw
= This
->eax_prop
.dwEnvironment
;
1705 *pcbReturned
= sizeof(DWORD
);
1710 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
1711 res
= DSERR_INVALIDPARAM
;
1712 if(cbPropData
>= sizeof(FLOAT
))
1717 } data
= { pPropData
};
1719 *data
.fl
= This
->eax_prop
.flEnvironmentSize
;
1720 *pcbReturned
= sizeof(FLOAT
);
1724 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
1725 res
= DSERR_INVALIDPARAM
;
1726 if(cbPropData
>= sizeof(FLOAT
))
1731 } data
= { pPropData
};
1733 *data
.fl
= This
->eax_prop
.flEnvironmentDiffusion
;
1734 *pcbReturned
= sizeof(FLOAT
);
1739 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
1740 res
= DSERR_INVALIDPARAM
;
1741 if(cbPropData
>= sizeof(FLOAT
))
1746 } data
= { pPropData
};
1748 *data
.fl
= This
->eax_prop
.flAirAbsorptionHF
;
1749 *pcbReturned
= sizeof(FLOAT
);
1754 case DSPROPERTY_EAXLISTENER_FLAGS
:
1755 res
= DSERR_INVALIDPARAM
;
1756 if(cbPropData
>= sizeof(DWORD
))
1761 } data
= { pPropData
};
1763 *data
.dw
= This
->eax_prop
.dwFlags
;
1764 *pcbReturned
= sizeof(DWORD
);
1770 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", dwPropID
);
1774 LeaveCriticalSection(This
->crst
);
1777 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
1782 static HRESULT WINAPI
DS8PrimaryProp_Set(IKsPropertySet
*iface
,
1783 REFGUID guidPropSet
, ULONG dwPropID
,
1784 LPVOID pInstanceData
, ULONG cbInstanceData
,
1785 LPVOID pPropData
, ULONG cbPropData
)
1787 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1788 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1789 (void)pInstanceData
;
1790 (void)cbInstanceData
;
1792 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1794 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
1795 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
1797 EnterCriticalSection(This
->crst
);
1798 setALContext(This
->ctx
);
1800 if(This
->effect
== 0)
1801 res
= E_PROP_ID_UNSUPPORTED
;
1804 case 0: /* 0 = not setting any property, just apply */
1808 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
1810 res
= DSERR_INVALIDPARAM
;
1811 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1815 const EAXLISTENERPROPERTIES
*props
;
1816 } data
= { pPropData
};
1818 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
1819 This
->eax_prop
= *data
.props
;
1820 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DENSITY
,
1821 (data
.props
->flEnvironmentSize
< 2.0f
) ?
1822 (data
.props
->flEnvironmentSize
- 1.0f
) : 1.0f
);
1823 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1824 data
.props
->flEnvironmentDiffusion
);
1826 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAIN
,
1827 mB_to_gain(data
.props
->lRoom
));
1828 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAINHF
,
1829 mB_to_gain(data
.props
->lRoomHF
));
1831 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1832 data
.props
->flRoomRolloffFactor
);
1834 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DECAY_TIME
,
1835 data
.props
->flDecayTime
);
1836 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DECAY_HFRATIO
,
1837 data
.props
->flDecayHFRatio
);
1839 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_REFLECTIONS_GAIN
,
1840 mB_to_gain(data
.props
->lReflections
));
1841 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_REFLECTIONS_DELAY
,
1842 data
.props
->flReflectionsDelay
);
1844 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_LATE_REVERB_GAIN
,
1845 mB_to_gain(data
.props
->lReverb
));
1846 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_LATE_REVERB_DELAY
,
1847 data
.props
->flReverbDelay
);
1849 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1850 mB_to_gain(data
.props
->flAirAbsorptionHF
));
1852 This
->ExtAL
->Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
1853 (data
.props
->dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
1854 AL_TRUE
: AL_FALSE
);
1858 This
->dirty
.bit
.effect
= 1;
1863 case DSPROPERTY_EAXLISTENER_ROOM
:
1864 res
= DSERR_INVALIDPARAM
;
1865 if(cbPropData
>= sizeof(LONG
))
1870 } data
= { pPropData
};
1872 This
->eax_prop
.lRoom
= *data
.l
;
1873 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAIN
,
1874 mB_to_gain(This
->eax_prop
.lRoom
));
1877 This
->dirty
.bit
.effect
= 1;
1881 case DSPROPERTY_EAXLISTENER_ROOMHF
:
1882 res
= DSERR_INVALIDPARAM
;
1883 if(cbPropData
>= sizeof(LONG
))
1888 } data
= { pPropData
};
1890 This
->eax_prop
.lRoomHF
= *data
.l
;
1891 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAINHF
,
1892 mB_to_gain(This
->eax_prop
.lRoomHF
));
1895 This
->dirty
.bit
.effect
= 1;
1900 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
1901 res
= DSERR_INVALIDPARAM
;
1902 if(cbPropData
>= sizeof(FLOAT
))
1907 } data
= { pPropData
};
1909 This
->eax_prop
.flRoomRolloffFactor
= *data
.fl
;
1910 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1911 This
->eax_prop
.flRoomRolloffFactor
);
1914 This
->dirty
.bit
.effect
= 1;
1919 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
1920 res
= DSERR_INVALIDPARAM
;
1921 if(cbPropData
>= sizeof(DWORD
))
1926 } data
= { pPropData
};
1928 if(*data
.dw
< EAX_ENVIRONMENT_COUNT
)
1930 /* Get the environment index's default and pass it down to
1932 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1933 pPropData
= (void*)&EnvironmentDefaults
[*data
.dw
];
1934 cbPropData
= sizeof(EnvironmentDefaults
[*data
.dw
]);
1940 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
1941 res
= DSERR_INVALIDPARAM
;
1942 if(cbPropData
>= sizeof(FLOAT
))
1947 } data
= { pPropData
};
1949 if(*data
.fl
>= 1.0f
&& *data
.fl
<= 100.0f
)
1951 double scale
= (*data
.fl
)/This
->eax_prop
.flEnvironmentSize
;
1953 This
->eax_prop
.flEnvironmentSize
= *data
.fl
;
1955 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYTIMESCALE
))
1957 This
->eax_prop
.flDecayTime
*= scale
;
1958 This
->eax_prop
.flDecayTime
= clampF(This
->eax_prop
.flDecayTime
, 0.1f
, 20.0f
);
1960 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSSCALE
))
1962 This
->eax_prop
.lReflections
+= gain_to_mB(1.0/scale
);
1963 This
->eax_prop
.lReflections
= clampI(This
->eax_prop
.lReflections
, -10000, 1000);
1965 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE
))
1967 This
->eax_prop
.flReflectionsDelay
*= scale
;
1968 This
->eax_prop
.flReflectionsDelay
= clampF(This
->eax_prop
.flReflectionsDelay
, 0.0f
, 0.3f
);
1970 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBSCALE
))
1972 This
->eax_prop
.lReverb
+= gain_to_mB(1.0/scale
);
1973 This
->eax_prop
.lReverb
= clampI(This
->eax_prop
.lReverb
, -10000, 2000);
1975 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBDELAYSCALE
))
1977 This
->eax_prop
.flReverbDelay
*= scale
;
1978 This
->eax_prop
.flReverbDelay
= clampF(This
->eax_prop
.flReverbDelay
, 0.0f
, 0.1f
);
1981 /* Pass the updated environment properties down to ALLPARAMETERS */
1982 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1983 pPropData
= (void*)&This
->eax_prop
;
1984 cbPropData
= sizeof(This
->eax_prop
);
1989 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
1990 res
= DSERR_INVALIDPARAM
;
1991 if(cbPropData
>= sizeof(FLOAT
))
1996 } data
= { pPropData
};
1998 This
->eax_prop
.flEnvironmentDiffusion
= *data
.fl
;
1999 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
2000 This
->eax_prop
.flEnvironmentDiffusion
);
2003 This
->dirty
.bit
.effect
= 1;
2008 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
2009 res
= DSERR_INVALIDPARAM
;
2010 if(cbPropData
>= sizeof(FLOAT
))
2015 } data
= { pPropData
};
2017 This
->eax_prop
.flAirAbsorptionHF
= *data
.fl
;
2018 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
2019 mB_to_gain(This
->eax_prop
.flAirAbsorptionHF
));
2022 This
->dirty
.bit
.effect
= 1;
2027 case DSPROPERTY_EAXLISTENER_FLAGS
:
2028 res
= DSERR_INVALIDPARAM
;
2029 if(cbPropData
>= sizeof(DWORD
))
2034 } data
= { pPropData
};
2036 This
->eax_prop
.dwFlags
= *data
.dw
;
2037 This
->ExtAL
->Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
2038 (This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
2039 AL_TRUE
: AL_FALSE
);
2042 This
->dirty
.bit
.effect
= 1;
2048 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", propid
);
2052 if(res
== DS_OK
&& immediate
)
2053 IDirectSound3DListener_CommitDeferredSettings(&This
->IDirectSound3DListener_iface
);
2056 LeaveCriticalSection(This
->crst
);
2059 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2064 static HRESULT WINAPI
DS8PrimaryProp_QuerySupport(IKsPropertySet
*iface
,
2065 REFGUID guidPropSet
, ULONG dwPropID
,
2066 PULONG pTypeSupport
)
2068 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
2069 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
2071 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2073 EnterCriticalSection(This
->crst
);
2075 if(This
->effect
== 0)
2076 res
= E_PROP_ID_UNSUPPORTED
;
2077 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
||
2078 dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
||
2079 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
||
2080 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
||
2081 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
||
2082 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
||
2083 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
||
2084 dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
||
2085 dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
2087 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
|KSPROPERTY_SUPPORT_SET
;
2091 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", dwPropID
);
2093 LeaveCriticalSection(This
->crst
);
2096 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2101 static const IKsPropertySetVtbl DS8PrimaryProp_Vtbl
=
2103 DS8PrimaryProp_QueryInterface
,
2104 DS8PrimaryProp_AddRef
,
2105 DS8PrimaryProp_Release
,
2108 DS8PrimaryProp_QuerySupport